Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 <stdio.h>
  31.  
  32. #include "radeon_compiler_util.h"
  33. #include "radeon_list.h"
  34. #include "radeon_variable.h"
  35. #include "r300_reg.h"
  36.  
  37. /**
  38.  * Rewrite IF instructions to use the ALU result special register.
  39.  */
  40. int r500_transform_IF(
  41.         struct radeon_compiler * c,
  42.         struct rc_instruction * inst_if,
  43.         void *data)
  44. {
  45.         struct rc_variable * writer;
  46.         struct rc_list * writer_list, * list_ptr;
  47.         struct rc_list * var_list = rc_get_variables(c);
  48.         unsigned int generic_if = 0;
  49.         unsigned int alu_chan;
  50.  
  51.         if (inst_if->U.I.Opcode != RC_OPCODE_IF) {
  52.                 return 0;
  53.         }
  54.  
  55.         writer_list = rc_variable_list_get_writers(
  56.                         var_list, inst_if->Type, &inst_if->U.I.SrcReg[0]);
  57.         if (!writer_list) {
  58.                 generic_if = 1;
  59.         } else {
  60.  
  61.                 /* Make sure it is safe for the writers to write to
  62.                  * ALU Result */
  63.                 for (list_ptr = writer_list; list_ptr;
  64.                                                 list_ptr = list_ptr->Next) {
  65.                         struct rc_instruction * inst;
  66.                         writer = list_ptr->Item;
  67.                         /* We are going to modify the destination register
  68.                          * of writer, so if it has a reader other than
  69.                          * inst_if (aka ReaderCount > 1) we must fall back to
  70.                          * our generic IF.
  71.                          * If the writer has a lower IP than inst_if, this
  72.                          * means that inst_if is above the writer in a loop.
  73.                          * I'm not sure why this would ever happen, but
  74.                          * if it does we want to make sure we fall back
  75.                          * to our generic IF. */
  76.                         if (writer->ReaderCount > 1 || writer->Inst->IP < inst_if->IP) {
  77.                                 generic_if = 1;
  78.                                 break;
  79.                         }
  80.  
  81.                         /* The ALU Result is not preserved across IF
  82.                          * instructions, so if there is another IF
  83.                          * instruction between writer and inst_if, then
  84.                          * we need to fall back to generic IF. */
  85.                         for (inst = writer->Inst; inst != inst_if; inst = inst->Next) {
  86.                                 const struct rc_opcode_info * info =
  87.                                         rc_get_opcode_info(inst->U.I.Opcode);
  88.                                 if (info->IsFlowControl) {
  89.                                         generic_if = 1;
  90.                                         break;
  91.                                 }
  92.                         }
  93.                         if (generic_if) {
  94.                                 break;
  95.                         }
  96.                 }
  97.         }
  98.  
  99.         if (GET_SWZ(inst_if->U.I.SrcReg[0].Swizzle, 0) == RC_SWIZZLE_X) {
  100.                 alu_chan = RC_ALURESULT_X;
  101.         } else {
  102.                 alu_chan = RC_ALURESULT_W;
  103.         }
  104.         if (generic_if) {
  105.                 struct rc_instruction * inst_mov =
  106.                                 rc_insert_new_instruction(c, inst_if->Prev);
  107.  
  108.                 inst_mov->U.I.Opcode = RC_OPCODE_MOV;
  109.                 inst_mov->U.I.DstReg.WriteMask = 0;
  110.                 inst_mov->U.I.DstReg.File = RC_FILE_NONE;
  111.                 inst_mov->U.I.ALUResultCompare = RC_COMPARE_FUNC_NOTEQUAL;
  112.                 inst_mov->U.I.WriteALUResult = alu_chan;
  113.                 inst_mov->U.I.SrcReg[0] = inst_if->U.I.SrcReg[0];
  114.                 if (alu_chan == RC_ALURESULT_X) {
  115.                         inst_mov->U.I.SrcReg[0].Swizzle = combine_swizzles4(
  116.                                         inst_mov->U.I.SrcReg[0].Swizzle,
  117.                                         RC_SWIZZLE_X, RC_SWIZZLE_UNUSED,
  118.                                         RC_SWIZZLE_UNUSED, RC_SWIZZLE_UNUSED);
  119.                 } else {
  120.                         inst_mov->U.I.SrcReg[0].Swizzle = combine_swizzles4(
  121.                                         inst_mov->U.I.SrcReg[0].Swizzle,
  122.                                         RC_SWIZZLE_UNUSED, RC_SWIZZLE_UNUSED,
  123.                                         RC_SWIZZLE_UNUSED, RC_SWIZZLE_Z);
  124.                 }
  125.         } else {
  126.                 rc_compare_func compare_func = RC_COMPARE_FUNC_NEVER;
  127.                 unsigned int reverse_srcs = 0;
  128.                 unsigned int preserve_opcode = 0;
  129.                 for (list_ptr = writer_list; list_ptr;
  130.                                                 list_ptr = list_ptr->Next) {
  131.                         writer = list_ptr->Item;
  132.                         switch(writer->Inst->U.I.Opcode) {
  133.                         case RC_OPCODE_SEQ:
  134.                                 compare_func = RC_COMPARE_FUNC_EQUAL;
  135.                                 break;
  136.                         case RC_OPCODE_SNE:
  137.                                 compare_func = RC_COMPARE_FUNC_NOTEQUAL;
  138.                                 break;
  139.                         case RC_OPCODE_SLE:
  140.                                 reverse_srcs = 1;
  141.                                 /* Fall through */
  142.                         case RC_OPCODE_SGE:
  143.                                 compare_func = RC_COMPARE_FUNC_GEQUAL;
  144.                                 break;
  145.                         case RC_OPCODE_SGT:
  146.                                 reverse_srcs = 1;
  147.                                 /* Fall through */
  148.                         case RC_OPCODE_SLT:
  149.                                 compare_func = RC_COMPARE_FUNC_LESS;
  150.                                 break;
  151.                         default:
  152.                                 compare_func = RC_COMPARE_FUNC_NOTEQUAL;
  153.                                 preserve_opcode = 1;
  154.                                 break;
  155.                         }
  156.                         if (!preserve_opcode) {
  157.                                 writer->Inst->U.I.Opcode = RC_OPCODE_SUB;
  158.                         }
  159.                         writer->Inst->U.I.DstReg.WriteMask = 0;
  160.                         writer->Inst->U.I.DstReg.File = RC_FILE_NONE;
  161.                         writer->Inst->U.I.WriteALUResult = alu_chan;
  162.                         writer->Inst->U.I.ALUResultCompare = compare_func;
  163.                         if (reverse_srcs) {
  164.                                 struct rc_src_register temp_src;
  165.                                 temp_src = writer->Inst->U.I.SrcReg[0];
  166.                                 writer->Inst->U.I.SrcReg[0] =
  167.                                         writer->Inst->U.I.SrcReg[1];
  168.                                 writer->Inst->U.I.SrcReg[1] = temp_src;
  169.                         }
  170.                 }
  171.         }
  172.  
  173.         inst_if->U.I.SrcReg[0].File = RC_FILE_SPECIAL;
  174.         inst_if->U.I.SrcReg[0].Index = RC_SPECIAL_ALU_RESULT;
  175.         inst_if->U.I.SrcReg[0].Swizzle = RC_MAKE_SWIZZLE(
  176.                                 RC_SWIZZLE_X, RC_SWIZZLE_UNUSED,
  177.                                 RC_SWIZZLE_UNUSED, RC_SWIZZLE_UNUSED);
  178.         inst_if->U.I.SrcReg[0].Negate = 0;
  179.  
  180.         return 1;
  181. }
  182.  
  183. static int r500_swizzle_is_native(rc_opcode opcode, struct rc_src_register reg)
  184. {
  185.         unsigned int relevant;
  186.         int i;
  187.  
  188.         if (opcode == RC_OPCODE_TEX ||
  189.             opcode == RC_OPCODE_TXB ||
  190.             opcode == RC_OPCODE_TXP ||
  191.             opcode == RC_OPCODE_TXD ||
  192.             opcode == RC_OPCODE_TXL ||
  193.             opcode == RC_OPCODE_KIL) {
  194.                 if (reg.Abs)
  195.                         return 0;
  196.  
  197.                 if (opcode == RC_OPCODE_KIL && (reg.Swizzle != RC_SWIZZLE_XYZW || reg.Negate != RC_MASK_NONE))
  198.                         return 0;
  199.  
  200.                 for(i = 0; i < 4; ++i) {
  201.                         unsigned int swz = GET_SWZ(reg.Swizzle, i);
  202.                         if (swz == RC_SWIZZLE_UNUSED) {
  203.                                 reg.Negate &= ~(1 << i);
  204.                                 continue;
  205.                         }
  206.                         if (swz >= 4)
  207.                                 return 0;
  208.                 }
  209.  
  210.                 if (reg.Negate)
  211.                         return 0;
  212.  
  213.                 return 1;
  214.         } else if (opcode == RC_OPCODE_DDX || opcode == RC_OPCODE_DDY) {
  215.                 /* DDX/MDH and DDY/MDV explicitly ignore incoming swizzles;
  216.                  * if it doesn't fit perfectly into a .xyzw case... */
  217.                 if (reg.Swizzle == RC_SWIZZLE_XYZW && !reg.Abs && !reg.Negate)
  218.                         return 1;
  219.  
  220.                 return 0;
  221.         } else if (reg.File == RC_FILE_INLINE) {
  222.                 return 1;
  223.         } else {
  224.                 /* ALU instructions support almost everything */
  225.                 relevant = 0;
  226.                 for(i = 0; i < 3; ++i) {
  227.                         unsigned int swz = GET_SWZ(reg.Swizzle, i);
  228.                         if (swz != RC_SWIZZLE_UNUSED && swz != RC_SWIZZLE_ZERO)
  229.                                 relevant |= 1 << i;
  230.                 }
  231.                 if ((reg.Negate & relevant) && ((reg.Negate & relevant) != relevant))
  232.                         return 0;
  233.  
  234.                 return 1;
  235.         }
  236. }
  237.  
  238. /**
  239.  * Split source register access.
  240.  *
  241.  * The only thing we *cannot* do in an ALU instruction is per-component
  242.  * negation.
  243.  */
  244. static void r500_swizzle_split(struct rc_src_register src, unsigned int usemask,
  245.                 struct rc_swizzle_split * split)
  246. {
  247.         unsigned int negatebase[2] = { 0, 0 };
  248.         int i;
  249.  
  250.         for(i = 0; i < 4; ++i) {
  251.                 unsigned int swz = GET_SWZ(src.Swizzle, i);
  252.                 if (swz == RC_SWIZZLE_UNUSED || !GET_BIT(usemask, i))
  253.                         continue;
  254.                 negatebase[GET_BIT(src.Negate, i)] |= 1 << i;
  255.         }
  256.  
  257.         split->NumPhases = 0;
  258.  
  259.         for(i = 0; i <= 1; ++i) {
  260.                 if (!negatebase[i])
  261.                         continue;
  262.  
  263.                 split->Phase[split->NumPhases++] = negatebase[i];
  264.         }
  265. }
  266.  
  267. struct rc_swizzle_caps r500_swizzle_caps = {
  268.         .IsNative = r500_swizzle_is_native,
  269.         .Split = r500_swizzle_split
  270. };
  271.  
  272. static char *toswiz(int swiz_val) {
  273.   switch(swiz_val) {
  274.   case 0: return "R";
  275.   case 1: return "G";
  276.   case 2: return "B";
  277.   case 3: return "A";
  278.   case 4: return "0";
  279.   case 5: return "H";
  280.   case 6: return "1";
  281.   case 7: return "U";
  282.   }
  283.   return NULL;
  284. }
  285.  
  286. static char *toop(int op_val)
  287. {
  288.   char *str = NULL;
  289.   switch (op_val) {
  290.   case 0: str = "MAD"; break;
  291.   case 1: str = "DP3"; break;
  292.   case 2: str = "DP4"; break;
  293.   case 3: str = "D2A"; break;
  294.   case 4: str = "MIN"; break;
  295.   case 5: str = "MAX"; break;
  296.   case 6: str = "Reserved"; break;
  297.   case 7: str = "CND"; break;
  298.   case 8: str = "CMP"; break;
  299.   case 9: str = "FRC"; break;
  300.   case 10: str = "SOP"; break;
  301.   case 11: str = "MDH"; break;
  302.   case 12: str = "MDV"; break;
  303.   }
  304.   return str;
  305. }
  306.  
  307. static char *to_alpha_op(int op_val)
  308. {
  309.   char *str = NULL;
  310.   switch (op_val) {
  311.   case 0: str = "MAD"; break;
  312.   case 1: str = "DP"; break;
  313.   case 2: str = "MIN"; break;
  314.   case 3: str = "MAX"; break;
  315.   case 4: str = "Reserved"; break;
  316.   case 5: str = "CND"; break;
  317.   case 6: str = "CMP"; break;
  318.   case 7: str = "FRC"; break;
  319.   case 8: str = "EX2"; break;
  320.   case 9: str = "LN2"; break;
  321.   case 10: str = "RCP"; break;
  322.   case 11: str = "RSQ"; break;
  323.   case 12: str = "SIN"; break;
  324.   case 13: str = "COS"; break;
  325.   case 14: str = "MDH"; break;
  326.   case 15: str = "MDV"; break;
  327.   }
  328.   return str;
  329. }
  330.  
  331. static char *to_mask(int val)
  332. {
  333.   char *str = NULL;
  334.   switch(val) {
  335.   case 0: str = "NONE"; break;
  336.   case 1: str = "R"; break;
  337.   case 2: str = "G"; break;
  338.   case 3: str = "RG"; break;
  339.   case 4: str = "B"; break;
  340.   case 5: str = "RB"; break;
  341.   case 6: str = "GB"; break;
  342.   case 7: str = "RGB"; break;
  343.   case 8: str = "A"; break;
  344.   case 9: str = "AR"; break;
  345.   case 10: str = "AG"; break;
  346.   case 11: str = "ARG"; break;
  347.   case 12: str = "AB"; break;
  348.   case 13: str = "ARB"; break;
  349.   case 14: str = "AGB"; break;
  350.   case 15: str = "ARGB"; break;
  351.   }
  352.   return str;
  353. }
  354.  
  355. static char *to_texop(int val)
  356. {
  357.   switch(val) {
  358.   case 0: return "NOP";
  359.   case 1: return "LD";
  360.   case 2: return "TEXKILL";
  361.   case 3: return "PROJ";
  362.   case 4: return "LODBIAS";
  363.   case 5: return "LOD";
  364.   case 6: return "DXDY";
  365.   }
  366.   return NULL;
  367. }
  368.  
  369. void r500FragmentProgramDump(struct radeon_compiler *c, void *user)
  370. {
  371.   struct r300_fragment_program_compiler *compiler = (struct r300_fragment_program_compiler*)c;
  372.   struct r500_fragment_program_code *code = &compiler->code->code.r500;
  373.   int n, i;
  374.   uint32_t inst;
  375.   uint32_t inst0;
  376.   char *str = NULL;
  377.   fprintf(stderr, "R500 Fragment Program:\n--------\n");
  378.  
  379.   for (n = 0; n < code->inst_end+1; n++) {
  380.     inst0 = inst = code->inst[n].inst0;
  381.     fprintf(stderr,"%d\t0:CMN_INST   0x%08x:", n, inst);
  382.     switch(inst & 0x3) {
  383.     case R500_INST_TYPE_ALU: str = "ALU"; break;
  384.     case R500_INST_TYPE_OUT: str = "OUT"; break;
  385.     case R500_INST_TYPE_FC: str = "FC"; break;
  386.     case R500_INST_TYPE_TEX: str = "TEX"; break;
  387.     };
  388.     fprintf(stderr,"%s %s %s %s %s ", str,
  389.             inst & R500_INST_TEX_SEM_WAIT ? "TEX_WAIT" : "",
  390.             inst & R500_INST_LAST ? "LAST" : "",
  391.             inst & R500_INST_NOP ? "NOP" : "",
  392.             inst & R500_INST_ALU_WAIT ? "ALU WAIT" : "");
  393.     fprintf(stderr,"wmask: %s omask: %s\n", to_mask((inst >> 11) & 0xf),
  394.             to_mask((inst >> 15) & 0xf));
  395.  
  396.     switch(inst0 & 0x3) {
  397.     case R500_INST_TYPE_ALU:
  398.     case R500_INST_TYPE_OUT:
  399.       fprintf(stderr,"\t1:RGB_ADDR   0x%08x:", code->inst[n].inst1);
  400.       inst = code->inst[n].inst1;
  401.  
  402.       fprintf(stderr,"Addr0: %d%c, Addr1: %d%c, Addr2: %d%c, srcp:%d\n",
  403.               inst & 0xff, (inst & (1<<8)) ? 'c' : 't',
  404.               (inst >> 10) & 0xff, (inst & (1<<18)) ? 'c' : 't',
  405.               (inst >> 20) & 0xff, (inst & (1<<28)) ? 'c' : 't',
  406.               (inst >> 30));
  407.  
  408.       fprintf(stderr,"\t2:ALPHA_ADDR 0x%08x:", code->inst[n].inst2);
  409.       inst = code->inst[n].inst2;
  410.       fprintf(stderr,"Addr0: %d%c, Addr1: %d%c, Addr2: %d%c, srcp:%d\n",
  411.               inst & 0xff, (inst & (1<<8)) ? 'c' : 't',
  412.               (inst >> 10) & 0xff, (inst & (1<<18)) ? 'c' : 't',
  413.               (inst >> 20) & 0xff, (inst & (1<<28)) ? 'c' : 't',
  414.               (inst >> 30));
  415.       fprintf(stderr,"\t3 RGB_INST:  0x%08x:", code->inst[n].inst3);
  416.       inst = code->inst[n].inst3;
  417.       fprintf(stderr,"rgb_A_src:%d %s/%s/%s %d rgb_B_src:%d %s/%s/%s %d targ: %d\n",
  418.               (inst) & 0x3, toswiz((inst >> 2) & 0x7), toswiz((inst >> 5) & 0x7), toswiz((inst >> 8) & 0x7),
  419.               (inst >> 11) & 0x3,
  420.               (inst >> 13) & 0x3, toswiz((inst >> 15) & 0x7), toswiz((inst >> 18) & 0x7), toswiz((inst >> 21) & 0x7),
  421.               (inst >> 24) & 0x3, (inst >> 29) & 0x3);
  422.  
  423.  
  424.       fprintf(stderr,"\t4 ALPHA_INST:0x%08x:", code->inst[n].inst4);
  425.       inst = code->inst[n].inst4;
  426.       fprintf(stderr,"%s dest:%d%s alp_A_src:%d %s %d alp_B_src:%d %s %d targ %d w:%d\n", to_alpha_op(inst & 0xf),
  427.               (inst >> 4) & 0x7f, inst & (1<<11) ? "(rel)":"",
  428.               (inst >> 12) & 0x3, toswiz((inst >> 14) & 0x7), (inst >> 17) & 0x3,
  429.               (inst >> 19) & 0x3, toswiz((inst >> 21) & 0x7), (inst >> 24) & 0x3,
  430.               (inst >> 29) & 0x3,
  431.               (inst >> 31) & 0x1);
  432.  
  433.       fprintf(stderr,"\t5 RGBA_INST: 0x%08x:", code->inst[n].inst5);
  434.       inst = code->inst[n].inst5;
  435.       fprintf(stderr,"%s dest:%d%s rgb_C_src:%d %s/%s/%s %d alp_C_src:%d %s %d\n", toop(inst & 0xf),
  436.               (inst >> 4) & 0x7f, inst & (1<<11) ? "(rel)":"",
  437.               (inst >> 12) & 0x3, toswiz((inst >> 14) & 0x7), toswiz((inst >> 17) & 0x7), toswiz((inst >> 20) & 0x7),
  438.               (inst >> 23) & 0x3,
  439.               (inst >> 25) & 0x3, toswiz((inst >> 27) & 0x7), (inst >> 30) & 0x3);
  440.       break;
  441.     case R500_INST_TYPE_FC:
  442.       fprintf(stderr, "\t2:FC_INST    0x%08x:", code->inst[n].inst2);
  443.       inst = code->inst[n].inst2;
  444.       /* JUMP_FUNC JUMP_ANY*/
  445.       fprintf(stderr, "0x%02x %1x ", inst >> 8 & 0xff,
  446.           (inst & R500_FC_JUMP_ANY) >> 5);
  447.      
  448.       /* OP */
  449.       switch(inst & 0x7){
  450.       case R500_FC_OP_JUMP:
  451.         fprintf(stderr, "JUMP");
  452.         break;
  453.       case R500_FC_OP_LOOP:
  454.         fprintf(stderr, "LOOP");
  455.         break;
  456.       case R500_FC_OP_ENDLOOP:
  457.         fprintf(stderr, "ENDLOOP");
  458.         break;
  459.       case R500_FC_OP_REP:
  460.         fprintf(stderr, "REP");
  461.         break;
  462.       case R500_FC_OP_ENDREP:
  463.         fprintf(stderr, "ENDREP");
  464.         break;
  465.       case R500_FC_OP_BREAKLOOP:
  466.         fprintf(stderr, "BREAKLOOP");
  467.         break;
  468.       case R500_FC_OP_BREAKREP:
  469.         fprintf(stderr, "BREAKREP");
  470.         break;
  471.       case R500_FC_OP_CONTINUE:
  472.         fprintf(stderr, "CONTINUE");
  473.         break;
  474.       }
  475.       fprintf(stderr," ");
  476.       /* A_OP */
  477.       switch(inst & (0x3 << 6)){
  478.       case R500_FC_A_OP_NONE:
  479.         fprintf(stderr, "NONE");
  480.         break;
  481.       case R500_FC_A_OP_POP:
  482.         fprintf(stderr, "POP");
  483.         break;
  484.       case R500_FC_A_OP_PUSH:
  485.         fprintf(stderr, "PUSH");
  486.         break;
  487.       }
  488.       /* B_OP0 B_OP1 */
  489.       for(i=0; i<2; i++){
  490.         fprintf(stderr, " ");
  491.         switch(inst & (0x3 << (24 + (i * 2)))){
  492.         /* R500_FC_B_OP0_NONE
  493.          * R500_FC_B_OP1_NONE */
  494.         case 0:
  495.           fprintf(stderr, "NONE");
  496.           break;
  497.         case R500_FC_B_OP0_DECR:
  498.         case R500_FC_B_OP1_DECR:
  499.           fprintf(stderr, "DECR");
  500.           break;
  501.         case R500_FC_B_OP0_INCR:
  502.         case R500_FC_B_OP1_INCR:
  503.           fprintf(stderr, "INCR");
  504.           break;
  505.         }
  506.       }
  507.       /*POP_CNT B_ELSE */
  508.       fprintf(stderr, " %d %1x", (inst >> 16) & 0x1f, (inst & R500_FC_B_ELSE) >> 4);
  509.       inst = code->inst[n].inst3;
  510.       /* JUMP_ADDR */
  511.       fprintf(stderr, " %d", inst >> 16);
  512.      
  513.       if(code->inst[n].inst2 & R500_FC_IGNORE_UNCOVERED){
  514.         fprintf(stderr, " IGN_UNC");
  515.       }
  516.       inst = code->inst[n].inst3;
  517.       fprintf(stderr, "\n\t3:FC_ADDR    0x%08x:", inst);
  518.       fprintf(stderr, "BOOL: 0x%02x, INT: 0x%02x, JUMP_ADDR: %d, JMP_GLBL: %1x\n",
  519.       inst & 0x1f, (inst >> 8) & 0x1f, (inst >> 16) & 0x1ff, inst >> 31);
  520.       break;
  521.     case R500_INST_TYPE_TEX:
  522.       inst = code->inst[n].inst1;
  523.       fprintf(stderr,"\t1:TEX_INST:  0x%08x: id: %d op:%s, %s, %s %s\n", inst, (inst >> 16) & 0xf,
  524.               to_texop((inst >> 22) & 0x7), (inst & (1<<25)) ? "ACQ" : "",
  525.               (inst & (1<<26)) ? "IGNUNC" : "", (inst & (1<<27)) ? "UNSCALED" : "SCALED");
  526.       inst = code->inst[n].inst2;
  527.       fprintf(stderr,"\t2:TEX_ADDR:  0x%08x: src: %d%s %s/%s/%s/%s dst: %d%s %s/%s/%s/%s\n", inst,
  528.               inst & 127, inst & (1<<7) ? "(rel)" : "",
  529.               toswiz((inst >> 8) & 0x3), toswiz((inst >> 10) & 0x3),
  530.               toswiz((inst >> 12) & 0x3), toswiz((inst >> 14) & 0x3),
  531.               (inst >> 16) & 127, inst & (1<<23) ? "(rel)" : "",
  532.               toswiz((inst >> 24) & 0x3), toswiz((inst >> 26) & 0x3),
  533.               toswiz((inst >> 28) & 0x3), toswiz((inst >> 30) & 0x3));
  534.  
  535.       fprintf(stderr,"\t3:TEX_DXDY:  0x%08x\n", code->inst[n].inst3);
  536.       break;
  537.     }
  538.     fprintf(stderr,"\n");
  539.   }
  540.  
  541. }
  542.