1 /************************************************************************** 2 * 3 * Copyright 2003 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #include <stdio.h> 29 30 #include "i915_reg.h" 31 #include "i915_debug.h" 32 #include "main/imports.h" 33 34 static const char *opcodes[0x20] = { 35 "NOP", 36 "ADD", 37 "MOV", 38 "MUL", 39 "MAD", 40 "DP2ADD", 41 "DP3", 42 "DP4", 43 "FRC", 44 "RCP", 45 "RSQ", 46 "EXP", 47 "LOG", 48 "CMP", 49 "MIN", 50 "MAX", 51 "FLR", 52 "MOD", 53 "TRC", 54 "SGE", 55 "SLT", 56 "TEXLD", 57 "TEXLDP", 58 "TEXLDB", 59 "TEXKILL", 60 "DCL", 61 "0x1a", 62 "0x1b", 63 "0x1c", 64 "0x1d", 65 "0x1e", 66 "0x1f", 67 }; 68 69 70 static const int args[0x20] = { 71 0, /* 0 nop */ 72 2, /* 1 add */ 73 1, /* 2 mov */ 74 2, /* 3 m ul */ 75 3, /* 4 mad */ 76 3, /* 5 dp2add */ 77 2, /* 6 dp3 */ 78 2, /* 7 dp4 */ 79 1, /* 8 frc */ 80 1, /* 9 rcp */ 81 1, /* a rsq */ 82 1, /* b exp */ 83 1, /* c log */ 84 3, /* d cmp */ 85 2, /* e min */ 86 2, /* f max */ 87 1, /* 10 flr */ 88 1, /* 11 mod */ 89 1, /* 12 trc */ 90 2, /* 13 sge */ 91 2, /* 14 slt */ 92 1, 93 1, 94 1, 95 1, 96 0, 97 0, 98 0, 99 0, 100 0, 101 0, 102 0, 103 }; 104 105 106 static const char *regname[0x8] = { 107 "R", 108 "T", 109 "CONST", 110 "S", 111 "OC", 112 "OD", 113 "U", 114 "UNKNOWN", 115 }; 116 117 static void 118 print_reg_type_nr(GLuint type, GLuint nr) 119 { 120 switch (type) { 121 case REG_TYPE_T: 122 switch (nr) { 123 case T_DIFFUSE: 124 printf("T_DIFFUSE"); 125 return; 126 case T_SPECULAR: 127 printf("T_SPECULAR"); 128 return; 129 case T_FOG_W: 130 printf("T_FOG_W"); 131 return; 132 default: 133 printf("T_TEX%d", nr); 134 return; 135 } 136 case REG_TYPE_OC: 137 if (nr == 0) { 138 printf("oC"); 139 return; 140 } 141 break; 142 case REG_TYPE_OD: 143 if (nr == 0) { 144 printf("oD"); 145 return; 146 } 147 break; 148 default: 149 break; 150 } 151 152 printf("%s[%d]", regname[type], nr); 153 } 154 155 #define REG_SWIZZLE_MASK 0x7777 156 #define REG_NEGATE_MASK 0x8888 157 158 #define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \ 159 (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \ 160 (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \ 161 (SRC_W << A2_SRC2_CHANNEL_W_SHIFT)) 162 163 164 static void 165 print_reg_neg_swizzle(GLuint reg) 166 { 167 int i; 168 169 if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW && 170 (reg & REG_NEGATE_MASK) == 0) 171 return; 172 173 printf("."); 174 175 for (i = 3; i >= 0; i--) { 176 if (reg & (1 << ((i * 4) + 3))) 177 printf("-"); 178 179 switch ((reg >> (i * 4)) & 0x7) { 180 case 0: 181 printf("x"); 182 break; 183 case 1: 184 printf("y"); 185 break; 186 case 2: 187 printf("z"); 188 break; 189 case 3: 190 printf("w"); 191 break; 192 case 4: 193 printf("0"); 194 break; 195 case 5: 196 printf("1"); 197 break; 198 default: 199 printf("?"); 200 break; 201 } 202 } 203 } 204 205 206 static void 207 print_src_reg(GLuint dword) 208 { 209 GLuint nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK; 210 GLuint type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK; 211 print_reg_type_nr(type, nr); 212 print_reg_neg_swizzle(dword); 213 } 214 215 216 static void 217 print_dest_reg(GLuint dword) 218 { 219 GLuint nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK; 220 GLuint type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK; 221 print_reg_type_nr(type, nr); 222 if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL) 223 return; 224 printf("."); 225 if (dword & A0_DEST_CHANNEL_X) 226 printf("x"); 227 if (dword & A0_DEST_CHANNEL_Y) 228 printf("y"); 229 if (dword & A0_DEST_CHANNEL_Z) 230 printf("z"); 231 if (dword & A0_DEST_CHANNEL_W) 232 printf("w"); 233 } 234 235 236 #define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT)) 237 #define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT)) 238 #define GET_SRC2_REG(r) (r) 239 240 241 static void 242 print_arith_op(GLuint opcode, const GLuint * program) 243 { 244 if (opcode != A0_NOP) { 245 print_dest_reg(program[0]); 246 if (program[0] & A0_DEST_SATURATE) 247 printf(" = SATURATE "); 248 else 249 printf(" = "); 250 } 251 252 printf("%s ", opcodes[opcode]); 253 254 print_src_reg(GET_SRC0_REG(program[0], program[1])); 255 if (args[opcode] == 1) { 256 printf("\n"); 257 return; 258 } 259 260 printf(", "); 261 print_src_reg(GET_SRC1_REG(program[1], program[2])); 262 if (args[opcode] == 2) { 263 printf("\n"); 264 return; 265 } 266 267 printf(", "); 268 print_src_reg(GET_SRC2_REG(program[2])); 269 printf("\n"); 270 return; 271 } 272 273 274 static void 275 print_tex_op(GLuint opcode, const GLuint * program) 276 { 277 print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); 278 printf(" = "); 279 280 printf("%s ", opcodes[opcode]); 281 282 printf("S[%d],", program[0] & T0_SAMPLER_NR_MASK); 283 284 print_reg_type_nr((program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) & 285 REG_TYPE_MASK, 286 (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK); 287 printf("\n"); 288 } 289 290 static void 291 print_dcl_op(GLuint opcode, const GLuint * program) 292 { 293 printf("%s ", opcodes[opcode]); 294 print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); 295 printf("\n"); 296 } 297 298 299 void 300 i915_disassemble_program(const GLuint * program, GLuint sz) 301 { 302 GLint i; 303 304 printf("\t\tBEGIN\n"); 305 306 assert((program[0] & 0x1ff) + 2 == sz); 307 308 program++; 309 for (i = 1; i < sz; i += 3, program += 3) { 310 GLuint opcode = program[0] & (0x1f << 24); 311 312 printf("\t\t"); 313 314 if ((GLint) opcode >= A0_NOP && opcode <= A0_SLT) 315 print_arith_op(opcode >> 24, program); 316 else if (opcode >= T0_TEXLD && opcode <= T0_TEXKILL) 317 print_tex_op(opcode >> 24, program); 318 else if (opcode == D0_DCL) 319 print_dcl_op(opcode >> 24, program); 320 else 321 printf("Unknown opcode 0x%x\n", opcode); 322 } 323 324 printf("\t\tEND\n\n"); 325 } 326 327 328