1/*
2 * Copyright © 2022 Imagination Technologies Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
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
13 * Software.
14 *
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 THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#include <assert.h>
25#include <stdint.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <stdbool.h>
29
30#include "pvr_rogue_pds_defs.h"
31#include "pvr_rogue_pds_encode.h"
32#include "pvr_rogue_pds_disasm.h"
33#include "util/macros.h"
34
35static void pvr_error_check(PVR_ERR_CALLBACK err_callback,
36                            struct pvr_dissassembler_error error)
37{
38   if (err_callback)
39      err_callback(error);
40   else
41      fprintf(stderr, "ERROR: %s\n", error.text);
42}
43
44#define X(a) #a,
45static const char *const instructions[] = { PVR_INSTRUCTIONS };
46#undef X
47
48static void error_reg_range(uint32_t raw,
49                            void *context,
50                            PVR_ERR_CALLBACK err_callback,
51                            uint32_t parameter,
52                            struct pvr_dissassembler_error error)
53{
54   char param[32];
55
56   error.type = PVR_PDS_ERR_PARAM_RANGE;
57   error.instruction = error.instruction;
58   error.parameter = parameter;
59   error.raw = raw;
60
61   if (parameter == 0)
62      snprintf(param, sizeof(param), "dst");
63   else
64      snprintf(param, sizeof(param), "src%u", parameter - 1);
65
66   error.text = malloc(PVR_PDS_MAX_INST_STR_LEN);
67   assert(error.text);
68
69   snprintf(error.text,
70            PVR_PDS_MAX_INST_STR_LEN,
71            "Register out of range, instruction: %s, operand: %s, value: %u",
72            instructions[error.instruction],
73            param,
74            raw);
75   pvr_error_check(err_callback, error);
76}
77
78static struct pvr_operand *
79pvr_pds_disassemble_regs32(void *context,
80                           PVR_ERR_CALLBACK err_callback,
81                           struct pvr_dissassembler_error error,
82                           uint32_t instruction,
83                           uint32_t parameter)
84{
85   struct pvr_operand *op = calloc(1, sizeof(*op));
86   assert(op);
87
88   op->type = UNRESOLVED;
89   instruction &= PVR_ROGUE_PDSINST_REGS32_MASK;
90   switch (pvr_pds_inst_decode_field_range_regs32(instruction)) {
91   case PVR_ROGUE_PDSINST_REGS32_CONST32:
92      op->type = CONST32;
93      op->address = instruction - PVR_ROGUE_PDSINST_REGS32_CONST32_LOWER;
94      op->absolute_address = op->address;
95      break;
96   case PVR_ROGUE_PDSINST_REGS32_TEMP32:
97      op->type = TEMP32;
98      op->address = instruction - PVR_ROGUE_PDSINST_REGS32_TEMP32_LOWER;
99      op->absolute_address = op->address;
100      break;
101   case PVR_ROGUE_PDSINST_REGS32_PTEMP32:
102      op->type = PTEMP32;
103      op->address = instruction - PVR_ROGUE_PDSINST_REGS32_PTEMP32_LOWER;
104      op->absolute_address = op->address;
105      break;
106   default:
107      error_reg_range(instruction, context, err_callback, parameter, error);
108   }
109   return op;
110}
111static struct pvr_operand *
112pvr_pds_disassemble_regs32tp(void *context,
113                             PVR_ERR_CALLBACK err_callback,
114                             struct pvr_dissassembler_error error,
115                             uint32_t instruction,
116                             uint32_t parameter)
117{
118   struct pvr_operand *op = calloc(1, sizeof(*op));
119   assert(op);
120
121   op->type = UNRESOLVED;
122   instruction &= PVR_ROGUE_PDSINST_REGS32TP_MASK;
123   switch (pvr_pds_inst_decode_field_range_regs32tp(instruction)) {
124   case PVR_ROGUE_PDSINST_REGS32TP_TEMP32:
125      op->type = TEMP32;
126      op->address = instruction - PVR_ROGUE_PDSINST_REGS32TP_TEMP32_LOWER;
127      op->absolute_address = op->address;
128      break;
129   case PVR_ROGUE_PDSINST_REGS32TP_PTEMP32:
130      op->type = PTEMP32;
131      op->address = instruction - PVR_ROGUE_PDSINST_REGS32TP_PTEMP32_LOWER;
132      op->absolute_address = op->address;
133      break;
134   default:
135      error_reg_range(instruction, context, err_callback, parameter, error);
136   }
137   return op;
138}
139static struct pvr_operand *
140pvr_pds_disassemble_regs32t(void *context,
141                            PVR_ERR_CALLBACK err_callback,
142                            struct pvr_dissassembler_error error,
143                            uint32_t instruction,
144                            uint32_t parameter)
145{
146   struct pvr_operand *op = calloc(1, sizeof(*op));
147   assert(op);
148
149   op->type = UNRESOLVED;
150   instruction &= PVR_ROGUE_PDSINST_REGS32T_MASK;
151   switch (pvr_pds_inst_decode_field_range_regs32t(instruction)) {
152   case PVR_ROGUE_PDSINST_REGS32T_TEMP32:
153      op->type = TEMP32;
154      op->address = instruction - PVR_ROGUE_PDSINST_REGS32T_TEMP32_LOWER;
155      op->absolute_address = op->address;
156      break;
157   default:
158      error_reg_range(instruction, context, err_callback, parameter, error);
159   }
160   return op;
161}
162
163static struct pvr_operand *
164pvr_pds_disassemble_regs64(void *context,
165                           PVR_ERR_CALLBACK err_callback,
166                           struct pvr_dissassembler_error error,
167                           uint32_t instruction,
168                           uint32_t parameter)
169{
170   struct pvr_operand *op = calloc(1, sizeof(*op));
171   assert(op);
172
173   op->type = UNRESOLVED;
174   instruction &= PVR_ROGUE_PDSINST_REGS64_MASK;
175   switch (pvr_pds_inst_decode_field_range_regs64(instruction)) {
176   case PVR_ROGUE_PDSINST_REGS64_CONST64:
177      op->type = CONST64;
178      op->address = instruction - PVR_ROGUE_PDSINST_REGS64_CONST64_LOWER;
179      op->absolute_address = op->address * 2;
180      break;
181   case PVR_ROGUE_PDSINST_REGS64_TEMP64:
182      op->type = TEMP64;
183      op->address = instruction - PVR_ROGUE_PDSINST_REGS64_TEMP64_LOWER;
184      op->absolute_address = op->address * 2;
185      break;
186   case PVR_ROGUE_PDSINST_REGS64_PTEMP64:
187      op->type = PTEMP64;
188      op->address = instruction - PVR_ROGUE_PDSINST_REGS64_PTEMP64_LOWER;
189      op->absolute_address = op->address * 2;
190      break;
191   default:
192      error_reg_range(instruction, context, err_callback, parameter, error);
193   }
194
195   return op;
196}
197static struct pvr_operand *
198pvr_pds_disassemble_regs64t(void *context,
199                            PVR_ERR_CALLBACK err_callback,
200                            struct pvr_dissassembler_error error,
201                            uint32_t instruction,
202                            uint32_t parameter)
203{
204   struct pvr_operand *op = calloc(1, sizeof(*op));
205   assert(op);
206
207   op->type = UNRESOLVED;
208   instruction &= PVR_ROGUE_PDSINST_REGS64T_MASK;
209   switch (pvr_pds_inst_decode_field_range_regs64tp(instruction)) {
210   case PVR_ROGUE_PDSINST_REGS64T_TEMP64:
211      op->type = TEMP64;
212      op->address = instruction - PVR_ROGUE_PDSINST_REGS64T_TEMP64_LOWER;
213      op->absolute_address = op->address * 2;
214      break;
215   default:
216      error_reg_range(instruction, context, err_callback, parameter, error);
217   }
218   return op;
219}
220
221static struct pvr_operand *
222pvr_pds_disassemble_regs64C(void *context,
223                            PVR_ERR_CALLBACK err_callback,
224                            struct pvr_dissassembler_error error,
225                            uint32_t instruction,
226                            uint32_t parameter)
227{
228   struct pvr_operand *op = calloc(1, sizeof(*op));
229   assert(op);
230
231   op->type = UNRESOLVED;
232   instruction &= PVR_ROGUE_PDSINST_REGS64C_MASK;
233   switch (pvr_rogue_pds_inst_decode_field_range_regs64c(instruction)) {
234   case PVR_ROGUE_PDSINST_REGS64C_CONST64:
235      op->type = CONST64;
236      op->address = instruction - PVR_ROGUE_PDSINST_REGS64C_CONST64_LOWER;
237      op->absolute_address = op->address * 2;
238      break;
239   default:
240      error_reg_range(instruction, context, err_callback, parameter, error);
241   }
242   return op;
243}
244
245static struct pvr_operand *
246pvr_pds_disassemble_regs64tp(void *context,
247                             PVR_ERR_CALLBACK err_callback,
248                             struct pvr_dissassembler_error error,
249                             uint32_t instruction,
250                             uint32_t parameter)
251{
252   struct pvr_operand *op = calloc(1, sizeof(*op));
253   assert(op);
254
255   op->type = UNRESOLVED;
256   instruction &= PVR_ROGUE_PDSINST_REGS64TP_MASK;
257   switch (pvr_pds_inst_decode_field_range_regs64tp(instruction)) {
258   case PVR_ROGUE_PDSINST_REGS64TP_TEMP64:
259      op->type = TEMP64;
260      op->address = instruction - PVR_ROGUE_PDSINST_REGS64TP_TEMP64_LOWER;
261      op->absolute_address = op->address * 2;
262      break;
263   case PVR_ROGUE_PDSINST_REGS64TP_PTEMP64:
264      op->type = PTEMP64;
265      op->address = instruction - PVR_ROGUE_PDSINST_REGS64TP_PTEMP64_LOWER;
266      op->absolute_address = op->address * 2;
267      break;
268   default:
269      error_reg_range(instruction, context, err_callback, parameter, error);
270   }
271   return op;
272}
273
274#define PVR_TYPE_OPCODE BITFIELD_BIT(31U)
275#define PVR_TYPE_OPCODE_SP BITFIELD_BIT(27U)
276#define PVR_TYPE_OPCODEB BITFIELD_BIT(30U)
277
278#define PVR_TYPE_OPCODE_SHIFT 28U
279#define PVR_TYPE_OPCODE_SP_SHIFT 23U
280#define PVR_TYPE_OPCODEB_SHIFT 29U
281
282static struct pvr_instruction *
283pvr_pds_disassemble_instruction_add64(void *context,
284                                      PVR_ERR_CALLBACK err_callback,
285                                      struct pvr_dissassembler_error error,
286                                      uint32_t instruction)
287{
288   struct pvr_add *add = malloc(sizeof(*add));
289   assert(add);
290
291   add->instruction.type = INS_ADD64;
292   add->instruction.next = NULL;
293
294   add->cc = instruction & PVR_ROGUE_PDSINST_ADD64_CC_ENABLE;
295   add->alum = instruction & PVR_ROGUE_PDSINST_ADD64_ALUM_SIGNED;
296   add->sna = instruction & PVR_ROGUE_PDSINST_ADD64_SNA_SUB;
297
298   add->src0 = pvr_pds_disassemble_regs64(context,
299                                          err_callback,
300                                          error,
301                                          instruction >>
302                                             PVR_ROGUE_PDSINST_ADD64_SRC0_SHIFT,
303                                          1);
304   add->src0->instruction = &add->instruction;
305   add->src1 = pvr_pds_disassemble_regs64(context,
306                                          err_callback,
307                                          error,
308                                          instruction >>
309                                             PVR_ROGUE_PDSINST_ADD64_SRC1_SHIFT,
310                                          2);
311   add->src1->instruction = &add->instruction;
312   add->dst = pvr_pds_disassemble_regs64tp(context,
313                                           err_callback,
314                                           error,
315                                           instruction >>
316                                              PVR_ROGUE_PDSINST_ADD64_DST_SHIFT,
317                                           0);
318   add->dst->instruction = &add->instruction;
319
320   return &add->instruction;
321}
322
323static struct pvr_instruction *
324pvr_pds_disassemble_instruction_add32(void *context,
325                                      PVR_ERR_CALLBACK err_callback,
326                                      struct pvr_dissassembler_error error,
327                                      uint32_t instruction)
328{
329   struct pvr_add *add = malloc(sizeof(*add));
330   assert(add);
331
332   add->instruction.type = INS_ADD32;
333   add->instruction.next = NULL;
334
335   add->cc = instruction & PVR_ROGUE_PDSINST_ADD32_CC_ENABLE;
336   add->alum = instruction & PVR_ROGUE_PDSINST_ADD32_ALUM_SIGNED;
337   add->sna = instruction & PVR_ROGUE_PDSINST_ADD32_SNA_SUB;
338
339   add->src0 = pvr_pds_disassemble_regs32(context,
340                                          err_callback,
341                                          error,
342                                          instruction >>
343                                             PVR_ROGUE_PDSINST_ADD32_SRC0_SHIFT,
344                                          1);
345   add->src0->instruction = &add->instruction;
346   add->src1 = pvr_pds_disassemble_regs32(context,
347                                          err_callback,
348                                          error,
349                                          instruction >>
350                                             PVR_ROGUE_PDSINST_ADD32_SRC1_SHIFT,
351                                          2);
352   add->src1->instruction = &add->instruction;
353   add->dst = pvr_pds_disassemble_regs32tp(context,
354                                           err_callback,
355                                           error,
356                                           instruction >>
357                                              PVR_ROGUE_PDSINST_ADD32_DST_SHIFT,
358                                           0);
359   add->dst->instruction = &add->instruction;
360
361   return &add->instruction;
362}
363
364static struct pvr_instruction *
365pvr_pds_disassemble_instruction_stm(void *context,
366                                    PVR_ERR_CALLBACK err_callback,
367                                    struct pvr_dissassembler_error error,
368                                    uint32_t instruction)
369{
370   struct pvr_stm *stm = malloc(sizeof(*stm));
371   assert(stm);
372
373   stm->instruction.next = NULL;
374   stm->instruction.type = INS_STM;
375
376   stm->cc = instruction & (1 << PVR_ROGUE_PDSINST_STM_CCS_CCS_CC_SHIFT);
377   stm->ccs_global = instruction &
378                     (1 << PVR_ROGUE_PDSINST_STM_CCS_CCS_GLOBAL_SHIFT);
379   stm->ccs_so = instruction & (1 << PVR_ROGUE_PDSINST_STM_CCS_CCS_SO_SHIFT);
380   stm->tst = instruction & (1 << PVR_ROGUE_PDSINST_STM_SO_TST_SHIFT);
381
382   stm->stream_out = (instruction >> PVR_ROGUE_PDSINST_STM_SO_SHIFT) &
383                     PVR_ROGUE_PDSINST_SO_MASK;
384
385   stm->src0 = pvr_pds_disassemble_regs64tp(
386      context,
387      err_callback,
388      error,
389      instruction >> PVR_ROGUE_PDSINST_STM_SO_SRC0_SHIFT,
390      1);
391   stm->src0->instruction = &stm->instruction;
392
393   stm->src1 = pvr_pds_disassemble_regs64tp(
394      context,
395      err_callback,
396      error,
397      instruction >> PVR_ROGUE_PDSINST_STM_SO_SRC1_SHIFT,
398      2);
399   stm->src1->instruction = &stm->instruction;
400
401   stm->src2 = pvr_pds_disassemble_regs32(
402      context,
403      err_callback,
404      error,
405      instruction >> PVR_ROGUE_PDSINST_STM_SO_SRC2_SHIFT,
406      3);
407   stm->src2->instruction = &stm->instruction;
408
409   stm->src3 = pvr_pds_disassemble_regs64tp(
410      context,
411      err_callback,
412      error,
413      instruction >> PVR_ROGUE_PDSINST_STM_SO_SRC3_SHIFT,
414      4);
415   stm->src3->instruction = &stm->instruction;
416
417   return &stm->instruction;
418}
419
420static struct pvr_instruction *
421pvr_pds_disassemble_instruction_sftlp32(void *context,
422                                        PVR_ERR_CALLBACK err_callback,
423                                        struct pvr_dissassembler_error error,
424                                        uint32_t instruction)
425{
426   struct pvr_sftlp *ins = malloc(sizeof(*ins));
427   assert(ins);
428
429   ins->instruction.next = NULL;
430   ins->instruction.type = INS_SFTLP32;
431
432   ins->cc = instruction & PVR_ROGUE_PDSINST_SFTLP32_CC_ENABLE;
433   ins->IM = instruction & PVR_ROGUE_PDSINST_SFTLP32_IM_ENABLE;
434   ins->lop = (instruction >> PVR_ROGUE_PDSINST_SFTLP32_LOP_SHIFT) &
435              PVR_ROGUE_PDSINST_LOP_MASK;
436   ins->src0 = pvr_pds_disassemble_regs32t(
437      context,
438      err_callback,
439      error,
440      instruction >> PVR_ROGUE_PDSINST_SFTLP32_SRC0_SHIFT,
441      1);
442   ins->src0->instruction = &ins->instruction;
443   ins->src1 = pvr_pds_disassemble_regs32(
444      context,
445      err_callback,
446      error,
447      instruction >> PVR_ROGUE_PDSINST_SFTLP32_SRC1_SHIFT,
448      2);
449   ins->src1->instruction = &ins->instruction;
450   ins->dst = pvr_pds_disassemble_regs32t(
451      context,
452      err_callback,
453      error,
454      instruction >> PVR_ROGUE_PDSINST_SFTLP32_DST_SHIFT,
455      0);
456   ins->dst->instruction = &ins->instruction;
457
458   if (ins->IM) {
459      signed char cImmediate =
460         ((instruction >> PVR_ROGUE_PDSINST_SFTLP32_SRC2_SHIFT) &
461          PVR_ROGUE_PDSINST_REGS32_MASK)
462         << 2;
463      ins->src2 = calloc(1, sizeof(*ins->src2));
464      assert(ins->src2);
465
466      ins->src2->literal = abs((cImmediate / 4));
467      ins->src2->negate = cImmediate < 0;
468      ins->src2->instruction = &ins->instruction;
469   } else {
470      ins->src2 = pvr_pds_disassemble_regs32tp(
471         context,
472         err_callback,
473         error,
474         (instruction >> PVR_ROGUE_PDSINST_SFTLP32_SRC2_SHIFT),
475         3);
476      ins->src2->instruction = &ins->instruction;
477   }
478
479   return &ins->instruction;
480}
481
482static struct pvr_instruction *
483pvr_pds_disassemble_instruction_sftlp64(void *context,
484                                        PVR_ERR_CALLBACK err_callback,
485                                        struct pvr_dissassembler_error error,
486                                        uint32_t instruction)
487{
488   struct pvr_sftlp *ins = malloc(sizeof(*ins));
489   assert(ins);
490
491   ins->instruction.next = NULL;
492   ins->instruction.type = INS_SFTLP64;
493
494   ins->cc = instruction & PVR_ROGUE_PDSINST_SFTLP64_CC_ENABLE;
495   ins->IM = instruction & PVR_ROGUE_PDSINST_SFTLP64_IM_ENABLE;
496   ins->lop = (instruction >> PVR_ROGUE_PDSINST_SFTLP64_LOP_SHIFT) &
497              PVR_ROGUE_PDSINST_LOP_MASK;
498   ins->src0 = pvr_pds_disassemble_regs64tp(
499      context,
500      err_callback,
501      error,
502      instruction >> PVR_ROGUE_PDSINST_SFTLP64_SRC0_SHIFT,
503      1);
504   ins->src0->instruction = &ins->instruction;
505   ins->src1 = pvr_pds_disassemble_regs64tp(
506      context,
507      err_callback,
508      error,
509      instruction >> PVR_ROGUE_PDSINST_SFTLP64_SRC1_SHIFT,
510      2);
511   ins->src1->instruction = &ins->instruction;
512   ins->dst = pvr_pds_disassemble_regs64tp(
513      context,
514      err_callback,
515      error,
516      instruction >> PVR_ROGUE_PDSINST_SFTLP64_DST_SHIFT,
517      0);
518   ins->dst->instruction = &ins->instruction;
519
520   if (ins->IM) {
521      signed char cImmediate =
522         (instruction >> PVR_ROGUE_PDSINST_SFTLP64_SRC2_SHIFT) &
523         PVR_ROGUE_PDSINST_REGS32_MASK;
524      ins->src2 = calloc(1, sizeof(*ins->src2));
525      assert(ins->src2);
526
527      ins->src2->literal = (abs(cImmediate) > 63) ? 63 : abs(cImmediate);
528      ins->src2->negate = (cImmediate < 0);
529      ins->src2->instruction = &ins->instruction;
530   } else {
531      ins->src2 = pvr_pds_disassemble_regs32(
532         context,
533         err_callback,
534         error,
535         (instruction >> PVR_ROGUE_PDSINST_SFTLP64_SRC2_SHIFT),
536         3);
537      ins->src2->instruction = &ins->instruction;
538   }
539
540   return &ins->instruction;
541}
542static struct pvr_instruction *
543pvr_pds_disassemble_instruction_cmp(void *context,
544                                    PVR_ERR_CALLBACK err_callback,
545                                    struct pvr_dissassembler_error error,
546                                    uint32_t instruction)
547{
548   struct pvr_cmp *cmp = malloc(sizeof(*cmp));
549   assert(cmp);
550
551   cmp->instruction.next = NULL;
552   cmp->instruction.type = INS_CMP;
553   cmp->cc = instruction & PVR_ROGUE_PDSINST_CMP_CC_ENABLE;
554   cmp->IM = instruction & PVR_ROGUE_PDSINST_CMP_IM_ENABLE;
555   cmp->cop = instruction >> PVR_ROGUE_PDSINST_CMP_COP_SHIFT &
556              PVR_ROGUE_PDSINST_COP_MASK;
557   cmp->src0 = pvr_pds_disassemble_regs64tp(context,
558                                            err_callback,
559                                            error,
560                                            instruction >>
561                                               PVR_ROGUE_PDSINST_CMP_SRC0_SHIFT,
562                                            1);
563   cmp->src0->instruction = &cmp->instruction;
564
565   if (cmp->IM) {
566      uint32_t immediate = (instruction >> PVR_ROGUE_PDSINST_CMP_SRC1_SHIFT) &
567                           PVR_ROGUE_PDSINST_IMM16_MASK;
568      cmp->src1 = calloc(1, sizeof(*cmp->src1));
569      assert(cmp->src1);
570
571      cmp->src1->type = LITERAL_NUM;
572      cmp->src1->literal = immediate;
573   } else {
574      cmp->src1 = pvr_pds_disassemble_regs64(
575         context,
576         err_callback,
577         error,
578         instruction >> PVR_ROGUE_PDSINST_CMP_SRC1_SHIFT,
579         2);
580   }
581   cmp->src1->instruction = &cmp->instruction;
582
583   return &cmp->instruction;
584}
585
586static struct pvr_instruction *
587pvr_pds_disassemble_instruction_sp_ld_st(void *context,
588                                         PVR_ERR_CALLBACK err_callback,
589                                         struct pvr_dissassembler_error error,
590                                         bool ld,
591                                         uint32_t instruction,
592                                         bool cc)
593{
594   struct pvr_ldst *ins = malloc(sizeof(*ins));
595   assert(ins);
596
597   ins->instruction.next = NULL;
598   ins->instruction.type = ld ? INS_LD : INS_ST;
599
600   ins->cc = cc;
601   ins->src0 =
602      pvr_pds_disassemble_regs64(context,
603                                 err_callback,
604                                 error,
605                                 instruction >> PVR_ROGUE_PDSINST_LD_SRC0_SHIFT,
606                                 1);
607   ins->src0->instruction = &ins->instruction;
608   ins->st = !ld;
609
610   return &ins->instruction;
611}
612
613static struct pvr_instruction *
614pvr_pds_disassemble_instruction_sp_stmc(uint32_t instruction, bool cc)
615{
616   struct pvr_stmc *stmc = malloc(sizeof(*stmc));
617   assert(stmc);
618
619   stmc->instruction.next = NULL;
620   stmc->instruction.type = INS_STMC;
621
622   stmc->cc = cc;
623   stmc->src0 = calloc(1, sizeof(*stmc->src0));
624   assert(stmc->src0);
625
626   stmc->src0->type = LITERAL_NUM;
627   stmc->src0->literal = (instruction >> PVR_ROGUE_PDSINST_STMC_SOMASK_SHIFT) &
628                         PVR_ROGUE_PDSINST_SOMASK_MASK;
629   stmc->src0->instruction = &stmc->instruction;
630
631   return &stmc->instruction;
632}
633
634static struct pvr_instruction *
635pvr_pds_disassemble_instruction_sp_limm(void *context,
636                                        PVR_ERR_CALLBACK err_callback,
637                                        struct pvr_dissassembler_error error,
638                                        uint32_t instruction,
639                                        bool cc)
640{
641   struct pvr_limm *limm = malloc(sizeof(*limm));
642   assert(limm);
643   limm->instruction.next = NULL;
644   limm->instruction.type = INS_LIMM;
645
646   limm->cc = cc;
647   limm->GR = (instruction & PVR_ROGUE_PDSINST_LIMM_GR_ENABLE) != 0;
648   limm->src0 = calloc(1, sizeof(*limm->src0));
649   assert(limm->src0);
650
651   limm->src0->type = LITERAL_NUM;
652   limm->src0->literal = (instruction >> PVR_ROGUE_PDSINST_LIMM_SRC0_SHIFT) &
653                         PVR_ROGUE_PDSINST_IMM16_MASK;
654   limm->src0->instruction = &limm->instruction;
655   limm->dst = pvr_pds_disassemble_regs32t(context,
656                                           err_callback,
657                                           error,
658                                           instruction >>
659                                              PVR_ROGUE_PDSINST_LIMM_SRC1_SHIFT,
660                                           0);
661   limm->dst->instruction = &limm->instruction;
662
663   return &limm->instruction;
664}
665
666static struct pvr_instruction *
667pvr_pds_disassemble_simple(enum pvr_instruction_type type, bool cc)
668{
669   struct pvr_simple *ins = malloc(sizeof(*ins));
670   assert(ins);
671
672   ins->instruction.next = NULL;
673   ins->instruction.type = type;
674   ins->cc = cc;
675
676   return &ins->instruction;
677}
678
679static struct pvr_instruction *
680pvr_pds_disassemble_instruction_bra(uint32_t instruction)
681{
682   uint32_t branch_addr;
683   struct pvr_bra *bra = (struct pvr_bra *)malloc(sizeof(*bra));
684   assert(bra);
685
686   bra->instruction.type = INS_BRA;
687   bra->instruction.next = NULL;
688
689   branch_addr = (instruction >> PVR_ROGUE_PDSINST_BRA_ADDR_SHIFT) &
690                 PVR_ROGUE_PDSINST_BRAADDR_MASK;
691   bra->address = (branch_addr & 0x40000U) ? ((int)branch_addr) - 0x80000
692                                           : (int)branch_addr;
693
694   bra->srcc = malloc(sizeof(*bra->srcc));
695   assert(bra->srcc);
696
697   bra->srcc->predicate = (instruction >> PVR_ROGUE_PDSINST_BRA_SRCC_SHIFT) &
698                          PVR_ROGUE_PDSINST_PREDICATE_MASK;
699   bra->srcc->negate = instruction & PVR_ROGUE_PDSINST_BRA_NEG_ENABLE;
700
701   bra->setc = malloc(sizeof(*bra->setc));
702   assert(bra->setc);
703
704   bra->setc->predicate = (instruction >> PVR_ROGUE_PDSINST_BRA_SETC_SHIFT) &
705                          PVR_ROGUE_PDSINST_PREDICATE_MASK;
706
707   bra->target = NULL;
708
709   return &bra->instruction;
710}
711
712static struct pvr_instruction *
713pvr_pds_disassemble_instruction_sp(void *context,
714                                   PVR_ERR_CALLBACK err_callback,
715                                   struct pvr_dissassembler_error error,
716                                   uint32_t instruction)
717{
718   uint32_t op = (instruction >> PVR_TYPE_OPCODE_SP_SHIFT) &
719                 PVR_ROGUE_PDSINST_OPCODESP_MASK;
720   bool cc = instruction & PVR_TYPE_OPCODE_SP;
721
722   switch (op) {
723   case PVR_ROGUE_PDSINST_OPCODESP_LD:
724      error.instruction = INS_LD;
725      return pvr_pds_disassemble_instruction_sp_ld_st(
726         context,
727         err_callback,
728         error,
729         true,
730         instruction,
731         instruction & (1 << PVR_ROGUE_PDSINST_LD_CC_SHIFT));
732   case PVR_ROGUE_PDSINST_OPCODESP_ST:
733      error.instruction = INS_ST;
734      return pvr_pds_disassemble_instruction_sp_ld_st(
735         context,
736         err_callback,
737         error,
738         false,
739         instruction,
740         instruction & (1 << PVR_ROGUE_PDSINST_ST_CC_SHIFT));
741   case PVR_ROGUE_PDSINST_OPCODESP_STMC:
742      error.instruction = INS_STMC;
743      return pvr_pds_disassemble_instruction_sp_stmc(instruction, cc);
744   case PVR_ROGUE_PDSINST_OPCODESP_LIMM:
745      error.instruction = INS_LIMM;
746      return pvr_pds_disassemble_instruction_sp_limm(context,
747                                                     err_callback,
748                                                     error,
749                                                     instruction,
750                                                     cc);
751   case PVR_ROGUE_PDSINST_OPCODESP_WDF:
752      error.instruction = INS_WDF;
753      return pvr_pds_disassemble_simple(INS_WDF, cc);
754   case PVR_ROGUE_PDSINST_OPCODESP_LOCK:
755      error.instruction = INS_LOCK;
756      return pvr_pds_disassemble_simple(INS_LOCK, cc);
757   case PVR_ROGUE_PDSINST_OPCODESP_RELEASE:
758      error.instruction = INS_RELEASE;
759      return pvr_pds_disassemble_simple(INS_RELEASE, cc);
760   case PVR_ROGUE_PDSINST_OPCODESP_HALT:
761      error.instruction = INS_HALT;
762      return pvr_pds_disassemble_simple(INS_HALT, cc);
763   case PVR_ROGUE_PDSINST_OPCODESP_NOP:
764      error.instruction = INS_NOP;
765      return pvr_pds_disassemble_simple(INS_NOP, cc);
766   default:
767      error.type = PVR_PDS_ERR_SP_UNKNOWN;
768      error.text = "opcode unknown for special instruction";
769      pvr_error_check(err_callback, error);
770      return NULL;
771   }
772}
773
774static struct pvr_instruction *
775pvr_pds_disassemble_instruction_ddmad(void *context,
776                                      PVR_ERR_CALLBACK err_callback,
777                                      struct pvr_dissassembler_error error,
778                                      uint32_t instruction)
779{
780   struct pvr_ddmad *ddmad = malloc(sizeof(*ddmad));
781   assert(ddmad);
782
783   ddmad->instruction.next = NULL;
784   ddmad->instruction.type = INS_DDMAD;
785
786   ddmad->cc = instruction & PVR_ROGUE_PDSINST_DDMAD_CC_ENABLE;
787   ddmad->END = instruction & PVR_ROGUE_PDSINST_DDMAD_END_ENABLE;
788
789   ddmad->src0 = pvr_pds_disassemble_regs32(
790      context,
791      err_callback,
792      error,
793      instruction >> PVR_ROGUE_PDSINST_DDMAD_SRC0_SHIFT,
794      1);
795   ddmad->src0->instruction = &ddmad->instruction;
796
797   ddmad->src1 = pvr_pds_disassemble_regs32t(
798      context,
799      err_callback,
800      error,
801      instruction >> PVR_ROGUE_PDSINST_DDMAD_SRC1_SHIFT,
802      2);
803   ddmad->src1->instruction = &ddmad->instruction;
804
805   ddmad->src2 = pvr_pds_disassemble_regs64(
806      context,
807      err_callback,
808      error,
809      instruction >> PVR_ROGUE_PDSINST_DDMAD_SRC2_SHIFT,
810      3);
811   ddmad->src2->instruction = &ddmad->instruction;
812
813   ddmad->src3 = pvr_pds_disassemble_regs64C(
814      context,
815      err_callback,
816      error,
817      instruction >> PVR_ROGUE_PDSINST_DDMAD_SRC3_SHIFT,
818      4);
819   ddmad->src3->instruction = &ddmad->instruction;
820
821   return &ddmad->instruction;
822}
823
824static struct pvr_instruction *
825pvr_pds_disassemble_instruction_mad(void *context,
826                                    PVR_ERR_CALLBACK err_callback,
827                                    struct pvr_dissassembler_error error,
828                                    uint32_t instruction)
829{
830   struct pvr_mad *mad = malloc(sizeof(*mad));
831   assert(mad);
832
833   mad->instruction.next = NULL;
834   mad->instruction.type = INS_MAD;
835
836   mad->cc = instruction & PVR_ROGUE_PDSINST_MAD_CC_ENABLE;
837   mad->sna = instruction & PVR_ROGUE_PDSINST_MAD_SNA_SUB;
838   mad->alum = (instruction & PVR_ROGUE_PDSINST_MAD_ALUM_SIGNED);
839
840   mad->src0 = pvr_pds_disassemble_regs32(context,
841                                          err_callback,
842                                          error,
843                                          instruction >>
844                                             PVR_ROGUE_PDSINST_MAD_SRC0_SHIFT,
845                                          1);
846   mad->src0->instruction = &mad->instruction;
847
848   mad->src1 = pvr_pds_disassemble_regs32(context,
849                                          err_callback,
850                                          error,
851                                          instruction >>
852                                             PVR_ROGUE_PDSINST_MAD_SRC1_SHIFT,
853                                          2);
854   mad->src1->instruction = &mad->instruction;
855
856   mad->src2 = pvr_pds_disassemble_regs64(context,
857                                          err_callback,
858                                          error,
859                                          instruction >>
860                                             PVR_ROGUE_PDSINST_MAD_SRC2_SHIFT,
861                                          3);
862   mad->src2->instruction = &mad->instruction;
863
864   mad->dst = pvr_pds_disassemble_regs64t(context,
865                                          err_callback,
866                                          error,
867                                          instruction >>
868                                             PVR_ROGUE_PDSINST_MAD_DST_SHIFT,
869                                          0);
870   mad->dst->instruction = &mad->instruction;
871
872   return &mad->instruction;
873}
874
875static struct pvr_instruction *
876pvr_pds_disassemble_instruction_dout(void *context,
877                                     PVR_ERR_CALLBACK err_callback,
878                                     struct pvr_dissassembler_error error,
879                                     uint32_t instruction)
880{
881   struct pvr_dout *dout = malloc(sizeof(*dout));
882   assert(dout);
883
884   dout->instruction.next = NULL;
885   dout->instruction.type = INS_DOUT;
886
887   dout->END = instruction & PVR_ROGUE_PDSINST_DOUT_END_ENABLE;
888   dout->cc = instruction & PVR_ROGUE_PDSINST_DOUT_CC_ENABLE;
889   dout->dst = (instruction >> PVR_ROGUE_PDSINST_DOUT_DST_SHIFT) &
890               PVR_ROGUE_PDSINST_DSTDOUT_MASK;
891
892   dout->src0 = pvr_pds_disassemble_regs64(context,
893                                           err_callback,
894                                           error,
895                                           instruction >>
896                                              PVR_ROGUE_PDSINST_DOUT_SRC0_SHIFT,
897                                           1);
898   dout->src0->instruction = &dout->instruction;
899
900   dout->src1 = pvr_pds_disassemble_regs32(context,
901                                           err_callback,
902                                           error,
903                                           instruction >>
904                                              PVR_ROGUE_PDSINST_DOUT_SRC1_SHIFT,
905                                           2);
906   dout->src1->instruction = &dout->instruction;
907
908   return &dout->instruction;
909}
910
911static void pvr_pds_free_instruction_limm(struct pvr_limm *inst)
912{
913   free(inst->dst);
914   free(inst->src0);
915   free(inst);
916}
917
918static void pvr_pds_free_instruction_add(struct pvr_add *inst)
919{
920   free(inst->dst);
921   free(inst->src0);
922   free(inst->src1);
923   free(inst);
924}
925
926static void pvr_pds_free_instruction_cmp(struct pvr_cmp *inst)
927{
928   free(inst->src0);
929   free(inst->src1);
930   free(inst);
931}
932
933static void pvr_pds_free_instruction_mad(struct pvr_mad *inst)
934{
935   free(inst->dst);
936   free(inst->src0);
937   free(inst->src1);
938   free(inst->src2);
939   free(inst);
940}
941
942static void pvr_pds_free_instruction_bra(struct pvr_bra *inst)
943{
944   free(inst->setc);
945   free(inst->srcc);
946   free(inst);
947}
948
949static void pvr_pds_free_instruction_ddmad(struct pvr_ddmad *inst)
950{
951   free(inst->src0);
952   free(inst->src1);
953   free(inst->src2);
954   free(inst->src3);
955   free(inst);
956}
957
958static void pvr_pds_free_instruction_dout(struct pvr_dout *inst)
959{
960   free(inst->src0);
961   free(inst->src1);
962   free(inst);
963}
964
965static void pvr_pds_free_instruction_ldst(struct pvr_ldst *inst)
966{
967   free(inst->src0);
968   free(inst);
969}
970
971static void pvr_pds_free_instruction_simple(struct pvr_simple *inst)
972{
973   free(inst);
974}
975
976static void pvr_pds_free_instruction_sfltp(struct pvr_sftlp *inst)
977{
978   free(inst->dst);
979   free(inst->src0);
980   free(inst->src1);
981   free(inst->src2);
982   free(inst);
983}
984
985static void pvr_pds_free_instruction_stm(struct pvr_stm *inst)
986{
987   free(inst->src0);
988   free(inst->src1);
989   free(inst->src2);
990   free(inst->src3);
991   free(inst);
992}
993
994static void pvr_pds_free_instruction_stmc(struct pvr_stmc *inst)
995{
996   free(inst->src0);
997   free(inst);
998}
999
1000void pvr_pds_free_instruction(struct pvr_instruction *instruction)
1001{
1002   if (!instruction)
1003      return;
1004
1005   switch (instruction->type) {
1006   case INS_LIMM:
1007      pvr_pds_free_instruction_limm((struct pvr_limm *)instruction);
1008      break;
1009   case INS_ADD64:
1010   case INS_ADD32:
1011      pvr_pds_free_instruction_add((struct pvr_add *)instruction);
1012      break;
1013   case INS_CMP:
1014      pvr_pds_free_instruction_cmp((struct pvr_cmp *)instruction);
1015      break;
1016   case INS_MAD:
1017      pvr_pds_free_instruction_mad((struct pvr_mad *)instruction);
1018      break;
1019   case INS_BRA:
1020      pvr_pds_free_instruction_bra((struct pvr_bra *)instruction);
1021      break;
1022   case INS_DDMAD:
1023      pvr_pds_free_instruction_ddmad((struct pvr_ddmad *)instruction);
1024      break;
1025   case INS_DOUT:
1026      pvr_pds_free_instruction_dout((struct pvr_dout *)instruction);
1027      break;
1028   case INS_LD:
1029   case INS_ST:
1030      pvr_pds_free_instruction_ldst((struct pvr_ldst *)instruction);
1031      break;
1032   case INS_WDF:
1033   case INS_LOCK:
1034   case INS_RELEASE:
1035   case INS_HALT:
1036   case INS_NOP:
1037      pvr_pds_free_instruction_simple((struct pvr_simple *)instruction);
1038      break;
1039   case INS_SFTLP64:
1040   case INS_SFTLP32:
1041      pvr_pds_free_instruction_sfltp((struct pvr_sftlp *)instruction);
1042      break;
1043   case INS_STM:
1044      pvr_pds_free_instruction_stm((struct pvr_stm *)instruction);
1045      break;
1046   case INS_STMC:
1047      pvr_pds_free_instruction_stmc((struct pvr_stmc *)instruction);
1048      break;
1049   }
1050}
1051
1052struct pvr_instruction *
1053pvr_pds_disassemble_instruction2(void *context,
1054                                 PVR_ERR_CALLBACK err_callback,
1055                                 uint32_t instruction)
1056{
1057   struct pvr_dissassembler_error error = { .context = context };
1058
1059   /* First we need to find out what type of OPCODE we are dealing with. */
1060   if (instruction & PVR_TYPE_OPCODE) {
1061      uint32_t opcode_C = (instruction >> PVR_TYPE_OPCODE_SHIFT) &
1062                          PVR_ROGUE_PDSINST_OPCODEC_MASK;
1063      switch (opcode_C) {
1064      case PVR_ROGUE_PDSINST_OPCODEC_ADD64:
1065         error.instruction = INS_ADD64;
1066         return pvr_pds_disassemble_instruction_add64(context,
1067                                                      err_callback,
1068                                                      error,
1069                                                      instruction);
1070      case PVR_ROGUE_PDSINST_OPCODEC_ADD32:
1071         error.instruction = INS_ADD32;
1072         return pvr_pds_disassemble_instruction_add32(context,
1073                                                      err_callback,
1074                                                      error,
1075                                                      instruction);
1076      case PVR_ROGUE_PDSINST_OPCODEC_SFTLP64:
1077         error.instruction = INS_SFTLP64;
1078         return pvr_pds_disassemble_instruction_sftlp64(context,
1079                                                        err_callback,
1080                                                        error,
1081                                                        instruction);
1082      case PVR_ROGUE_PDSINST_OPCODEC_CMP:
1083         error.instruction = INS_CMP;
1084         return pvr_pds_disassemble_instruction_cmp(context,
1085                                                    err_callback,
1086                                                    error,
1087                                                    instruction);
1088      case PVR_ROGUE_PDSINST_OPCODEC_BRA:
1089         error.instruction = INS_BRA;
1090         return pvr_pds_disassemble_instruction_bra(instruction);
1091      case PVR_ROGUE_PDSINST_OPCODEC_SP:
1092         return pvr_pds_disassemble_instruction_sp(context,
1093                                                   err_callback,
1094                                                   error,
1095                                                   instruction);
1096      case PVR_ROGUE_PDSINST_OPCODEC_DDMAD:
1097         error.instruction = INS_DDMAD;
1098         return pvr_pds_disassemble_instruction_ddmad(context,
1099                                                      err_callback,
1100                                                      error,
1101                                                      instruction);
1102      case PVR_ROGUE_PDSINST_OPCODEC_DOUT:
1103         error.instruction = INS_DOUT;
1104         return pvr_pds_disassemble_instruction_dout(context,
1105                                                     err_callback,
1106                                                     error,
1107                                                     instruction);
1108      }
1109   } else if (instruction & PVR_TYPE_OPCODEB) {
1110      uint32_t opcode_B = (instruction >> PVR_TYPE_OPCODEB_SHIFT) &
1111                          PVR_ROGUE_PDSINST_OPCODEB_MASK;
1112      switch (opcode_B) {
1113      case PVR_ROGUE_PDSINST_OPCODEB_SFTLP32:
1114         error.instruction = INS_SFTLP32;
1115         return pvr_pds_disassemble_instruction_sftlp32(context,
1116                                                        err_callback,
1117                                                        error,
1118                                                        instruction);
1119      case PVR_ROGUE_PDSINST_OPCODEB_STM:
1120         error.instruction = INS_STM;
1121         return pvr_pds_disassemble_instruction_stm(context,
1122                                                    err_callback,
1123                                                    error,
1124                                                    instruction);
1125      }
1126   } else { /* Opcode A - MAD instruction. */
1127      error.instruction = INS_MAD;
1128      return pvr_pds_disassemble_instruction_mad(context,
1129                                                 err_callback,
1130                                                 error,
1131                                                 instruction);
1132   }
1133   return NULL;
1134}
1135