Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2013 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 <string.h>
  28. #include <assert.h>
  29.  
  30. #include <util/u_debug.h>
  31.  
  32. #include "disasm.h"
  33. #include "instr-a3xx.h"
  34.  
  35. static enum debug_t debug;
  36.  
  37. #define printf debug_printf
  38.  
  39. static const char *levels[] = {
  40.                 "",
  41.                 "\t",
  42.                 "\t\t",
  43.                 "\t\t\t",
  44.                 "\t\t\t\t",
  45.                 "\t\t\t\t\t",
  46.                 "\t\t\t\t\t\t",
  47.                 "\t\t\t\t\t\t\t",
  48.                 "\t\t\t\t\t\t\t\t",
  49.                 "\t\t\t\t\t\t\t\t\t",
  50.                 "x",
  51.                 "x",
  52.                 "x",
  53.                 "x",
  54.                 "x",
  55.                 "x",
  56. };
  57.  
  58. static const char *component = "xyzw";
  59.  
  60. static const char *type[] = {
  61.                 [TYPE_F16] = "f16",
  62.                 [TYPE_F32] = "f32",
  63.                 [TYPE_U16] = "u16",
  64.                 [TYPE_U32] = "u32",
  65.                 [TYPE_S16] = "s16",
  66.                 [TYPE_S32] = "s32",
  67.                 [TYPE_U8]  = "u8",
  68.                 [TYPE_S8]  = "s8",
  69. };
  70.  
  71. static void print_reg(reg_t reg, bool full, bool r, bool c, bool im,
  72.                 bool neg, bool abs, bool addr_rel)
  73. {
  74.         const char type = c ? 'c' : 'r';
  75.  
  76.         // XXX I prefer - and || for neg/abs, but preserving format used
  77.         // by libllvm-a3xx for easy diffing..
  78.  
  79.         if (abs && neg)
  80.                 printf("(absneg)");
  81.         else if (neg)
  82.                 printf("(neg)");
  83.         else if (abs)
  84.                 printf("(abs)");
  85.  
  86.         if (r)
  87.                 printf("(r)");
  88.  
  89.         if (im) {
  90.                 printf("%d", reg.iim_val);
  91.         } else if (addr_rel) {
  92.                 /* I would just use %+d but trying to make it diff'able with
  93.                  * libllvm-a3xx...
  94.                  */
  95.                 if (reg.iim_val < 0)
  96.                         printf("%s%c<a0.x - %d>", full ? "" : "h", type, -reg.iim_val);
  97.                 else if (reg.iim_val > 0)
  98.                         printf("%s%c<a0.x + %d>", full ? "" : "h", type, reg.iim_val);
  99.                 else
  100.                         printf("%s%c<a0.x>", full ? "" : "h", type);
  101.         } else if ((reg.num == REG_A0) && !c) {
  102.                 printf("a0.%c", component[reg.comp]);
  103.         } else if ((reg.num == REG_P0) && !c) {
  104.                 printf("p0.%c", component[reg.comp]);
  105.         } else {
  106.                 printf("%s%c%d.%c", full ? "" : "h", type, reg.num, component[reg.comp]);
  107.         }
  108. }
  109.  
  110.  
  111. /* current instruction repeat flag: */
  112. static unsigned repeat;
  113.  
  114. static void print_reg_dst(reg_t reg, bool full, bool addr_rel)
  115. {
  116.         print_reg(reg, full, false, false, false, false, false, addr_rel);
  117. }
  118.  
  119. static void print_reg_src(reg_t reg, bool full, bool r, bool c, bool im,
  120.                 bool neg, bool abs, bool addr_rel)
  121. {
  122.         print_reg(reg, full, r, c, im, neg, abs, addr_rel);
  123. }
  124.  
  125. static void print_instr_cat0(instr_t *instr)
  126. {
  127.         instr_cat0_t *cat0 = &instr->cat0;
  128.  
  129.         switch (cat0->opc) {
  130.         case OPC_KILL:
  131.                 printf(" %sp0.%c", cat0->inv ? "!" : "",
  132.                                 component[cat0->comp]);
  133.                 break;
  134.         case OPC_BR:
  135.                 printf(" %sp0.%c, #%d", cat0->inv ? "!" : "",
  136.                                 component[cat0->comp], cat0->immed);
  137.                 break;
  138.         case OPC_JUMP:
  139.         case OPC_CALL:
  140.                 printf(" #%d", cat0->immed);
  141.                 break;
  142.         }
  143.  
  144.         if ((debug & PRINT_VERBOSE) && (cat0->dummy1|cat0->dummy2|cat0->dummy3|cat0->dummy4))
  145.                 printf("\t{0: %x,%x,%x,%x}", cat0->dummy1, cat0->dummy2, cat0->dummy3, cat0->dummy4);
  146. }
  147.  
  148. static void print_instr_cat1(instr_t *instr)
  149. {
  150.         instr_cat1_t *cat1 = &instr->cat1;
  151.  
  152.         if (cat1->ul)
  153.                 printf("(ul)");
  154.  
  155.         if (cat1->src_type == cat1->dst_type) {
  156.                 if ((cat1->src_type == TYPE_S16) && (((reg_t)cat1->dst).num == REG_A0)) {
  157.                         /* special case (nmemonic?): */
  158.                         printf("mova");
  159.                 } else {
  160.                         printf("mov.%s%s", type[cat1->src_type], type[cat1->dst_type]);
  161.                 }
  162.         } else {
  163.                 printf("cov.%s%s", type[cat1->src_type], type[cat1->dst_type]);
  164.         }
  165.  
  166.         printf(" ");
  167.  
  168.         if (cat1->even)
  169.                 printf("(even)");
  170.  
  171.         if (cat1->pos_inf)
  172.                 printf("(pos_infinity)");
  173.  
  174.         print_reg_dst((reg_t)(cat1->dst), type_size(cat1->dst_type) == 32,
  175.                         cat1->dst_rel);
  176.  
  177.         printf(", ");
  178.  
  179.         /* ugg, have to special case this.. vs print_reg().. */
  180.         if (cat1->src_im) {
  181.                 if (type_float(cat1->src_type))
  182.                         printf("(%f)", cat1->fim_val);
  183.                 else if (type_uint(cat1->src_type))
  184.                         printf("0x%08x", cat1->uim_val);
  185.                 else
  186.                         printf("%d", cat1->iim_val);
  187.         } else if (cat1->src_rel && !cat1->src_c) {
  188.                 /* I would just use %+d but trying to make it diff'able with
  189.                  * libllvm-a3xx...
  190.                  */
  191.                 char type = cat1->src_rel_c ? 'c' : 'r';
  192.                 if (cat1->off < 0)
  193.                         printf("%c<a0.x - %d>", type, -cat1->off);
  194.                 else if (cat1->off > 0)
  195.                         printf("%c<a0.x + %d>", type, cat1->off);
  196.                 else
  197.                         printf("c<a0.x>");
  198.         } else {
  199.                 print_reg_src((reg_t)(cat1->src), type_size(cat1->src_type) == 32,
  200.                                 cat1->src_r, cat1->src_c, cat1->src_im, false, false, false);
  201.         }
  202.  
  203.         if ((debug & PRINT_VERBOSE) && (cat1->must_be_0))
  204.                 printf("\t{1: %x}", cat1->must_be_0);
  205. }
  206.  
  207. static void print_instr_cat2(instr_t *instr)
  208. {
  209.         instr_cat2_t *cat2 = &instr->cat2;
  210.         static const char *cond[] = {
  211.                         "lt",
  212.                         "le",
  213.                         "gt",
  214.                         "ge",
  215.                         "eq",
  216.                         "ne",
  217.                         "?6?",
  218.         };
  219.  
  220.         switch (cat2->opc) {
  221.         case OPC_CMPS_F:
  222.         case OPC_CMPS_U:
  223.         case OPC_CMPS_S:
  224.         case OPC_CMPV_F:
  225.         case OPC_CMPV_U:
  226.         case OPC_CMPV_S:
  227.                 printf(".%s", cond[cat2->cond]);
  228.                 break;
  229.         }
  230.  
  231.         printf(" ");
  232.         if (cat2->ei)
  233.                 printf("(ei)");
  234.         print_reg_dst((reg_t)(cat2->dst), cat2->full ^ cat2->dst_half, false);
  235.         printf(", ");
  236.  
  237.         if (cat2->c1.src1_c) {
  238.                 print_reg_src((reg_t)(cat2->c1.src1), cat2->full, cat2->src1_r,
  239.                                 cat2->c1.src1_c, cat2->src1_im, cat2->src1_neg,
  240.                                 cat2->src1_abs, false);
  241.         } else if (cat2->rel1.src1_rel) {
  242.                 print_reg_src((reg_t)(cat2->rel1.src1), cat2->full, cat2->src1_r,
  243.                                 cat2->rel1.src1_c, cat2->src1_im, cat2->src1_neg,
  244.                                 cat2->src1_abs, cat2->rel1.src1_rel);
  245.         } else {
  246.                 print_reg_src((reg_t)(cat2->src1), cat2->full, cat2->src1_r,
  247.                                 false, cat2->src1_im, cat2->src1_neg,
  248.                                 cat2->src1_abs, false);
  249.         }
  250.  
  251.         switch (cat2->opc) {
  252.         case OPC_ABSNEG_F:
  253.         case OPC_ABSNEG_S:
  254.         case OPC_CLZ_B:
  255.         case OPC_CLZ_S:
  256.         case OPC_SIGN_F:
  257.         case OPC_FLOOR_F:
  258.         case OPC_CEIL_F:
  259.         case OPC_RNDNE_F:
  260.         case OPC_RNDAZ_F:
  261.         case OPC_TRUNC_F:
  262.         case OPC_NOT_B:
  263.         case OPC_BFREV_B:
  264.         case OPC_SETRM:
  265.         case OPC_CBITS_B:
  266.                 /* these only have one src reg */
  267.                 break;
  268.         default:
  269.                 printf(", ");
  270.                 if (cat2->c2.src2_c) {
  271.                         print_reg_src((reg_t)(cat2->c2.src2), cat2->full, cat2->src2_r,
  272.                                         cat2->c2.src2_c, cat2->src2_im, cat2->src2_neg,
  273.                                         cat2->src2_abs, false);
  274.                 } else if (cat2->rel2.src2_rel) {
  275.                         print_reg_src((reg_t)(cat2->rel2.src2), cat2->full, cat2->src2_r,
  276.                                         cat2->rel2.src2_c, cat2->src2_im, cat2->src2_neg,
  277.                                         cat2->src2_abs, cat2->rel2.src2_rel);
  278.                 } else {
  279.                         print_reg_src((reg_t)(cat2->src2), cat2->full, cat2->src2_r,
  280.                                         false, cat2->src2_im, cat2->src2_neg,
  281.                                         cat2->src2_abs, false);
  282.                 }
  283.                 break;
  284.         }
  285. }
  286.  
  287. static void print_instr_cat3(instr_t *instr)
  288. {
  289.         instr_cat3_t *cat3 = &instr->cat3;
  290.         bool full = instr_cat3_full(cat3);
  291.  
  292.         printf(" ");
  293.         print_reg_dst((reg_t)(cat3->dst), full ^ cat3->dst_half, false);
  294.         printf(", ");
  295.         if (cat3->c1.src1_c) {
  296.                 print_reg_src((reg_t)(cat3->c1.src1), full,
  297.                                 cat3->src1_r, cat3->c1.src1_c, false, cat3->src1_neg,
  298.                                 false, false);
  299.         } else if (cat3->rel1.src1_rel) {
  300.                 print_reg_src((reg_t)(cat3->rel1.src1), full,
  301.                                 cat3->src1_r, cat3->rel1.src1_c, false, cat3->src1_neg,
  302.                                 false, cat3->rel1.src1_rel);
  303.         } else {
  304.                 print_reg_src((reg_t)(cat3->src1), full,
  305.                                 cat3->src1_r, false, false, cat3->src1_neg,
  306.                                 false, false);
  307.         }
  308.         printf(", ");
  309.         print_reg_src((reg_t)cat3->src2, full,
  310.                         cat3->src2_r, cat3->src2_c, false, cat3->src2_neg,
  311.                         false, false);
  312.         printf(", ");
  313.         if (cat3->c2.src3_c) {
  314.                 print_reg_src((reg_t)(cat3->c2.src3), full,
  315.                                 cat3->src3_r, cat3->c2.src3_c, false, cat3->src3_neg,
  316.                                 false, false);
  317.         } else if (cat3->rel2.src3_rel) {
  318.                 print_reg_src((reg_t)(cat3->rel2.src3), full,
  319.                                 cat3->src3_r, cat3->rel2.src3_c, false, cat3->src3_neg,
  320.                                 false, cat3->rel2.src3_rel);
  321.         } else {
  322.                 print_reg_src((reg_t)(cat3->src3), full,
  323.                                 cat3->src3_r, false, false, cat3->src3_neg,
  324.                                 false, false);
  325.         }
  326. }
  327.  
  328. static void print_instr_cat4(instr_t *instr)
  329. {
  330.         instr_cat4_t *cat4 = &instr->cat4;
  331.  
  332.         printf(" ");
  333.         print_reg_dst((reg_t)(cat4->dst), cat4->full ^ cat4->dst_half, false);
  334.         printf(", ");
  335.  
  336.         if (cat4->c.src_c) {
  337.                 print_reg_src((reg_t)(cat4->c.src), cat4->full,
  338.                                 cat4->src_r, cat4->c.src_c, cat4->src_im,
  339.                                 cat4->src_neg, cat4->src_abs, false);
  340.         } else if (cat4->rel.src_rel) {
  341.                 print_reg_src((reg_t)(cat4->rel.src), cat4->full,
  342.                                 cat4->src_r, cat4->rel.src_c, cat4->src_im,
  343.                                 cat4->src_neg, cat4->src_abs, cat4->rel.src_rel);
  344.         } else {
  345.                 print_reg_src((reg_t)(cat4->src), cat4->full,
  346.                                 cat4->src_r, false, cat4->src_im,
  347.                                 cat4->src_neg, cat4->src_abs, false);
  348.         }
  349.  
  350.         if ((debug & PRINT_VERBOSE) && (cat4->dummy1|cat4->dummy2))
  351.                 printf("\t{4: %x,%x}", cat4->dummy1, cat4->dummy2);
  352. }
  353.  
  354. static void print_instr_cat5(instr_t *instr)
  355. {
  356.         static const struct {
  357.                 bool src1, src2, samp, tex;
  358.         } info[0x1f] = {
  359.                         [OPC_ISAM]     = { true,  false, true,  true,  },
  360.                         [OPC_ISAML]    = { true,  true,  true,  true,  },
  361.                         [OPC_ISAMM]    = { true,  false, true,  true,  },
  362.                         [OPC_SAM]      = { true,  false, true,  true,  },
  363.                         [OPC_SAMB]     = { true,  true,  true,  true,  },
  364.                         [OPC_SAML]     = { true,  true,  true,  true,  },
  365.                         [OPC_SAMGQ]    = { true,  false, true,  true,  },
  366.                         [OPC_GETLOD]   = { true,  false, true,  true,  },
  367.                         [OPC_CONV]     = { true,  true,  true,  true,  },
  368.                         [OPC_CONVM]    = { true,  true,  true,  true,  },
  369.                         [OPC_GETSIZE]  = { true,  false, false, true,  },
  370.                         [OPC_GETBUF]   = { false, false, false, true,  },
  371.                         [OPC_GETPOS]   = { true,  false, false, true,  },
  372.                         [OPC_GETINFO]  = { false, false, false, true,  },
  373.                         [OPC_DSX]      = { true,  false, false, false, },
  374.                         [OPC_DSY]      = { true,  false, false, false, },
  375.                         [OPC_GATHER4R] = { true,  false, true,  true,  },
  376.                         [OPC_GATHER4G] = { true,  false, true,  true,  },
  377.                         [OPC_GATHER4B] = { true,  false, true,  true,  },
  378.                         [OPC_GATHER4A] = { true,  false, true,  true,  },
  379.                         [OPC_SAMGP0]   = { true,  false, true,  true,  },
  380.                         [OPC_SAMGP1]   = { true,  false, true,  true,  },
  381.                         [OPC_SAMGP2]   = { true,  false, true,  true,  },
  382.                         [OPC_SAMGP3]   = { true,  false, true,  true,  },
  383.                         [OPC_DSXPP_1]  = { true,  false, false, false, },
  384.                         [OPC_DSYPP_1]  = { true,  false, false, false, },
  385.                         [OPC_RGETPOS]  = { false, false, false, false, },
  386.                         [OPC_RGETINFO] = { false, false, false, false, },
  387.         };
  388.         instr_cat5_t *cat5 = &instr->cat5;
  389.         int i;
  390.  
  391.         if (cat5->is_3d)   printf(".3d");
  392.         if (cat5->is_a)    printf(".a");
  393.         if (cat5->is_o)    printf(".o");
  394.         if (cat5->is_p)    printf(".p");
  395.         if (cat5->is_s)    printf(".s");
  396.         if (cat5->is_s2en) printf(".s2en");
  397.  
  398.         printf(" ");
  399.  
  400.         switch (cat5->opc) {
  401.         case OPC_DSXPP_1:
  402.         case OPC_DSYPP_1:
  403.                 break;
  404.         default:
  405.                 printf("(%s)", type[cat5->type]);
  406.                 break;
  407.         }
  408.  
  409.         printf("(");
  410.         for (i = 0; i < 4; i++)
  411.                 if (cat5->wrmask & (1 << i))
  412.                         printf("%c", "xyzw"[i]);
  413.         printf(")");
  414.  
  415.         print_reg_dst((reg_t)(cat5->dst), type_size(cat5->type) == 32, false);
  416.  
  417.         if (info[cat5->opc].src1) {
  418.                 printf(", ");
  419.                 print_reg_src((reg_t)(cat5->src1), cat5->full, false, false, false,
  420.                                 false, false, false);
  421.         }
  422.  
  423.         if (cat5->is_s2en) {
  424.                 printf(", ");
  425.                 print_reg_src((reg_t)(cat5->s2en.src2), cat5->full, false, false, false,
  426.                                 false, false, false);
  427.                 printf(", ");
  428.                 print_reg_src((reg_t)(cat5->s2en.src3), false, false, false, false,
  429.                                 false, false, false);
  430.         } else {
  431.                 if (cat5->is_o || info[cat5->opc].src2) {
  432.                         printf(", ");
  433.                         print_reg_src((reg_t)(cat5->norm.src2), cat5->full,
  434.                                         false, false, false, false, false, false);
  435.                 }
  436.                 if (info[cat5->opc].samp)
  437.                         printf(", s#%d", cat5->norm.samp);
  438.                 if (info[cat5->opc].tex)
  439.                         printf(", t#%d", cat5->norm.tex);
  440.         }
  441.  
  442.         if (debug & PRINT_VERBOSE) {
  443.                 if (cat5->is_s2en) {
  444.                         if ((debug & PRINT_VERBOSE) && (cat5->s2en.dummy1|cat5->s2en.dummy2|cat5->dummy2))
  445.                                 printf("\t{5: %x,%x,%x}", cat5->s2en.dummy1, cat5->s2en.dummy2, cat5->dummy2);
  446.                 } else {
  447.                         if ((debug & PRINT_VERBOSE) && (cat5->norm.dummy1|cat5->dummy2))
  448.                                 printf("\t{5: %x,%x}", cat5->norm.dummy1, cat5->dummy2);
  449.                 }
  450.         }
  451. }
  452.  
  453. static void print_instr_cat6(instr_t *instr)
  454. {
  455.         instr_cat6_t *cat6 = &instr->cat6;
  456.         char sd = 0, ss = 0;  /* dst/src address space */
  457.         bool full = type_size(cat6->type) == 32;
  458.         bool nodst = false;
  459.  
  460.         printf(".%s ", type[cat6->type]);
  461.  
  462.         switch (cat6->opc) {
  463.         case OPC_STG:
  464.                 sd = 'g';
  465.                 break;
  466.         case OPC_STP:
  467.                 sd = 'p';
  468.                 break;
  469.         case OPC_STL:
  470.         case OPC_STLW:
  471.                 sd = 'l';
  472.                 break;
  473.  
  474.         case OPC_LDG:
  475.                 ss = 'g';
  476.                 break;
  477.         case OPC_LDP:
  478.                 ss = 'p';
  479.                 break;
  480.         case OPC_LDL:
  481.         case OPC_LDLW:
  482.         case OPC_LDLV:
  483.                 ss = 'l';
  484.                 break;
  485.  
  486.         case OPC_L2G:
  487.                 ss = 'l';
  488.                 sd = 'g';
  489.                 break;
  490.  
  491.         case OPC_G2L:
  492.                 ss = 'g';
  493.                 sd = 'l';
  494.                 break;
  495.  
  496.         case OPC_PREFETCH:
  497.                 ss = 'g';
  498.                 nodst = true;
  499.                 break;
  500.  
  501.         case OPC_STI:
  502.                 full = false;  // XXX or inverts??
  503.                 break;
  504.         }
  505.  
  506.         if (cat6->has_off) {
  507.                 if (!nodst) {
  508.                         if (sd)
  509.                                 printf("%c[", sd);
  510.                         print_reg_dst((reg_t)(cat6->a.dst), full, false);
  511.                         if (sd)
  512.                                 printf("]");
  513.                         printf(", ");
  514.                 }
  515.                 if (ss)
  516.                         printf("%c[", ss);
  517.                 print_reg_src((reg_t)(cat6->a.src1), true,
  518.                                 false, false, cat6->a.src1_im, false, false, false);
  519.                 if (cat6->a.off)
  520.                         printf("%+d", cat6->a.off);
  521.                 if (ss)
  522.                         printf("]");
  523.                 printf(", ");
  524.                 print_reg_src((reg_t)(cat6->a.src2), full,
  525.                                 false, false, cat6->a.src2_im, false, false, false);
  526.         } else {
  527.                 if (!nodst) {
  528.                         if (sd)
  529.                                 printf("%c[", sd);
  530.                         print_reg_dst((reg_t)(cat6->b.dst), full, false);
  531.                         if (sd)
  532.                                 printf("]");
  533.                         printf(", ");
  534.                 }
  535.                 if (ss)
  536.                         printf("%c[", ss);
  537.                 print_reg_src((reg_t)(cat6->b.src1), true,
  538.                                 false, false, cat6->b.src1_im, false, false, false);
  539.                 if (ss)
  540.                         printf("]");
  541.                 printf(", ");
  542.                 print_reg_src((reg_t)(cat6->b.src2), full,
  543.                                 false, false, cat6->b.src2_im, false, false, false);
  544.         }
  545.  
  546.         if (debug & PRINT_VERBOSE) {
  547.                 switch (cat6->opc) {
  548.                 case OPC_LDG:
  549.                 case OPC_LDP:
  550.                         /* load instructions: */
  551.                         if (cat6->a.dummy2|cat6->a.dummy3)
  552.                                 printf("\t{6: %x,%x}", cat6->a.dummy2, cat6->a.dummy3);
  553.                         break;
  554.                 case OPC_STG:
  555.                 case OPC_STP:
  556.                 case OPC_STI:
  557.                         /* store instructions: */
  558.                         if (cat6->b.dummy2|cat6->b.dummy2)
  559.                                 printf("\t{6: %x,%x}", cat6->b.dummy2, cat6->b.dummy3);
  560.                         if (cat6->b.ignore0)
  561.                                 printf("\t{?? %x}", cat6->b.ignore0);
  562.                         break;
  563.                 }
  564.         }
  565. }
  566.  
  567. /* size of largest OPC field of all the instruction categories: */
  568. #define NOPC_BITS 6
  569.  
  570. struct opc_info {
  571.         uint16_t cat;
  572.         uint16_t opc;
  573.         const char *name;
  574.         void (*print)(instr_t *instr);
  575. } opcs[1 << (3+NOPC_BITS)] = {
  576. #define OPC(cat, opc, name) [((cat) << NOPC_BITS) | (opc)] = { (cat), (opc), #name, print_instr_cat##cat }
  577.         /* category 0: */
  578.         OPC(0, OPC_NOP,          nop),
  579.         OPC(0, OPC_BR,           br),
  580.         OPC(0, OPC_JUMP,         jump),
  581.         OPC(0, OPC_CALL,         call),
  582.         OPC(0, OPC_RET,          ret),
  583.         OPC(0, OPC_KILL,         kill),
  584.         OPC(0, OPC_END,          end),
  585.         OPC(0, OPC_EMIT,         emit),
  586.         OPC(0, OPC_CUT,          cut),
  587.         OPC(0, OPC_CHMASK,       chmask),
  588.         OPC(0, OPC_CHSH,         chsh),
  589.         OPC(0, OPC_FLOW_REV,     flow_rev),
  590.  
  591.         /* category 1: */
  592.         OPC(1, 0, ),
  593.  
  594.         /* category 2: */
  595.         OPC(2, OPC_ADD_F,        add.f),
  596.         OPC(2, OPC_MIN_F,        min.f),
  597.         OPC(2, OPC_MAX_F,        max.f),
  598.         OPC(2, OPC_MUL_F,        mul.f),
  599.         OPC(2, OPC_SIGN_F,       sign.f),
  600.         OPC(2, OPC_CMPS_F,       cmps.f),
  601.         OPC(2, OPC_ABSNEG_F,     absneg.f),
  602.         OPC(2, OPC_CMPV_F,       cmpv.f),
  603.         OPC(2, OPC_FLOOR_F,      floor.f),
  604.         OPC(2, OPC_CEIL_F,       ceil.f),
  605.         OPC(2, OPC_RNDNE_F,      rndne.f),
  606.         OPC(2, OPC_RNDAZ_F,      rndaz.f),
  607.         OPC(2, OPC_TRUNC_F,      trunc.f),
  608.         OPC(2, OPC_ADD_U,        add.u),
  609.         OPC(2, OPC_ADD_S,        add.s),
  610.         OPC(2, OPC_SUB_U,        sub.u),
  611.         OPC(2, OPC_SUB_S,        sub.s),
  612.         OPC(2, OPC_CMPS_U,       cmps.u),
  613.         OPC(2, OPC_CMPS_S,       cmps.s),
  614.         OPC(2, OPC_MIN_U,        min.u),
  615.         OPC(2, OPC_MIN_S,        min.s),
  616.         OPC(2, OPC_MAX_U,        max.u),
  617.         OPC(2, OPC_MAX_S,        max.s),
  618.         OPC(2, OPC_ABSNEG_S,     absneg.s),
  619.         OPC(2, OPC_AND_B,        and.b),
  620.         OPC(2, OPC_OR_B,         or.b),
  621.         OPC(2, OPC_NOT_B,        not.b),
  622.         OPC(2, OPC_XOR_B,        xor.b),
  623.         OPC(2, OPC_CMPV_U,       cmpv.u),
  624.         OPC(2, OPC_CMPV_S,       cmpv.s),
  625.         OPC(2, OPC_MUL_U,        mul.u),
  626.         OPC(2, OPC_MUL_S,        mul.s),
  627.         OPC(2, OPC_MULL_U,       mull.u),
  628.         OPC(2, OPC_BFREV_B,      bfrev.b),
  629.         OPC(2, OPC_CLZ_S,        clz.s),
  630.         OPC(2, OPC_CLZ_B,        clz.b),
  631.         OPC(2, OPC_SHL_B,        shl.b),
  632.         OPC(2, OPC_SHR_B,        shr.b),
  633.         OPC(2, OPC_ASHR_B,       ashr.b),
  634.         OPC(2, OPC_BARY_F,       bary.f),
  635.         OPC(2, OPC_MGEN_B,       mgen.b),
  636.         OPC(2, OPC_GETBIT_B,     getbit.b),
  637.         OPC(2, OPC_SETRM,        setrm),
  638.         OPC(2, OPC_CBITS_B,      cbits.b),
  639.         OPC(2, OPC_SHB,          shb),
  640.         OPC(2, OPC_MSAD,         msad),
  641.  
  642.         /* category 3: */
  643.         OPC(3, OPC_MAD_U16,      mad.u16),
  644.         OPC(3, OPC_MADSH_U16,    madsh.u16),
  645.         OPC(3, OPC_MAD_S16,      mad.s16),
  646.         OPC(3, OPC_MADSH_M16,    madsh.m16),
  647.         OPC(3, OPC_MAD_U24,      mad.u24),
  648.         OPC(3, OPC_MAD_S24,      mad.s24),
  649.         OPC(3, OPC_MAD_F16,      mad.f16),
  650.         OPC(3, OPC_MAD_F32,      mad.f32),
  651.         OPC(3, OPC_SEL_B16,      sel.b16),
  652.         OPC(3, OPC_SEL_B32,      sel.b32),
  653.         OPC(3, OPC_SEL_S16,      sel.s16),
  654.         OPC(3, OPC_SEL_S32,      sel.s32),
  655.         OPC(3, OPC_SEL_F16,      sel.f16),
  656.         OPC(3, OPC_SEL_F32,      sel.f32),
  657.         OPC(3, OPC_SAD_S16,      sad.s16),
  658.         OPC(3, OPC_SAD_S32,      sad.s32),
  659.  
  660.         /* category 4: */
  661.         OPC(4, OPC_RCP,          rcp),
  662.         OPC(4, OPC_RSQ,          rsq),
  663.         OPC(4, OPC_LOG2,         log2),
  664.         OPC(4, OPC_EXP2,         exp2),
  665.         OPC(4, OPC_SIN,          sin),
  666.         OPC(4, OPC_COS,          cos),
  667.         OPC(4, OPC_SQRT,         sqrt),
  668.  
  669.         /* category 5: */
  670.         OPC(5, OPC_ISAM,         isam),
  671.         OPC(5, OPC_ISAML,        isaml),
  672.         OPC(5, OPC_ISAMM,        isamm),
  673.         OPC(5, OPC_SAM,          sam),
  674.         OPC(5, OPC_SAMB,         samb),
  675.         OPC(5, OPC_SAML,         saml),
  676.         OPC(5, OPC_SAMGQ,        samgq),
  677.         OPC(5, OPC_GETLOD,       getlod),
  678.         OPC(5, OPC_CONV,         conv),
  679.         OPC(5, OPC_CONVM,        convm),
  680.         OPC(5, OPC_GETSIZE,      getsize),
  681.         OPC(5, OPC_GETBUF,       getbuf),
  682.         OPC(5, OPC_GETPOS,       getpos),
  683.         OPC(5, OPC_GETINFO,      getinfo),
  684.         OPC(5, OPC_DSX,          dsx),
  685.         OPC(5, OPC_DSY,          dsy),
  686.         OPC(5, OPC_GATHER4R,     gather4r),
  687.         OPC(5, OPC_GATHER4G,     gather4g),
  688.         OPC(5, OPC_GATHER4B,     gather4b),
  689.         OPC(5, OPC_GATHER4A,     gather4a),
  690.         OPC(5, OPC_SAMGP0,       samgp0),
  691.         OPC(5, OPC_SAMGP1,       samgp1),
  692.         OPC(5, OPC_SAMGP2,       samgp2),
  693.         OPC(5, OPC_SAMGP3,       samgp3),
  694.         OPC(5, OPC_DSXPP_1,      dsxpp.1),
  695.         OPC(5, OPC_DSYPP_1,      dsypp.1),
  696.         OPC(5, OPC_RGETPOS,      rgetpos),
  697.         OPC(5, OPC_RGETINFO,     rgetinfo),
  698.  
  699.  
  700.         /* category 6: */
  701.         OPC(6, OPC_LDG,          ldg),
  702.         OPC(6, OPC_LDL,          ldl),
  703.         OPC(6, OPC_LDP,          ldp),
  704.         OPC(6, OPC_STG,          stg),
  705.         OPC(6, OPC_STL,          stl),
  706.         OPC(6, OPC_STP,          stp),
  707.         OPC(6, OPC_STI,          sti),
  708.         OPC(6, OPC_G2L,          g2l),
  709.         OPC(6, OPC_L2G,          l2g),
  710.         OPC(6, OPC_PREFETCH,     prefetch),
  711.         OPC(6, OPC_LDLW,         ldlw),
  712.         OPC(6, OPC_STLW,         stlw),
  713.         OPC(6, OPC_RESFMT,       resfmt),
  714.         OPC(6, OPC_RESINFO,      resinf),
  715.         OPC(6, OPC_ATOMIC_ADD_L,     atomic.add.l),
  716.         OPC(6, OPC_ATOMIC_SUB_L,     atomic.sub.l),
  717.         OPC(6, OPC_ATOMIC_XCHG_L,    atomic.xchg.l),
  718.         OPC(6, OPC_ATOMIC_INC_L,     atomic.inc.l),
  719.         OPC(6, OPC_ATOMIC_DEC_L,     atomic.dec.l),
  720.         OPC(6, OPC_ATOMIC_CMPXCHG_L, atomic.cmpxchg.l),
  721.         OPC(6, OPC_ATOMIC_MIN_L,     atomic.min.l),
  722.         OPC(6, OPC_ATOMIC_MAX_L,     atomic.max.l),
  723.         OPC(6, OPC_ATOMIC_AND_L,     atomic.and.l),
  724.         OPC(6, OPC_ATOMIC_OR_L,      atomic.or.l),
  725.         OPC(6, OPC_ATOMIC_XOR_L,     atomic.xor.l),
  726.         OPC(6, OPC_LDGB_TYPED_4D,    ldgb.typed.4d),
  727.         OPC(6, OPC_STGB_4D_4,    stgb.4d.4),
  728.         OPC(6, OPC_STIB,         stib),
  729.         OPC(6, OPC_LDC_4,        ldc.4),
  730.         OPC(6, OPC_LDLV,         ldlv),
  731.  
  732.  
  733. #undef OPC
  734. };
  735.  
  736. #define GETINFO(instr) (&(opcs[((instr)->opc_cat << NOPC_BITS) | instr_opc(instr)]))
  737.  
  738. // XXX hack.. probably should move this table somewhere common:
  739. #include "ir3.h"
  740. const char *ir3_instr_name(struct ir3_instruction *instr)
  741. {
  742.         if (instr->category == -1) return "??meta??";
  743.         return opcs[(instr->category << NOPC_BITS) | instr->opc].name;
  744. }
  745.  
  746. static void print_instr(uint32_t *dwords, int level, int n)
  747. {
  748.         instr_t *instr = (instr_t *)dwords;
  749.         uint32_t opc = instr_opc(instr);
  750.         const char *name;
  751.  
  752.         if (debug & PRINT_VERBOSE)
  753.                 printf("%s%04d[%08xx_%08xx] ", levels[level], n, dwords[1], dwords[0]);
  754.  
  755.         /* NOTE: order flags are printed is a bit fugly.. but for now I
  756.          * try to match the order in llvm-a3xx disassembler for easy
  757.          * diff'ing..
  758.          */
  759.  
  760.         if (instr->sync)
  761.                 printf("(sy)");
  762.         if (instr->ss && (instr->opc_cat <= 4))
  763.                 printf("(ss)");
  764.         if (instr->jmp_tgt)
  765.                 printf("(jp)");
  766.         if (instr->repeat && (instr->opc_cat <= 4)) {
  767.                 printf("(rpt%d)", instr->repeat);
  768.                 repeat = instr->repeat;
  769.         } else {
  770.                 repeat = 0;
  771.         }
  772.         if (instr->ul && ((2 <= instr->opc_cat) && (instr->opc_cat <= 4)))
  773.                 printf("(ul)");
  774.  
  775.         name = GETINFO(instr)->name;
  776.  
  777.         if (name) {
  778.                 printf("%s", name);
  779.                 GETINFO(instr)->print(instr);
  780.         } else {
  781.                 printf("unknown(%d,%d)", instr->opc_cat, opc);
  782.         }
  783.  
  784.         printf("\n");
  785. }
  786.  
  787. int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, enum shader_t type)
  788. {
  789.         int i;
  790.  
  791.         assert((sizedwords % 2) == 0);
  792.  
  793.         for (i = 0; i < sizedwords; i += 2)
  794.                 print_instr(&dwords[i], level, i/2);
  795.  
  796.         return 0;
  797. }
  798.