00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "i915_reg.h"
00030 #include "i915_debug.h"
00031 #include "pipe/p_winsys.h"
00032 #include "util/u_memory.h"
00033
00034
00035 static void
00036 PRINTF(
00037 struct debug_stream *stream,
00038 const char *fmt,
00039 ... )
00040 {
00041 va_list args;
00042
00043 va_start( args, fmt );
00044 debug_vprintf( fmt, args );
00045 va_end( args );
00046 }
00047
00048
00049 static const char *opcodes[0x20] = {
00050 "NOP",
00051 "ADD",
00052 "MOV",
00053 "MUL",
00054 "MAD",
00055 "DP2ADD",
00056 "DP3",
00057 "DP4",
00058 "FRC",
00059 "RCP",
00060 "RSQ",
00061 "EXP",
00062 "LOG",
00063 "CMP",
00064 "MIN",
00065 "MAX",
00066 "FLR",
00067 "MOD",
00068 "TRC",
00069 "SGE",
00070 "SLT",
00071 "TEXLD",
00072 "TEXLDP",
00073 "TEXLDB",
00074 "TEXKILL",
00075 "DCL",
00076 "0x1a",
00077 "0x1b",
00078 "0x1c",
00079 "0x1d",
00080 "0x1e",
00081 "0x1f",
00082 };
00083
00084
00085 static const int args[0x20] = {
00086 0,
00087 2,
00088 1,
00089 2,
00090 3,
00091 3,
00092 2,
00093 2,
00094 1,
00095 1,
00096 1,
00097 1,
00098 1,
00099 3,
00100 2,
00101 2,
00102 1,
00103 1,
00104 1,
00105 2,
00106 2,
00107 1,
00108 1,
00109 1,
00110 1,
00111 0,
00112 0,
00113 0,
00114 0,
00115 0,
00116 0,
00117 0,
00118 };
00119
00120
00121 static const char *regname[0x8] = {
00122 "R",
00123 "T",
00124 "CONST",
00125 "S",
00126 "OC",
00127 "OD",
00128 "U",
00129 "UNKNOWN",
00130 };
00131
00132 static void
00133 print_reg_type_nr(struct debug_stream *stream, unsigned type, unsigned nr)
00134 {
00135 switch (type) {
00136 case REG_TYPE_T:
00137 switch (nr) {
00138 case T_DIFFUSE:
00139 PRINTF(stream, "T_DIFFUSE");
00140 return;
00141 case T_SPECULAR:
00142 PRINTF(stream, "T_SPECULAR");
00143 return;
00144 case T_FOG_W:
00145 PRINTF(stream, "T_FOG_W");
00146 return;
00147 default:
00148 PRINTF(stream, "T_TEX%d", nr);
00149 return;
00150 }
00151 case REG_TYPE_OC:
00152 if (nr == 0) {
00153 PRINTF(stream, "oC");
00154 return;
00155 }
00156 break;
00157 case REG_TYPE_OD:
00158 if (nr == 0) {
00159 PRINTF(stream, "oD");
00160 return;
00161 }
00162 break;
00163 default:
00164 break;
00165 }
00166
00167 PRINTF(stream, "%s[%d]", regname[type], nr);
00168 }
00169
00170 #define REG_SWIZZLE_MASK 0x7777
00171 #define REG_NEGATE_MASK 0x8888
00172
00173 #define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \
00174 (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \
00175 (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \
00176 (SRC_W << A2_SRC2_CHANNEL_W_SHIFT))
00177
00178
00179 static void
00180 print_reg_neg_swizzle(struct debug_stream *stream, unsigned reg)
00181 {
00182 int i;
00183
00184 if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW &&
00185 (reg & REG_NEGATE_MASK) == 0)
00186 return;
00187
00188 PRINTF(stream, ".");
00189
00190 for (i = 3; i >= 0; i--) {
00191 if (reg & (1 << ((i * 4) + 3)))
00192 PRINTF(stream, "-");
00193
00194 switch ((reg >> (i * 4)) & 0x7) {
00195 case 0:
00196 PRINTF(stream, "x");
00197 break;
00198 case 1:
00199 PRINTF(stream, "y");
00200 break;
00201 case 2:
00202 PRINTF(stream, "z");
00203 break;
00204 case 3:
00205 PRINTF(stream, "w");
00206 break;
00207 case 4:
00208 PRINTF(stream, "0");
00209 break;
00210 case 5:
00211 PRINTF(stream, "1");
00212 break;
00213 default:
00214 PRINTF(stream, "?");
00215 break;
00216 }
00217 }
00218 }
00219
00220
00221 static void
00222 print_src_reg(struct debug_stream *stream, unsigned dword)
00223 {
00224 unsigned nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK;
00225 unsigned type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK;
00226 print_reg_type_nr(stream, type, nr);
00227 print_reg_neg_swizzle(stream, dword);
00228 }
00229
00230
00231 static void
00232 print_dest_reg(struct debug_stream *stream, unsigned dword)
00233 {
00234 unsigned nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK;
00235 unsigned type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK;
00236 print_reg_type_nr(stream, type, nr);
00237 if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL)
00238 return;
00239 PRINTF(stream, ".");
00240 if (dword & A0_DEST_CHANNEL_X)
00241 PRINTF(stream, "x");
00242 if (dword & A0_DEST_CHANNEL_Y)
00243 PRINTF(stream, "y");
00244 if (dword & A0_DEST_CHANNEL_Z)
00245 PRINTF(stream, "z");
00246 if (dword & A0_DEST_CHANNEL_W)
00247 PRINTF(stream, "w");
00248 }
00249
00250
00251 #define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT))
00252 #define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT))
00253 #define GET_SRC2_REG(r) (r)
00254
00255
00256 static void
00257 print_arith_op(struct debug_stream *stream,
00258 unsigned opcode, const unsigned * program)
00259 {
00260 if (opcode != A0_NOP) {
00261 print_dest_reg(stream, program[0]);
00262 if (program[0] & A0_DEST_SATURATE)
00263 PRINTF(stream, " = SATURATE ");
00264 else
00265 PRINTF(stream, " = ");
00266 }
00267
00268 PRINTF(stream, "%s ", opcodes[opcode]);
00269
00270 print_src_reg(stream, GET_SRC0_REG(program[0], program[1]));
00271 if (args[opcode] == 1) {
00272 PRINTF(stream, "\n");
00273 return;
00274 }
00275
00276 PRINTF(stream, ", ");
00277 print_src_reg(stream, GET_SRC1_REG(program[1], program[2]));
00278 if (args[opcode] == 2) {
00279 PRINTF(stream, "\n");
00280 return;
00281 }
00282
00283 PRINTF(stream, ", ");
00284 print_src_reg(stream, GET_SRC2_REG(program[2]));
00285 PRINTF(stream, "\n");
00286 return;
00287 }
00288
00289
00290 static void
00291 print_tex_op(struct debug_stream *stream,
00292 unsigned opcode, const unsigned * program)
00293 {
00294 print_dest_reg(stream, program[0] | A0_DEST_CHANNEL_ALL);
00295 PRINTF(stream, " = ");
00296
00297 PRINTF(stream, "%s ", opcodes[opcode]);
00298
00299 PRINTF(stream, "S[%d],", program[0] & T0_SAMPLER_NR_MASK);
00300
00301 print_reg_type_nr(stream,
00302 (program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) &
00303 REG_TYPE_MASK,
00304 (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK);
00305 PRINTF(stream, "\n");
00306 }
00307
00308 static void
00309 print_texkil_op(struct debug_stream *stream,
00310 unsigned opcode, const unsigned * program)
00311 {
00312 PRINTF(stream, "TEXKIL ");
00313
00314 print_reg_type_nr(stream,
00315 (program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) &
00316 REG_TYPE_MASK,
00317 (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK);
00318 PRINTF(stream, "\n");
00319 }
00320
00321 static void
00322 print_dcl_op(struct debug_stream *stream,
00323 unsigned opcode, const unsigned * program)
00324 {
00325 PRINTF(stream, "%s ", opcodes[opcode]);
00326 print_dest_reg(stream,
00327 program[0] | A0_DEST_CHANNEL_ALL);
00328 PRINTF(stream, "\n");
00329 }
00330
00331
00332 void
00333 i915_disassemble_program(struct debug_stream *stream,
00334 const unsigned * program, unsigned sz)
00335 {
00336 unsigned i;
00337
00338 PRINTF(stream, "\t\tBEGIN\n");
00339
00340 assert((program[0] & 0x1ff) + 2 == sz);
00341
00342 program++;
00343 for (i = 1; i < sz; i += 3, program += 3) {
00344 unsigned opcode = program[0] & (0x1f << 24);
00345
00346 PRINTF(stream, "\t\t");
00347
00348 if ((int) opcode >= A0_NOP && opcode <= A0_SLT)
00349 print_arith_op(stream, opcode >> 24, program);
00350 else if (opcode >= T0_TEXLD && opcode < T0_TEXKILL)
00351 print_tex_op(stream, opcode >> 24, program);
00352 else if (opcode == T0_TEXKILL)
00353 print_texkil_op(stream, opcode >> 24, program);
00354 else if (opcode == D0_DCL)
00355 print_dcl_op(stream, opcode >> 24, program);
00356 else
00357 PRINTF(stream, "Unknown opcode 0x%x\n", opcode);
00358 }
00359
00360 PRINTF(stream, "\t\tEND\n\n");
00361 }
00362
00363