3fbdb30acff45be434f21c761629829dc64f2a5c
[mesa.git] / src / mesa / drivers / dri / r300 / r500_fragprog.c
1 /*
2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28 #include "r500_fragprog.h"
29
30 #include "radeon_nqssadce.h"
31 #include "radeon_program_alu.h"
32
33
34 /**
35 * Transform TEX, TXP, TXB, and KIL instructions in the following way:
36 * - premultiply texture coordinates for RECT
37 * - extract operand swizzles
38 * - introduce a temporary register when write masks are needed
39 *
40 */
41 static GLboolean transform_TEX(
42 struct radeon_transform_context *t,
43 struct prog_instruction* orig_inst, void* data)
44 {
45 struct r500_fragment_program_compiler *compiler =
46 (struct r500_fragment_program_compiler*)data;
47 struct prog_instruction inst = *orig_inst;
48 struct prog_instruction* tgt;
49 GLboolean destredirect = GL_FALSE;
50
51 if (inst.Opcode != OPCODE_TEX &&
52 inst.Opcode != OPCODE_TXB &&
53 inst.Opcode != OPCODE_TXP &&
54 inst.Opcode != OPCODE_KIL)
55 return GL_FALSE;
56
57 /* ARB_shadow & EXT_shadow_funcs */
58 if (inst.Opcode != OPCODE_KIL &&
59 t->Program->ShadowSamplers & (1 << inst.TexSrcUnit)) {
60 GLuint comparefunc = GL_NEVER + compiler->fp->state.unit[inst.TexSrcUnit].texture_compare_func;
61
62 if (comparefunc == GL_NEVER || comparefunc == GL_ALWAYS) {
63 tgt = radeonAppendInstructions(t->Program, 1);
64
65 tgt->Opcode = OPCODE_MOV;
66 tgt->DstReg.File = inst.DstReg.File;
67 tgt->DstReg.Index = inst.DstReg.Index;
68 tgt->DstReg.WriteMask = inst.DstReg.WriteMask;
69 tgt->SrcReg[0].File = PROGRAM_BUILTIN;
70 tgt->SrcReg[0].Swizzle = comparefunc == GL_ALWAYS ? SWIZZLE_1111 : SWIZZLE_0000;
71 return GL_TRUE;
72 }
73
74 inst.DstReg.File = PROGRAM_TEMPORARY;
75 inst.DstReg.Index = radeonFindFreeTemporary(t);
76 inst.DstReg.WriteMask = WRITEMASK_XYZW;
77 } else if (inst.Opcode != OPCODE_KIL && inst.DstReg.File != PROGRAM_TEMPORARY) {
78 int tempreg = radeonFindFreeTemporary(t);
79
80 inst.DstReg.File = PROGRAM_TEMPORARY;
81 inst.DstReg.Index = tempreg;
82 inst.DstReg.WriteMask = WRITEMASK_XYZW;
83 destredirect = GL_TRUE;
84 }
85
86 tgt = radeonAppendInstructions(t->Program, 1);
87 _mesa_copy_instructions(tgt, &inst, 1);
88
89 if (inst.Opcode != OPCODE_KIL &&
90 t->Program->ShadowSamplers & (1 << inst.TexSrcUnit)) {
91 GLuint comparefunc = GL_NEVER + compiler->fp->state.unit[inst.TexSrcUnit].texture_compare_func;
92 GLuint depthmode = compiler->fp->state.unit[inst.TexSrcUnit].depth_texture_mode;
93 int rcptemp = radeonFindFreeTemporary(t);
94
95 tgt = radeonAppendInstructions(t->Program, 3);
96
97 tgt[0].Opcode = OPCODE_RCP;
98 tgt[0].DstReg.File = PROGRAM_TEMPORARY;
99 tgt[0].DstReg.Index = rcptemp;
100 tgt[0].DstReg.WriteMask = WRITEMASK_W;
101 tgt[0].SrcReg[0] = inst.SrcReg[0];
102 tgt[0].SrcReg[0].Swizzle = SWIZZLE_WWWW;
103
104 tgt[1].Opcode = OPCODE_MAD;
105 tgt[1].DstReg = inst.DstReg;
106 tgt[1].DstReg.WriteMask = orig_inst->DstReg.WriteMask;
107 tgt[1].SrcReg[0] = inst.SrcReg[0];
108 tgt[1].SrcReg[0].Swizzle = SWIZZLE_ZZZZ;
109 tgt[1].SrcReg[1].File = PROGRAM_TEMPORARY;
110 tgt[1].SrcReg[1].Index = rcptemp;
111 tgt[1].SrcReg[1].Swizzle = SWIZZLE_WWWW;
112 tgt[1].SrcReg[2].File = PROGRAM_TEMPORARY;
113 tgt[1].SrcReg[2].Index = inst.DstReg.Index;
114 if (depthmode == 0) /* GL_LUMINANCE */
115 tgt[1].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z);
116 else if (depthmode == 2) /* GL_ALPHA */
117 tgt[1].SrcReg[2].Swizzle = SWIZZLE_WWWW;
118
119 /* Recall that SrcReg[0] is tex, SrcReg[2] is r and:
120 * r < tex <=> -tex+r < 0
121 * r >= tex <=> not (-tex+r < 0 */
122 if (comparefunc == GL_LESS || comparefunc == GL_GEQUAL)
123 tgt[1].SrcReg[2].NegateBase = tgt[0].SrcReg[2].NegateBase ^ NEGATE_XYZW;
124 else
125 tgt[1].SrcReg[0].NegateBase = tgt[0].SrcReg[0].NegateBase ^ NEGATE_XYZW;
126
127 tgt[2].Opcode = OPCODE_CMP;
128 tgt[2].DstReg = orig_inst->DstReg;
129 tgt[2].SrcReg[0].File = PROGRAM_TEMPORARY;
130 tgt[2].SrcReg[0].Index = tgt[1].DstReg.Index;
131 tgt[2].SrcReg[1].File = PROGRAM_BUILTIN;
132 tgt[2].SrcReg[2].File = PROGRAM_BUILTIN;
133
134 if (comparefunc == GL_LESS || comparefunc == GL_GREATER) {
135 tgt[2].SrcReg[1].Swizzle = SWIZZLE_1111;
136 tgt[2].SrcReg[2].Swizzle = SWIZZLE_0000;
137 } else {
138 tgt[2].SrcReg[1].Swizzle = SWIZZLE_0000;
139 tgt[2].SrcReg[2].Swizzle = SWIZZLE_1111;
140 }
141 } else if (destredirect) {
142 tgt = radeonAppendInstructions(t->Program, 1);
143
144 tgt->Opcode = OPCODE_MOV;
145 tgt->DstReg = orig_inst->DstReg;
146 tgt->SrcReg[0].File = PROGRAM_TEMPORARY;
147 tgt->SrcReg[0].Index = inst.DstReg.Index;
148 }
149
150 return GL_TRUE;
151 }
152
153
154 static void update_params(r300ContextPtr r300, struct r500_fragment_program *fp)
155 {
156 struct gl_fragment_program *mp = &fp->mesa_program;
157
158 /* Ask Mesa nicely to fill in ParameterValues for us */
159 if (mp->Base.Parameters)
160 _mesa_load_state_parameters(r300->radeon.glCtx, mp->Base.Parameters);
161 }
162
163
164 /**
165 * Transform the program to support fragment.position.
166 *
167 * Introduce a small fragment at the start of the program that will be
168 * the only code that directly reads the FRAG_ATTRIB_WPOS input.
169 * All other code pieces that reference that input will be rewritten
170 * to read from a newly allocated temporary.
171 *
172 * \todo if/when r5xx supports the radeon_program architecture, this is a
173 * likely candidate for code sharing.
174 */
175 static void insert_WPOS_trailer(struct r500_fragment_program_compiler *compiler)
176 {
177 GLuint InputsRead = compiler->fp->mesa_program.Base.InputsRead;
178
179 if (!(InputsRead & FRAG_BIT_WPOS))
180 return;
181
182 static gl_state_index tokens[STATE_LENGTH] = {
183 STATE_INTERNAL, STATE_R300_WINDOW_DIMENSION, 0, 0, 0
184 };
185 struct prog_instruction *fpi;
186 GLuint window_index;
187 int i = 0;
188 GLuint tempregi = _mesa_find_free_register(compiler->program, PROGRAM_TEMPORARY);
189
190 _mesa_insert_instructions(compiler->program, 0, 3);
191 fpi = compiler->program->Instructions;
192
193 /* perspective divide */
194 fpi[i].Opcode = OPCODE_RCP;
195
196 fpi[i].DstReg.File = PROGRAM_TEMPORARY;
197 fpi[i].DstReg.Index = tempregi;
198 fpi[i].DstReg.WriteMask = WRITEMASK_W;
199 fpi[i].DstReg.CondMask = COND_TR;
200
201 fpi[i].SrcReg[0].File = PROGRAM_INPUT;
202 fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
203 fpi[i].SrcReg[0].Swizzle = SWIZZLE_WWWW;
204 i++;
205
206 fpi[i].Opcode = OPCODE_MUL;
207
208 fpi[i].DstReg.File = PROGRAM_TEMPORARY;
209 fpi[i].DstReg.Index = tempregi;
210 fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
211 fpi[i].DstReg.CondMask = COND_TR;
212
213 fpi[i].SrcReg[0].File = PROGRAM_INPUT;
214 fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
215 fpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
216
217 fpi[i].SrcReg[1].File = PROGRAM_TEMPORARY;
218 fpi[i].SrcReg[1].Index = tempregi;
219 fpi[i].SrcReg[1].Swizzle = SWIZZLE_WWWW;
220 i++;
221
222 /* viewport transformation */
223 window_index = _mesa_add_state_reference(compiler->program->Parameters, tokens);
224
225 fpi[i].Opcode = OPCODE_MAD;
226
227 fpi[i].DstReg.File = PROGRAM_TEMPORARY;
228 fpi[i].DstReg.Index = tempregi;
229 fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
230 fpi[i].DstReg.CondMask = COND_TR;
231
232 fpi[i].SrcReg[0].File = PROGRAM_TEMPORARY;
233 fpi[i].SrcReg[0].Index = tempregi;
234 fpi[i].SrcReg[0].Swizzle =
235 MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
236
237 fpi[i].SrcReg[1].File = PROGRAM_STATE_VAR;
238 fpi[i].SrcReg[1].Index = window_index;
239 fpi[i].SrcReg[1].Swizzle =
240 MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
241
242 fpi[i].SrcReg[2].File = PROGRAM_STATE_VAR;
243 fpi[i].SrcReg[2].Index = window_index;
244 fpi[i].SrcReg[2].Swizzle =
245 MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
246 i++;
247
248 for (; i < compiler->program->NumInstructions; ++i) {
249 int reg;
250 for (reg = 0; reg < 3; reg++) {
251 if (fpi[i].SrcReg[reg].File == PROGRAM_INPUT &&
252 fpi[i].SrcReg[reg].Index == FRAG_ATTRIB_WPOS) {
253 fpi[i].SrcReg[reg].File = PROGRAM_TEMPORARY;
254 fpi[i].SrcReg[reg].Index = tempregi;
255 }
256 }
257 }
258 }
259
260
261 static void nqssadce_init(struct nqssadce_state* s)
262 {
263 s->Outputs[FRAG_RESULT_COLR].Sourced = WRITEMASK_XYZW;
264 s->Outputs[FRAG_RESULT_DEPR].Sourced = WRITEMASK_W;
265 }
266
267 static GLboolean is_native_swizzle(GLuint opcode, struct prog_src_register reg)
268 {
269 GLuint relevant;
270 int i;
271
272 if (opcode == OPCODE_TEX ||
273 opcode == OPCODE_TXB ||
274 opcode == OPCODE_TXP ||
275 opcode == OPCODE_KIL) {
276 if (reg.Abs)
277 return GL_FALSE;
278
279 if (reg.NegateAbs)
280 reg.NegateBase ^= 15;
281
282 if (opcode == OPCODE_KIL) {
283 if (reg.Swizzle != SWIZZLE_NOOP)
284 return GL_FALSE;
285 } else {
286 for(i = 0; i < 4; ++i) {
287 GLuint swz = GET_SWZ(reg.Swizzle, i);
288 if (swz == SWIZZLE_NIL) {
289 reg.NegateBase &= ~(1 << i);
290 continue;
291 }
292 if (swz >= 4)
293 return GL_FALSE;
294 }
295 }
296
297 if (reg.NegateBase)
298 return GL_FALSE;
299
300 return GL_TRUE;
301 } else {
302 /* ALU instructions support almost everything */
303 if (reg.Abs)
304 return GL_TRUE;
305
306 relevant = 0;
307 for(i = 0; i < 3; ++i) {
308 GLuint swz = GET_SWZ(reg.Swizzle, i);
309 if (swz != SWIZZLE_NIL && swz != SWIZZLE_ZERO)
310 relevant |= 1 << i;
311 }
312 if ((reg.NegateBase & relevant) && ((reg.NegateBase & relevant) != relevant))
313 return GL_FALSE;
314
315 return GL_TRUE;
316 }
317 }
318
319 /**
320 * Implement a MOV with a potentially non-native swizzle.
321 *
322 * The only thing we *cannot* do in an ALU instruction is per-component
323 * negation. Therefore, we split the MOV into two instructions when necessary.
324 */
325 static void nqssadce_build_swizzle(struct nqssadce_state *s,
326 struct prog_dst_register dst, struct prog_src_register src)
327 {
328 struct prog_instruction *inst;
329 GLuint negatebase[2] = { 0, 0 };
330 int i;
331
332 for(i = 0; i < 4; ++i) {
333 GLuint swz = GET_SWZ(src.Swizzle, i);
334 if (swz == SWIZZLE_NIL)
335 continue;
336 negatebase[GET_BIT(src.NegateBase, i)] |= 1 << i;
337 }
338
339 _mesa_insert_instructions(s->Program, s->IP, (negatebase[0] ? 1 : 0) + (negatebase[1] ? 1 : 0));
340 inst = s->Program->Instructions + s->IP;
341
342 for(i = 0; i <= 1; ++i) {
343 if (!negatebase[i])
344 continue;
345
346 inst->Opcode = OPCODE_MOV;
347 inst->DstReg = dst;
348 inst->DstReg.WriteMask = negatebase[i];
349 inst->SrcReg[0] = src;
350 inst++;
351 s->IP++;
352 }
353 }
354
355 static GLuint build_dtm(GLuint depthmode)
356 {
357 switch(depthmode) {
358 default:
359 case GL_LUMINANCE: return 0;
360 case GL_INTENSITY: return 1;
361 case GL_ALPHA: return 2;
362 }
363 }
364
365 static GLuint build_func(GLuint comparefunc)
366 {
367 return comparefunc - GL_NEVER;
368 }
369
370
371 /**
372 * Collect all external state that is relevant for compiling the given
373 * fragment program.
374 */
375 static void build_state(
376 r300ContextPtr r300,
377 struct r500_fragment_program *fp,
378 struct r500_fragment_program_external_state *state)
379 {
380 int unit;
381
382 _mesa_bzero(state, sizeof(*state));
383
384 for(unit = 0; unit < 16; ++unit) {
385 if (fp->mesa_program.Base.ShadowSamplers & (1 << unit)) {
386 struct gl_texture_object* tex = r300->radeon.glCtx->Texture.Unit[unit]._Current;
387
388 state->unit[unit].depth_texture_mode = build_dtm(tex->DepthMode);
389 state->unit[unit].texture_compare_func = build_func(tex->CompareFunc);
390 }
391 }
392 }
393
394 static void dump_program(struct r500_fragment_program_code *code);
395
396 void r500TranslateFragmentShader(r300ContextPtr r300,
397 struct r500_fragment_program *fp)
398 {
399 struct r500_fragment_program_external_state state;
400
401 build_state(r300, fp, &state);
402 if (_mesa_memcmp(&fp->state, &state, sizeof(state))) {
403 /* TODO: cache compiled programs */
404 fp->translated = GL_FALSE;
405 _mesa_memcpy(&fp->state, &state, sizeof(state));
406 }
407
408 if (!fp->translated) {
409 struct r500_fragment_program_compiler compiler;
410
411 compiler.r300 = r300;
412 compiler.fp = fp;
413 compiler.code = &fp->code;
414 compiler.program = _mesa_clone_program(r300->radeon.glCtx, &fp->mesa_program.Base);
415
416 if (RADEON_DEBUG & DEBUG_PIXEL) {
417 _mesa_printf("Compiler: Initial program:\n");
418 _mesa_print_program(compiler.program);
419 }
420
421 insert_WPOS_trailer(&compiler);
422
423 struct radeon_program_transformation transformations[3] = {
424 { &transform_TEX, &compiler },
425 { &radeonTransformALU, 0 },
426 { &radeonTransformTrigScale, 0 }
427 };
428 radeonLocalTransform(r300->radeon.glCtx, compiler.program,
429 3, transformations);
430
431 if (RADEON_DEBUG & DEBUG_PIXEL) {
432 _mesa_printf("Compiler: after native rewrite:\n");
433 _mesa_print_program(compiler.program);
434 }
435
436 struct radeon_nqssadce_descr nqssadce = {
437 .Init = &nqssadce_init,
438 .IsNativeSwizzle = &is_native_swizzle,
439 .BuildSwizzle = &nqssadce_build_swizzle,
440 .RewriteDepthOut = GL_TRUE
441 };
442 radeonNqssaDce(r300->radeon.glCtx, compiler.program, &nqssadce);
443
444 if (RADEON_DEBUG & DEBUG_PIXEL) {
445 _mesa_printf("Compiler: after NqSSA-DCE:\n");
446 _mesa_print_program(compiler.program);
447 }
448
449 fp->translated = r500FragmentProgramEmit(&compiler);
450
451 /* Subtle: Rescue any parameters that have been added during transformations */
452 _mesa_free_parameter_list(fp->mesa_program.Base.Parameters);
453 fp->mesa_program.Base.Parameters = compiler.program->Parameters;
454 compiler.program->Parameters = 0;
455
456 _mesa_reference_program(r300->radeon.glCtx, &compiler.program, 0);
457
458 r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM);
459
460 if (RADEON_DEBUG & DEBUG_PIXEL) {
461 if (fp->translated) {
462 _mesa_printf("Machine-readable code:\n");
463 dump_program(&fp->code);
464 }
465 }
466
467 }
468
469 update_params(r300, fp);
470
471 }
472
473 static char *toswiz(int swiz_val) {
474 switch(swiz_val) {
475 case 0: return "R";
476 case 1: return "G";
477 case 2: return "B";
478 case 3: return "A";
479 case 4: return "0";
480 case 5: return "1/2";
481 case 6: return "1";
482 case 7: return "U";
483 }
484 return NULL;
485 }
486
487 static char *toop(int op_val)
488 {
489 char *str = NULL;
490 switch (op_val) {
491 case 0: str = "MAD"; break;
492 case 1: str = "DP3"; break;
493 case 2: str = "DP4"; break;
494 case 3: str = "D2A"; break;
495 case 4: str = "MIN"; break;
496 case 5: str = "MAX"; break;
497 case 6: str = "Reserved"; break;
498 case 7: str = "CND"; break;
499 case 8: str = "CMP"; break;
500 case 9: str = "FRC"; break;
501 case 10: str = "SOP"; break;
502 case 11: str = "MDH"; break;
503 case 12: str = "MDV"; break;
504 }
505 return str;
506 }
507
508 static char *to_alpha_op(int op_val)
509 {
510 char *str = NULL;
511 switch (op_val) {
512 case 0: str = "MAD"; break;
513 case 1: str = "DP"; break;
514 case 2: str = "MIN"; break;
515 case 3: str = "MAX"; break;
516 case 4: str = "Reserved"; break;
517 case 5: str = "CND"; break;
518 case 6: str = "CMP"; break;
519 case 7: str = "FRC"; break;
520 case 8: str = "EX2"; break;
521 case 9: str = "LN2"; break;
522 case 10: str = "RCP"; break;
523 case 11: str = "RSQ"; break;
524 case 12: str = "SIN"; break;
525 case 13: str = "COS"; break;
526 case 14: str = "MDH"; break;
527 case 15: str = "MDV"; break;
528 }
529 return str;
530 }
531
532 static char *to_mask(int val)
533 {
534 char *str = NULL;
535 switch(val) {
536 case 0: str = "NONE"; break;
537 case 1: str = "R"; break;
538 case 2: str = "G"; break;
539 case 3: str = "RG"; break;
540 case 4: str = "B"; break;
541 case 5: str = "RB"; break;
542 case 6: str = "GB"; break;
543 case 7: str = "RGB"; break;
544 case 8: str = "A"; break;
545 case 9: str = "AR"; break;
546 case 10: str = "AG"; break;
547 case 11: str = "ARG"; break;
548 case 12: str = "AB"; break;
549 case 13: str = "ARB"; break;
550 case 14: str = "AGB"; break;
551 case 15: str = "ARGB"; break;
552 }
553 return str;
554 }
555
556 static char *to_texop(int val)
557 {
558 switch(val) {
559 case 0: return "NOP";
560 case 1: return "LD";
561 case 2: return "TEXKILL";
562 case 3: return "PROJ";
563 case 4: return "LODBIAS";
564 case 5: return "LOD";
565 case 6: return "DXDY";
566 }
567 return NULL;
568 }
569
570 static void dump_program(struct r500_fragment_program_code *code)
571 {
572
573 fprintf(stderr, "R500 Fragment Program:\n--------\n");
574
575 int n;
576 uint32_t inst;
577 uint32_t inst0;
578 char *str = NULL;
579
580 if (code->const_nr) {
581 fprintf(stderr, "--------\nConstants:\n");
582 for (n = 0; n < code->const_nr; n++) {
583 fprintf(stderr, "Constant %d: %i[%i]\n", n,
584 code->constant[n].File, code->constant[n].Index);
585 }
586 fprintf(stderr, "--------\n");
587 }
588
589 for (n = 0; n < code->inst_end+1; n++) {
590 inst0 = inst = code->inst[n].inst0;
591 fprintf(stderr,"%d\t0:CMN_INST 0x%08x:", n, inst);
592 switch(inst & 0x3) {
593 case R500_INST_TYPE_ALU: str = "ALU"; break;
594 case R500_INST_TYPE_OUT: str = "OUT"; break;
595 case R500_INST_TYPE_FC: str = "FC"; break;
596 case R500_INST_TYPE_TEX: str = "TEX"; break;
597 };
598 fprintf(stderr,"%s %s %s %s %s ", str,
599 inst & R500_INST_TEX_SEM_WAIT ? "TEX_WAIT" : "",
600 inst & R500_INST_LAST ? "LAST" : "",
601 inst & R500_INST_NOP ? "NOP" : "",
602 inst & R500_INST_ALU_WAIT ? "ALU WAIT" : "");
603 fprintf(stderr,"wmask: %s omask: %s\n", to_mask((inst >> 11) & 0xf),
604 to_mask((inst >> 15) & 0xf));
605
606 switch(inst0 & 0x3) {
607 case 0:
608 case 1:
609 fprintf(stderr,"\t1:RGB_ADDR 0x%08x:", code->inst[n].inst1);
610 inst = code->inst[n].inst1;
611
612 fprintf(stderr,"Addr0: %d%c, Addr1: %d%c, Addr2: %d%c, srcp:%d\n",
613 inst & 0xff, (inst & (1<<8)) ? 'c' : 't',
614 (inst >> 10) & 0xff, (inst & (1<<18)) ? 'c' : 't',
615 (inst >> 20) & 0xff, (inst & (1<<28)) ? 'c' : 't',
616 (inst >> 30));
617
618 fprintf(stderr,"\t2:ALPHA_ADDR 0x%08x:", code->inst[n].inst2);
619 inst = code->inst[n].inst2;
620 fprintf(stderr,"Addr0: %d%c, Addr1: %d%c, Addr2: %d%c, srcp:%d\n",
621 inst & 0xff, (inst & (1<<8)) ? 'c' : 't',
622 (inst >> 10) & 0xff, (inst & (1<<18)) ? 'c' : 't',
623 (inst >> 20) & 0xff, (inst & (1<<28)) ? 'c' : 't',
624 (inst >> 30));
625 fprintf(stderr,"\t3 RGB_INST: 0x%08x:", code->inst[n].inst3);
626 inst = code->inst[n].inst3;
627 fprintf(stderr,"rgb_A_src:%d %s/%s/%s %d rgb_B_src:%d %s/%s/%s %d\n",
628 (inst) & 0x3, toswiz((inst >> 2) & 0x7), toswiz((inst >> 5) & 0x7), toswiz((inst >> 8) & 0x7),
629 (inst >> 11) & 0x3,
630 (inst >> 13) & 0x3, toswiz((inst >> 15) & 0x7), toswiz((inst >> 18) & 0x7), toswiz((inst >> 21) & 0x7),
631 (inst >> 24) & 0x3);
632
633
634 fprintf(stderr,"\t4 ALPHA_INST:0x%08x:", code->inst[n].inst4);
635 inst = code->inst[n].inst4;
636 fprintf(stderr,"%s dest:%d%s alp_A_src:%d %s %d alp_B_src:%d %s %d w:%d\n", to_alpha_op(inst & 0xf),
637 (inst >> 4) & 0x7f, inst & (1<<11) ? "(rel)":"",
638 (inst >> 12) & 0x3, toswiz((inst >> 14) & 0x7), (inst >> 17) & 0x3,
639 (inst >> 19) & 0x3, toswiz((inst >> 21) & 0x7), (inst >> 24) & 0x3,
640 (inst >> 31) & 0x1);
641
642 fprintf(stderr,"\t5 RGBA_INST: 0x%08x:", code->inst[n].inst5);
643 inst = code->inst[n].inst5;
644 fprintf(stderr,"%s dest:%d%s rgb_C_src:%d %s/%s/%s %d alp_C_src:%d %s %d\n", toop(inst & 0xf),
645 (inst >> 4) & 0x7f, inst & (1<<11) ? "(rel)":"",
646 (inst >> 12) & 0x3, toswiz((inst >> 14) & 0x7), toswiz((inst >> 17) & 0x7), toswiz((inst >> 20) & 0x7),
647 (inst >> 23) & 0x3,
648 (inst >> 25) & 0x3, toswiz((inst >> 27) & 0x7), (inst >> 30) & 0x3);
649 break;
650 case 2:
651 break;
652 case 3:
653 inst = code->inst[n].inst1;
654 fprintf(stderr,"\t1:TEX_INST: 0x%08x: id: %d op:%s, %s, %s %s\n", inst, (inst >> 16) & 0xf,
655 to_texop((inst >> 22) & 0x7), (inst & (1<<25)) ? "ACQ" : "",
656 (inst & (1<<26)) ? "IGNUNC" : "", (inst & (1<<27)) ? "UNSCALED" : "SCALED");
657 inst = code->inst[n].inst2;
658 fprintf(stderr,"\t2:TEX_ADDR: 0x%08x: src: %d%s %s/%s/%s/%s dst: %d%s %s/%s/%s/%s\n", inst,
659 inst & 127, inst & (1<<7) ? "(rel)" : "",
660 toswiz((inst >> 8) & 0x3), toswiz((inst >> 10) & 0x3),
661 toswiz((inst >> 12) & 0x3), toswiz((inst >> 14) & 0x3),
662 (inst >> 16) & 127, inst & (1<<23) ? "(rel)" : "",
663 toswiz((inst >> 24) & 0x3), toswiz((inst >> 26) & 0x3),
664 toswiz((inst >> 28) & 0x3), toswiz((inst >> 30) & 0x3));
665
666 fprintf(stderr,"\t3:TEX_DXDY: 0x%08x\n", code->inst[n].inst3);
667 break;
668 }
669 fprintf(stderr,"\n");
670 }
671
672 }