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 35static 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, 45static const char *const instructions[] = { PVR_INSTRUCTIONS }; 46#undef X 47 48static 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 78static struct pvr_operand * 79pvr_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} 111static struct pvr_operand * 112pvr_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} 139static struct pvr_operand * 140pvr_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 163static struct pvr_operand * 164pvr_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} 197static struct pvr_operand * 198pvr_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 221static struct pvr_operand * 222pvr_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 245static struct pvr_operand * 246pvr_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 282static struct pvr_instruction * 283pvr_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 323static struct pvr_instruction * 324pvr_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 364static struct pvr_instruction * 365pvr_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 420static struct pvr_instruction * 421pvr_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 482static struct pvr_instruction * 483pvr_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} 542static struct pvr_instruction * 543pvr_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 586static struct pvr_instruction * 587pvr_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 613static struct pvr_instruction * 614pvr_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 634static struct pvr_instruction * 635pvr_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 666static struct pvr_instruction * 667pvr_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 679static struct pvr_instruction * 680pvr_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 712static struct pvr_instruction * 713pvr_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 774static struct pvr_instruction * 775pvr_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 824static struct pvr_instruction * 825pvr_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 875static struct pvr_instruction * 876pvr_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 911static void pvr_pds_free_instruction_limm(struct pvr_limm *inst) 912{ 913 free(inst->dst); 914 free(inst->src0); 915 free(inst); 916} 917 918static 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 926static void pvr_pds_free_instruction_cmp(struct pvr_cmp *inst) 927{ 928 free(inst->src0); 929 free(inst->src1); 930 free(inst); 931} 932 933static 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 942static void pvr_pds_free_instruction_bra(struct pvr_bra *inst) 943{ 944 free(inst->setc); 945 free(inst->srcc); 946 free(inst); 947} 948 949static 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 958static void pvr_pds_free_instruction_dout(struct pvr_dout *inst) 959{ 960 free(inst->src0); 961 free(inst->src1); 962 free(inst); 963} 964 965static void pvr_pds_free_instruction_ldst(struct pvr_ldst *inst) 966{ 967 free(inst->src0); 968 free(inst); 969} 970 971static void pvr_pds_free_instruction_simple(struct pvr_simple *inst) 972{ 973 free(inst); 974} 975 976static 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 985static 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 994static void pvr_pds_free_instruction_stmc(struct pvr_stmc *inst) 995{ 996 free(inst->src0); 997 free(inst); 998} 999 1000void 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 1052struct pvr_instruction * 1053pvr_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