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 #ifndef PVR_ROGUE_PDS_DISASM_H 25 #define PVR_ROGUE_PDS_DISASM_H 26 27 #include <stdbool.h> 28 #include <stdint.h> 29 30 #include "util/log.h" 31 32 /* Type of operand for an instruction. */ 33 #define PVR_PDS_OPERAND_TYPES \ 34 X(TEMP32, temp, 32) \ 35 X(PTEMP32, ptemp, 32) \ 36 X(CONST32, const, 32) \ 37 X(TEMP64, temp, 64) \ 38 X(PTEMP64, ptemp, 64) \ 39 X(CONST64, const, 64) \ 40 X(UNRESOLVED, UNRESOLVED, 0) \ 41 X(LITERAL_NUM, literal, 0) 42 43 #define X(enum, str, size) enum, 44 enum pvr_operand_type { PVR_PDS_OPERAND_TYPES }; 45 #undef X 46 47 #if defined(DUMP_PDS) 48 # define PVR_PDS_PRINT_INST(X) pvr_pds_print_instruction(X) 49 # define PVR_PDS_PRINT_DATA(X, Y, Z) \ 50 mesa_logd("\t%s : DATA = 0x%lX ADDRESS = 0x%X\n", X, (uint64_t)(Y), Z) 51 #else 52 # define PVR_PDS_PRINT_INST(X) 53 # define PVR_PDS_PRINT_DATA(X, Y, Z) 54 #endif 55 56 #define PVR_INSTRUCTION_STMP 57 #define PVR_INSTRUCTION_IDIV 58 #define PVR_INSTRUCTION_AA 59 #define PVR_INSTRUCTION_POL 60 #define PVR_INSTRUCTION_IDF 61 62 #define PVR_INSTRUCTIONS \ 63 X(STM) \ 64 PVR_INSTRUCTION_STMP \ 65 PVR_INSTRUCTION_IDIV \ 66 PVR_INSTRUCTION_AA \ 67 PVR_INSTRUCTION_IDF \ 68 PVR_INSTRUCTION_POL \ 69 X(STMC) \ 70 X(LD) \ 71 X(ST) \ 72 X(ADD32) \ 73 X(ADD64) \ 74 X(MAD) \ 75 X(DDMAD) \ 76 X(DOUT) \ 77 X(CMP) \ 78 X(BRA) \ 79 X(LIMM) \ 80 X(SFTLP32) \ 81 X(SFTLP64) \ 82 X(WDF) \ 83 X(LOCK) \ 84 X(RELEASE) \ 85 X(HALT) \ 86 X(NOP) 87 88 #define X(a) INS_##a, 89 enum pvr_instruction_type { PVR_INSTRUCTIONS }; 90 #undef X 91 92 struct pvr_predicate { 93 uint32_t predicate; 94 bool negate; 95 }; 96 97 struct pvr_instruction; 98 99 /* Operands are either sources or dst of an instruction. */ 100 struct pvr_operand { 101 enum pvr_operand_type type; 102 103 struct pvr_instruction *instruction; 104 uint64_t literal; /* Literal value if type == LITERAL_NUM */ 105 int address; /* Address in word-sizes. */ 106 unsigned absolute_address; /* Address in segment, */ 107 unsigned index; /* Index within instruction, 0 = dst, 1 = src0 .. */ 108 bool negate; /* True if the literal is negative. */ 109 }; 110 111 #define PVR_PDS_LOP \ 112 X(LOP_NONE, none) \ 113 X(LOP_NOT, ~) \ 114 X(LOP_AND, &) \ 115 X(LOP_OR, |) \ 116 X(LOP_XOR, xor) \ 117 X(LOP_XNOR, xnor) \ 118 X(LOP_NAND, nand) \ 119 X(LOP_NOR, nor) 120 121 #define X(lop, str) lop, 122 enum pvr_pds_lop { PVR_PDS_LOP }; 123 #undef X 124 125 #define PVR_PDS_DOUT_DSTS \ 126 X(DOUT_D, doutd) \ 127 X(DOUT_W, doutw) \ 128 X(DOUT_U, doutu) \ 129 X(DOUT_V, doutv) \ 130 X(DOUT_I, douti) \ 131 X(DOUT_C, doutc) \ 132 X(DOUT_R, doutr) \ 133 X(DOUT_INVALID0, invalid) 134 135 #define X(dout_dst, str) dout_dst, 136 enum pvr_dout_type { PVR_PDS_DOUT_DSTS }; 137 #undef X 138 139 #define PVR_PDS_MAX_INST_STR_LEN 256 140 141 enum pvr_cop { COP_EQ, COP_GT, COP_LT, COP_NE }; 142 143 struct pvr_instruction { 144 enum pvr_instruction_type type; 145 struct pvr_instruction *next; 146 }; 147 148 struct pvr_add { 149 struct pvr_instruction instruction; 150 struct pvr_operand *dst; 151 struct pvr_operand *src1; 152 struct pvr_operand *src0; 153 bool cc; 154 bool sna; 155 bool alum; 156 }; 157 158 struct pvr_simple { 159 struct pvr_instruction instruction; 160 bool cc; 161 }; 162 163 struct pvr_ldst { 164 struct pvr_instruction instruction; 165 bool cc; 166 struct pvr_operand *src0; 167 bool st; 168 }; 169 170 struct pvr_mad { 171 struct pvr_instruction instruction; 172 struct pvr_operand *dst; 173 struct pvr_operand *src0; 174 struct pvr_operand *src1; 175 struct pvr_operand *src2; 176 bool cc; 177 bool sna; 178 bool alum; 179 }; 180 181 struct pvr_stm { 182 struct pvr_instruction instruction; 183 struct pvr_operand *src0; 184 struct pvr_operand *src1; 185 struct pvr_operand *src2; 186 struct pvr_operand *src3; 187 unsigned stream_out; 188 bool tst; 189 bool cc; 190 bool ccs_global; 191 bool ccs_so; 192 }; 193 194 struct pvr_stmc { 195 struct pvr_instruction instruction; 196 struct pvr_operand *src0; 197 bool cc; 198 }; 199 200 struct pvr_bra { 201 struct pvr_instruction instruction; 202 struct pvr_predicate *srcc; 203 struct pvr_predicate *setc; /* negate ignored */ 204 char *target; 205 signed address; /* signed relative address */ 206 }; 207 208 struct pvr_dout { 209 struct pvr_instruction instruction; 210 struct pvr_operand *src0; 211 struct pvr_operand *src1; 212 enum pvr_dout_type dst; 213 bool cc; 214 bool END; 215 }; 216 217 struct pvr_ddmad { 218 struct pvr_instruction instruction; 219 struct pvr_operand *src0; 220 struct pvr_operand *src1; 221 struct pvr_operand *src2; 222 struct pvr_operand *src3; 223 bool cc; 224 bool END; 225 }; 226 227 struct pvr_sftlp { 228 struct pvr_instruction instruction; 229 enum pvr_pds_lop lop; 230 struct pvr_operand *dst; 231 struct pvr_operand *src0; 232 struct pvr_operand *src1; 233 struct pvr_operand *src2; 234 bool cc; 235 bool IM; 236 }; 237 238 struct pvr_limm { 239 struct pvr_instruction instruction; 240 bool cc; 241 bool GR; 242 struct pvr_operand *dst; 243 struct pvr_operand *src0; 244 }; 245 246 struct pvr_cmp { 247 struct pvr_instruction instruction; 248 enum pvr_cop cop; 249 bool IM; 250 bool cc; 251 struct pvr_operand *src0; 252 struct pvr_operand *src1; 253 }; 254 255 #define PVR_PDS_ERR_PARAM_RANGE 0 /* Error when register is out of range. */ 256 #define PVR_PDS_ERR_SP_UNKNOWN \ 257 1 /* Error when opcode for sp instruction is unknown. */ 258 259 struct pvr_dissassembler_error { 260 uint32_t type; /* One of PDS_ERR_* */ 261 enum pvr_instruction_type instruction; /* The type of instruction where 262 the error occurred. */ 263 char *text; /* A string representation of the error. */ 264 uint32_t parameter; /* The parameter of the instruction, 0 = dst, 265 1 = src0.. */ 266 uint32_t raw; /* The raw value that caused the error. */ 267 268 void *context; /* The passed in context. */ 269 }; 270 271 /* Callback when an error happens. */ 272 typedef void (*PVR_ERR_CALLBACK)(struct pvr_dissassembler_error); 273 274 void pvr_pds_free_instruction(struct pvr_instruction *inst); 275 struct pvr_instruction * 276 pvr_pds_disassemble_instruction2(void *context, 277 PVR_ERR_CALLBACK error_call_back, 278 uint32_t instruction); 279 void pvr_pds_disassemble_instruction(char *buffer, 280 size_t instr_len, 281 struct pvr_instruction *instruction); 282 283 #if defined(DUMP_PDS) 284 void pvr_pds_print_instruction(uint32_t instr); 285 #endif 286 287 #endif /* PVR_ROGUE_PDS_DISASM_H */ 288