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#include <assert.h> 30 31#include "main/glheader.h" 32 33#include "i915_reg.h" 34#include "i915_debug.h" 35#include "main/glheader.h" 36 37static const char *opcodes[0x20] = { 38 "NOP", 39 "ADD", 40 "MOV", 41 "MUL", 42 "MAD", 43 "DP2ADD", 44 "DP3", 45 "DP4", 46 "FRC", 47 "RCP", 48 "RSQ", 49 "EXP", 50 "LOG", 51 "CMP", 52 "MIN", 53 "MAX", 54 "FLR", 55 "MOD", 56 "TRC", 57 "SGE", 58 "SLT", 59 "TEXLD", 60 "TEXLDP", 61 "TEXLDB", 62 "TEXKILL", 63 "DCL", 64 "0x1a", 65 "0x1b", 66 "0x1c", 67 "0x1d", 68 "0x1e", 69 "0x1f", 70}; 71 72 73static const int args[0x20] = { 74 0, /* 0 nop */ 75 2, /* 1 add */ 76 1, /* 2 mov */ 77 2, /* 3 m ul */ 78 3, /* 4 mad */ 79 3, /* 5 dp2add */ 80 2, /* 6 dp3 */ 81 2, /* 7 dp4 */ 82 1, /* 8 frc */ 83 1, /* 9 rcp */ 84 1, /* a rsq */ 85 1, /* b exp */ 86 1, /* c log */ 87 3, /* d cmp */ 88 2, /* e min */ 89 2, /* f max */ 90 1, /* 10 flr */ 91 1, /* 11 mod */ 92 1, /* 12 trc */ 93 2, /* 13 sge */ 94 2, /* 14 slt */ 95 1, 96 1, 97 1, 98 1, 99 0, 100 0, 101 0, 102 0, 103 0, 104 0, 105 0, 106}; 107 108 109static const char *regname[0x8] = { 110 "R", 111 "T", 112 "CONST", 113 "S", 114 "OC", 115 "OD", 116 "U", 117 "UNKNOWN", 118}; 119 120static void 121print_reg_type_nr(GLuint type, GLuint nr) 122{ 123 switch (type) { 124 case REG_TYPE_T: 125 switch (nr) { 126 case T_DIFFUSE: 127 printf("T_DIFFUSE"); 128 return; 129 case T_SPECULAR: 130 printf("T_SPECULAR"); 131 return; 132 case T_FOG_W: 133 printf("T_FOG_W"); 134 return; 135 default: 136 printf("T_TEX%d", nr); 137 return; 138 } 139 case REG_TYPE_OC: 140 if (nr == 0) { 141 printf("oC"); 142 return; 143 } 144 break; 145 case REG_TYPE_OD: 146 if (nr == 0) { 147 printf("oD"); 148 return; 149 } 150 break; 151 default: 152 break; 153 } 154 155 printf("%s[%d]", regname[type], nr); 156} 157 158#define REG_SWIZZLE_MASK 0x7777 159#define REG_NEGATE_MASK 0x8888 160 161#define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \ 162 (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \ 163 (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \ 164 (SRC_W << A2_SRC2_CHANNEL_W_SHIFT)) 165 166 167static void 168print_reg_neg_swizzle(GLuint reg) 169{ 170 int i; 171 172 if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW && 173 (reg & REG_NEGATE_MASK) == 0) 174 return; 175 176 printf("."); 177 178 for (i = 3; i >= 0; i--) { 179 if (reg & (1 << ((i * 4) + 3))) 180 printf("-"); 181 182 switch ((reg >> (i * 4)) & 0x7) { 183 case 0: 184 printf("x"); 185 break; 186 case 1: 187 printf("y"); 188 break; 189 case 2: 190 printf("z"); 191 break; 192 case 3: 193 printf("w"); 194 break; 195 case 4: 196 printf("0"); 197 break; 198 case 5: 199 printf("1"); 200 break; 201 default: 202 printf("?"); 203 break; 204 } 205 } 206} 207 208 209static void 210print_src_reg(GLuint dword) 211{ 212 GLuint nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK; 213 GLuint type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK; 214 print_reg_type_nr(type, nr); 215 print_reg_neg_swizzle(dword); 216} 217 218 219static void 220print_dest_reg(GLuint dword) 221{ 222 GLuint nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK; 223 GLuint type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK; 224 print_reg_type_nr(type, nr); 225 if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL) 226 return; 227 printf("."); 228 if (dword & A0_DEST_CHANNEL_X) 229 printf("x"); 230 if (dword & A0_DEST_CHANNEL_Y) 231 printf("y"); 232 if (dword & A0_DEST_CHANNEL_Z) 233 printf("z"); 234 if (dword & A0_DEST_CHANNEL_W) 235 printf("w"); 236} 237 238 239#define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT)) 240#define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT)) 241#define GET_SRC2_REG(r) (r) 242 243 244static void 245print_arith_op(GLuint opcode, const GLuint * program) 246{ 247 if (opcode != A0_NOP) { 248 print_dest_reg(program[0]); 249 if (program[0] & A0_DEST_SATURATE) 250 printf(" = SATURATE "); 251 else 252 printf(" = "); 253 } 254 255 printf("%s ", opcodes[opcode]); 256 257 print_src_reg(GET_SRC0_REG(program[0], program[1])); 258 if (args[opcode] == 1) { 259 printf("\n"); 260 return; 261 } 262 263 printf(", "); 264 print_src_reg(GET_SRC1_REG(program[1], program[2])); 265 if (args[opcode] == 2) { 266 printf("\n"); 267 return; 268 } 269 270 printf(", "); 271 print_src_reg(GET_SRC2_REG(program[2])); 272 printf("\n"); 273 return; 274} 275 276 277static void 278print_tex_op(GLuint opcode, const GLuint * program) 279{ 280 print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); 281 printf(" = "); 282 283 printf("%s ", opcodes[opcode]); 284 285 printf("S[%d],", program[0] & T0_SAMPLER_NR_MASK); 286 287 print_reg_type_nr((program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) & 288 REG_TYPE_MASK, 289 (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK); 290 printf("\n"); 291} 292 293static void 294print_dcl_op(GLuint opcode, const GLuint * program) 295{ 296 printf("%s ", opcodes[opcode]); 297 print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); 298 printf("\n"); 299} 300 301 302void 303i915_disassemble_program(const GLuint * program, GLuint sz) 304{ 305 GLint i; 306 307 printf("\t\tBEGIN\n"); 308 309 assert((program[0] & 0x1ff) + 2 == sz); 310 311 program++; 312 for (i = 1; i < sz; i += 3, program += 3) { 313 GLuint opcode = program[0] & (0x1f << 24); 314 315 printf("\t\t"); 316 317 if ((GLint) opcode >= A0_NOP && opcode <= A0_SLT) 318 print_arith_op(opcode >> 24, program); 319 else if (opcode >= T0_TEXLD && opcode <= T0_TEXKILL) 320 print_tex_op(opcode >> 24, program); 321 else if (opcode == D0_DCL) 322 print_dcl_op(opcode >> 24, program); 323 else 324 printf("Unknown opcode 0x%x\n", opcode); 325 } 326 327 printf("\t\tEND\n\n"); 328} 329 330 331