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