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