2 * Copyright © 2014 Broadcom
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 #include "vc4_qpu_defines.h"
30 static const char *qpu_add_opcodes
[] = {
32 [QPU_A_FADD
] = "fadd",
33 [QPU_A_FSUB
] = "fsub",
34 [QPU_A_FMIN
] = "fmin",
35 [QPU_A_FMAX
] = "fmax",
36 [QPU_A_FMINABS
] = "fminabs",
37 [QPU_A_FMAXABS
] = "fmaxabs",
38 [QPU_A_FTOI
] = "ftoi",
39 [QPU_A_ITOF
] = "itof",
53 [QPU_A_V8ADDS
] = "v8adds",
54 [QPU_A_V8SUBS
] = "v8subs",
57 static const char *qpu_mul_opcodes
[] = {
59 [QPU_M_FMUL
] = "fmul",
60 [QPU_M_MUL24
] = "mul24",
61 [QPU_M_V8MULD
] = "v8muld",
62 [QPU_M_V8MIN
] = "v8min",
63 [QPU_M_V8MAX
] = "v8max",
64 [QPU_M_V8ADDS
] = "v8adds",
65 [QPU_M_V8SUBS
] = "v8subs",
68 static const char *qpu_sig
[] = {
69 [QPU_SIG_SW_BREAKPOINT
] = "sig_brk",
71 [QPU_SIG_THREAD_SWITCH
] = "sig_switch",
72 [QPU_SIG_PROG_END
] = "sig_end",
73 [QPU_SIG_WAIT_FOR_SCOREBOARD
] = "sig_wait_score",
74 [QPU_SIG_SCOREBOARD_UNLOCK
] = "sig_unlock_score",
75 [QPU_SIG_LAST_THREAD_SWITCH
] = "sig_thread_switch",
76 [QPU_SIG_COVERAGE_LOAD
] = "sig_coverage_load",
77 [QPU_SIG_COLOR_LOAD
] = "sig_color_load",
78 [QPU_SIG_COLOR_LOAD_END
] = "sig_color_load_end",
79 [QPU_SIG_LOAD_TMU0
] = "load_tmu0",
80 [QPU_SIG_LOAD_TMU1
] = "load_tmu1",
81 [QPU_SIG_ALPHA_MASK_LOAD
] = "sig_alpha_mask_load",
82 [QPU_SIG_SMALL_IMM
] = "sig_small_imm",
83 [QPU_SIG_LOAD_IMM
] = "sig_load_imm",
84 [QPU_SIG_BRANCH
] = "sig_branch",
87 static const char *qpu_pack_mul
[] = {
88 [QPU_PACK_MUL_NOP
] = "",
89 [QPU_PACK_MUL_8888
] = "8888",
90 [QPU_PACK_MUL_8A
] = "8a",
91 [QPU_PACK_MUL_8B
] = "8b",
92 [QPU_PACK_MUL_8C
] = "8c",
93 [QPU_PACK_MUL_8D
] = "8d",
96 static const char *special_read_a
[] = {
119 static const char *special_read_b
[] = {
143 * This has the B-file descriptions for register writes.
145 * Since only a couple of regs are different between A and B, the A overrides
146 * are in get_special_write_desc().
148 static const char *special_write
[] = {
153 [QPU_W_TMU_NOSWAP
] = "tmu_noswap",
155 [QPU_W_HOST_INT
] = "host_int",
157 [QPU_W_UNIFORMS_ADDRESS
] = "uniforms_addr",
158 [QPU_W_QUAD_XY
] = "quad_y",
159 [QPU_W_MS_FLAGS
] = "ms_flags",
160 [QPU_W_TLB_STENCIL_SETUP
] = "tlb_stencil_setup",
161 [QPU_W_TLB_Z
] = "tlb_z",
162 [QPU_W_TLB_COLOR_MS
] = "tlb_color_ms",
163 [QPU_W_TLB_COLOR_ALL
] = "tlb_color_all",
165 [QPU_W_VPMVCD_SETUP
] = "vw_setup",
166 [QPU_W_VPM_ADDR
] = "vw_addr",
167 [QPU_W_MUTEX_RELEASE
] = "mutex_release",
168 [QPU_W_SFU_RECIP
] = "sfu_recip",
169 [QPU_W_SFU_RECIPSQRT
] = "sfu_recipsqrt",
170 [QPU_W_SFU_EXP
] = "sfu_exp",
171 [QPU_W_SFU_LOG
] = "sfu_log",
172 [QPU_W_TMU0_S
] = "tmu0_s",
173 [QPU_W_TMU0_T
] = "tmu0_t",
174 [QPU_W_TMU0_R
] = "tmu0_r",
175 [QPU_W_TMU0_B
] = "tmu0_b",
176 [QPU_W_TMU1_S
] = "tmu1_s",
177 [QPU_W_TMU1_T
] = "tmu1_t",
178 [QPU_W_TMU1_R
] = "tmu1_r",
179 [QPU_W_TMU1_B
] = "tmu1_b",
182 static const char *qpu_pack_a
[] = {
183 [QPU_PACK_A_NOP
] = "",
184 [QPU_PACK_A_16A
] = ".16a",
185 [QPU_PACK_A_16B
] = ".16b",
186 [QPU_PACK_A_8888
] = ".8888",
187 [QPU_PACK_A_8A
] = ".8a",
188 [QPU_PACK_A_8B
] = ".8b",
189 [QPU_PACK_A_8C
] = ".8c",
190 [QPU_PACK_A_8D
] = ".8d",
192 [QPU_PACK_A_32_SAT
] = ".sat",
193 [QPU_PACK_A_16A_SAT
] = ".16a.sat",
194 [QPU_PACK_A_16B_SAT
] = ".16b.sat",
195 [QPU_PACK_A_8888_SAT
] = ".8888.sat",
196 [QPU_PACK_A_8A_SAT
] = ".8a.sat",
197 [QPU_PACK_A_8B_SAT
] = ".8b.sat",
198 [QPU_PACK_A_8C_SAT
] = ".8c.sat",
199 [QPU_PACK_A_8D_SAT
] = ".8d.sat",
202 static const char *qpu_condflags
[] = {
203 [QPU_COND_NEVER
] = ".never",
204 [QPU_COND_ALWAYS
] = "",
205 [QPU_COND_ZS
] = ".zs",
206 [QPU_COND_ZC
] = ".zc",
207 [QPU_COND_NS
] = ".ns",
208 [QPU_COND_NC
] = ".nc",
209 [QPU_COND_CS
] = ".cs",
210 [QPU_COND_CC
] = ".cc",
213 #define DESC(array, index) \
214 ((index > ARRAY_SIZE(array) || !(array)[index]) ? \
215 "???" : (array)[index])
218 get_special_write_desc(int reg
, bool is_a
)
224 case QPU_W_VPMVCD_SETUP
:
231 return special_write
[reg
];
235 print_alu_dst(uint64_t inst
, bool is_mul
)
237 bool is_a
= is_mul
== ((inst
& QPU_WS
) != 0);
238 uint32_t waddr
= (is_mul
?
239 QPU_GET_FIELD(inst
, QPU_WADDR_MUL
) :
240 QPU_GET_FIELD(inst
, QPU_WADDR_ADD
));
241 const char *file
= is_a
? "a" : "b";
242 uint32_t pack
= QPU_GET_FIELD(inst
, QPU_PACK
);
245 fprintf(stderr
, "r%s%d", file
, waddr
);
246 else if (get_special_write_desc(waddr
, is_a
))
247 fprintf(stderr
, "%s", get_special_write_desc(waddr
, is_a
));
249 fprintf(stderr
, "%s%d?", file
, waddr
);
251 if (is_mul
&& (inst
& QPU_PM
)) {
252 fprintf(stderr
, ".%s", DESC(qpu_pack_mul
, pack
));
253 } else if (is_a
&& !(inst
& QPU_PM
)) {
254 fprintf(stderr
, "%s", DESC(qpu_pack_a
, pack
));
259 print_alu_src(uint64_t inst
, uint32_t mux
)
261 bool is_a
= mux
!= QPU_MUX_B
;
262 const char *file
= is_a
? "a" : "b";
263 uint32_t raddr
= (is_a
?
264 QPU_GET_FIELD(inst
, QPU_RADDR_A
) :
265 QPU_GET_FIELD(inst
, QPU_RADDR_B
));
267 if (mux
<= QPU_MUX_R5
)
268 fprintf(stderr
, "r%d", mux
);
270 QPU_GET_FIELD(inst
, QPU_SIG
) == QPU_SIG_SMALL_IMM
) {
271 uint32_t si
= QPU_GET_FIELD(inst
, QPU_SMALL_IMM
);
273 fprintf(stderr
, "%d", si
);
275 fprintf(stderr
, "%d", -16 + (si
- 16));
277 fprintf(stderr
, "%.1f", (float)(1 << (si
- 32)));
279 fprintf(stderr
, "%f", 1.0f
/ (256 / (si
- 39)));
281 fprintf(stderr
, "???");
282 } else if (raddr
<= 31)
283 fprintf(stderr
, "r%s%d", file
, raddr
);
286 fprintf(stderr
, "%s", DESC(special_read_a
, raddr
- 32));
288 fprintf(stderr
, "%s", DESC(special_read_b
, raddr
- 32));
293 print_add_op(uint64_t inst
)
295 uint32_t op_add
= QPU_GET_FIELD(inst
, QPU_OP_ADD
);
296 uint32_t cond
= QPU_GET_FIELD(inst
, QPU_COND_ADD
);
297 bool is_mov
= (op_add
== QPU_A_OR
&&
298 QPU_GET_FIELD(inst
, QPU_ADD_A
) ==
299 QPU_GET_FIELD(inst
, QPU_ADD_B
));
301 fprintf(stderr
, "%s%s%s ",
302 is_mov
? "mov" : DESC(qpu_add_opcodes
, op_add
),
303 ((inst
& QPU_SF
) && op_add
!= QPU_A_NOP
) ? ".sf" : "",
304 op_add
!= QPU_A_NOP
? DESC(qpu_condflags
, cond
) : "");
306 print_alu_dst(inst
, false);
307 fprintf(stderr
, ", ");
309 print_alu_src(inst
, QPU_GET_FIELD(inst
, QPU_ADD_A
));
312 fprintf(stderr
, ", ");
314 print_alu_src(inst
, QPU_GET_FIELD(inst
, QPU_ADD_B
));
319 print_mul_op(uint64_t inst
)
321 uint32_t op_add
= QPU_GET_FIELD(inst
, QPU_OP_ADD
);
322 uint32_t op_mul
= QPU_GET_FIELD(inst
, QPU_OP_MUL
);
323 uint32_t cond
= QPU_GET_FIELD(inst
, QPU_COND_MUL
);
324 bool is_mov
= (op_mul
== QPU_M_V8MIN
&&
325 QPU_GET_FIELD(inst
, QPU_MUL_A
) ==
326 QPU_GET_FIELD(inst
, QPU_MUL_B
));
328 fprintf(stderr
, "%s%s%s ",
329 is_mov
? "mov" : DESC(qpu_mul_opcodes
, op_mul
),
330 ((inst
& QPU_SF
) && op_add
== QPU_A_NOP
) ? ".sf" : "",
331 op_mul
!= QPU_M_NOP
? DESC(qpu_condflags
, cond
) : "");
333 print_alu_dst(inst
, true);
334 fprintf(stderr
, ", ");
336 print_alu_src(inst
, QPU_GET_FIELD(inst
, QPU_MUL_A
));
339 fprintf(stderr
, ", ");
340 print_alu_src(inst
, QPU_GET_FIELD(inst
, QPU_MUL_B
));
345 print_load_imm(uint64_t inst
)
348 uint32_t waddr_add
= QPU_GET_FIELD(inst
, QPU_WADDR_ADD
);
349 uint32_t waddr_mul
= QPU_GET_FIELD(inst
, QPU_WADDR_MUL
);
350 uint32_t cond_add
= QPU_GET_FIELD(inst
, QPU_COND_ADD
);
351 uint32_t cond_mul
= QPU_GET_FIELD(inst
, QPU_COND_MUL
);
353 fprintf(stderr
, "load_imm ");
354 print_alu_dst(inst
, false);
355 fprintf(stderr
, "%s, ", (waddr_add
!= QPU_W_NOP
?
356 DESC(qpu_condflags
, cond_add
) : ""));
357 print_alu_dst(inst
, true);
358 fprintf(stderr
, "%s, ", (waddr_mul
!= QPU_W_NOP
?
359 DESC(qpu_condflags
, cond_mul
) : ""));
360 fprintf(stderr
, "0x%08x (%f)", imm
, uif(imm
));
364 vc4_qpu_disasm(const uint64_t *instructions
, int num_instructions
)
366 for (int i
= 0; i
< num_instructions
; i
++) {
367 uint64_t inst
= instructions
[i
];
368 uint32_t sig
= QPU_GET_FIELD(inst
, QPU_SIG
);
372 fprintf(stderr
, "branch\n");
374 case QPU_SIG_LOAD_IMM
:
375 print_load_imm(inst
);
378 if (sig
!= QPU_SIG_NONE
)
379 fprintf(stderr
, "%s ", DESC(qpu_sig
, sig
));
381 fprintf(stderr
, " ; ");
384 if (num_instructions
!= 1)
385 fprintf(stderr
, "\n");