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