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