Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  8.  * license, and/or sell copies of the Software, and to permit persons to whom
  9.  * the Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18.  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21.  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
  22.  
  23. #include "radeon_program.h"
  24.  
  25. #include <stdio.h>
  26.  
  27. static const char * textarget_to_string(rc_texture_target target)
  28. {
  29.         switch(target) {
  30.         case RC_TEXTURE_2D_ARRAY: return "2D_ARRAY";
  31.         case RC_TEXTURE_1D_ARRAY: return "1D_ARRAY";
  32.         case RC_TEXTURE_CUBE: return "CUBE";
  33.         case RC_TEXTURE_3D: return "3D";
  34.         case RC_TEXTURE_RECT: return "RECT";
  35.         case RC_TEXTURE_2D: return "2D";
  36.         case RC_TEXTURE_1D: return "1D";
  37.         default: return "BAD_TEXTURE_TARGET";
  38.         }
  39. }
  40.  
  41. static const char * presubtract_op_to_string(rc_presubtract_op op)
  42. {
  43.         switch(op) {
  44.         case RC_PRESUB_NONE:
  45.                 return "NONE";
  46.         case RC_PRESUB_BIAS:
  47.                 return "(1 - 2 * src0)";
  48.         case RC_PRESUB_SUB:
  49.                 return "(src1 - src0)";
  50.         case RC_PRESUB_ADD:
  51.                 return "(src1 + src0)";
  52.         case RC_PRESUB_INV:
  53.                 return "(1 - src0)";
  54.         default:
  55.                 return "BAD_PRESUBTRACT_OP";
  56.         }
  57. }
  58.  
  59. static void print_omod_op(FILE * f, rc_omod_op op)
  60. {
  61.         const char * omod_str;
  62.  
  63.         switch(op) {
  64.         case RC_OMOD_MUL_1:
  65.         case RC_OMOD_DISABLE:
  66.                 return;
  67.         case RC_OMOD_MUL_2:
  68.                 omod_str = "* 2";
  69.                 break;
  70.         case RC_OMOD_MUL_4:
  71.                 omod_str = "* 4";
  72.                 break;
  73.         case RC_OMOD_MUL_8:
  74.                 omod_str = "* 8";
  75.                 break;
  76.         case RC_OMOD_DIV_2:
  77.                 omod_str = "/ 2";
  78.                 break;
  79.         case RC_OMOD_DIV_4:
  80.                 omod_str = "/ 4";
  81.                 break;
  82.         case RC_OMOD_DIV_8:
  83.                 omod_str = "/ 8";
  84.                 break;
  85.         default:
  86.                 return;
  87.         }
  88.         fprintf(f, " %s", omod_str);
  89. }
  90.  
  91. static void rc_print_comparefunc(FILE * f, const char * lhs, rc_compare_func func, const char * rhs)
  92. {
  93.         if (func == RC_COMPARE_FUNC_NEVER) {
  94.                 fprintf(f, "false");
  95.         } else if (func == RC_COMPARE_FUNC_ALWAYS) {
  96.                 fprintf(f, "true");
  97.         } else {
  98.                 const char * op;
  99.                 switch(func) {
  100.                 case RC_COMPARE_FUNC_LESS: op = "<"; break;
  101.                 case RC_COMPARE_FUNC_EQUAL: op = "=="; break;
  102.                 case RC_COMPARE_FUNC_LEQUAL: op = "<="; break;
  103.                 case RC_COMPARE_FUNC_GREATER: op = ">"; break;
  104.                 case RC_COMPARE_FUNC_NOTEQUAL: op = "!="; break;
  105.                 case RC_COMPARE_FUNC_GEQUAL: op = ">="; break;
  106.                 default: op = "???"; break;
  107.                 }
  108.                 fprintf(f, "%s %s %s", lhs, op, rhs);
  109.         }
  110. }
  111.  
  112. static void rc_print_inline_float(FILE * f, int index)
  113. {
  114.         int r300_exponent = (index >> 3) & 0xf;
  115.         unsigned r300_mantissa = index & 0x7;
  116.         unsigned float_exponent;
  117.         unsigned real_float;
  118.         float * print_float = (float*) &real_float;
  119.  
  120.         r300_exponent -= 7;
  121.         float_exponent = r300_exponent + 127;
  122.         real_float = (r300_mantissa << 20) | (float_exponent << 23);
  123.  
  124.         fprintf(f, "%f (0x%x)", *print_float, index);
  125.  
  126. }
  127.  
  128. static void rc_print_register(FILE * f, rc_register_file file, int index, unsigned int reladdr)
  129. {
  130.         if (file == RC_FILE_NONE) {
  131.                 fprintf(f, "none");
  132.         } else if (file == RC_FILE_SPECIAL) {
  133.                 switch(index) {
  134.                 case RC_SPECIAL_ALU_RESULT: fprintf(f, "aluresult"); break;
  135.                 default: fprintf(f, "special[%i]", index); break;
  136.                 }
  137.         } else if (file == RC_FILE_INLINE) {
  138.                 rc_print_inline_float(f, index);
  139.         } else {
  140.                 const char * filename;
  141.                 switch(file) {
  142.                 case RC_FILE_TEMPORARY: filename = "temp"; break;
  143.                 case RC_FILE_INPUT: filename = "input"; break;
  144.                 case RC_FILE_OUTPUT: filename = "output"; break;
  145.                 case RC_FILE_ADDRESS: filename = "addr"; break;
  146.                 case RC_FILE_CONSTANT: filename = "const"; break;
  147.                 default: filename = "BAD FILE"; break;
  148.                 }
  149.                 fprintf(f, "%s[%i%s]", filename, index, reladdr ? " + addr[0]" : "");
  150.         }
  151. }
  152.  
  153. static void rc_print_mask(FILE * f, unsigned int mask)
  154. {
  155.         if (mask & RC_MASK_X) fprintf(f, "x");
  156.         if (mask & RC_MASK_Y) fprintf(f, "y");
  157.         if (mask & RC_MASK_Z) fprintf(f, "z");
  158.         if (mask & RC_MASK_W) fprintf(f, "w");
  159. }
  160.  
  161. static void rc_print_dst_register(FILE * f, struct rc_dst_register dst)
  162. {
  163.         rc_print_register(f, dst.File, dst.Index, 0);
  164.         if (dst.WriteMask != RC_MASK_XYZW) {
  165.                 fprintf(f, ".");
  166.                 rc_print_mask(f, dst.WriteMask);
  167.         }
  168. }
  169.  
  170. static char rc_swizzle_char(unsigned int swz)
  171. {
  172.         switch(swz) {
  173.         case RC_SWIZZLE_X: return 'x';
  174.         case RC_SWIZZLE_Y: return 'y';
  175.         case RC_SWIZZLE_Z: return 'z';
  176.         case RC_SWIZZLE_W: return 'w';
  177.         case RC_SWIZZLE_ZERO: return '0';
  178.         case RC_SWIZZLE_ONE: return '1';
  179.         case RC_SWIZZLE_HALF: return 'H';
  180.         case RC_SWIZZLE_UNUSED: return '_';
  181.         }
  182.         fprintf(stderr, "bad swz: %u\n", swz);
  183.         return '?';
  184. }
  185.  
  186. static void rc_print_swizzle(FILE * f, unsigned int swizzle, unsigned int negate)
  187. {
  188.         unsigned int comp;
  189.         for(comp = 0; comp < 4; ++comp) {
  190.                 rc_swizzle swz = GET_SWZ(swizzle, comp);
  191.                 if (GET_BIT(negate, comp))
  192.                         fprintf(f, "-");
  193.                 fprintf(f, "%c", rc_swizzle_char(swz));
  194.         }
  195. }
  196.  
  197. static void rc_print_presub_instruction(FILE * f,
  198.                                         struct rc_presub_instruction inst)
  199. {
  200.         fprintf(f,"(");
  201.         switch(inst.Opcode){
  202.         case RC_PRESUB_BIAS:
  203.                 fprintf(f, "1 - 2 * ");
  204.                 rc_print_register(f, inst.SrcReg[0].File,
  205.                                 inst.SrcReg[0].Index,inst.SrcReg[0].RelAddr);
  206.                 break;
  207.         case RC_PRESUB_SUB:
  208.                 rc_print_register(f, inst.SrcReg[1].File,
  209.                                 inst.SrcReg[1].Index,inst.SrcReg[1].RelAddr);
  210.                 fprintf(f, " - ");
  211.                 rc_print_register(f, inst.SrcReg[0].File,
  212.                                 inst.SrcReg[0].Index,inst.SrcReg[0].RelAddr);
  213.                 break;
  214.         case RC_PRESUB_ADD:
  215.                 rc_print_register(f, inst.SrcReg[1].File,
  216.                                 inst.SrcReg[1].Index,inst.SrcReg[1].RelAddr);
  217.                 fprintf(f, " + ");
  218.                 rc_print_register(f, inst.SrcReg[0].File,
  219.                                 inst.SrcReg[0].Index,inst.SrcReg[0].RelAddr);
  220.                 break;
  221.         case RC_PRESUB_INV:
  222.                 fprintf(f, "1 - ");
  223.                 rc_print_register(f, inst.SrcReg[0].File,
  224.                                 inst.SrcReg[0].Index,inst.SrcReg[0].RelAddr);
  225.                 break;
  226.         default:
  227.                 break;
  228.         }
  229.         fprintf(f, ")");
  230. }
  231.  
  232. static void rc_print_src_register(FILE * f, struct rc_instruction * inst,
  233.                                                 struct rc_src_register src)
  234. {
  235.         int trivial_negate = (src.Negate == RC_MASK_NONE || src.Negate == RC_MASK_XYZW);
  236.  
  237.         if (src.Negate == RC_MASK_XYZW)
  238.                 fprintf(f, "-");
  239.         if (src.Abs)
  240.                 fprintf(f, "|");
  241.  
  242.         if(src.File == RC_FILE_PRESUB)
  243.                 rc_print_presub_instruction(f, inst->U.I.PreSub);
  244.         else
  245.                 rc_print_register(f, src.File, src.Index, src.RelAddr);
  246.  
  247.         if (src.Abs && !trivial_negate)
  248.                 fprintf(f, "|");
  249.  
  250.         if (src.Swizzle != RC_SWIZZLE_XYZW || !trivial_negate) {
  251.                 fprintf(f, ".");
  252.                 rc_print_swizzle(f, src.Swizzle, trivial_negate ? 0 : src.Negate);
  253.         }
  254.  
  255.         if (src.Abs && trivial_negate)
  256.                 fprintf(f, "|");
  257. }
  258.  
  259. static unsigned update_branch_depth(rc_opcode opcode, unsigned *branch_depth)
  260. {
  261.         switch (opcode) {
  262.         case RC_OPCODE_IF:
  263.         case RC_OPCODE_BGNLOOP:
  264.                 return (*branch_depth)++ * 2;
  265.  
  266.         case RC_OPCODE_ENDIF:
  267.         case RC_OPCODE_ENDLOOP:
  268.                 assert(*branch_depth > 0);
  269.                 return --(*branch_depth) * 2;
  270.  
  271.         case RC_OPCODE_ELSE:
  272.                 assert(*branch_depth > 0);
  273.                 return (*branch_depth - 1) * 2;
  274.  
  275.         default:
  276.                 return *branch_depth * 2;
  277.         }
  278. }
  279.  
  280. static void rc_print_normal_instruction(FILE * f, struct rc_instruction * inst, unsigned *branch_depth)
  281. {
  282.         const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
  283.         unsigned int reg;
  284.         unsigned spaces = update_branch_depth(inst->U.I.Opcode, branch_depth);
  285.  
  286.         for (unsigned i = 0; i < spaces; i++)
  287.                 fprintf(f, " ");
  288.  
  289.         fprintf(f, "%s", opcode->Name);
  290.  
  291.         switch(inst->U.I.SaturateMode) {
  292.         case RC_SATURATE_NONE: break;
  293.         case RC_SATURATE_ZERO_ONE: fprintf(f, "_SAT"); break;
  294.         case RC_SATURATE_MINUS_PLUS_ONE: fprintf(f, "_SAT2"); break;
  295.         default: fprintf(f, "_BAD_SAT"); break;
  296.         }
  297.  
  298.         if (opcode->HasDstReg) {
  299.                 fprintf(f, " ");
  300.                 rc_print_dst_register(f, inst->U.I.DstReg);
  301.                 print_omod_op(f, inst->U.I.Omod);
  302.                 if (opcode->NumSrcRegs)
  303.                         fprintf(f, ",");
  304.         }
  305.  
  306.         for(reg = 0; reg < opcode->NumSrcRegs; ++reg) {
  307.                 if (reg > 0)
  308.                         fprintf(f, ",");
  309.                 fprintf(f, " ");
  310.                 rc_print_src_register(f, inst, inst->U.I.SrcReg[reg]);
  311.         }
  312.  
  313.         if (opcode->HasTexture) {
  314.                 fprintf(f, ", %s%s[%u]%s%s",
  315.                         textarget_to_string(inst->U.I.TexSrcTarget),
  316.                         inst->U.I.TexShadow ? "SHADOW" : "",
  317.                         inst->U.I.TexSrcUnit,
  318.                         inst->U.I.TexSemWait ? " SEM_WAIT" : "",
  319.                         inst->U.I.TexSemAcquire ? " SEM_ACQUIRE" : "");
  320.         }
  321.  
  322.         fprintf(f, ";");
  323.  
  324.         if (inst->U.I.WriteALUResult) {
  325.                 fprintf(f, " [aluresult = (");
  326.                 rc_print_comparefunc(f,
  327.                         (inst->U.I.WriteALUResult == RC_ALURESULT_X) ? "x" : "w",
  328.                         inst->U.I.ALUResultCompare, "0");
  329.                 fprintf(f, ")]");
  330.         }
  331.  
  332.         if (inst->U.I.DstReg.Pred == RC_PRED_SET) {
  333.                 fprintf(f, " PRED_SET");
  334.         } else if (inst->U.I.DstReg.Pred == RC_PRED_INV) {
  335.                 fprintf(f, " PRED_INV");
  336.         }
  337.  
  338.         fprintf(f, "\n");
  339. }
  340.  
  341. static void rc_print_pair_instruction(FILE * f, struct rc_instruction * fullinst, unsigned *branch_depth)
  342. {
  343.         struct rc_pair_instruction * inst = &fullinst->U.P;
  344.         int printedsrc = 0;
  345.         unsigned spaces = update_branch_depth(inst->RGB.Opcode != RC_OPCODE_NOP ?
  346.                                               inst->RGB.Opcode : inst->Alpha.Opcode, branch_depth);
  347.  
  348.         for (unsigned i = 0; i < spaces; i++)
  349.                 fprintf(f, " ");
  350.  
  351.         for(unsigned int src = 0; src < 3; ++src) {
  352.                 if (inst->RGB.Src[src].Used) {
  353.                         if (printedsrc)
  354.                                 fprintf(f, ", ");
  355.                         fprintf(f, "src%i.xyz = ", src);
  356.                         rc_print_register(f, inst->RGB.Src[src].File, inst->RGB.Src[src].Index, 0);
  357.                         printedsrc = 1;
  358.                 }
  359.                 if (inst->Alpha.Src[src].Used) {
  360.                         if (printedsrc)
  361.                                 fprintf(f, ", ");
  362.                         fprintf(f, "src%i.w = ", src);
  363.                         rc_print_register(f, inst->Alpha.Src[src].File, inst->Alpha.Src[src].Index, 0);
  364.                         printedsrc = 1;
  365.                 }
  366.         }
  367.         if(inst->RGB.Src[RC_PAIR_PRESUB_SRC].Used) {
  368.                 fprintf(f, ", srcp.xyz = %s",
  369.                         presubtract_op_to_string(
  370.                                         inst->RGB.Src[RC_PAIR_PRESUB_SRC].Index));
  371.         }
  372.         if(inst->Alpha.Src[RC_PAIR_PRESUB_SRC].Used) {
  373.                 fprintf(f, ", srcp.w = %s",
  374.                         presubtract_op_to_string(
  375.                                         inst->Alpha.Src[RC_PAIR_PRESUB_SRC].Index));
  376.         }
  377.         if (inst->SemWait) {
  378.                 fprintf(f, " SEM_WAIT");
  379.         }
  380.         fprintf(f, "\n");
  381.  
  382.         if (inst->RGB.Opcode != RC_OPCODE_NOP) {
  383.                 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->RGB.Opcode);
  384.  
  385.                 for (unsigned i = 0; i < spaces; i++)
  386.                         fprintf(f, " ");
  387.  
  388.                 fprintf(f, "     %s%s", opcode->Name, inst->RGB.Saturate ? "_SAT" : "");
  389.                 if (inst->RGB.WriteMask)
  390.                         fprintf(f, " temp[%i].%s%s%s", inst->RGB.DestIndex,
  391.                                 (inst->RGB.WriteMask & 1) ? "x" : "",
  392.                                 (inst->RGB.WriteMask & 2) ? "y" : "",
  393.                                 (inst->RGB.WriteMask & 4) ? "z" : "");
  394.                 if (inst->RGB.OutputWriteMask)
  395.                         fprintf(f, " color[%i].%s%s%s", inst->RGB.Target,
  396.                                 (inst->RGB.OutputWriteMask & 1) ? "x" : "",
  397.                                 (inst->RGB.OutputWriteMask & 2) ? "y" : "",
  398.                                 (inst->RGB.OutputWriteMask & 4) ? "z" : "");
  399.                 if (inst->WriteALUResult == RC_ALURESULT_X)
  400.                         fprintf(f, " aluresult");
  401.  
  402.                 print_omod_op(f, inst->RGB.Omod);
  403.  
  404.                 for(unsigned int arg = 0; arg < opcode->NumSrcRegs; ++arg) {
  405.                         const char* abs = inst->RGB.Arg[arg].Abs ? "|" : "";
  406.                         const char* neg = inst->RGB.Arg[arg].Negate ? "-" : "";
  407.                         fprintf(f, ", %s%ssrc", neg, abs);
  408.                         if(inst->RGB.Arg[arg].Source == RC_PAIR_PRESUB_SRC)
  409.                                 fprintf(f,"p");
  410.                         else
  411.                                 fprintf(f,"%d", inst->RGB.Arg[arg].Source);
  412.                         fprintf(f,".%c%c%c%s",
  413.                                 rc_swizzle_char(GET_SWZ(inst->RGB.Arg[arg].Swizzle, 0)),
  414.                                 rc_swizzle_char(GET_SWZ(inst->RGB.Arg[arg].Swizzle, 1)),
  415.                                 rc_swizzle_char(GET_SWZ(inst->RGB.Arg[arg].Swizzle, 2)),
  416.                                 abs);
  417.                 }
  418.                 fprintf(f, "\n");
  419.         }
  420.  
  421.         if (inst->Alpha.Opcode != RC_OPCODE_NOP) {
  422.                 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Alpha.Opcode);
  423.  
  424.                 for (unsigned i = 0; i < spaces; i++)
  425.                         fprintf(f, " ");
  426.  
  427.                 fprintf(f, "     %s%s", opcode->Name, inst->Alpha.Saturate ? "_SAT" : "");
  428.                 if (inst->Alpha.WriteMask)
  429.                         fprintf(f, " temp[%i].w", inst->Alpha.DestIndex);
  430.                 if (inst->Alpha.OutputWriteMask)
  431.                         fprintf(f, " color[%i].w", inst->Alpha.Target);
  432.                 if (inst->Alpha.DepthWriteMask)
  433.                         fprintf(f, " depth.w");
  434.                 if (inst->WriteALUResult == RC_ALURESULT_W)
  435.                         fprintf(f, " aluresult");
  436.  
  437.                 print_omod_op(f, inst->Alpha.Omod);
  438.  
  439.                 for(unsigned int arg = 0; arg < opcode->NumSrcRegs; ++arg) {
  440.                         const char* abs = inst->Alpha.Arg[arg].Abs ? "|" : "";
  441.                         const char* neg = inst->Alpha.Arg[arg].Negate ? "-" : "";
  442.                         fprintf(f, ", %s%ssrc", neg, abs);
  443.                         if(inst->Alpha.Arg[arg].Source == RC_PAIR_PRESUB_SRC)
  444.                                 fprintf(f,"p");
  445.                         else
  446.                                 fprintf(f,"%d", inst->Alpha.Arg[arg].Source);
  447.                         fprintf(f,".%c%s",
  448.                                 rc_swizzle_char(GET_SWZ(inst->Alpha.Arg[arg].Swizzle, 0)), abs);
  449.                 }
  450.                 fprintf(f, "\n");
  451.         }
  452.  
  453.         if (inst->WriteALUResult) {
  454.                 for (unsigned i = 0; i < spaces; i++)
  455.                         fprintf(f, " ");
  456.  
  457.                 fprintf(f, "      [aluresult = (");
  458.                 rc_print_comparefunc(f, "result", inst->ALUResultCompare, "0");
  459.                 fprintf(f, ")]\n");
  460.         }
  461. }
  462.  
  463. /**
  464.  * Print program to stderr, default options.
  465.  */
  466. void rc_print_program(const struct rc_program *prog)
  467. {
  468.         unsigned int linenum = 0;
  469.         unsigned branch_depth = 0;
  470.         struct rc_instruction *inst;
  471.  
  472.         fprintf(stderr, "# Radeon Compiler Program\n");
  473.  
  474.         for(inst = prog->Instructions.Next; inst != &prog->Instructions; inst = inst->Next) {
  475.                 fprintf(stderr, "%3d: ", linenum);
  476.  
  477.                 if (inst->Type == RC_INSTRUCTION_PAIR)
  478.                         rc_print_pair_instruction(stderr, inst, &branch_depth);
  479.                 else
  480.                         rc_print_normal_instruction(stderr, inst, &branch_depth);
  481.  
  482.                 linenum++;
  483.         }
  484. }
  485.