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