Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright (c) 2012 Rob Clark <robdclark@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.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21.  * SOFTWARE.
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <stdint.h>
  27. #include <unistd.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #include <fcntl.h>
  31. #include <string.h>
  32.  
  33. #include "disasm.h"
  34. #include "instr-a2xx.h"
  35.  
  36. static const char *levels[] = {
  37.                 "\t",
  38.                 "\t\t",
  39.                 "\t\t\t",
  40.                 "\t\t\t\t",
  41.                 "\t\t\t\t\t",
  42.                 "\t\t\t\t\t\t",
  43.                 "\t\t\t\t\t\t\t",
  44.                 "\t\t\t\t\t\t\t\t",
  45.                 "\t\t\t\t\t\t\t\t\t",
  46.                 "x",
  47.                 "x",
  48.                 "x",
  49.                 "x",
  50.                 "x",
  51.                 "x",
  52. };
  53.  
  54. static enum debug_t debug;
  55.  
  56. /*
  57.  * ALU instructions:
  58.  */
  59.  
  60. static const char chan_names[] = {
  61.                 'x', 'y', 'z', 'w',
  62.                 /* these only apply to FETCH dst's: */
  63.                 '0', '1', '?', '_',
  64. };
  65.  
  66. static void print_srcreg(uint32_t num, uint32_t type,
  67.                 uint32_t swiz, uint32_t negate, uint32_t abs)
  68. {
  69.         if (negate)
  70.                 printf("-");
  71.         if (abs)
  72.                 printf("|");
  73.         printf("%c%u", type ? 'R' : 'C', num);
  74.         if (swiz) {
  75.                 int i;
  76.                 printf(".");
  77.                 for (i = 0; i < 4; i++) {
  78.                         printf("%c", chan_names[(swiz + i) & 0x3]);
  79.                         swiz >>= 2;
  80.                 }
  81.         }
  82.         if (abs)
  83.                 printf("|");
  84. }
  85.  
  86. static void print_dstreg(uint32_t num, uint32_t mask, uint32_t dst_exp)
  87. {
  88.         printf("%s%u", dst_exp ? "export" : "R", num);
  89.         if (mask != 0xf) {
  90.                 int i;
  91.                 printf(".");
  92.                 for (i = 0; i < 4; i++) {
  93.                         printf("%c", (mask & 0x1) ? chan_names[i] : '_');
  94.                         mask >>= 1;
  95.                 }
  96.         }
  97. }
  98.  
  99. static void print_export_comment(uint32_t num, enum shader_t type)
  100. {
  101.         const char *name = NULL;
  102.         switch (type) {
  103.         case SHADER_VERTEX:
  104.                 switch (num) {
  105.                 case 62: name = "gl_Position";  break;
  106.                 case 63: name = "gl_PointSize"; break;
  107.                 }
  108.                 break;
  109.         case SHADER_FRAGMENT:
  110.                 switch (num) {
  111.                 case 0:  name = "gl_FragColor"; break;
  112.                 }
  113.                 break;
  114.         }
  115.         /* if we had a symbol table here, we could look
  116.          * up the name of the varying..
  117.          */
  118.         if (name) {
  119.                 printf("\t; %s", name);
  120.         }
  121. }
  122.  
  123. struct {
  124.         uint32_t num_srcs;
  125.         const char *name;
  126. } vector_instructions[0x20] = {
  127. #define INSTR(opc, num_srcs) [opc] = { num_srcs, #opc }
  128.                 INSTR(ADDv, 2),
  129.                 INSTR(MULv, 2),
  130.                 INSTR(MAXv, 2),
  131.                 INSTR(MINv, 2),
  132.                 INSTR(SETEv, 2),
  133.                 INSTR(SETGTv, 2),
  134.                 INSTR(SETGTEv, 2),
  135.                 INSTR(SETNEv, 2),
  136.                 INSTR(FRACv, 1),
  137.                 INSTR(TRUNCv, 1),
  138.                 INSTR(FLOORv, 1),
  139.                 INSTR(MULADDv, 3),
  140.                 INSTR(CNDEv, 3),
  141.                 INSTR(CNDGTEv, 3),
  142.                 INSTR(CNDGTv, 3),
  143.                 INSTR(DOT4v, 2),
  144.                 INSTR(DOT3v, 2),
  145.                 INSTR(DOT2ADDv, 3),  // ???
  146.                 INSTR(CUBEv, 2),
  147.                 INSTR(MAX4v, 1),
  148.                 INSTR(PRED_SETE_PUSHv, 2),
  149.                 INSTR(PRED_SETNE_PUSHv, 2),
  150.                 INSTR(PRED_SETGT_PUSHv, 2),
  151.                 INSTR(PRED_SETGTE_PUSHv, 2),
  152.                 INSTR(KILLEv, 2),
  153.                 INSTR(KILLGTv, 2),
  154.                 INSTR(KILLGTEv, 2),
  155.                 INSTR(KILLNEv, 2),
  156.                 INSTR(DSTv, 2),
  157.                 INSTR(MOVAv, 1),
  158. }, scalar_instructions[0x40] = {
  159.                 INSTR(ADDs, 1),
  160.                 INSTR(ADD_PREVs, 1),
  161.                 INSTR(MULs, 1),
  162.                 INSTR(MUL_PREVs, 1),
  163.                 INSTR(MUL_PREV2s, 1),
  164.                 INSTR(MAXs, 1),
  165.                 INSTR(MINs, 1),
  166.                 INSTR(SETEs, 1),
  167.                 INSTR(SETGTs, 1),
  168.                 INSTR(SETGTEs, 1),
  169.                 INSTR(SETNEs, 1),
  170.                 INSTR(FRACs, 1),
  171.                 INSTR(TRUNCs, 1),
  172.                 INSTR(FLOORs, 1),
  173.                 INSTR(EXP_IEEE, 1),
  174.                 INSTR(LOG_CLAMP, 1),
  175.                 INSTR(LOG_IEEE, 1),
  176.                 INSTR(RECIP_CLAMP, 1),
  177.                 INSTR(RECIP_FF, 1),
  178.                 INSTR(RECIP_IEEE, 1),
  179.                 INSTR(RECIPSQ_CLAMP, 1),
  180.                 INSTR(RECIPSQ_FF, 1),
  181.                 INSTR(RECIPSQ_IEEE, 1),
  182.                 INSTR(MOVAs, 1),
  183.                 INSTR(MOVA_FLOORs, 1),
  184.                 INSTR(SUBs, 1),
  185.                 INSTR(SUB_PREVs, 1),
  186.                 INSTR(PRED_SETEs, 1),
  187.                 INSTR(PRED_SETNEs, 1),
  188.                 INSTR(PRED_SETGTs, 1),
  189.                 INSTR(PRED_SETGTEs, 1),
  190.                 INSTR(PRED_SET_INVs, 1),
  191.                 INSTR(PRED_SET_POPs, 1),
  192.                 INSTR(PRED_SET_CLRs, 1),
  193.                 INSTR(PRED_SET_RESTOREs, 1),
  194.                 INSTR(KILLEs, 1),
  195.                 INSTR(KILLGTs, 1),
  196.                 INSTR(KILLGTEs, 1),
  197.                 INSTR(KILLNEs, 1),
  198.                 INSTR(KILLONEs, 1),
  199.                 INSTR(SQRT_IEEE, 1),
  200.                 INSTR(MUL_CONST_0, 1),
  201.                 INSTR(MUL_CONST_1, 1),
  202.                 INSTR(ADD_CONST_0, 1),
  203.                 INSTR(ADD_CONST_1, 1),
  204.                 INSTR(SUB_CONST_0, 1),
  205.                 INSTR(SUB_CONST_1, 1),
  206.                 INSTR(SIN, 1),
  207.                 INSTR(COS, 1),
  208.                 INSTR(RETAIN_PREV, 1),
  209. #undef INSTR
  210. };
  211.  
  212. static int disasm_alu(uint32_t *dwords, uint32_t alu_off,
  213.                 int level, int sync, enum shader_t type)
  214. {
  215.         instr_alu_t *alu = (instr_alu_t *)dwords;
  216.  
  217.         printf("%s", levels[level]);
  218.         if (debug & PRINT_RAW) {
  219.                 printf("%02x: %08x %08x %08x\t", alu_off,
  220.                                 dwords[0], dwords[1], dwords[2]);
  221.         }
  222.  
  223.         printf("   %sALU:\t", sync ? "(S)" : "   ");
  224.  
  225.         printf("%s", vector_instructions[alu->vector_opc].name);
  226.  
  227.         if (alu->pred_select & 0x2) {
  228.                 /* seems to work similar to conditional execution in ARM instruction
  229.                  * set, so let's use a similar syntax for now:
  230.                  */
  231.                 printf((alu->pred_select & 0x1) ? "EQ" : "NE");
  232.         }
  233.  
  234.         printf("\t");
  235.  
  236.         print_dstreg(alu->vector_dest, alu->vector_write_mask, alu->export_data);
  237.         printf(" = ");
  238.         if (vector_instructions[alu->vector_opc].num_srcs == 3) {
  239.                 print_srcreg(alu->src3_reg, alu->src3_sel, alu->src3_swiz,
  240.                                 alu->src3_reg_negate, alu->src3_reg_abs);
  241.                 printf(", ");
  242.         }
  243.         print_srcreg(alu->src1_reg, alu->src1_sel, alu->src1_swiz,
  244.                         alu->src1_reg_negate, alu->src1_reg_abs);
  245.         if (vector_instructions[alu->vector_opc].num_srcs > 1) {
  246.                 printf(", ");
  247.                 print_srcreg(alu->src2_reg, alu->src2_sel, alu->src2_swiz,
  248.                                 alu->src2_reg_negate, alu->src2_reg_abs);
  249.         }
  250.  
  251.         if (alu->vector_clamp)
  252.                 printf(" CLAMP");
  253.  
  254.         if (alu->export_data)
  255.                 print_export_comment(alu->vector_dest, type);
  256.  
  257.         printf("\n");
  258.  
  259.         if (alu->scalar_write_mask || !alu->vector_write_mask) {
  260.                 /* 2nd optional scalar op: */
  261.  
  262.                 printf("%s", levels[level]);
  263.                 if (debug & PRINT_RAW)
  264.                         printf("                          \t");
  265.  
  266.                 if (scalar_instructions[alu->scalar_opc].name) {
  267.                         printf("\t    \t%s\t", scalar_instructions[alu->scalar_opc].name);
  268.                 } else {
  269.                         printf("\t    \tOP(%u)\t", alu->scalar_opc);
  270.                 }
  271.  
  272.                 print_dstreg(alu->scalar_dest, alu->scalar_write_mask, alu->export_data);
  273.                 printf(" = ");
  274.                 print_srcreg(alu->src3_reg, alu->src3_sel, alu->src3_swiz,
  275.                                 alu->src3_reg_negate, alu->src3_reg_abs);
  276.                 // TODO ADD/MUL must have another src?!?
  277.                 if (alu->scalar_clamp)
  278.                         printf(" CLAMP");
  279.                 if (alu->export_data)
  280.                         print_export_comment(alu->scalar_dest, type);
  281.                 printf("\n");
  282.         }
  283.  
  284.         return 0;
  285. }
  286.  
  287.  
  288. /*
  289.  * FETCH instructions:
  290.  */
  291.  
  292. struct {
  293.         const char *name;
  294. } fetch_types[0xff] = {
  295. #define TYPE(id) [id] = { #id }
  296.                 TYPE(FMT_1_REVERSE),
  297.                 TYPE(FMT_32_FLOAT),
  298.                 TYPE(FMT_32_32_FLOAT),
  299.                 TYPE(FMT_32_32_32_FLOAT),
  300.                 TYPE(FMT_32_32_32_32_FLOAT),
  301.                 TYPE(FMT_16),
  302.                 TYPE(FMT_16_16),
  303.                 TYPE(FMT_16_16_16_16),
  304.                 TYPE(FMT_8),
  305.                 TYPE(FMT_8_8),
  306.                 TYPE(FMT_8_8_8_8),
  307.                 TYPE(FMT_32),
  308.                 TYPE(FMT_32_32),
  309.                 TYPE(FMT_32_32_32_32),
  310. #undef TYPE
  311. };
  312.  
  313. static void print_fetch_dst(uint32_t dst_reg, uint32_t dst_swiz)
  314. {
  315.         int i;
  316.         printf("\tR%u.", dst_reg);
  317.         for (i = 0; i < 4; i++) {
  318.                 printf("%c", chan_names[dst_swiz & 0x7]);
  319.                 dst_swiz >>= 3;
  320.         }
  321. }
  322.  
  323. static void print_fetch_vtx(instr_fetch_t *fetch)
  324. {
  325.         instr_fetch_vtx_t *vtx = &fetch->vtx;
  326.  
  327.         if (vtx->pred_select) {
  328.                 /* seems to work similar to conditional execution in ARM instruction
  329.                  * set, so let's use a similar syntax for now:
  330.                  */
  331.                 printf(vtx->pred_condition ? "EQ" : "NE");
  332.         }
  333.  
  334.         print_fetch_dst(vtx->dst_reg, vtx->dst_swiz);
  335.         printf(" = R%u.", vtx->src_reg);
  336.         printf("%c", chan_names[vtx->src_swiz & 0x3]);
  337.         if (fetch_types[vtx->format].name) {
  338.                 printf(" %s", fetch_types[vtx->format].name);
  339.         } else  {
  340.                 printf(" TYPE(0x%x)", vtx->format);
  341.         }
  342.         printf(" %s", vtx->format_comp_all ? "SIGNED" : "UNSIGNED");
  343.         if (!vtx->num_format_all)
  344.                 printf(" NORMALIZED");
  345.         printf(" STRIDE(%u)", vtx->stride);
  346.         if (vtx->offset)
  347.                 printf(" OFFSET(%u)", vtx->offset);
  348.         printf(" CONST(%u, %u)", vtx->const_index, vtx->const_index_sel);
  349.         if (0) {
  350.                 // XXX
  351.                 printf(" src_reg_am=%u", vtx->src_reg_am);
  352.                 printf(" dst_reg_am=%u", vtx->dst_reg_am);
  353.                 printf(" num_format_all=%u", vtx->num_format_all);
  354.                 printf(" signed_rf_mode_all=%u", vtx->signed_rf_mode_all);
  355.                 printf(" exp_adjust_all=%u", vtx->exp_adjust_all);
  356.         }
  357. }
  358.  
  359. static void print_fetch_tex(instr_fetch_t *fetch)
  360. {
  361.         static const char *filter[] = {
  362.                         [TEX_FILTER_POINT] = "POINT",
  363.                         [TEX_FILTER_LINEAR] = "LINEAR",
  364.                         [TEX_FILTER_BASEMAP] = "BASEMAP",
  365.         };
  366.         static const char *aniso_filter[] = {
  367.                         [ANISO_FILTER_DISABLED] = "DISABLED",
  368.                         [ANISO_FILTER_MAX_1_1] = "MAX_1_1",
  369.                         [ANISO_FILTER_MAX_2_1] = "MAX_2_1",
  370.                         [ANISO_FILTER_MAX_4_1] = "MAX_4_1",
  371.                         [ANISO_FILTER_MAX_8_1] = "MAX_8_1",
  372.                         [ANISO_FILTER_MAX_16_1] = "MAX_16_1",
  373.         };
  374.         static const char *arbitrary_filter[] = {
  375.                         [ARBITRARY_FILTER_2X4_SYM] = "2x4_SYM",
  376.                         [ARBITRARY_FILTER_2X4_ASYM] = "2x4_ASYM",
  377.                         [ARBITRARY_FILTER_4X2_SYM] = "4x2_SYM",
  378.                         [ARBITRARY_FILTER_4X2_ASYM] = "4x2_ASYM",
  379.                         [ARBITRARY_FILTER_4X4_SYM] = "4x4_SYM",
  380.                         [ARBITRARY_FILTER_4X4_ASYM] = "4x4_ASYM",
  381.         };
  382.         static const char *sample_loc[] = {
  383.                         [SAMPLE_CENTROID] = "CENTROID",
  384.                         [SAMPLE_CENTER] = "CENTER",
  385.         };
  386.         instr_fetch_tex_t *tex = &fetch->tex;
  387.         uint32_t src_swiz = tex->src_swiz;
  388.         int i;
  389.  
  390.         if (tex->pred_select) {
  391.                 /* seems to work similar to conditional execution in ARM instruction
  392.                  * set, so let's use a similar syntax for now:
  393.                  */
  394.                 printf(tex->pred_condition ? "EQ" : "NE");
  395.         }
  396.  
  397.         print_fetch_dst(tex->dst_reg, tex->dst_swiz);
  398.         printf(" = R%u.", tex->src_reg);
  399.         for (i = 0; i < 3; i++) {
  400.                 printf("%c", chan_names[src_swiz & 0x3]);
  401.                 src_swiz >>= 2;
  402.         }
  403.         printf(" CONST(%u)", tex->const_idx);
  404.         if (tex->fetch_valid_only)
  405.                 printf(" VALID_ONLY");
  406.         if (tex->tx_coord_denorm)
  407.                 printf(" DENORM");
  408.         if (tex->mag_filter != TEX_FILTER_USE_FETCH_CONST)
  409.                 printf(" MAG(%s)", filter[tex->mag_filter]);
  410.         if (tex->min_filter != TEX_FILTER_USE_FETCH_CONST)
  411.                 printf(" MIN(%s)", filter[tex->min_filter]);
  412.         if (tex->mip_filter != TEX_FILTER_USE_FETCH_CONST)
  413.                 printf(" MIP(%s)", filter[tex->mip_filter]);
  414.         if (tex->aniso_filter != ANISO_FILTER_USE_FETCH_CONST)
  415.                 printf(" ANISO(%s)", aniso_filter[tex->aniso_filter]);
  416.         if (tex->arbitrary_filter != ARBITRARY_FILTER_USE_FETCH_CONST)
  417.                 printf(" ARBITRARY(%s)", arbitrary_filter[tex->arbitrary_filter]);
  418.         if (tex->vol_mag_filter != TEX_FILTER_USE_FETCH_CONST)
  419.                 printf(" VOL_MAG(%s)", filter[tex->vol_mag_filter]);
  420.         if (tex->vol_min_filter != TEX_FILTER_USE_FETCH_CONST)
  421.                 printf(" VOL_MIN(%s)", filter[tex->vol_min_filter]);
  422.         if (!tex->use_comp_lod) {
  423.                 printf(" LOD(%u)", tex->use_comp_lod);
  424.                 printf(" LOD_BIAS(%u)", tex->lod_bias);
  425.         }
  426.         if (tex->use_reg_gradients)
  427.                 printf(" USE_REG_GRADIENTS");
  428.         printf(" LOCATION(%s)", sample_loc[tex->sample_location]);
  429.         if (tex->offset_x || tex->offset_y || tex->offset_z)
  430.                 printf(" OFFSET(%u,%u,%u)", tex->offset_x, tex->offset_y, tex->offset_z);
  431. }
  432.  
  433. struct {
  434.         const char *name;
  435.         void (*fxn)(instr_fetch_t *cf);
  436. } fetch_instructions[] = {
  437. #define INSTR(opc, name, fxn) [opc] = { name, fxn }
  438.                 INSTR(VTX_FETCH, "VERTEX", print_fetch_vtx),
  439.                 INSTR(TEX_FETCH, "SAMPLE", print_fetch_tex),
  440.                 INSTR(TEX_GET_BORDER_COLOR_FRAC, "?", print_fetch_tex),
  441.                 INSTR(TEX_GET_COMP_TEX_LOD, "?", print_fetch_tex),
  442.                 INSTR(TEX_GET_GRADIENTS, "?", print_fetch_tex),
  443.                 INSTR(TEX_GET_WEIGHTS, "?", print_fetch_tex),
  444.                 INSTR(TEX_SET_TEX_LOD, "SET_TEX_LOD", print_fetch_tex),
  445.                 INSTR(TEX_SET_GRADIENTS_H, "?", print_fetch_tex),
  446.                 INSTR(TEX_SET_GRADIENTS_V, "?", print_fetch_tex),
  447.                 INSTR(TEX_RESERVED_4, "?", print_fetch_tex),
  448. #undef INSTR
  449. };
  450.  
  451. static int disasm_fetch(uint32_t *dwords, uint32_t alu_off, int level, int sync)
  452. {
  453.         instr_fetch_t *fetch = (instr_fetch_t *)dwords;
  454.  
  455.         printf("%s", levels[level]);
  456.         if (debug & PRINT_RAW) {
  457.                 printf("%02x: %08x %08x %08x\t", alu_off,
  458.                                 dwords[0], dwords[1], dwords[2]);
  459.         }
  460.  
  461.         printf("   %sFETCH:\t", sync ? "(S)" : "   ");
  462.         printf("%s", fetch_instructions[fetch->opc].name);
  463.         fetch_instructions[fetch->opc].fxn(fetch);
  464.         printf("\n");
  465.  
  466.         return 0;
  467. }
  468.  
  469. /*
  470.  * CF instructions:
  471.  */
  472.  
  473. static int cf_exec(instr_cf_t *cf)
  474. {
  475.         return (cf->opc == EXEC) ||
  476.                         (cf->opc == EXEC_END) ||
  477.                         (cf->opc == COND_EXEC) ||
  478.                         (cf->opc == COND_EXEC_END) ||
  479.                         (cf->opc == COND_PRED_EXEC) ||
  480.                         (cf->opc == COND_PRED_EXEC_END) ||
  481.                         (cf->opc == COND_EXEC_PRED_CLEAN) ||
  482.                         (cf->opc == COND_EXEC_PRED_CLEAN_END);
  483. }
  484.  
  485. static int cf_cond_exec(instr_cf_t *cf)
  486. {
  487.         return (cf->opc == COND_EXEC) ||
  488.                         (cf->opc == COND_EXEC_END) ||
  489.                         (cf->opc == COND_PRED_EXEC) ||
  490.                         (cf->opc == COND_PRED_EXEC_END) ||
  491.                         (cf->opc == COND_EXEC_PRED_CLEAN) ||
  492.                         (cf->opc == COND_EXEC_PRED_CLEAN_END);
  493. }
  494.  
  495. static void print_cf_nop(instr_cf_t *cf)
  496. {
  497. }
  498.  
  499. static void print_cf_exec(instr_cf_t *cf)
  500. {
  501.         printf(" ADDR(0x%x) CNT(0x%x)", cf->exec.address, cf->exec.count);
  502.         if (cf->exec.yeild)
  503.                 printf(" YIELD");
  504.         if (cf->exec.vc)
  505.                 printf(" VC(0x%x)", cf->exec.vc);
  506.         if (cf->exec.bool_addr)
  507.                 printf(" BOOL_ADDR(0x%x)", cf->exec.bool_addr);
  508.         if (cf->exec.address_mode == ABSOLUTE_ADDR)
  509.                 printf(" ABSOLUTE_ADDR");
  510.         if (cf_cond_exec(cf))
  511.                 printf(" COND(%d)", cf->exec.condition);
  512. }
  513.  
  514. static void print_cf_loop(instr_cf_t *cf)
  515. {
  516.         printf(" ADDR(0x%x) LOOP_ID(%d)", cf->loop.address, cf->loop.loop_id);
  517.         if (cf->loop.address_mode == ABSOLUTE_ADDR)
  518.                 printf(" ABSOLUTE_ADDR");
  519. }
  520.  
  521. static void print_cf_jmp_call(instr_cf_t *cf)
  522. {
  523.         printf(" ADDR(0x%x) DIR(%d)", cf->jmp_call.address, cf->jmp_call.direction);
  524.         if (cf->jmp_call.force_call)
  525.                 printf(" FORCE_CALL");
  526.         if (cf->jmp_call.predicated_jmp)
  527.                 printf(" COND(%d)", cf->jmp_call.condition);
  528.         if (cf->jmp_call.bool_addr)
  529.                 printf(" BOOL_ADDR(0x%x)", cf->jmp_call.bool_addr);
  530.         if (cf->jmp_call.address_mode == ABSOLUTE_ADDR)
  531.                 printf(" ABSOLUTE_ADDR");
  532. }
  533.  
  534. static void print_cf_alloc(instr_cf_t *cf)
  535. {
  536.         static const char *bufname[] = {
  537.                         [SQ_NO_ALLOC] = "NO ALLOC",
  538.                         [SQ_POSITION] = "POSITION",
  539.                         [SQ_PARAMETER_PIXEL] = "PARAM/PIXEL",
  540.                         [SQ_MEMORY] = "MEMORY",
  541.         };
  542.         printf(" %s SIZE(0x%x)", bufname[cf->alloc.buffer_select], cf->alloc.size);
  543.         if (cf->alloc.no_serial)
  544.                 printf(" NO_SERIAL");
  545.         if (cf->alloc.alloc_mode) // ???
  546.                 printf(" ALLOC_MODE");
  547. }
  548.  
  549. struct {
  550.         const char *name;
  551.         void (*fxn)(instr_cf_t *cf);
  552. } cf_instructions[] = {
  553. #define INSTR(opc, fxn) [opc] = { #opc, fxn }
  554.                 INSTR(NOP, print_cf_nop),
  555.                 INSTR(EXEC, print_cf_exec),
  556.                 INSTR(EXEC_END, print_cf_exec),
  557.                 INSTR(COND_EXEC, print_cf_exec),
  558.                 INSTR(COND_EXEC_END, print_cf_exec),
  559.                 INSTR(COND_PRED_EXEC, print_cf_exec),
  560.                 INSTR(COND_PRED_EXEC_END, print_cf_exec),
  561.                 INSTR(LOOP_START, print_cf_loop),
  562.                 INSTR(LOOP_END, print_cf_loop),
  563.                 INSTR(COND_CALL, print_cf_jmp_call),
  564.                 INSTR(RETURN, print_cf_jmp_call),
  565.                 INSTR(COND_JMP, print_cf_jmp_call),
  566.                 INSTR(ALLOC, print_cf_alloc),
  567.                 INSTR(COND_EXEC_PRED_CLEAN, print_cf_exec),
  568.                 INSTR(COND_EXEC_PRED_CLEAN_END, print_cf_exec),
  569.                 INSTR(MARK_VS_FETCH_DONE, print_cf_nop),  // ??
  570. #undef INSTR
  571. };
  572.  
  573. static void print_cf(instr_cf_t *cf, int level)
  574. {
  575.         printf("%s", levels[level]);
  576.         if (debug & PRINT_RAW) {
  577.                 uint16_t *words = (uint16_t *)cf;
  578.                 printf("    %04x %04x %04x            \t",
  579.                                 words[0], words[1], words[2]);
  580.         }
  581.         printf("%s", cf_instructions[cf->opc].name);
  582.         cf_instructions[cf->opc].fxn(cf);
  583.         printf("\n");
  584. }
  585.  
  586. /*
  587.  * The adreno shader microcode consists of two parts:
  588.  *   1) A CF (control-flow) program, at the header of the compiled shader,
  589.  *      which refers to ALU/FETCH instructions that follow it by address.
  590.  *   2) ALU and FETCH instructions
  591.  */
  592.  
  593. int disasm_a2xx(uint32_t *dwords, int sizedwords, int level, enum shader_t type)
  594. {
  595.         instr_cf_t *cfs = (instr_cf_t *)dwords;
  596.         int idx, max_idx;
  597.  
  598.         for (idx = 0; ; idx++) {
  599.                 instr_cf_t *cf = &cfs[idx];
  600.                 if (cf_exec(cf)) {
  601.                         max_idx = 2 * cf->exec.address;
  602.                         break;
  603.                 }
  604.         }
  605.  
  606.         for (idx = 0; idx < max_idx; idx++) {
  607.                 instr_cf_t *cf = &cfs[idx];
  608.  
  609.                 print_cf(cf, level);
  610.  
  611.                 if (cf_exec(cf)) {
  612.                         uint32_t sequence = cf->exec.serialize;
  613.                         uint32_t i;
  614.                         for (i = 0; i < cf->exec.count; i++) {
  615.                                 uint32_t alu_off = (cf->exec.address + i);
  616.                                 if (sequence & 0x1) {
  617.                                         disasm_fetch(dwords + alu_off * 3, alu_off, level, sequence & 0x2);
  618.                                 } else {
  619.                                         disasm_alu(dwords + alu_off * 3, alu_off, level, sequence & 0x2, type);
  620.                                 }
  621.                                 sequence >>= 2;
  622.                         }
  623.                 }
  624.         }
  625.  
  626.         return 0;
  627. }
  628.  
  629. void disasm_set_debug(enum debug_t d)
  630. {
  631.         debug = d;
  632. }
  633.