1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 5bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 6bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights 7bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 9bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18bf215546Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <stdbool.h> 25bf215546Sopenharmony_ci#include <stdint.h> 26bf215546Sopenharmony_ci#include <stdio.h> 27bf215546Sopenharmony_ci#include <stdlib.h> 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "pvr_rogue_pds_defs.h" 30bf215546Sopenharmony_ci#include "pvr_rogue_pds_disasm.h" 31bf215546Sopenharmony_ci#include "pvr_rogue_pds_encode.h" 32bf215546Sopenharmony_ci#include "util/log.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#define X(lop, str) #str, 35bf215546Sopenharmony_cistatic const char *const LOP[] = { PVR_PDS_LOP }; 36bf215546Sopenharmony_ci#undef X 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_cistatic void pvr_pds_disassemble_operand(struct pvr_operand *op, 39bf215546Sopenharmony_ci char *instr_str, 40bf215546Sopenharmony_ci size_t instr_len) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci#define X(enum, str, size) { #str, #size }, 43bf215546Sopenharmony_ci static const char *const regs[][2] = { PVR_PDS_OPERAND_TYPES }; 44bf215546Sopenharmony_ci#undef X 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci if (op->type == LITERAL_NUM) { 47bf215546Sopenharmony_ci snprintf(instr_str, 48bf215546Sopenharmony_ci instr_len, 49bf215546Sopenharmony_ci "%s (%llu)", 50bf215546Sopenharmony_ci regs[op->type][0], 51bf215546Sopenharmony_ci (unsigned long long)op->literal); 52bf215546Sopenharmony_ci } else if (op->type == UNRESOLVED) { 53bf215546Sopenharmony_ci snprintf(instr_str, instr_len, "UNRESOLVED"); 54bf215546Sopenharmony_ci } else { 55bf215546Sopenharmony_ci snprintf(instr_str, 56bf215546Sopenharmony_ci instr_len, 57bf215546Sopenharmony_ci "%s[%u].%s", 58bf215546Sopenharmony_ci regs[op->type][0], 59bf215546Sopenharmony_ci op->absolute_address, 60bf215546Sopenharmony_ci regs[op->type][1]); 61bf215546Sopenharmony_ci } 62bf215546Sopenharmony_ci} 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_add64(struct pvr_add *add, 65bf215546Sopenharmony_ci char *instr_str, 66bf215546Sopenharmony_ci size_t instr_len) 67bf215546Sopenharmony_ci{ 68bf215546Sopenharmony_ci char dst[32]; 69bf215546Sopenharmony_ci char src0[32]; 70bf215546Sopenharmony_ci char src1[32]; 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci pvr_pds_disassemble_operand(add->src0, src0, sizeof(src0)); 73bf215546Sopenharmony_ci pvr_pds_disassemble_operand(add->src1, src1, sizeof(src1)); 74bf215546Sopenharmony_ci pvr_pds_disassemble_operand(add->dst, dst, sizeof(dst)); 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci snprintf(instr_str, 77bf215546Sopenharmony_ci instr_len, 78bf215546Sopenharmony_ci "%-16s%s%s = %s %s %s %s", 79bf215546Sopenharmony_ci "ADD64", 80bf215546Sopenharmony_ci add->cc ? "? " : "", 81bf215546Sopenharmony_ci dst, 82bf215546Sopenharmony_ci src0, 83bf215546Sopenharmony_ci add->sna ? "-" : "+", 84bf215546Sopenharmony_ci src1, 85bf215546Sopenharmony_ci add->alum ? "[signed]" : ""); 86bf215546Sopenharmony_ci} 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_add32(struct pvr_add *add, 89bf215546Sopenharmony_ci char *instr_str, 90bf215546Sopenharmony_ci size_t instr_len) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci char dst[32]; 93bf215546Sopenharmony_ci char src0[32]; 94bf215546Sopenharmony_ci char src1[32]; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci pvr_pds_disassemble_operand(add->src0, src0, sizeof(src0)); 97bf215546Sopenharmony_ci pvr_pds_disassemble_operand(add->src1, src1, sizeof(src1)); 98bf215546Sopenharmony_ci pvr_pds_disassemble_operand(add->dst, dst, sizeof(dst)); 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci snprintf(instr_str, 101bf215546Sopenharmony_ci instr_len, 102bf215546Sopenharmony_ci "%-16s%s%s = %s %s %s %s", 103bf215546Sopenharmony_ci "ADD32", 104bf215546Sopenharmony_ci add->cc ? "? " : "", 105bf215546Sopenharmony_ci dst, 106bf215546Sopenharmony_ci src0, 107bf215546Sopenharmony_ci add->sna ? "-" : "+", 108bf215546Sopenharmony_ci src1, 109bf215546Sopenharmony_ci add->alum ? "[signed]" : ""); 110bf215546Sopenharmony_ci} 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_cistatic void 113bf215546Sopenharmony_cipvr_pds_disassemble_instruction_sftlp32(struct pvr_sftlp *instruction, 114bf215546Sopenharmony_ci char *instr_str, 115bf215546Sopenharmony_ci size_t instr_len) 116bf215546Sopenharmony_ci{ 117bf215546Sopenharmony_ci char dst[32]; 118bf215546Sopenharmony_ci char src0[32]; 119bf215546Sopenharmony_ci char src1[32]; 120bf215546Sopenharmony_ci char src2[32]; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0)); 123bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src1, src1, sizeof(src1)); 124bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->dst, dst, sizeof(dst)); 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci if (instruction->IM) 127bf215546Sopenharmony_ci snprintf(src2, sizeof(src2), "%u", (uint32_t)instruction->src2->literal); 128bf215546Sopenharmony_ci else 129bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src2, src2, sizeof(src2)); 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci if (instruction->lop == LOP_NONE) { 132bf215546Sopenharmony_ci snprintf(instr_str, 133bf215546Sopenharmony_ci instr_len, 134bf215546Sopenharmony_ci "%-16s%s%s = %s %s %s", 135bf215546Sopenharmony_ci "SFTLP32", 136bf215546Sopenharmony_ci instruction->cc ? "? " : "", 137bf215546Sopenharmony_ci dst, 138bf215546Sopenharmony_ci src0, 139bf215546Sopenharmony_ci instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<", 140bf215546Sopenharmony_ci src2); 141bf215546Sopenharmony_ci } else if (instruction->lop == LOP_NOT) { 142bf215546Sopenharmony_ci snprintf(instr_str, 143bf215546Sopenharmony_ci instr_len, 144bf215546Sopenharmony_ci "%-16s%s%s = (~%s) %s %s", 145bf215546Sopenharmony_ci "SFTLP32", 146bf215546Sopenharmony_ci instruction->cc ? "? " : "", 147bf215546Sopenharmony_ci dst, 148bf215546Sopenharmony_ci src0, 149bf215546Sopenharmony_ci instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<", 150bf215546Sopenharmony_ci src2); 151bf215546Sopenharmony_ci } else { 152bf215546Sopenharmony_ci snprintf(instr_str, 153bf215546Sopenharmony_ci instr_len, 154bf215546Sopenharmony_ci "%-16s%s%s = (%s %s %s) %s %s", 155bf215546Sopenharmony_ci "SFTLP32", 156bf215546Sopenharmony_ci instruction->cc ? "? " : "", 157bf215546Sopenharmony_ci dst, 158bf215546Sopenharmony_ci src0, 159bf215546Sopenharmony_ci LOP[instruction->lop], 160bf215546Sopenharmony_ci src1, 161bf215546Sopenharmony_ci instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<", 162bf215546Sopenharmony_ci src2); 163bf215546Sopenharmony_ci } 164bf215546Sopenharmony_ci} 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_stm(struct pvr_stm *instruction, 167bf215546Sopenharmony_ci char *instr_str, 168bf215546Sopenharmony_ci size_t instr_len) 169bf215546Sopenharmony_ci{ 170bf215546Sopenharmony_ci char src0[32]; 171bf215546Sopenharmony_ci char src1[32]; 172bf215546Sopenharmony_ci char src2[32]; 173bf215546Sopenharmony_ci char src3[32]; 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci char stm_pred[64]; 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0)); 178bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src1, src1, sizeof(src1)); 179bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src2, src2, sizeof(src2)); 180bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src3, src3, sizeof(src3)); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci if (instruction->ccs_global) 183bf215546Sopenharmony_ci snprintf(stm_pred, sizeof(stm_pred), "overflow_any"); 184bf215546Sopenharmony_ci else if (instruction->ccs_so) 185bf215546Sopenharmony_ci snprintf(stm_pred, sizeof(stm_pred), "overflow_current"); 186bf215546Sopenharmony_ci else 187bf215546Sopenharmony_ci stm_pred[0] = 0; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci snprintf(instr_str, 190bf215546Sopenharmony_ci instr_len, 191bf215546Sopenharmony_ci "%-16s%s%s%s stm%u = %s, %s, %s, %s", 192bf215546Sopenharmony_ci "STM", 193bf215546Sopenharmony_ci instruction->cc ? "? " : "", 194bf215546Sopenharmony_ci stm_pred, 195bf215546Sopenharmony_ci instruction->tst ? " (TST only)" : "", 196bf215546Sopenharmony_ci instruction->stream_out, 197bf215546Sopenharmony_ci src0, 198bf215546Sopenharmony_ci src1, 199bf215546Sopenharmony_ci src2, 200bf215546Sopenharmony_ci src3); 201bf215546Sopenharmony_ci} 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_cistatic void pds_disassemble_instruction_stmc(struct pvr_stmc *instruction, 204bf215546Sopenharmony_ci char *instr_str, 205bf215546Sopenharmony_ci size_t instr_len) 206bf215546Sopenharmony_ci{ 207bf215546Sopenharmony_ci char src0[32]; 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0)); 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci snprintf(instr_str, 212bf215546Sopenharmony_ci instr_len, 213bf215546Sopenharmony_ci "%-16s%s %s", 214bf215546Sopenharmony_ci "STMC", 215bf215546Sopenharmony_ci instruction->cc ? "? " : "", 216bf215546Sopenharmony_ci src0); 217bf215546Sopenharmony_ci} 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_cistatic void 220bf215546Sopenharmony_cipvr_pds_disassemble_instruction_sftlp64(struct pvr_sftlp *instruction, 221bf215546Sopenharmony_ci char *instr_str, 222bf215546Sopenharmony_ci size_t instr_len) 223bf215546Sopenharmony_ci{ 224bf215546Sopenharmony_ci char dst[32]; 225bf215546Sopenharmony_ci char src0[32]; 226bf215546Sopenharmony_ci char src1[32]; 227bf215546Sopenharmony_ci char src2[32]; 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0)); 230bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src1, src1, sizeof(src1)); 231bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->dst, dst, sizeof(dst)); 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci if (instruction->IM) 234bf215546Sopenharmony_ci snprintf(src2, sizeof(src2), "%u", (uint32_t)instruction->src2->literal); 235bf215546Sopenharmony_ci else 236bf215546Sopenharmony_ci pvr_pds_disassemble_operand(instruction->src2, src2, sizeof(src2)); 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci if (instruction->lop == LOP_NONE) { 239bf215546Sopenharmony_ci snprintf(instr_str, 240bf215546Sopenharmony_ci instr_len, 241bf215546Sopenharmony_ci "%-16s%s%s = %s %s %s", 242bf215546Sopenharmony_ci "SFTLP64", 243bf215546Sopenharmony_ci instruction->cc ? "? " : "", 244bf215546Sopenharmony_ci dst, 245bf215546Sopenharmony_ci src0, 246bf215546Sopenharmony_ci instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<", 247bf215546Sopenharmony_ci src2); 248bf215546Sopenharmony_ci } else if (instruction->lop == LOP_NOT) { 249bf215546Sopenharmony_ci snprintf(instr_str, 250bf215546Sopenharmony_ci instr_len, 251bf215546Sopenharmony_ci "%-16s%s%s = (~%s) %s %s", 252bf215546Sopenharmony_ci "SFTLP64", 253bf215546Sopenharmony_ci instruction->cc ? "? " : "", 254bf215546Sopenharmony_ci dst, 255bf215546Sopenharmony_ci src0, 256bf215546Sopenharmony_ci instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<", 257bf215546Sopenharmony_ci src2); 258bf215546Sopenharmony_ci } else { 259bf215546Sopenharmony_ci snprintf(instr_str, 260bf215546Sopenharmony_ci instr_len, 261bf215546Sopenharmony_ci "%-16s%s%s = (%s %s %s) %s %s", 262bf215546Sopenharmony_ci "SFTLP64", 263bf215546Sopenharmony_ci instruction->cc ? "? " : "", 264bf215546Sopenharmony_ci dst, 265bf215546Sopenharmony_ci src0, 266bf215546Sopenharmony_ci LOP[instruction->lop], 267bf215546Sopenharmony_ci src1, 268bf215546Sopenharmony_ci instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<", 269bf215546Sopenharmony_ci src2); 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci} 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_cmp(struct pvr_cmp *cmp, 274bf215546Sopenharmony_ci char *instr_str, 275bf215546Sopenharmony_ci size_t instr_len) 276bf215546Sopenharmony_ci{ 277bf215546Sopenharmony_ci char src0[32]; 278bf215546Sopenharmony_ci char src1[32]; 279bf215546Sopenharmony_ci static const char *const COP[] = { "=", ">", "<", "!=" }; 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci pvr_pds_disassemble_operand(cmp->src0, src0, sizeof(src0)); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci if (cmp->IM) { 284bf215546Sopenharmony_ci snprintf(src1, 285bf215546Sopenharmony_ci sizeof(src1), 286bf215546Sopenharmony_ci "%#04llx", 287bf215546Sopenharmony_ci (unsigned long long)cmp->src1->literal); 288bf215546Sopenharmony_ci } else { 289bf215546Sopenharmony_ci pvr_pds_disassemble_operand(cmp->src1, src1, sizeof(src1)); 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci snprintf(instr_str, 293bf215546Sopenharmony_ci instr_len, 294bf215546Sopenharmony_ci "%-16s%sP0 = (%s %s %s)", 295bf215546Sopenharmony_ci "CMP", 296bf215546Sopenharmony_ci cmp->cc ? "? " : "", 297bf215546Sopenharmony_ci src0, 298bf215546Sopenharmony_ci COP[cmp->cop], 299bf215546Sopenharmony_ci src1); 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_ldst(struct pvr_ldst *ins, 303bf215546Sopenharmony_ci char *instr_str, 304bf215546Sopenharmony_ci size_t instr_len) 305bf215546Sopenharmony_ci{ 306bf215546Sopenharmony_ci char src0[PVR_PDS_MAX_INST_STR_LEN]; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci pvr_pds_disassemble_operand(ins->src0, src0, sizeof(src0)); 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci if (ins->st) { 311bf215546Sopenharmony_ci snprintf(instr_str, 312bf215546Sopenharmony_ci instr_len, 313bf215546Sopenharmony_ci "%-16s%s%s: mem(%s) <= src(%s)", 314bf215546Sopenharmony_ci "ST", 315bf215546Sopenharmony_ci ins->cc ? "? " : "", 316bf215546Sopenharmony_ci src0, 317bf215546Sopenharmony_ci "?", 318bf215546Sopenharmony_ci "?"); 319bf215546Sopenharmony_ci } else { 320bf215546Sopenharmony_ci snprintf(instr_str, 321bf215546Sopenharmony_ci instr_len, 322bf215546Sopenharmony_ci "%-16s%s%s: dst(%s) <= mem(%s)", 323bf215546Sopenharmony_ci "ld", 324bf215546Sopenharmony_ci ins->cc ? "? " : "", 325bf215546Sopenharmony_ci src0, 326bf215546Sopenharmony_ci "?", 327bf215546Sopenharmony_ci "?"); 328bf215546Sopenharmony_ci } 329bf215546Sopenharmony_ci} 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_cistatic void pvr_pds_disassemble_simple(struct pvr_simple *simple, 332bf215546Sopenharmony_ci const char *type, 333bf215546Sopenharmony_ci char *instr_str, 334bf215546Sopenharmony_ci size_t instr_len) 335bf215546Sopenharmony_ci{ 336bf215546Sopenharmony_ci snprintf(instr_str, instr_len, "%-16s%s", type, simple->cc ? "? " : ""); 337bf215546Sopenharmony_ci} 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_limm(struct pvr_limm *limm, 340bf215546Sopenharmony_ci char *instr_str, 341bf215546Sopenharmony_ci size_t instr_len) 342bf215546Sopenharmony_ci{ 343bf215546Sopenharmony_ci int32_t imm = (uint32_t)limm->src0->literal; 344bf215546Sopenharmony_ci char dst[PVR_PDS_MAX_INST_STR_LEN]; 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci pvr_pds_disassemble_operand(limm->dst, dst, sizeof(dst)); 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci if (limm->GR) { 349bf215546Sopenharmony_ci char *pchGReg; 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci switch (imm) { 352bf215546Sopenharmony_ci case 0: 353bf215546Sopenharmony_ci pchGReg = "cluster"; 354bf215546Sopenharmony_ci break; 355bf215546Sopenharmony_ci case 1: 356bf215546Sopenharmony_ci pchGReg = "instance"; 357bf215546Sopenharmony_ci break; 358bf215546Sopenharmony_ci default: 359bf215546Sopenharmony_ci pchGReg = "unknown"; 360bf215546Sopenharmony_ci } 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci snprintf(instr_str, 363bf215546Sopenharmony_ci instr_len, 364bf215546Sopenharmony_ci "%-16s%s%s = G%d (%s)", 365bf215546Sopenharmony_ci "LIMM", 366bf215546Sopenharmony_ci limm->cc ? "? " : "", 367bf215546Sopenharmony_ci dst, 368bf215546Sopenharmony_ci imm, 369bf215546Sopenharmony_ci pchGReg); 370bf215546Sopenharmony_ci } else { 371bf215546Sopenharmony_ci snprintf(instr_str, 372bf215546Sopenharmony_ci instr_len, 373bf215546Sopenharmony_ci "%-16s%s%s = %#04x", 374bf215546Sopenharmony_ci "LIMM", 375bf215546Sopenharmony_ci limm->cc ? "? " : "", 376bf215546Sopenharmony_ci dst, 377bf215546Sopenharmony_ci imm); 378bf215546Sopenharmony_ci } 379bf215546Sopenharmony_ci} 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_ddmad(struct pvr_ddmad *ddmad, 382bf215546Sopenharmony_ci char *instr_str, 383bf215546Sopenharmony_ci size_t instr_len) 384bf215546Sopenharmony_ci{ 385bf215546Sopenharmony_ci char src0[PVR_PDS_MAX_INST_STR_LEN]; 386bf215546Sopenharmony_ci char src1[PVR_PDS_MAX_INST_STR_LEN]; 387bf215546Sopenharmony_ci char src2[PVR_PDS_MAX_INST_STR_LEN]; 388bf215546Sopenharmony_ci char src3[PVR_PDS_MAX_INST_STR_LEN]; 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci pvr_pds_disassemble_operand(ddmad->src0, src0, sizeof(src0)); 391bf215546Sopenharmony_ci pvr_pds_disassemble_operand(ddmad->src1, src1, sizeof(src1)); 392bf215546Sopenharmony_ci pvr_pds_disassemble_operand(ddmad->src2, src2, sizeof(src2)); 393bf215546Sopenharmony_ci pvr_pds_disassemble_operand(ddmad->src3, src3, sizeof(src3)); 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci snprintf(instr_str, 396bf215546Sopenharmony_ci instr_len, 397bf215546Sopenharmony_ci "%-16s%sdoutd = (%s * %s) + %s, %s%s", 398bf215546Sopenharmony_ci "DDMAD", 399bf215546Sopenharmony_ci ddmad->cc ? "? " : "", 400bf215546Sopenharmony_ci src0, 401bf215546Sopenharmony_ci src1, 402bf215546Sopenharmony_ci src2, 403bf215546Sopenharmony_ci src3, 404bf215546Sopenharmony_ci ddmad->END ? "; HALT" : ""); 405bf215546Sopenharmony_ci} 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_cistatic void pvr_pds_disassemble_predicate(uint32_t predicate, 408bf215546Sopenharmony_ci char *buffer, 409bf215546Sopenharmony_ci size_t buffer_length) 410bf215546Sopenharmony_ci{ 411bf215546Sopenharmony_ci switch (predicate) { 412bf215546Sopenharmony_ci case PVR_ROGUE_PDSINST_PREDICATE_P0: 413bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "p0"); 414bf215546Sopenharmony_ci break; 415bf215546Sopenharmony_ci case PVR_ROGUE_PDSINST_PREDICATE_IF0: 416bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "if0"); 417bf215546Sopenharmony_ci break; 418bf215546Sopenharmony_ci case PVR_ROGUE_PDSINST_PREDICATE_IF1: 419bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "if1"); 420bf215546Sopenharmony_ci break; 421bf215546Sopenharmony_ci case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_0: 422bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "so_overflow_0"); 423bf215546Sopenharmony_ci break; 424bf215546Sopenharmony_ci case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_1: 425bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "so_overflow_1"); 426bf215546Sopenharmony_ci break; 427bf215546Sopenharmony_ci case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_2: 428bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "so_overflow_2"); 429bf215546Sopenharmony_ci break; 430bf215546Sopenharmony_ci case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_3: 431bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "so_overflow_3"); 432bf215546Sopenharmony_ci break; 433bf215546Sopenharmony_ci case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_GLOBAL: 434bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "so_overflow_any"); 435bf215546Sopenharmony_ci break; 436bf215546Sopenharmony_ci case PVR_ROGUE_PDSINST_PREDICATE_KEEP: 437bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "keep"); 438bf215546Sopenharmony_ci break; 439bf215546Sopenharmony_ci case PVR_ROGUE_PDSINST_PREDICATE_OOB: 440bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "oob"); 441bf215546Sopenharmony_ci break; 442bf215546Sopenharmony_ci default: 443bf215546Sopenharmony_ci snprintf(buffer, buffer_length, "%s", "<ERROR>"); 444bf215546Sopenharmony_ci break; 445bf215546Sopenharmony_ci } 446bf215546Sopenharmony_ci} 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_bra(struct pvr_bra *bra, 449bf215546Sopenharmony_ci char *instr_str, 450bf215546Sopenharmony_ci size_t instr_len) 451bf215546Sopenharmony_ci{ 452bf215546Sopenharmony_ci char setc_pred[32]; 453bf215546Sopenharmony_ci char srcc_pred[32]; 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci pvr_pds_disassemble_predicate(bra->srcc->predicate, 456bf215546Sopenharmony_ci srcc_pred, 457bf215546Sopenharmony_ci sizeof(srcc_pred)); 458bf215546Sopenharmony_ci pvr_pds_disassemble_predicate(bra->setc->predicate, 459bf215546Sopenharmony_ci setc_pred, 460bf215546Sopenharmony_ci sizeof(setc_pred)); 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci if (bra->setc->predicate != PVR_ROGUE_PDSINST_PREDICATE_KEEP) { 463bf215546Sopenharmony_ci snprintf(instr_str, 464bf215546Sopenharmony_ci instr_len, 465bf215546Sopenharmony_ci "%-16sif %s%s %d ( setc = %s )", 466bf215546Sopenharmony_ci "BRA", 467bf215546Sopenharmony_ci bra->srcc->negate ? "! " : "", 468bf215546Sopenharmony_ci srcc_pred, 469bf215546Sopenharmony_ci bra->address, 470bf215546Sopenharmony_ci setc_pred); 471bf215546Sopenharmony_ci } else { 472bf215546Sopenharmony_ci snprintf(instr_str, 473bf215546Sopenharmony_ci instr_len, 474bf215546Sopenharmony_ci "%-16sif %s%s %d", 475bf215546Sopenharmony_ci "BRA", 476bf215546Sopenharmony_ci bra->srcc->negate ? "! " : "", 477bf215546Sopenharmony_ci srcc_pred, 478bf215546Sopenharmony_ci bra->address); 479bf215546Sopenharmony_ci } 480bf215546Sopenharmony_ci} 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_mad(struct pvr_mad *mad, 483bf215546Sopenharmony_ci char *instr_str, 484bf215546Sopenharmony_ci size_t instr_len) 485bf215546Sopenharmony_ci{ 486bf215546Sopenharmony_ci char src0[PVR_PDS_MAX_INST_STR_LEN]; 487bf215546Sopenharmony_ci char src1[PVR_PDS_MAX_INST_STR_LEN]; 488bf215546Sopenharmony_ci char src2[PVR_PDS_MAX_INST_STR_LEN]; 489bf215546Sopenharmony_ci char dst[PVR_PDS_MAX_INST_STR_LEN]; 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci pvr_pds_disassemble_operand(mad->src0, src0, sizeof(src0)); 492bf215546Sopenharmony_ci pvr_pds_disassemble_operand(mad->src1, src1, sizeof(src1)); 493bf215546Sopenharmony_ci pvr_pds_disassemble_operand(mad->src2, src2, sizeof(src2)); 494bf215546Sopenharmony_ci pvr_pds_disassemble_operand(mad->dst, dst, sizeof(dst)); 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci snprintf(instr_str, 497bf215546Sopenharmony_ci instr_len, 498bf215546Sopenharmony_ci "%-16s%s%s = (%s * %s) %s %s%s", 499bf215546Sopenharmony_ci "MAD", 500bf215546Sopenharmony_ci mad->cc ? "? " : "", 501bf215546Sopenharmony_ci dst, 502bf215546Sopenharmony_ci src0, 503bf215546Sopenharmony_ci src1, 504bf215546Sopenharmony_ci mad->sna ? "-" : "+", 505bf215546Sopenharmony_ci src2, 506bf215546Sopenharmony_ci mad->alum ? " [signed]" : ""); 507bf215546Sopenharmony_ci} 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_cistatic void pvr_pds_disassemble_instruction_dout(struct pvr_dout *dout, 510bf215546Sopenharmony_ci char *instr_str, 511bf215546Sopenharmony_ci size_t instr_len) 512bf215546Sopenharmony_ci{ 513bf215546Sopenharmony_ci char src0[PVR_PDS_MAX_INST_STR_LEN]; 514bf215546Sopenharmony_ci char src1[PVR_PDS_MAX_INST_STR_LEN]; 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_ci#define X(dout_dst, str) #str, 517bf215546Sopenharmony_ci static const char *const dst[] = { PVR_PDS_DOUT_DSTS }; 518bf215546Sopenharmony_ci#undef X 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci pvr_pds_disassemble_operand(dout->src0, src0, sizeof(src0)); 521bf215546Sopenharmony_ci pvr_pds_disassemble_operand(dout->src1, src1, sizeof(src1)); 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci { 524bf215546Sopenharmony_ci snprintf(instr_str, 525bf215546Sopenharmony_ci instr_len, 526bf215546Sopenharmony_ci "%-16s%s%s = %s, %s%s", 527bf215546Sopenharmony_ci "DOUT", 528bf215546Sopenharmony_ci dout->cc ? "? " : "", 529bf215546Sopenharmony_ci dst[dout->dst], 530bf215546Sopenharmony_ci src0, 531bf215546Sopenharmony_ci src1, 532bf215546Sopenharmony_ci dout->END ? "; HALT" : ""); 533bf215546Sopenharmony_ci } 534bf215546Sopenharmony_ci} 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_civoid pvr_pds_disassemble_instruction(char *instr_str, 537bf215546Sopenharmony_ci size_t instr_len, 538bf215546Sopenharmony_ci struct pvr_instruction *instruction) 539bf215546Sopenharmony_ci{ 540bf215546Sopenharmony_ci if (!instruction) { 541bf215546Sopenharmony_ci snprintf(instr_str, 542bf215546Sopenharmony_ci instr_len, 543bf215546Sopenharmony_ci "Instruction was not disassembled properly\n"); 544bf215546Sopenharmony_ci return; 545bf215546Sopenharmony_ci } 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_ci switch (instruction->type) { 548bf215546Sopenharmony_ci case INS_LIMM: 549bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_limm((struct pvr_limm *)instruction, 550bf215546Sopenharmony_ci instr_str, 551bf215546Sopenharmony_ci instr_len); 552bf215546Sopenharmony_ci break; 553bf215546Sopenharmony_ci case INS_ADD64: 554bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_add64((struct pvr_add *)instruction, 555bf215546Sopenharmony_ci instr_str, 556bf215546Sopenharmony_ci instr_len); 557bf215546Sopenharmony_ci break; 558bf215546Sopenharmony_ci case INS_ADD32: 559bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_add32((struct pvr_add *)instruction, 560bf215546Sopenharmony_ci instr_str, 561bf215546Sopenharmony_ci instr_len); 562bf215546Sopenharmony_ci break; 563bf215546Sopenharmony_ci case INS_CMP: 564bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_cmp((struct pvr_cmp *)instruction, 565bf215546Sopenharmony_ci instr_str, 566bf215546Sopenharmony_ci instr_len); 567bf215546Sopenharmony_ci break; 568bf215546Sopenharmony_ci case INS_MAD: 569bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_mad((struct pvr_mad *)instruction, 570bf215546Sopenharmony_ci instr_str, 571bf215546Sopenharmony_ci instr_len); 572bf215546Sopenharmony_ci break; 573bf215546Sopenharmony_ci case INS_BRA: 574bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_bra((struct pvr_bra *)instruction, 575bf215546Sopenharmony_ci instr_str, 576bf215546Sopenharmony_ci instr_len); 577bf215546Sopenharmony_ci break; 578bf215546Sopenharmony_ci case INS_DDMAD: 579bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_ddmad((struct pvr_ddmad *)instruction, 580bf215546Sopenharmony_ci instr_str, 581bf215546Sopenharmony_ci instr_len); 582bf215546Sopenharmony_ci break; 583bf215546Sopenharmony_ci case INS_DOUT: 584bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_dout((struct pvr_dout *)instruction, 585bf215546Sopenharmony_ci instr_str, 586bf215546Sopenharmony_ci instr_len); 587bf215546Sopenharmony_ci break; 588bf215546Sopenharmony_ci case INS_LD: 589bf215546Sopenharmony_ci case INS_ST: 590bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_ldst((struct pvr_ldst *)instruction, 591bf215546Sopenharmony_ci instr_str, 592bf215546Sopenharmony_ci instr_len); 593bf215546Sopenharmony_ci break; 594bf215546Sopenharmony_ci case INS_WDF: 595bf215546Sopenharmony_ci pvr_pds_disassemble_simple((struct pvr_simple *)instruction, 596bf215546Sopenharmony_ci "WDF", 597bf215546Sopenharmony_ci instr_str, 598bf215546Sopenharmony_ci instr_len); 599bf215546Sopenharmony_ci break; 600bf215546Sopenharmony_ci case INS_LOCK: 601bf215546Sopenharmony_ci pvr_pds_disassemble_simple((struct pvr_simple *)instruction, 602bf215546Sopenharmony_ci "LOCK", 603bf215546Sopenharmony_ci instr_str, 604bf215546Sopenharmony_ci instr_len); 605bf215546Sopenharmony_ci break; 606bf215546Sopenharmony_ci case INS_RELEASE: 607bf215546Sopenharmony_ci pvr_pds_disassemble_simple((struct pvr_simple *)instruction, 608bf215546Sopenharmony_ci "RELEASE", 609bf215546Sopenharmony_ci instr_str, 610bf215546Sopenharmony_ci instr_len); 611bf215546Sopenharmony_ci break; 612bf215546Sopenharmony_ci case INS_HALT: 613bf215546Sopenharmony_ci pvr_pds_disassemble_simple((struct pvr_simple *)instruction, 614bf215546Sopenharmony_ci "HALT", 615bf215546Sopenharmony_ci instr_str, 616bf215546Sopenharmony_ci instr_len); 617bf215546Sopenharmony_ci break; 618bf215546Sopenharmony_ci case INS_NOP: 619bf215546Sopenharmony_ci pvr_pds_disassemble_simple((struct pvr_simple *)instruction, 620bf215546Sopenharmony_ci "NOP", 621bf215546Sopenharmony_ci instr_str, 622bf215546Sopenharmony_ci instr_len); 623bf215546Sopenharmony_ci break; 624bf215546Sopenharmony_ci case INS_SFTLP32: 625bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_sftlp32((struct pvr_sftlp *)instruction, 626bf215546Sopenharmony_ci instr_str, 627bf215546Sopenharmony_ci instr_len); 628bf215546Sopenharmony_ci break; 629bf215546Sopenharmony_ci case INS_SFTLP64: 630bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_sftlp64((struct pvr_sftlp *)instruction, 631bf215546Sopenharmony_ci instr_str, 632bf215546Sopenharmony_ci instr_len); 633bf215546Sopenharmony_ci break; 634bf215546Sopenharmony_ci case INS_STM: 635bf215546Sopenharmony_ci pvr_pds_disassemble_instruction_stm((struct pvr_stm *)instruction, 636bf215546Sopenharmony_ci instr_str, 637bf215546Sopenharmony_ci instr_len); 638bf215546Sopenharmony_ci break; 639bf215546Sopenharmony_ci case INS_STMC: 640bf215546Sopenharmony_ci pds_disassemble_instruction_stmc((struct pvr_stmc *)instruction, 641bf215546Sopenharmony_ci instr_str, 642bf215546Sopenharmony_ci instr_len); 643bf215546Sopenharmony_ci break; 644bf215546Sopenharmony_ci default: 645bf215546Sopenharmony_ci snprintf(instr_str, instr_len, "Printing not implemented\n"); 646bf215546Sopenharmony_ci break; 647bf215546Sopenharmony_ci } 648bf215546Sopenharmony_ci} 649bf215546Sopenharmony_ci 650bf215546Sopenharmony_ci#if defined(DUMP_PDS) 651bf215546Sopenharmony_civoid pvr_pds_print_instruction(uint32_t instr) 652bf215546Sopenharmony_ci{ 653bf215546Sopenharmony_ci char instruction_str[1024]; 654bf215546Sopenharmony_ci struct pvr_instruction *decoded = 655bf215546Sopenharmony_ci pvr_pds_disassemble_instruction2(0, 0, instr); 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ci if (!decoded) { 658bf215546Sopenharmony_ci mesa_logd("%X\n", instr); 659bf215546Sopenharmony_ci } else { 660bf215546Sopenharmony_ci pvr_pds_disassemble_instruction(instruction_str, 661bf215546Sopenharmony_ci sizeof(instruction_str), 662bf215546Sopenharmony_ci decoded); 663bf215546Sopenharmony_ci mesa_logd("\t0x%08x, /* %s */\n", instr, instruction_str); 664bf215546Sopenharmony_ci } 665bf215546Sopenharmony_ci} 666bf215546Sopenharmony_ci#endif 667