1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
5bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
6bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights
7bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
9bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18bf215546Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <stdbool.h>
25bf215546Sopenharmony_ci#include <stdint.h>
26bf215546Sopenharmony_ci#include <stdio.h>
27bf215546Sopenharmony_ci#include <stdlib.h>
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "pvr_rogue_pds_defs.h"
30bf215546Sopenharmony_ci#include "pvr_rogue_pds_disasm.h"
31bf215546Sopenharmony_ci#include "pvr_rogue_pds_encode.h"
32bf215546Sopenharmony_ci#include "util/log.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#define X(lop, str) #str,
35bf215546Sopenharmony_cistatic const char *const LOP[] = { PVR_PDS_LOP };
36bf215546Sopenharmony_ci#undef X
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_cistatic void pvr_pds_disassemble_operand(struct pvr_operand *op,
39bf215546Sopenharmony_ci                                        char *instr_str,
40bf215546Sopenharmony_ci                                        size_t instr_len)
41bf215546Sopenharmony_ci{
42bf215546Sopenharmony_ci#define X(enum, str, size) { #str, #size },
43bf215546Sopenharmony_ci   static const char *const regs[][2] = { PVR_PDS_OPERAND_TYPES };
44bf215546Sopenharmony_ci#undef X
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci   if (op->type == LITERAL_NUM) {
47bf215546Sopenharmony_ci      snprintf(instr_str,
48bf215546Sopenharmony_ci               instr_len,
49bf215546Sopenharmony_ci               "%s (%llu)",
50bf215546Sopenharmony_ci               regs[op->type][0],
51bf215546Sopenharmony_ci               (unsigned long long)op->literal);
52bf215546Sopenharmony_ci   } else if (op->type == UNRESOLVED) {
53bf215546Sopenharmony_ci      snprintf(instr_str, instr_len, "UNRESOLVED");
54bf215546Sopenharmony_ci   } else {
55bf215546Sopenharmony_ci      snprintf(instr_str,
56bf215546Sopenharmony_ci               instr_len,
57bf215546Sopenharmony_ci               "%s[%u].%s",
58bf215546Sopenharmony_ci               regs[op->type][0],
59bf215546Sopenharmony_ci               op->absolute_address,
60bf215546Sopenharmony_ci               regs[op->type][1]);
61bf215546Sopenharmony_ci   }
62bf215546Sopenharmony_ci}
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_add64(struct pvr_add *add,
65bf215546Sopenharmony_ci                                                  char *instr_str,
66bf215546Sopenharmony_ci                                                  size_t instr_len)
67bf215546Sopenharmony_ci{
68bf215546Sopenharmony_ci   char dst[32];
69bf215546Sopenharmony_ci   char src0[32];
70bf215546Sopenharmony_ci   char src1[32];
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(add->src0, src0, sizeof(src0));
73bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(add->src1, src1, sizeof(src1));
74bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(add->dst, dst, sizeof(dst));
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   snprintf(instr_str,
77bf215546Sopenharmony_ci            instr_len,
78bf215546Sopenharmony_ci            "%-16s%s%s = %s %s %s %s",
79bf215546Sopenharmony_ci            "ADD64",
80bf215546Sopenharmony_ci            add->cc ? "? " : "",
81bf215546Sopenharmony_ci            dst,
82bf215546Sopenharmony_ci            src0,
83bf215546Sopenharmony_ci            add->sna ? "-" : "+",
84bf215546Sopenharmony_ci            src1,
85bf215546Sopenharmony_ci            add->alum ? "[signed]" : "");
86bf215546Sopenharmony_ci}
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_add32(struct pvr_add *add,
89bf215546Sopenharmony_ci                                                  char *instr_str,
90bf215546Sopenharmony_ci                                                  size_t instr_len)
91bf215546Sopenharmony_ci{
92bf215546Sopenharmony_ci   char dst[32];
93bf215546Sopenharmony_ci   char src0[32];
94bf215546Sopenharmony_ci   char src1[32];
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(add->src0, src0, sizeof(src0));
97bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(add->src1, src1, sizeof(src1));
98bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(add->dst, dst, sizeof(dst));
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   snprintf(instr_str,
101bf215546Sopenharmony_ci            instr_len,
102bf215546Sopenharmony_ci            "%-16s%s%s = %s %s %s %s",
103bf215546Sopenharmony_ci            "ADD32",
104bf215546Sopenharmony_ci            add->cc ? "? " : "",
105bf215546Sopenharmony_ci            dst,
106bf215546Sopenharmony_ci            src0,
107bf215546Sopenharmony_ci            add->sna ? "-" : "+",
108bf215546Sopenharmony_ci            src1,
109bf215546Sopenharmony_ci            add->alum ? "[signed]" : "");
110bf215546Sopenharmony_ci}
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_cistatic void
113bf215546Sopenharmony_cipvr_pds_disassemble_instruction_sftlp32(struct pvr_sftlp *instruction,
114bf215546Sopenharmony_ci                                        char *instr_str,
115bf215546Sopenharmony_ci                                        size_t instr_len)
116bf215546Sopenharmony_ci{
117bf215546Sopenharmony_ci   char dst[32];
118bf215546Sopenharmony_ci   char src0[32];
119bf215546Sopenharmony_ci   char src1[32];
120bf215546Sopenharmony_ci   char src2[32];
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0));
123bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->src1, src1, sizeof(src1));
124bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->dst, dst, sizeof(dst));
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci   if (instruction->IM)
127bf215546Sopenharmony_ci      snprintf(src2, sizeof(src2), "%u", (uint32_t)instruction->src2->literal);
128bf215546Sopenharmony_ci   else
129bf215546Sopenharmony_ci      pvr_pds_disassemble_operand(instruction->src2, src2, sizeof(src2));
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   if (instruction->lop == LOP_NONE) {
132bf215546Sopenharmony_ci      snprintf(instr_str,
133bf215546Sopenharmony_ci               instr_len,
134bf215546Sopenharmony_ci               "%-16s%s%s = %s %s %s",
135bf215546Sopenharmony_ci               "SFTLP32",
136bf215546Sopenharmony_ci               instruction->cc ? "? " : "",
137bf215546Sopenharmony_ci               dst,
138bf215546Sopenharmony_ci               src0,
139bf215546Sopenharmony_ci               instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
140bf215546Sopenharmony_ci               src2);
141bf215546Sopenharmony_ci   } else if (instruction->lop == LOP_NOT) {
142bf215546Sopenharmony_ci      snprintf(instr_str,
143bf215546Sopenharmony_ci               instr_len,
144bf215546Sopenharmony_ci               "%-16s%s%s = (~%s) %s %s",
145bf215546Sopenharmony_ci               "SFTLP32",
146bf215546Sopenharmony_ci               instruction->cc ? "? " : "",
147bf215546Sopenharmony_ci               dst,
148bf215546Sopenharmony_ci               src0,
149bf215546Sopenharmony_ci               instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
150bf215546Sopenharmony_ci               src2);
151bf215546Sopenharmony_ci   } else {
152bf215546Sopenharmony_ci      snprintf(instr_str,
153bf215546Sopenharmony_ci               instr_len,
154bf215546Sopenharmony_ci               "%-16s%s%s = (%s %s %s) %s %s",
155bf215546Sopenharmony_ci               "SFTLP32",
156bf215546Sopenharmony_ci               instruction->cc ? "? " : "",
157bf215546Sopenharmony_ci               dst,
158bf215546Sopenharmony_ci               src0,
159bf215546Sopenharmony_ci               LOP[instruction->lop],
160bf215546Sopenharmony_ci               src1,
161bf215546Sopenharmony_ci               instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
162bf215546Sopenharmony_ci               src2);
163bf215546Sopenharmony_ci   }
164bf215546Sopenharmony_ci}
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_stm(struct pvr_stm *instruction,
167bf215546Sopenharmony_ci                                                char *instr_str,
168bf215546Sopenharmony_ci                                                size_t instr_len)
169bf215546Sopenharmony_ci{
170bf215546Sopenharmony_ci   char src0[32];
171bf215546Sopenharmony_ci   char src1[32];
172bf215546Sopenharmony_ci   char src2[32];
173bf215546Sopenharmony_ci   char src3[32];
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci   char stm_pred[64];
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0));
178bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->src1, src1, sizeof(src1));
179bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->src2, src2, sizeof(src2));
180bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->src3, src3, sizeof(src3));
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   if (instruction->ccs_global)
183bf215546Sopenharmony_ci      snprintf(stm_pred, sizeof(stm_pred), "overflow_any");
184bf215546Sopenharmony_ci   else if (instruction->ccs_so)
185bf215546Sopenharmony_ci      snprintf(stm_pred, sizeof(stm_pred), "overflow_current");
186bf215546Sopenharmony_ci   else
187bf215546Sopenharmony_ci      stm_pred[0] = 0;
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   snprintf(instr_str,
190bf215546Sopenharmony_ci            instr_len,
191bf215546Sopenharmony_ci            "%-16s%s%s%s stm%u = %s, %s, %s, %s",
192bf215546Sopenharmony_ci            "STM",
193bf215546Sopenharmony_ci            instruction->cc ? "? " : "",
194bf215546Sopenharmony_ci            stm_pred,
195bf215546Sopenharmony_ci            instruction->tst ? " (TST only)" : "",
196bf215546Sopenharmony_ci            instruction->stream_out,
197bf215546Sopenharmony_ci            src0,
198bf215546Sopenharmony_ci            src1,
199bf215546Sopenharmony_ci            src2,
200bf215546Sopenharmony_ci            src3);
201bf215546Sopenharmony_ci}
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_cistatic void pds_disassemble_instruction_stmc(struct pvr_stmc *instruction,
204bf215546Sopenharmony_ci                                             char *instr_str,
205bf215546Sopenharmony_ci                                             size_t instr_len)
206bf215546Sopenharmony_ci{
207bf215546Sopenharmony_ci   char src0[32];
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0));
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   snprintf(instr_str,
212bf215546Sopenharmony_ci            instr_len,
213bf215546Sopenharmony_ci            "%-16s%s %s",
214bf215546Sopenharmony_ci            "STMC",
215bf215546Sopenharmony_ci            instruction->cc ? "? " : "",
216bf215546Sopenharmony_ci            src0);
217bf215546Sopenharmony_ci}
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_cistatic void
220bf215546Sopenharmony_cipvr_pds_disassemble_instruction_sftlp64(struct pvr_sftlp *instruction,
221bf215546Sopenharmony_ci                                        char *instr_str,
222bf215546Sopenharmony_ci                                        size_t instr_len)
223bf215546Sopenharmony_ci{
224bf215546Sopenharmony_ci   char dst[32];
225bf215546Sopenharmony_ci   char src0[32];
226bf215546Sopenharmony_ci   char src1[32];
227bf215546Sopenharmony_ci   char src2[32];
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0));
230bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->src1, src1, sizeof(src1));
231bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(instruction->dst, dst, sizeof(dst));
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci   if (instruction->IM)
234bf215546Sopenharmony_ci      snprintf(src2, sizeof(src2), "%u", (uint32_t)instruction->src2->literal);
235bf215546Sopenharmony_ci   else
236bf215546Sopenharmony_ci      pvr_pds_disassemble_operand(instruction->src2, src2, sizeof(src2));
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci   if (instruction->lop == LOP_NONE) {
239bf215546Sopenharmony_ci      snprintf(instr_str,
240bf215546Sopenharmony_ci               instr_len,
241bf215546Sopenharmony_ci               "%-16s%s%s = %s %s %s",
242bf215546Sopenharmony_ci               "SFTLP64",
243bf215546Sopenharmony_ci               instruction->cc ? "? " : "",
244bf215546Sopenharmony_ci               dst,
245bf215546Sopenharmony_ci               src0,
246bf215546Sopenharmony_ci               instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
247bf215546Sopenharmony_ci               src2);
248bf215546Sopenharmony_ci   } else if (instruction->lop == LOP_NOT) {
249bf215546Sopenharmony_ci      snprintf(instr_str,
250bf215546Sopenharmony_ci               instr_len,
251bf215546Sopenharmony_ci               "%-16s%s%s = (~%s) %s %s",
252bf215546Sopenharmony_ci               "SFTLP64",
253bf215546Sopenharmony_ci               instruction->cc ? "? " : "",
254bf215546Sopenharmony_ci               dst,
255bf215546Sopenharmony_ci               src0,
256bf215546Sopenharmony_ci               instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
257bf215546Sopenharmony_ci               src2);
258bf215546Sopenharmony_ci   } else {
259bf215546Sopenharmony_ci      snprintf(instr_str,
260bf215546Sopenharmony_ci               instr_len,
261bf215546Sopenharmony_ci               "%-16s%s%s = (%s %s %s) %s %s",
262bf215546Sopenharmony_ci               "SFTLP64",
263bf215546Sopenharmony_ci               instruction->cc ? "? " : "",
264bf215546Sopenharmony_ci               dst,
265bf215546Sopenharmony_ci               src0,
266bf215546Sopenharmony_ci               LOP[instruction->lop],
267bf215546Sopenharmony_ci               src1,
268bf215546Sopenharmony_ci               instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
269bf215546Sopenharmony_ci               src2);
270bf215546Sopenharmony_ci   }
271bf215546Sopenharmony_ci}
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_cmp(struct pvr_cmp *cmp,
274bf215546Sopenharmony_ci                                                char *instr_str,
275bf215546Sopenharmony_ci                                                size_t instr_len)
276bf215546Sopenharmony_ci{
277bf215546Sopenharmony_ci   char src0[32];
278bf215546Sopenharmony_ci   char src1[32];
279bf215546Sopenharmony_ci   static const char *const COP[] = { "=", ">", "<", "!=" };
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(cmp->src0, src0, sizeof(src0));
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci   if (cmp->IM) {
284bf215546Sopenharmony_ci      snprintf(src1,
285bf215546Sopenharmony_ci               sizeof(src1),
286bf215546Sopenharmony_ci               "%#04llx",
287bf215546Sopenharmony_ci               (unsigned long long)cmp->src1->literal);
288bf215546Sopenharmony_ci   } else {
289bf215546Sopenharmony_ci      pvr_pds_disassemble_operand(cmp->src1, src1, sizeof(src1));
290bf215546Sopenharmony_ci   }
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   snprintf(instr_str,
293bf215546Sopenharmony_ci            instr_len,
294bf215546Sopenharmony_ci            "%-16s%sP0 = (%s %s %s)",
295bf215546Sopenharmony_ci            "CMP",
296bf215546Sopenharmony_ci            cmp->cc ? "? " : "",
297bf215546Sopenharmony_ci            src0,
298bf215546Sopenharmony_ci            COP[cmp->cop],
299bf215546Sopenharmony_ci            src1);
300bf215546Sopenharmony_ci}
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_ldst(struct pvr_ldst *ins,
303bf215546Sopenharmony_ci                                                 char *instr_str,
304bf215546Sopenharmony_ci                                                 size_t instr_len)
305bf215546Sopenharmony_ci{
306bf215546Sopenharmony_ci   char src0[PVR_PDS_MAX_INST_STR_LEN];
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(ins->src0, src0, sizeof(src0));
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci   if (ins->st) {
311bf215546Sopenharmony_ci      snprintf(instr_str,
312bf215546Sopenharmony_ci               instr_len,
313bf215546Sopenharmony_ci               "%-16s%s%s: mem(%s) <= src(%s)",
314bf215546Sopenharmony_ci               "ST",
315bf215546Sopenharmony_ci               ins->cc ? "? " : "",
316bf215546Sopenharmony_ci               src0,
317bf215546Sopenharmony_ci               "?",
318bf215546Sopenharmony_ci               "?");
319bf215546Sopenharmony_ci   } else {
320bf215546Sopenharmony_ci      snprintf(instr_str,
321bf215546Sopenharmony_ci               instr_len,
322bf215546Sopenharmony_ci               "%-16s%s%s: dst(%s) <= mem(%s)",
323bf215546Sopenharmony_ci               "ld",
324bf215546Sopenharmony_ci               ins->cc ? "? " : "",
325bf215546Sopenharmony_ci               src0,
326bf215546Sopenharmony_ci               "?",
327bf215546Sopenharmony_ci               "?");
328bf215546Sopenharmony_ci   }
329bf215546Sopenharmony_ci}
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_cistatic void pvr_pds_disassemble_simple(struct pvr_simple *simple,
332bf215546Sopenharmony_ci                                       const char *type,
333bf215546Sopenharmony_ci                                       char *instr_str,
334bf215546Sopenharmony_ci                                       size_t instr_len)
335bf215546Sopenharmony_ci{
336bf215546Sopenharmony_ci   snprintf(instr_str, instr_len, "%-16s%s", type, simple->cc ? "? " : "");
337bf215546Sopenharmony_ci}
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_limm(struct pvr_limm *limm,
340bf215546Sopenharmony_ci                                                 char *instr_str,
341bf215546Sopenharmony_ci                                                 size_t instr_len)
342bf215546Sopenharmony_ci{
343bf215546Sopenharmony_ci   int32_t imm = (uint32_t)limm->src0->literal;
344bf215546Sopenharmony_ci   char dst[PVR_PDS_MAX_INST_STR_LEN];
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(limm->dst, dst, sizeof(dst));
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci   if (limm->GR) {
349bf215546Sopenharmony_ci      char *pchGReg;
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci      switch (imm) {
352bf215546Sopenharmony_ci      case 0:
353bf215546Sopenharmony_ci         pchGReg = "cluster";
354bf215546Sopenharmony_ci         break;
355bf215546Sopenharmony_ci      case 1:
356bf215546Sopenharmony_ci         pchGReg = "instance";
357bf215546Sopenharmony_ci         break;
358bf215546Sopenharmony_ci      default:
359bf215546Sopenharmony_ci         pchGReg = "unknown";
360bf215546Sopenharmony_ci      }
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci      snprintf(instr_str,
363bf215546Sopenharmony_ci               instr_len,
364bf215546Sopenharmony_ci               "%-16s%s%s = G%d (%s)",
365bf215546Sopenharmony_ci               "LIMM",
366bf215546Sopenharmony_ci               limm->cc ? "? " : "",
367bf215546Sopenharmony_ci               dst,
368bf215546Sopenharmony_ci               imm,
369bf215546Sopenharmony_ci               pchGReg);
370bf215546Sopenharmony_ci   } else {
371bf215546Sopenharmony_ci      snprintf(instr_str,
372bf215546Sopenharmony_ci               instr_len,
373bf215546Sopenharmony_ci               "%-16s%s%s = %#04x",
374bf215546Sopenharmony_ci               "LIMM",
375bf215546Sopenharmony_ci               limm->cc ? "? " : "",
376bf215546Sopenharmony_ci               dst,
377bf215546Sopenharmony_ci               imm);
378bf215546Sopenharmony_ci   }
379bf215546Sopenharmony_ci}
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_ddmad(struct pvr_ddmad *ddmad,
382bf215546Sopenharmony_ci                                                  char *instr_str,
383bf215546Sopenharmony_ci                                                  size_t instr_len)
384bf215546Sopenharmony_ci{
385bf215546Sopenharmony_ci   char src0[PVR_PDS_MAX_INST_STR_LEN];
386bf215546Sopenharmony_ci   char src1[PVR_PDS_MAX_INST_STR_LEN];
387bf215546Sopenharmony_ci   char src2[PVR_PDS_MAX_INST_STR_LEN];
388bf215546Sopenharmony_ci   char src3[PVR_PDS_MAX_INST_STR_LEN];
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(ddmad->src0, src0, sizeof(src0));
391bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(ddmad->src1, src1, sizeof(src1));
392bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(ddmad->src2, src2, sizeof(src2));
393bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(ddmad->src3, src3, sizeof(src3));
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   snprintf(instr_str,
396bf215546Sopenharmony_ci            instr_len,
397bf215546Sopenharmony_ci            "%-16s%sdoutd = (%s * %s) + %s, %s%s",
398bf215546Sopenharmony_ci            "DDMAD",
399bf215546Sopenharmony_ci            ddmad->cc ? "? " : "",
400bf215546Sopenharmony_ci            src0,
401bf215546Sopenharmony_ci            src1,
402bf215546Sopenharmony_ci            src2,
403bf215546Sopenharmony_ci            src3,
404bf215546Sopenharmony_ci            ddmad->END ? "; HALT" : "");
405bf215546Sopenharmony_ci}
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_cistatic void pvr_pds_disassemble_predicate(uint32_t predicate,
408bf215546Sopenharmony_ci                                          char *buffer,
409bf215546Sopenharmony_ci                                          size_t buffer_length)
410bf215546Sopenharmony_ci{
411bf215546Sopenharmony_ci   switch (predicate) {
412bf215546Sopenharmony_ci   case PVR_ROGUE_PDSINST_PREDICATE_P0:
413bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "p0");
414bf215546Sopenharmony_ci      break;
415bf215546Sopenharmony_ci   case PVR_ROGUE_PDSINST_PREDICATE_IF0:
416bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "if0");
417bf215546Sopenharmony_ci      break;
418bf215546Sopenharmony_ci   case PVR_ROGUE_PDSINST_PREDICATE_IF1:
419bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "if1");
420bf215546Sopenharmony_ci      break;
421bf215546Sopenharmony_ci   case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_0:
422bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "so_overflow_0");
423bf215546Sopenharmony_ci      break;
424bf215546Sopenharmony_ci   case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_1:
425bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "so_overflow_1");
426bf215546Sopenharmony_ci      break;
427bf215546Sopenharmony_ci   case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_2:
428bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "so_overflow_2");
429bf215546Sopenharmony_ci      break;
430bf215546Sopenharmony_ci   case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_3:
431bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "so_overflow_3");
432bf215546Sopenharmony_ci      break;
433bf215546Sopenharmony_ci   case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_GLOBAL:
434bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "so_overflow_any");
435bf215546Sopenharmony_ci      break;
436bf215546Sopenharmony_ci   case PVR_ROGUE_PDSINST_PREDICATE_KEEP:
437bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "keep");
438bf215546Sopenharmony_ci      break;
439bf215546Sopenharmony_ci   case PVR_ROGUE_PDSINST_PREDICATE_OOB:
440bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "oob");
441bf215546Sopenharmony_ci      break;
442bf215546Sopenharmony_ci   default:
443bf215546Sopenharmony_ci      snprintf(buffer, buffer_length, "%s", "<ERROR>");
444bf215546Sopenharmony_ci      break;
445bf215546Sopenharmony_ci   }
446bf215546Sopenharmony_ci}
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_bra(struct pvr_bra *bra,
449bf215546Sopenharmony_ci                                                char *instr_str,
450bf215546Sopenharmony_ci                                                size_t instr_len)
451bf215546Sopenharmony_ci{
452bf215546Sopenharmony_ci   char setc_pred[32];
453bf215546Sopenharmony_ci   char srcc_pred[32];
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci   pvr_pds_disassemble_predicate(bra->srcc->predicate,
456bf215546Sopenharmony_ci                                 srcc_pred,
457bf215546Sopenharmony_ci                                 sizeof(srcc_pred));
458bf215546Sopenharmony_ci   pvr_pds_disassemble_predicate(bra->setc->predicate,
459bf215546Sopenharmony_ci                                 setc_pred,
460bf215546Sopenharmony_ci                                 sizeof(setc_pred));
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci   if (bra->setc->predicate != PVR_ROGUE_PDSINST_PREDICATE_KEEP) {
463bf215546Sopenharmony_ci      snprintf(instr_str,
464bf215546Sopenharmony_ci               instr_len,
465bf215546Sopenharmony_ci               "%-16sif %s%s %d ( setc = %s )",
466bf215546Sopenharmony_ci               "BRA",
467bf215546Sopenharmony_ci               bra->srcc->negate ? "! " : "",
468bf215546Sopenharmony_ci               srcc_pred,
469bf215546Sopenharmony_ci               bra->address,
470bf215546Sopenharmony_ci               setc_pred);
471bf215546Sopenharmony_ci   } else {
472bf215546Sopenharmony_ci      snprintf(instr_str,
473bf215546Sopenharmony_ci               instr_len,
474bf215546Sopenharmony_ci               "%-16sif %s%s %d",
475bf215546Sopenharmony_ci               "BRA",
476bf215546Sopenharmony_ci               bra->srcc->negate ? "! " : "",
477bf215546Sopenharmony_ci               srcc_pred,
478bf215546Sopenharmony_ci               bra->address);
479bf215546Sopenharmony_ci   }
480bf215546Sopenharmony_ci}
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_mad(struct pvr_mad *mad,
483bf215546Sopenharmony_ci                                                char *instr_str,
484bf215546Sopenharmony_ci                                                size_t instr_len)
485bf215546Sopenharmony_ci{
486bf215546Sopenharmony_ci   char src0[PVR_PDS_MAX_INST_STR_LEN];
487bf215546Sopenharmony_ci   char src1[PVR_PDS_MAX_INST_STR_LEN];
488bf215546Sopenharmony_ci   char src2[PVR_PDS_MAX_INST_STR_LEN];
489bf215546Sopenharmony_ci   char dst[PVR_PDS_MAX_INST_STR_LEN];
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(mad->src0, src0, sizeof(src0));
492bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(mad->src1, src1, sizeof(src1));
493bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(mad->src2, src2, sizeof(src2));
494bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(mad->dst, dst, sizeof(dst));
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci   snprintf(instr_str,
497bf215546Sopenharmony_ci            instr_len,
498bf215546Sopenharmony_ci            "%-16s%s%s = (%s * %s) %s %s%s",
499bf215546Sopenharmony_ci            "MAD",
500bf215546Sopenharmony_ci            mad->cc ? "? " : "",
501bf215546Sopenharmony_ci            dst,
502bf215546Sopenharmony_ci            src0,
503bf215546Sopenharmony_ci            src1,
504bf215546Sopenharmony_ci            mad->sna ? "-" : "+",
505bf215546Sopenharmony_ci            src2,
506bf215546Sopenharmony_ci            mad->alum ? " [signed]" : "");
507bf215546Sopenharmony_ci}
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_dout(struct pvr_dout *dout,
510bf215546Sopenharmony_ci                                                 char *instr_str,
511bf215546Sopenharmony_ci                                                 size_t instr_len)
512bf215546Sopenharmony_ci{
513bf215546Sopenharmony_ci   char src0[PVR_PDS_MAX_INST_STR_LEN];
514bf215546Sopenharmony_ci   char src1[PVR_PDS_MAX_INST_STR_LEN];
515bf215546Sopenharmony_ci
516bf215546Sopenharmony_ci#define X(dout_dst, str) #str,
517bf215546Sopenharmony_ci   static const char *const dst[] = { PVR_PDS_DOUT_DSTS };
518bf215546Sopenharmony_ci#undef X
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(dout->src0, src0, sizeof(src0));
521bf215546Sopenharmony_ci   pvr_pds_disassemble_operand(dout->src1, src1, sizeof(src1));
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci   {
524bf215546Sopenharmony_ci      snprintf(instr_str,
525bf215546Sopenharmony_ci               instr_len,
526bf215546Sopenharmony_ci               "%-16s%s%s = %s, %s%s",
527bf215546Sopenharmony_ci               "DOUT",
528bf215546Sopenharmony_ci               dout->cc ? "? " : "",
529bf215546Sopenharmony_ci               dst[dout->dst],
530bf215546Sopenharmony_ci               src0,
531bf215546Sopenharmony_ci               src1,
532bf215546Sopenharmony_ci               dout->END ? "; HALT" : "");
533bf215546Sopenharmony_ci   }
534bf215546Sopenharmony_ci}
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_civoid pvr_pds_disassemble_instruction(char *instr_str,
537bf215546Sopenharmony_ci                                     size_t instr_len,
538bf215546Sopenharmony_ci                                     struct pvr_instruction *instruction)
539bf215546Sopenharmony_ci{
540bf215546Sopenharmony_ci   if (!instruction) {
541bf215546Sopenharmony_ci      snprintf(instr_str,
542bf215546Sopenharmony_ci               instr_len,
543bf215546Sopenharmony_ci               "Instruction was not disassembled properly\n");
544bf215546Sopenharmony_ci      return;
545bf215546Sopenharmony_ci   }
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_ci   switch (instruction->type) {
548bf215546Sopenharmony_ci   case INS_LIMM:
549bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_limm((struct pvr_limm *)instruction,
550bf215546Sopenharmony_ci                                           instr_str,
551bf215546Sopenharmony_ci                                           instr_len);
552bf215546Sopenharmony_ci      break;
553bf215546Sopenharmony_ci   case INS_ADD64:
554bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_add64((struct pvr_add *)instruction,
555bf215546Sopenharmony_ci                                            instr_str,
556bf215546Sopenharmony_ci                                            instr_len);
557bf215546Sopenharmony_ci      break;
558bf215546Sopenharmony_ci   case INS_ADD32:
559bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_add32((struct pvr_add *)instruction,
560bf215546Sopenharmony_ci                                            instr_str,
561bf215546Sopenharmony_ci                                            instr_len);
562bf215546Sopenharmony_ci      break;
563bf215546Sopenharmony_ci   case INS_CMP:
564bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_cmp((struct pvr_cmp *)instruction,
565bf215546Sopenharmony_ci                                          instr_str,
566bf215546Sopenharmony_ci                                          instr_len);
567bf215546Sopenharmony_ci      break;
568bf215546Sopenharmony_ci   case INS_MAD:
569bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_mad((struct pvr_mad *)instruction,
570bf215546Sopenharmony_ci                                          instr_str,
571bf215546Sopenharmony_ci                                          instr_len);
572bf215546Sopenharmony_ci      break;
573bf215546Sopenharmony_ci   case INS_BRA:
574bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_bra((struct pvr_bra *)instruction,
575bf215546Sopenharmony_ci                                          instr_str,
576bf215546Sopenharmony_ci                                          instr_len);
577bf215546Sopenharmony_ci      break;
578bf215546Sopenharmony_ci   case INS_DDMAD:
579bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_ddmad((struct pvr_ddmad *)instruction,
580bf215546Sopenharmony_ci                                            instr_str,
581bf215546Sopenharmony_ci                                            instr_len);
582bf215546Sopenharmony_ci      break;
583bf215546Sopenharmony_ci   case INS_DOUT:
584bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_dout((struct pvr_dout *)instruction,
585bf215546Sopenharmony_ci                                           instr_str,
586bf215546Sopenharmony_ci                                           instr_len);
587bf215546Sopenharmony_ci      break;
588bf215546Sopenharmony_ci   case INS_LD:
589bf215546Sopenharmony_ci   case INS_ST:
590bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_ldst((struct pvr_ldst *)instruction,
591bf215546Sopenharmony_ci                                           instr_str,
592bf215546Sopenharmony_ci                                           instr_len);
593bf215546Sopenharmony_ci      break;
594bf215546Sopenharmony_ci   case INS_WDF:
595bf215546Sopenharmony_ci      pvr_pds_disassemble_simple((struct pvr_simple *)instruction,
596bf215546Sopenharmony_ci                                 "WDF",
597bf215546Sopenharmony_ci                                 instr_str,
598bf215546Sopenharmony_ci                                 instr_len);
599bf215546Sopenharmony_ci      break;
600bf215546Sopenharmony_ci   case INS_LOCK:
601bf215546Sopenharmony_ci      pvr_pds_disassemble_simple((struct pvr_simple *)instruction,
602bf215546Sopenharmony_ci                                 "LOCK",
603bf215546Sopenharmony_ci                                 instr_str,
604bf215546Sopenharmony_ci                                 instr_len);
605bf215546Sopenharmony_ci      break;
606bf215546Sopenharmony_ci   case INS_RELEASE:
607bf215546Sopenharmony_ci      pvr_pds_disassemble_simple((struct pvr_simple *)instruction,
608bf215546Sopenharmony_ci                                 "RELEASE",
609bf215546Sopenharmony_ci                                 instr_str,
610bf215546Sopenharmony_ci                                 instr_len);
611bf215546Sopenharmony_ci      break;
612bf215546Sopenharmony_ci   case INS_HALT:
613bf215546Sopenharmony_ci      pvr_pds_disassemble_simple((struct pvr_simple *)instruction,
614bf215546Sopenharmony_ci                                 "HALT",
615bf215546Sopenharmony_ci                                 instr_str,
616bf215546Sopenharmony_ci                                 instr_len);
617bf215546Sopenharmony_ci      break;
618bf215546Sopenharmony_ci   case INS_NOP:
619bf215546Sopenharmony_ci      pvr_pds_disassemble_simple((struct pvr_simple *)instruction,
620bf215546Sopenharmony_ci                                 "NOP",
621bf215546Sopenharmony_ci                                 instr_str,
622bf215546Sopenharmony_ci                                 instr_len);
623bf215546Sopenharmony_ci      break;
624bf215546Sopenharmony_ci   case INS_SFTLP32:
625bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_sftlp32((struct pvr_sftlp *)instruction,
626bf215546Sopenharmony_ci                                              instr_str,
627bf215546Sopenharmony_ci                                              instr_len);
628bf215546Sopenharmony_ci      break;
629bf215546Sopenharmony_ci   case INS_SFTLP64:
630bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_sftlp64((struct pvr_sftlp *)instruction,
631bf215546Sopenharmony_ci                                              instr_str,
632bf215546Sopenharmony_ci                                              instr_len);
633bf215546Sopenharmony_ci      break;
634bf215546Sopenharmony_ci   case INS_STM:
635bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction_stm((struct pvr_stm *)instruction,
636bf215546Sopenharmony_ci                                          instr_str,
637bf215546Sopenharmony_ci                                          instr_len);
638bf215546Sopenharmony_ci      break;
639bf215546Sopenharmony_ci   case INS_STMC:
640bf215546Sopenharmony_ci      pds_disassemble_instruction_stmc((struct pvr_stmc *)instruction,
641bf215546Sopenharmony_ci                                       instr_str,
642bf215546Sopenharmony_ci                                       instr_len);
643bf215546Sopenharmony_ci      break;
644bf215546Sopenharmony_ci   default:
645bf215546Sopenharmony_ci      snprintf(instr_str, instr_len, "Printing not implemented\n");
646bf215546Sopenharmony_ci      break;
647bf215546Sopenharmony_ci   }
648bf215546Sopenharmony_ci}
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_ci#if defined(DUMP_PDS)
651bf215546Sopenharmony_civoid pvr_pds_print_instruction(uint32_t instr)
652bf215546Sopenharmony_ci{
653bf215546Sopenharmony_ci   char instruction_str[1024];
654bf215546Sopenharmony_ci   struct pvr_instruction *decoded =
655bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction2(0, 0, instr);
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_ci   if (!decoded) {
658bf215546Sopenharmony_ci      mesa_logd("%X\n", instr);
659bf215546Sopenharmony_ci   } else {
660bf215546Sopenharmony_ci      pvr_pds_disassemble_instruction(instruction_str,
661bf215546Sopenharmony_ci                                      sizeof(instruction_str),
662bf215546Sopenharmony_ci                                      decoded);
663bf215546Sopenharmony_ci      mesa_logd("\t0x%08x, /* %s */\n", instr, instruction_str);
664bf215546Sopenharmony_ci   }
665bf215546Sopenharmony_ci}
666bf215546Sopenharmony_ci#endif
667