Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2014 LunarG, Inc.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Chia-I Wu <olv@lunarg.com>
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include "genhw/genhw.h"
  30. #include "toy_compiler.h"
  31.  
  32. #define DISASM_PRINTER_BUFFER_SIZE 256
  33. #define DISASM_PRINTER_COLUMN_WIDTH 16
  34.  
  35. struct disasm_printer {
  36.    char buf[DISASM_PRINTER_BUFFER_SIZE];
  37.    int len;
  38. };
  39.  
  40. struct disasm_operand {
  41.    unsigned file:2;
  42.    unsigned type:4;
  43.  
  44.    unsigned addr_mode:1;
  45.    unsigned reg:8;
  46.    unsigned subreg:5;
  47.    unsigned addr_subreg:3;
  48.    unsigned addr_imm:10;
  49. };
  50.  
  51. struct disasm_dst_operand {
  52.    struct disasm_operand base;
  53.  
  54.    unsigned horz_stride:2;
  55.    unsigned writemask:4;
  56. };
  57.  
  58. struct disasm_src_operand {
  59.    struct disasm_operand base;
  60.  
  61.    unsigned vert_stride:4;
  62.    unsigned width:3;
  63.    unsigned horz_stride:2;
  64.    unsigned swizzle_x:2;
  65.    unsigned swizzle_y:2;
  66.    unsigned swizzle_z:2;
  67.    unsigned swizzle_w:2;
  68.    unsigned negate:1;
  69.    unsigned absolute:1;
  70. };
  71.  
  72. struct disasm_inst {
  73.    const struct ilo_dev *dev;
  74.  
  75.    unsigned has_jip:1;
  76.    unsigned has_uip:1;
  77.  
  78.    unsigned opcode:7;
  79.    unsigned access_mode:1;
  80.    unsigned mask_ctrl:1;
  81.    unsigned dep_ctrl:2;
  82.    unsigned qtr_ctrl:2;
  83.    unsigned thread_ctrl:2;
  84.    unsigned pred_ctrl:4;
  85.    unsigned pred_inv:1;
  86.    unsigned exec_size:3;
  87.  
  88.    unsigned cond_modifier:4;
  89.    unsigned sfid:4;
  90.    unsigned fc:4;
  91.  
  92.    unsigned acc_wr_ctrl:1;
  93.    unsigned branch_ctrl:1;
  94.  
  95.    unsigned cmpt_ctrl:1;
  96.    unsigned debug_ctrl:1;
  97.    unsigned saturate:1;
  98.  
  99.    unsigned nib_ctrl:1;
  100.  
  101.    unsigned flag_reg:1;
  102.    unsigned flag_subreg:1;
  103.  
  104.    struct disasm_dst_operand dst;
  105.    struct disasm_src_operand src0;
  106.    struct disasm_src_operand src1;
  107.    union {
  108.       struct disasm_src_operand src2;
  109.       uint64_t imm64;
  110.  
  111.       uint32_t ud;
  112.       int32_t d;
  113.       uint16_t uw;
  114.       int16_t w;
  115.       float f;
  116.  
  117.       struct {
  118.          int16_t jip;
  119.          int16_t uip;
  120.       } ip16;
  121.  
  122.       struct {
  123.          int32_t jip;
  124.          int32_t uip;
  125.       } ip32;
  126.    } u;
  127. };
  128.  
  129. static const struct {
  130.    const char *name;
  131.    int src_count;
  132. } disasm_opcode_table[128] = {
  133.    [GEN6_OPCODE_ILLEGAL]     = { "illegal",  0 },
  134.    [GEN6_OPCODE_MOV]         = { "mov",      1 },
  135.    [GEN6_OPCODE_SEL]         = { "sel",      2 },
  136.    [GEN6_OPCODE_MOVI]        = { "movi",     1 },
  137.    [GEN6_OPCODE_NOT]         = { "not",      1 },
  138.    [GEN6_OPCODE_AND]         = { "and",      2 },
  139.    [GEN6_OPCODE_OR]          = { "or",       2 },
  140.    [GEN6_OPCODE_XOR]         = { "xor",      2 },
  141.    [GEN6_OPCODE_SHR]         = { "shr",      2 },
  142.    [GEN6_OPCODE_SHL]         = { "shl",      2 },
  143.    [GEN6_OPCODE_DIM]         = { "dim",      1 },
  144.    [GEN6_OPCODE_ASR]         = { "asr",      2 },
  145.    [GEN6_OPCODE_CMP]         = { "cmp",      2 },
  146.    [GEN6_OPCODE_CMPN]        = { "cmpn",     2 },
  147.    [GEN7_OPCODE_CSEL]        = { "csel",     3 },
  148.    [GEN7_OPCODE_F32TO16]     = { "f32to16",  1 },
  149.    [GEN7_OPCODE_F16TO32]     = { "f16to32",  1 },
  150.    [GEN7_OPCODE_BFREV]       = { "bfrev",    1 },
  151.    [GEN7_OPCODE_BFE]         = { "bfe",      3 },
  152.    [GEN7_OPCODE_BFI1]        = { "bfi1",     2 },
  153.    [GEN7_OPCODE_BFI2]        = { "bfi2",     3 },
  154.    [GEN6_OPCODE_JMPI]        = { "jmpi",     1 },
  155.    [GEN7_OPCODE_BRD]         = { "brd",      1 },
  156.    [GEN6_OPCODE_IF]          = { "if",       2 },
  157.    [GEN7_OPCODE_BRC]         = { "brc",      1 },
  158.    [GEN6_OPCODE_ELSE]        = { "else",     1 },
  159.    [GEN6_OPCODE_ENDIF]       = { "endif",    0 },
  160.    [GEN6_OPCODE_CASE]        = { "case",     2 },
  161.    [GEN6_OPCODE_WHILE]       = { "while",    1 },
  162.    [GEN6_OPCODE_BREAK]       = { "break",    1 },
  163.    [GEN6_OPCODE_CONT]        = { "cont",     1 },
  164.    [GEN6_OPCODE_HALT]        = { "halt",     1 },
  165.    [GEN75_OPCODE_CALLA]      = { "calla",    1 },
  166.    [GEN6_OPCODE_CALL]        = { "call",     1 },
  167.    [GEN6_OPCODE_RETURN]      = { "return",   1 },
  168.    [GEN8_OPCODE_GOTO]        = { "goto",     1 },
  169.    [GEN6_OPCODE_WAIT]        = { "wait",     1 },
  170.    [GEN6_OPCODE_SEND]        = { "send",     1 },
  171.    [GEN6_OPCODE_SENDC]       = { "sendc",    1 },
  172.    [GEN6_OPCODE_MATH]        = { "math",     2 },
  173.    [GEN6_OPCODE_ADD]         = { "add",      2 },
  174.    [GEN6_OPCODE_MUL]         = { "mul",      2 },
  175.    [GEN6_OPCODE_AVG]         = { "avg",      2 },
  176.    [GEN6_OPCODE_FRC]         = { "frc",      1 },
  177.    [GEN6_OPCODE_RNDU]        = { "rndu",     1 },
  178.    [GEN6_OPCODE_RNDD]        = { "rndd",     1 },
  179.    [GEN6_OPCODE_RNDE]        = { "rnde",     1 },
  180.    [GEN6_OPCODE_RNDZ]        = { "rndz",     1 },
  181.    [GEN6_OPCODE_MAC]         = { "mac",      2 },
  182.    [GEN6_OPCODE_MACH]        = { "mach",     2 },
  183.    [GEN6_OPCODE_LZD]         = { "lzd",      1 },
  184.    [GEN7_OPCODE_FBH]         = { "fbh",      1 },
  185.    [GEN7_OPCODE_FBL]         = { "fbl",      1 },
  186.    [GEN7_OPCODE_CBIT]        = { "cbit",     1 },
  187.    [GEN7_OPCODE_ADDC]        = { "addc",     2 },
  188.    [GEN7_OPCODE_SUBB]        = { "subb",     2 },
  189.    [GEN6_OPCODE_SAD2]        = { "sad2",     2 },
  190.    [GEN6_OPCODE_SADA2]       = { "sada2",    2 },
  191.    [GEN6_OPCODE_DP4]         = { "dp4",      2 },
  192.    [GEN6_OPCODE_DPH]         = { "dph",      2 },
  193.    [GEN6_OPCODE_DP3]         = { "dp3",      2 },
  194.    [GEN6_OPCODE_DP2]         = { "dp2",      2 },
  195.    [GEN6_OPCODE_LINE]        = { "line",     2 },
  196.    [GEN6_OPCODE_PLN]         = { "pln",      2 },
  197.    [GEN6_OPCODE_MAD]         = { "mad",      3 },
  198.    [GEN6_OPCODE_LRP]         = { "lrp",      3 },
  199.    [GEN6_OPCODE_NOP]         = { "nop",      0 },
  200. };
  201.  
  202. static void
  203. disasm_inst_decode_dw0_opcode_gen6(struct disasm_inst *inst, uint32_t dw0)
  204. {
  205.    ILO_DEV_ASSERT(inst->dev, 6, 8);
  206.  
  207.    inst->opcode = GEN_EXTRACT(dw0, GEN6_INST_OPCODE);
  208.  
  209.    switch (inst->opcode) {
  210.    case GEN6_OPCODE_IF:
  211.       inst->has_jip = true;
  212.       inst->has_uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(7));
  213.       break;
  214.    case GEN6_OPCODE_ELSE:
  215.       inst->has_jip = true;
  216.       inst->has_uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(8));
  217.       break;
  218.    case GEN6_OPCODE_BREAK:
  219.    case GEN6_OPCODE_CONT:
  220.    case GEN6_OPCODE_HALT:
  221.       inst->has_uip = true;
  222.       /* fall through */
  223.    case GEN6_OPCODE_JMPI:
  224.    case GEN7_OPCODE_BRD:
  225.    case GEN7_OPCODE_BRC:
  226.    case GEN6_OPCODE_ENDIF:
  227.    case GEN6_OPCODE_CASE:
  228.    case GEN6_OPCODE_WHILE:
  229.    case GEN75_OPCODE_CALLA:
  230.    case GEN6_OPCODE_CALL:
  231.    case GEN6_OPCODE_RETURN:
  232.       inst->has_jip = true;
  233.       break;
  234.    default:
  235.       break;
  236.    }
  237. }
  238.  
  239. static void
  240. disasm_inst_decode_dw0_gen6(struct disasm_inst *inst, uint32_t dw0)
  241. {
  242.    ILO_DEV_ASSERT(inst->dev, 6, 8);
  243.  
  244.    disasm_inst_decode_dw0_opcode_gen6(inst, dw0);
  245.  
  246.    inst->access_mode = GEN_EXTRACT(dw0, GEN6_INST_ACCESSMODE);
  247.  
  248.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
  249.       inst->dep_ctrl = GEN_EXTRACT(dw0, GEN8_INST_DEPCTRL);
  250.       inst->nib_ctrl = (bool) (dw0 & GEN8_INST_NIBCTRL);
  251.    } else {
  252.       inst->mask_ctrl = GEN_EXTRACT(dw0, GEN6_INST_MASKCTRL);
  253.       inst->dep_ctrl = GEN_EXTRACT(dw0, GEN6_INST_DEPCTRL);
  254.    }
  255.  
  256.    inst->qtr_ctrl = GEN_EXTRACT(dw0, GEN6_INST_QTRCTRL);
  257.    inst->thread_ctrl = GEN_EXTRACT(dw0, GEN6_INST_THREADCTRL);
  258.    inst->pred_ctrl = GEN_EXTRACT(dw0, GEN6_INST_PREDCTRL);
  259.  
  260.    inst->pred_inv = (bool) (dw0 & GEN6_INST_PREDINV);
  261.  
  262.    inst->exec_size = GEN_EXTRACT(dw0, GEN6_INST_EXECSIZE);
  263.  
  264.    switch (inst->opcode) {
  265.    case GEN6_OPCODE_SEND:
  266.    case GEN6_OPCODE_SENDC:
  267.       inst->sfid = GEN_EXTRACT(dw0, GEN6_INST_SFID);
  268.       break;
  269.    case GEN6_OPCODE_MATH:
  270.       inst->fc = GEN_EXTRACT(dw0, GEN6_INST_FC);
  271.       break;
  272.    default:
  273.       inst->cond_modifier = GEN_EXTRACT(dw0, GEN6_INST_CONDMODIFIER);
  274.       break;
  275.    }
  276.  
  277.    switch (inst->opcode) {
  278.    case GEN6_OPCODE_IF:
  279.    case GEN6_OPCODE_ELSE:
  280.    case GEN8_OPCODE_GOTO:
  281.       if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
  282.          inst->branch_ctrl = (bool) (dw0 & GEN8_INST_BRANCHCTRL);
  283.          break;
  284.       }
  285.    default:
  286.       inst->acc_wr_ctrl = (bool) (dw0 & GEN6_INST_ACCWRCTRL);
  287.       break;
  288.    }
  289.  
  290.    inst->cmpt_ctrl = (bool) (dw0 & GEN6_INST_CMPTCTRL);
  291.    inst->debug_ctrl = (bool) (dw0 & GEN6_INST_DEBUGCTRL);
  292.    inst->saturate = (bool) (dw0 & GEN6_INST_SATURATE);
  293. }
  294.  
  295. static void
  296. disasm_inst_decode_dw1_low_gen6(struct disasm_inst *inst, uint32_t dw1)
  297. {
  298.    ILO_DEV_ASSERT(inst->dev, 6, 7.5);
  299.  
  300.    inst->dst.base.file = GEN_EXTRACT(dw1, GEN6_INST_DST_FILE);
  301.    inst->dst.base.type = GEN_EXTRACT(dw1, GEN6_INST_DST_TYPE);
  302.    inst->src0.base.file = GEN_EXTRACT(dw1, GEN6_INST_SRC0_FILE);
  303.    inst->src0.base.type = GEN_EXTRACT(dw1, GEN6_INST_SRC0_TYPE);
  304.    inst->src1.base.file = GEN_EXTRACT(dw1, GEN6_INST_SRC1_FILE);
  305.    inst->src1.base.type = GEN_EXTRACT(dw1, GEN6_INST_SRC1_TYPE);
  306.  
  307.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(7))
  308.       inst->nib_ctrl = (bool) (dw1 & GEN7_INST_NIBCTRL);
  309. }
  310.  
  311. static void
  312. disasm_inst_decode_dw1_low_gen8(struct disasm_inst *inst, uint32_t dw1)
  313. {
  314.    ILO_DEV_ASSERT(inst->dev, 8, 8);
  315.  
  316.    inst->flag_subreg = GEN_EXTRACT(dw1, GEN8_INST_FLAG_SUBREG);
  317.    inst->flag_reg = GEN_EXTRACT(dw1, GEN8_INST_FLAG_REG);
  318.    inst->mask_ctrl = GEN_EXTRACT(dw1, GEN8_INST_MASKCTRL);
  319.  
  320.    inst->dst.base.file = GEN_EXTRACT(dw1, GEN8_INST_DST_FILE);
  321.    inst->dst.base.type = GEN_EXTRACT(dw1, GEN8_INST_DST_TYPE);
  322.    inst->src0.base.file = GEN_EXTRACT(dw1, GEN8_INST_SRC0_FILE);
  323.    inst->src0.base.type = GEN_EXTRACT(dw1, GEN8_INST_SRC0_TYPE);
  324.  
  325.    inst->dst.base.addr_imm = GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM_BIT9) <<
  326.       GEN8_INST_DST_ADDR_IMM_BIT9__SHR;
  327. }
  328.  
  329. static void
  330. disasm_inst_decode_dw1_high_gen6(struct disasm_inst *inst, uint32_t dw1)
  331. {
  332.    ILO_DEV_ASSERT(inst->dev, 6, 8);
  333.  
  334.    inst->dst.base.addr_mode = GEN_EXTRACT(dw1, GEN6_INST_DST_ADDRMODE);
  335.  
  336.    if (inst->dst.base.addr_mode == GEN6_ADDRMODE_DIRECT) {
  337.       inst->dst.base.reg = GEN_EXTRACT(dw1, GEN6_INST_DST_REG);
  338.  
  339.       if (inst->access_mode == GEN6_ALIGN_1) {
  340.          inst->dst.base.subreg = GEN_EXTRACT(dw1, GEN6_INST_DST_SUBREG);
  341.       } else {
  342.          inst->dst.base.subreg =
  343.             GEN_EXTRACT(dw1, GEN6_INST_DST_SUBREG_ALIGN16) <<
  344.             GEN6_INST_DST_SUBREG_ALIGN16__SHR;
  345.       }
  346.    } else {
  347.       if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
  348.          inst->dst.base.addr_subreg =
  349.             GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_SUBREG);
  350.  
  351.          /* bit 9 is already set in disasm_inst_decode_dw1_low_gen8() */
  352.          if (inst->access_mode == GEN6_ALIGN_1) {
  353.             inst->dst.base.addr_imm |=
  354.                GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM);
  355.          } else {
  356.             inst->dst.base.addr_imm |=
  357.                GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM_ALIGN16) <<
  358.                GEN8_INST_DST_ADDR_IMM_ALIGN16__SHR;
  359.          }
  360.       } else {
  361.          inst->dst.base.addr_subreg =
  362.             GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_SUBREG);
  363.  
  364.          if (inst->access_mode == GEN6_ALIGN_1) {
  365.             inst->dst.base.addr_imm =
  366.                GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_IMM);
  367.          } else {
  368.             inst->dst.base.addr_imm =
  369.                GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_IMM_ALIGN16) <<
  370.                GEN6_INST_DST_ADDR_IMM_ALIGN16__SHR;
  371.          }
  372.       }
  373.    }
  374.  
  375.    inst->dst.horz_stride = GEN_EXTRACT(dw1, GEN6_INST_DST_HORZSTRIDE);
  376.  
  377.    if (inst->access_mode == GEN6_ALIGN_1)
  378.       inst->dst.writemask = 0xf;
  379.    else
  380.       inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_INST_DST_WRITEMASK);
  381. }
  382.  
  383. static void
  384. disasm_inst_decode_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
  385. {
  386.    ILO_DEV_ASSERT(inst->dev, 6, 8);
  387.  
  388.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(8))
  389.       disasm_inst_decode_dw1_low_gen8(inst, dw1);
  390.    else
  391.       disasm_inst_decode_dw1_low_gen6(inst, dw1);
  392.  
  393.    if (ilo_dev_gen(inst->dev) == ILO_GEN(6) &&
  394.        inst->has_jip && !inst->has_uip)
  395.       inst->u.imm64 = dw1 >> 16;
  396.    else
  397.       disasm_inst_decode_dw1_high_gen6(inst, dw1);
  398. }
  399.  
  400. static void
  401. disasm_inst_decode_dw2_dw3_gen6(struct disasm_inst *inst,
  402.                                 uint32_t dw2, uint32_t dw3)
  403. {
  404.    int imm_bits = 0, count, i;
  405.  
  406.    ILO_DEV_ASSERT(inst->dev, 6, 8);
  407.  
  408.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
  409.       /* how about real 64-bit immediates? */
  410.       if (inst->has_uip) {
  411.          imm_bits = 64;
  412.          inst->src1.base.file = GEN6_FILE_IMM;
  413.          inst->src1.base.type = GEN6_TYPE_D;
  414.       } else {
  415.          inst->src1.base.file = GEN_EXTRACT(dw2, GEN8_INST_SRC1_FILE);
  416.          inst->src1.base.type = GEN_EXTRACT(dw2, GEN8_INST_SRC1_TYPE);
  417.  
  418.          if (inst->src0.base.file == GEN6_FILE_IMM ||
  419.              inst->src1.base.file == GEN6_FILE_IMM)
  420.             imm_bits = 32;
  421.       }
  422.    } else {
  423.       if (ilo_dev_gen(inst->dev) >= ILO_GEN(7))
  424.          inst->flag_reg = GEN_EXTRACT(dw2, GEN7_INST_FLAG_REG);
  425.       inst->flag_subreg = GEN_EXTRACT(dw2, GEN6_INST_FLAG_SUBREG);
  426.  
  427.       if (inst->src0.base.file == GEN6_FILE_IMM ||
  428.           inst->src1.base.file == GEN6_FILE_IMM)
  429.          imm_bits = 32;
  430.    }
  431.  
  432.    switch (imm_bits) {
  433.    case 32:
  434.       inst->u.imm64 = dw3;
  435.       count = 1;
  436.       break;
  437.    case 64:
  438.       inst->u.imm64 = (uint64_t) dw2 << 32 | dw3;
  439.       count = 0;
  440.       break;
  441.    default:
  442.       count = 2;
  443.       break;
  444.    }
  445.  
  446.    for (i = 0; i < count; i++) {
  447.       struct disasm_src_operand *src = (i == 0) ? &inst->src0 : &inst->src1;
  448.       const uint32_t dw = (i == 0) ? dw2 : dw3;
  449.  
  450.       src->base.addr_mode = GEN_EXTRACT(dw, GEN6_INST_SRC_ADDRMODE);
  451.  
  452.       if (src->base.addr_mode == GEN6_ADDRMODE_DIRECT) {
  453.          src->base.reg = GEN_EXTRACT(dw, GEN6_INST_SRC_REG);
  454.  
  455.          if (inst->access_mode == GEN6_ALIGN_1) {
  456.             src->base.subreg = GEN_EXTRACT(dw, GEN6_INST_SRC_SUBREG);
  457.          } else {
  458.             src->base.subreg = GEN_EXTRACT(dw, GEN6_INST_SRC_SUBREG_ALIGN16) <<
  459.                GEN6_INST_SRC_SUBREG_ALIGN16__SHR;
  460.          }
  461.       } else {
  462.          if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
  463.             src->base.addr_subreg =
  464.                GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_SUBREG);
  465.  
  466.             if (inst->access_mode == GEN6_ALIGN_1) {
  467.                src->base.addr_imm = GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_IMM);
  468.             } else {
  469.                src->base.addr_imm =
  470.                   GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_IMM_ALIGN16) <<
  471.                   GEN8_INST_SRC_ADDR_IMM_ALIGN16__SHR;
  472.             }
  473.  
  474.             if (i == 0) {
  475.                inst->dst.base.addr_imm |= GEN_EXTRACT(dw,
  476.                      GEN8_INST_SRC0_ADDR_IMM_BIT9) <<
  477.                   GEN8_INST_SRC0_ADDR_IMM_BIT9__SHR;
  478.             } else {
  479.                inst->dst.base.addr_imm |= GEN_EXTRACT(dw,
  480.                      GEN8_INST_SRC1_ADDR_IMM_BIT9) <<
  481.                   GEN8_INST_SRC1_ADDR_IMM_BIT9__SHR;
  482.             }
  483.          } else {
  484.             src->base.addr_subreg =
  485.                GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_SUBREG);
  486.  
  487.             if (inst->access_mode == GEN6_ALIGN_1) {
  488.                src->base.addr_imm = GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_IMM);
  489.             } else {
  490.                src->base.addr_imm =
  491.                   GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_IMM_ALIGN16) <<
  492.                   GEN6_INST_SRC_ADDR_IMM_ALIGN16__SHR;
  493.             }
  494.          }
  495.       }
  496.  
  497.       src->vert_stride = GEN_EXTRACT(dw, GEN6_INST_SRC_VERTSTRIDE);
  498.  
  499.       if (inst->access_mode == GEN6_ALIGN_1) {
  500.          src->width = GEN_EXTRACT(dw, GEN6_INST_SRC_WIDTH);
  501.          src->horz_stride = GEN_EXTRACT(dw, GEN6_INST_SRC_HORZSTRIDE);
  502.  
  503.          src->swizzle_x = GEN6_SWIZZLE_X;
  504.          src->swizzle_y = GEN6_SWIZZLE_Y;
  505.          src->swizzle_z = GEN6_SWIZZLE_Z;
  506.          src->swizzle_w = GEN6_SWIZZLE_W;
  507.       } else {
  508.          src->width = GEN6_WIDTH_4;
  509.          src->horz_stride = GEN6_HORZSTRIDE_1;
  510.  
  511.          src->swizzle_x = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_X);
  512.          src->swizzle_y = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_Y);
  513.          src->swizzle_z = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_Z);
  514.          src->swizzle_w = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_W);
  515.       }
  516.  
  517.       src->negate = (bool) (dw & GEN6_INST_SRC_NEGATE);
  518.       src->absolute = (bool) (dw & GEN6_INST_SRC_ABSOLUTE);
  519.    }
  520. }
  521.  
  522. static void
  523. disasm_inst_decode_3src_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
  524. {
  525.    static const unsigned type_mapping[4] = {
  526.       [GEN7_TYPE_F_3SRC]   = GEN6_TYPE_F,
  527.       [GEN7_TYPE_D_3SRC]   = GEN6_TYPE_D,
  528.       [GEN7_TYPE_UD_3SRC]  = GEN6_TYPE_UD,
  529.       [GEN7_TYPE_DF_3SRC]  = GEN7_TYPE_DF,
  530.    };
  531.  
  532.    ILO_DEV_ASSERT(inst->dev, 6, 7.5);
  533.  
  534.    inst->flag_subreg = GEN_EXTRACT(dw1, GEN6_3SRC_FLAG_SUBREG);
  535.  
  536.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
  537.       inst->nib_ctrl = (bool) (dw1 & GEN7_3SRC_NIBCTRL);
  538.       inst->flag_reg = GEN_EXTRACT(dw1, GEN7_3SRC_FLAG_REG);
  539.  
  540.       inst->dst.base.file = GEN6_FILE_GRF;
  541.       inst->dst.base.type = GEN_EXTRACT(dw1, GEN7_3SRC_DST_TYPE);
  542.       inst->dst.base.type = type_mapping[inst->dst.base.type];
  543.  
  544.       inst->src0.base.type = GEN_EXTRACT(dw1, GEN7_3SRC_SRC_TYPE);
  545.       inst->src0.base.type = type_mapping[inst->src0.base.type];
  546.  
  547.       inst->src1.base.type = inst->src0.base.type;
  548.       inst->u.src2.base.type = inst->src0.base.type;
  549.    } else {
  550.       inst->dst.base.file = (dw1 & GEN6_3SRC_DST_FILE_MRF) ?
  551.          GEN6_FILE_MRF: GEN6_FILE_GRF;
  552.       inst->dst.base.type = GEN6_TYPE_F;
  553.  
  554.       inst->src0.base.type = GEN6_TYPE_F;
  555.       inst->src1.base.type = GEN6_TYPE_F;
  556.       inst->u.src2.base.type = GEN6_TYPE_F;
  557.    }
  558.  
  559.    inst->dst.base.addr_mode = GEN6_ADDRMODE_DIRECT;
  560.    inst->dst.base.reg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_REG);
  561.    inst->dst.base.subreg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_SUBREG) <<
  562.       GEN6_3SRC_DST_SUBREG__SHR;
  563.  
  564.    inst->dst.horz_stride = GEN6_HORZSTRIDE_1;
  565.    inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_3SRC_DST_WRITEMASK);
  566.  
  567.    inst->src0.base.file = GEN6_FILE_GRF;
  568.    inst->src0.negate = (bool) (dw1 & GEN6_3SRC_SRC0_NEGATE);
  569.    inst->src0.absolute = (bool) (dw1 & GEN6_3SRC_SRC0_ABSOLUTE);
  570.    inst->src1.base.file = GEN6_FILE_GRF;
  571.    inst->src1.negate = (bool) (dw1 & GEN6_3SRC_SRC1_NEGATE);
  572.    inst->src1.absolute = (bool) (dw1 & GEN6_3SRC_SRC1_ABSOLUTE);
  573.    inst->u.src2.base.file = GEN6_FILE_GRF;
  574.    inst->u.src2.negate = (bool) (dw1 & GEN6_3SRC_SRC2_NEGATE);
  575.    inst->u.src2.absolute = (bool) (dw1 & GEN6_3SRC_SRC2_ABSOLUTE);
  576. }
  577.  
  578. static void
  579. disasm_inst_decode_3src_dw1_gen8(struct disasm_inst *inst, uint32_t dw1)
  580. {
  581.    static const unsigned type_mapping[8] = {
  582.       [GEN7_TYPE_F_3SRC]   = GEN6_TYPE_F,
  583.       [GEN7_TYPE_D_3SRC]   = GEN6_TYPE_D,
  584.       [GEN7_TYPE_UD_3SRC]  = GEN6_TYPE_UD,
  585.       [GEN7_TYPE_DF_3SRC]  = GEN7_TYPE_DF,
  586.       /* map unknown types to unknown types */
  587.       [0x4]                = 0xf,
  588.       [0x5]                = 0xf,
  589.       [0x6]                = 0xf,
  590.       [0x7]                = 0xf,
  591.    };
  592.  
  593.    ILO_DEV_ASSERT(inst->dev, 8, 8);
  594.  
  595.    inst->flag_subreg = GEN_EXTRACT(dw1, GEN8_3SRC_FLAG_SUBREG);
  596.    inst->flag_reg = GEN_EXTRACT(dw1, GEN8_3SRC_FLAG_REG);
  597.    inst->mask_ctrl = GEN_EXTRACT(dw1, GEN8_3SRC_MASKCTRL);
  598.    inst->src0.absolute = (bool) (dw1 & GEN8_3SRC_SRC0_ABSOLUTE);
  599.    inst->src0.negate = (bool) (dw1 & GEN8_3SRC_SRC0_NEGATE);
  600.    inst->src1.negate = (bool) (dw1 & GEN8_3SRC_SRC1_NEGATE);
  601.    inst->src1.absolute = (bool) (dw1 & GEN8_3SRC_SRC1_ABSOLUTE);
  602.    inst->u.src2.negate = (bool) (dw1 & GEN8_3SRC_SRC2_NEGATE);
  603.    inst->u.src2.absolute = (bool) (dw1 & GEN8_3SRC_SRC2_ABSOLUTE);
  604.  
  605.    inst->src0.base.file = GEN6_FILE_GRF;
  606.    inst->src0.base.type = GEN_EXTRACT(dw1, GEN8_3SRC_SRC_TYPE);
  607.    inst->src0.base.type = type_mapping[inst->src0.base.type];
  608.  
  609.    inst->src1.base.file = GEN6_FILE_GRF;
  610.    inst->src1.base.type = inst->src0.base.type;
  611.  
  612.    inst->u.src2.base.file = GEN6_FILE_GRF;
  613.    inst->u.src2.base.type = inst->src0.base.type;
  614.  
  615.    inst->dst.base.file = GEN6_FILE_GRF;
  616.    inst->dst.base.type = GEN_EXTRACT(dw1, GEN8_3SRC_DST_TYPE);
  617.    inst->dst.base.type = type_mapping[inst->dst.base.type];
  618.    inst->dst.base.addr_mode = GEN6_ADDRMODE_DIRECT;
  619.    inst->dst.horz_stride = GEN6_HORZSTRIDE_1;
  620.  
  621.    inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_3SRC_DST_WRITEMASK);
  622.    inst->dst.base.subreg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_SUBREG) <<
  623.       GEN6_3SRC_DST_SUBREG__SHR;
  624.    inst->dst.base.reg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_REG);
  625. }
  626.  
  627. static void
  628. disasm_inst_decode_3src_dw2_dw3_gen6(struct disasm_inst *inst,
  629.                                      uint32_t dw2, uint32_t dw3)
  630. {
  631.    const uint64_t qw = (uint64_t) dw3 << 32 | dw2;
  632.    int i;
  633.  
  634.    ILO_DEV_ASSERT(inst->dev, 6, 8);
  635.  
  636.    for (i = 0; i < 3; i++) {
  637.       struct disasm_src_operand *src = (i == 0) ? &inst->src0 :
  638.                                        (i == 1) ? &inst->src1 :
  639.                                        &inst->u.src2;
  640.       const uint32_t dw = (i == 0) ? GEN_EXTRACT(qw, GEN6_3SRC_SRC_0) :
  641.                           (i == 1) ? GEN_EXTRACT(qw, GEN6_3SRC_SRC_1) :
  642.                           GEN_EXTRACT(qw, GEN6_3SRC_SRC_2);
  643.  
  644.       src->base.addr_mode = GEN6_ADDRMODE_DIRECT;
  645.       src->base.reg = GEN_EXTRACT(dw, GEN6_3SRC_SRC_REG);
  646.       src->base.subreg = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SUBREG) <<
  647.          GEN6_3SRC_SRC_SUBREG__SHR;
  648.  
  649.       if (dw & GEN6_3SRC_SRC_REPCTRL) {
  650.          src->vert_stride = GEN6_VERTSTRIDE_0;
  651.          src->width = GEN6_WIDTH_1;
  652.          src->horz_stride = GEN6_HORZSTRIDE_0;
  653.       } else {
  654.          src->vert_stride = GEN6_VERTSTRIDE_4;
  655.          src->width = GEN6_WIDTH_4;
  656.          src->horz_stride = GEN6_HORZSTRIDE_1;
  657.       }
  658.  
  659.       src->swizzle_x = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_X);
  660.       src->swizzle_y = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_Y);
  661.       src->swizzle_z = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_Z);
  662.       src->swizzle_w = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_W);
  663.    }
  664. }
  665.  
  666. /*
  667.  * When GEN6_INST_CMPTCTRL of DW0 is set, the instruction has 64 bits and is
  668.  * in EU_INSTRUCTION_COMPACT_TWO_SRC form.  We should have expanded it to its
  669.  * original form.
  670.  *
  671.  * Depending on the opcode, the 128-bits instruction is in one of the
  672.  * following forms
  673.  *
  674.  *  - EU_INSTRUCTION_BASIC_ONE_SRC
  675.  *  - EU_INSTRUCTION_BASIC_TWO_SRC
  676.  *  - EU_INSTRUCTION_BASIC_THREE_SRC
  677.  *  - EU_INSTRUCTION_BRANCH_CONDITIONAL
  678.  *  - EU_INSTRUCTION_BRANCH_ONE_SRC
  679.  *  - EU_INSTRUCTION_BRANCH_TWO_SRC
  680.  *  - EU_INSTRUCTION_ILLEGAL
  681.  *  - EU_INSTRUCTION_MATH
  682.  *  - EU_INSTRUCTION_NOP
  683.  *  - EU_INSTRUCTION_SEND
  684.  *
  685.  * In EU_INSTRUCTION_BASIC_ONE_SRC form,
  686.  *
  687.  *  - DW0 is EU_INSTRUCTION_HEADER
  688.  *  - DW1 is EU_INSTRUCTION_OPERAND_CONTROLS
  689.  *  - DW2 is Source 0 and EU_INSTRUCTION_FLAGS
  690.  *  - DW3 is reserved unless Source 0 is an immediate
  691.  *
  692.  * All other forms except EU_INSTRUCTION_BASIC_THREE_SRC are quite compatible
  693.  * with EU_INSTRUCTION_BASIC_ONE_SRC.
  694.  */
  695. static void
  696. disasm_inst_decode(struct disasm_inst *inst,
  697.                    const uint32_t *dw)
  698. {
  699.    assert(!(dw[0] & GEN6_INST_CMPTCTRL));
  700.  
  701.    disasm_inst_decode_dw0_gen6(inst, dw[0]);
  702.  
  703.    if (disasm_opcode_table[inst->opcode].src_count == 3) {
  704.       if (ilo_dev_gen(inst->dev) >= ILO_GEN(8))
  705.          disasm_inst_decode_3src_dw1_gen8(inst, dw[1]);
  706.       else
  707.          disasm_inst_decode_3src_dw1_gen6(inst, dw[1]);
  708.       disasm_inst_decode_3src_dw2_dw3_gen6(inst, dw[2], dw[3]);
  709.    } else {
  710.       disasm_inst_decode_dw1_gen6(inst, dw[1]);
  711.       disasm_inst_decode_dw2_dw3_gen6(inst, dw[2], dw[3]);
  712.    }
  713. }
  714.  
  715. static const char *
  716. disasm_inst_opcode(const struct disasm_inst *inst)
  717. {
  718.    return (disasm_opcode_table[inst->opcode].name) ?
  719.       disasm_opcode_table[inst->opcode].name : "BAD";
  720. }
  721.  
  722. static const char *
  723. disasm_inst_pred_ctrl(const struct disasm_inst *inst)
  724. {
  725.    if (inst->access_mode == GEN6_ALIGN_1) {
  726.       switch (inst->pred_ctrl) {
  727.       case GEN6_PREDCTRL_NORMAL: return "";
  728.       case GEN6_PREDCTRL_ANYV:   return ".anyv";
  729.       case GEN6_PREDCTRL_ALLV:   return ".allv";
  730.       case GEN6_PREDCTRL_ANY2H:  return ".any2h";
  731.       case GEN6_PREDCTRL_ALL2H:  return ".all2h";
  732.       case GEN6_PREDCTRL_ANY4H:  return ".any4h";
  733.       case GEN6_PREDCTRL_ALL4H:  return ".all4h";
  734.       case GEN6_PREDCTRL_ANY8H:  return ".any8h";
  735.       case GEN6_PREDCTRL_ALL8H:  return ".all8h";
  736.       case GEN6_PREDCTRL_ANY16H: return ".any16h";
  737.       case GEN6_PREDCTRL_ALL16H: return ".all16h";
  738.       case GEN7_PREDCTRL_ANY32H: return ".any32h";
  739.       case GEN7_PREDCTRL_ALL32H: return ".all32h";
  740.       default:                   return ".BAD";
  741.       }
  742.    } else {
  743.       switch (inst->pred_ctrl) {
  744.       case GEN6_PREDCTRL_NORMAL: return "";
  745.       case GEN6_PREDCTRL_X:      return ".x";
  746.       case GEN6_PREDCTRL_Y:      return ".y";
  747.       case GEN6_PREDCTRL_Z:      return ".z";
  748.       case GEN6_PREDCTRL_W:      return ".w";
  749.       default:                   return ".BAD";
  750.       }
  751.    }
  752. }
  753.  
  754. static char
  755. disasm_inst_pred_inv(const struct disasm_inst *inst)
  756. {
  757.    return (inst->pred_inv) ? '-' : '+';
  758. }
  759.  
  760. static const char *
  761. disasm_inst_exec_size(const struct disasm_inst *inst)
  762. {
  763.    switch (inst->exec_size) {
  764.    case GEN6_EXECSIZE_1:   return "1";
  765.    case GEN6_EXECSIZE_2:   return "2";
  766.    case GEN6_EXECSIZE_4:   return "4";
  767.    case GEN6_EXECSIZE_8:   return "8";
  768.    case GEN6_EXECSIZE_16:  return "16";
  769.    case GEN6_EXECSIZE_32:  return "32";
  770.    default:                return "BAD";
  771.    }
  772. }
  773.  
  774. static const char *
  775. disasm_inst_fc(const struct disasm_inst *inst)
  776. {
  777.    assert(inst->opcode == GEN6_OPCODE_MATH);
  778.  
  779.    switch (inst->fc) {
  780.    case GEN6_MATH_INV:                 return "inv";
  781.    case GEN6_MATH_LOG:                 return "log";
  782.    case GEN6_MATH_EXP:                 return "exp";
  783.    case GEN6_MATH_SQRT:                return "sqrt";
  784.    case GEN6_MATH_RSQ:                 return "rsq";
  785.    case GEN6_MATH_SIN:                 return "sin";
  786.    case GEN6_MATH_COS:                 return "cos";
  787.    case GEN6_MATH_FDIV:                return "fdiv";
  788.    case GEN6_MATH_POW:                 return "pow";
  789.    case GEN6_MATH_INT_DIV:             return "int_div";
  790.    case GEN6_MATH_INT_DIV_QUOTIENT:    return "int_div_quotient";
  791.    case GEN6_MATH_INT_DIV_REMAINDER:   return "int_div_remainder";
  792.    case GEN8_MATH_INVM:                return "invm";
  793.    case GEN8_MATH_RSQRTM:              return "rsqrtm";
  794.    default:                            return "BAD";
  795.    }
  796. }
  797.  
  798. static const char *
  799. disasm_inst_sfid(const struct disasm_inst *inst)
  800. {
  801.    assert(inst->opcode == GEN6_OPCODE_SEND ||
  802.           inst->opcode == GEN6_OPCODE_SENDC);
  803.  
  804.    switch (inst->sfid) {
  805.    case GEN6_SFID_NULL:          return "null";
  806.    case GEN6_SFID_SAMPLER:       return "sampler";
  807.    case GEN6_SFID_GATEWAY:       return "gateway";
  808.    case GEN6_SFID_DP_SAMPLER:    return "dp sampler";
  809.    case GEN6_SFID_DP_RC:         return "dp render";
  810.    case GEN6_SFID_URB:           return "urb";
  811.    case GEN6_SFID_SPAWNER:       return "spawner";
  812.    case GEN6_SFID_VME:           return "vme";
  813.    case GEN6_SFID_DP_CC:         return "dp const";
  814.    case GEN7_SFID_DP_DC0:        return "dp data 0";
  815.    case GEN7_SFID_PI:            return "pixel interp";
  816.    case GEN75_SFID_DP_DC1:       return "dp data 1";
  817.    default:                      return "BAD";
  818.    }
  819. }
  820.  
  821. static const char *
  822. disasm_inst_cond_modifier(const struct disasm_inst *inst)
  823. {
  824.    switch (inst->cond_modifier) {
  825.    case GEN6_COND_NONE:    return "";
  826.    case GEN6_COND_Z:       return ".z";
  827.    case GEN6_COND_NZ:      return ".nz";
  828.    case GEN6_COND_G:       return ".g";
  829.    case GEN6_COND_GE:      return ".ge";
  830.    case GEN6_COND_L:       return ".l";
  831.    case GEN6_COND_LE:      return ".le";
  832.    case GEN6_COND_O:       return ".o";
  833.    case GEN6_COND_U:       return ".u";
  834.    default:                return ".BAD";
  835.    }
  836. }
  837.  
  838. static const char *
  839. disasm_inst_debug_ctrl(const struct disasm_inst *inst)
  840. {
  841.    return (inst->debug_ctrl) ? ".breakpoint" : "";
  842. }
  843.  
  844. static const char *
  845. disasm_inst_saturate(const struct disasm_inst *inst)
  846. {
  847.    return (inst->saturate) ? ".sat" : "";
  848. }
  849.  
  850. static const char *
  851. disasm_inst_flag_reg(const struct disasm_inst *inst)
  852. {
  853.    static const char *flag_names[2][2] = {
  854.       { "f0",   "f0.1" },
  855.       { "f1.0", "f1.1" },
  856.    };
  857.  
  858.    return (inst->flag_reg <= 1 && inst->flag_subreg <= 1) ?
  859.       flag_names[inst->flag_reg][inst->flag_subreg] : "fBAD";
  860. }
  861.  
  862. static const char *
  863. disasm_inst_access_mode(const struct disasm_inst *inst)
  864. {
  865.    switch (inst->access_mode) {
  866.    case GEN6_ALIGN_1:   return " align1";
  867.    case GEN6_ALIGN_16:  return " align16";
  868.    default:             return " alignBAD";
  869.    }
  870. }
  871.  
  872. static const char *
  873. disasm_inst_mask_ctrl(const struct disasm_inst *inst)
  874. {
  875.    switch (inst->mask_ctrl) {
  876.    case GEN6_MASKCTRL_NORMAL: return "";
  877.    case GEN6_MASKCTRL_NOMASK: return " WE_all";
  878.    default:                   return " WE_BAD";
  879.    }
  880. }
  881.  
  882. static const char *
  883. disasm_inst_dep_ctrl(const struct disasm_inst *inst)
  884. {
  885.    switch (inst->dep_ctrl) {
  886.    case GEN6_DEPCTRL_NORMAL:  return "";
  887.    case GEN6_DEPCTRL_NODDCLR: return " NoDDClr";
  888.    case GEN6_DEPCTRL_NODDCHK: return " NoDDChk";
  889.    case GEN6_DEPCTRL_NEITHER: return " NoDDClr,NoDDChk";
  890.    default:                   return " NoDDBAD";
  891.    }
  892. }
  893.  
  894. static const char *
  895. disasm_inst_qtr_ctrl(const struct disasm_inst *inst)
  896. {
  897.    switch (inst->exec_size) {
  898.    case GEN6_EXECSIZE_8:
  899.       switch (inst->qtr_ctrl) {
  900.       case GEN6_QTRCTRL_1Q:   return " 1Q";
  901.       case GEN6_QTRCTRL_2Q:   return " 2Q";
  902.       case GEN6_QTRCTRL_3Q:   return " 3Q";
  903.       case GEN6_QTRCTRL_4Q:   return " 4Q";
  904.       default:                return " BADQ";
  905.       }
  906.       break;
  907.    case GEN6_EXECSIZE_16:
  908.       switch (inst->qtr_ctrl) {
  909.       case GEN6_QTRCTRL_1H:   return " 1H";
  910.       case GEN6_QTRCTRL_2H:   return " 2H";
  911.       default:                return " BADH";
  912.       }
  913.       break;
  914.    default:
  915.       return                  "";
  916.    }
  917.  
  918. }
  919.  
  920. static const char *
  921. disasm_inst_thread_ctrl(const struct disasm_inst *inst)
  922. {
  923.    switch (inst->thread_ctrl) {
  924.    case GEN6_THREADCTRL_NORMAL:  return "";
  925.    case GEN6_THREADCTRL_ATOMIC:  return " atomic";
  926.    case GEN6_THREADCTRL_SWITCH:  return " switch";
  927.    default:                      return " BAD";
  928.    }
  929. }
  930.  
  931. static const char *
  932. disasm_inst_acc_wr_ctrl(const struct disasm_inst *inst)
  933. {
  934.    return (inst->acc_wr_ctrl) ? " AccWrEnable" : "";
  935. }
  936.  
  937. static const char *
  938. disasm_inst_cmpt_ctrl(const struct disasm_inst *inst)
  939. {
  940.    return (inst->cmpt_ctrl) ? " compacted" : "";
  941. }
  942.  
  943. static const char *
  944. disasm_inst_eot(const struct disasm_inst *inst)
  945. {
  946.    const uint32_t mdesc = inst->u.ud;
  947.  
  948.    if (inst->opcode == GEN6_OPCODE_SEND ||
  949.        inst->opcode == GEN6_OPCODE_SENDC)
  950.       return (mdesc & GEN6_MSG_EOT) ? " EOT" : "";
  951.    else
  952.       return "";
  953. }
  954.  
  955. static const char *
  956. disasm_inst_file(const struct disasm_inst *inst,
  957.                  const struct disasm_operand *operand,
  958.                  bool *multi_regs)
  959. {
  960.    switch (operand->file) {
  961.    case GEN6_FILE_ARF:
  962.       switch (operand->reg & 0xf0) {
  963.       case GEN6_ARF_NULL:  *multi_regs = false; return "null";
  964.       case GEN6_ARF_A0:    *multi_regs = true;  return "a";
  965.       case GEN6_ARF_ACC0:  *multi_regs = true;  return "acc";
  966.       case GEN6_ARF_F0:    *multi_regs = true;  return "f";
  967.       case GEN6_ARF_SR0:   *multi_regs = true;  return "sr";
  968.       case GEN6_ARF_CR0:   *multi_regs = true;  return "cr";
  969.       case GEN6_ARF_N0:    *multi_regs = true;  return "n";
  970.       case GEN6_ARF_IP:    *multi_regs = false; return "ip";
  971.       case GEN6_ARF_TDR:   *multi_regs = false; return "tdr";
  972.       case GEN7_ARF_TM0:   *multi_regs = true;  return "tm";
  973.       default:             *multi_regs = false; return "BAD";
  974.       }
  975.       break;
  976.    case GEN6_FILE_GRF:     *multi_regs = true;  return "g";
  977.    case GEN6_FILE_MRF:     *multi_regs = true;  return "m";
  978.    case GEN6_FILE_IMM:     *multi_regs = true;  return "";
  979.    default:                *multi_regs = false; return "BAD";
  980.    }
  981. }
  982.  
  983. static const char *
  984. disasm_inst_type(const struct disasm_inst *inst,
  985.                  const struct disasm_operand *operand)
  986. {
  987.    if (operand->file == GEN6_FILE_IMM) {
  988.       switch (operand->type) {
  989.       case GEN6_TYPE_UD:      return "UD";
  990.       case GEN6_TYPE_D:       return "D";
  991.       case GEN6_TYPE_UW:      return "UW";
  992.       case GEN6_TYPE_W:       return "W";
  993.       case GEN6_TYPE_UV_IMM:  return "UV";
  994.       case GEN6_TYPE_VF_IMM:  return "VF";
  995.       case GEN6_TYPE_V_IMM:   return "V";
  996.       case GEN6_TYPE_F:       return "F";
  997.       case GEN8_TYPE_DF_IMM:  return "DF";
  998.       case GEN8_TYPE_HF_IMM:  return "HF";
  999.       default:                return "BAD";
  1000.       }
  1001.    } else {
  1002.       switch (operand->type) {
  1003.       case GEN6_TYPE_UD:      return "UD";
  1004.       case GEN6_TYPE_D:       return "D";
  1005.       case GEN6_TYPE_UW:      return "UW";
  1006.       case GEN6_TYPE_W:       return "W";
  1007.       case GEN6_TYPE_UB:      return "UB";
  1008.       case GEN6_TYPE_B:       return "B";
  1009.       case GEN7_TYPE_DF:      return "DF";
  1010.       case GEN6_TYPE_F:       return "F";
  1011.       case GEN8_TYPE_UQ:      return "UQ";
  1012.       case GEN8_TYPE_Q:       return "Q";
  1013.       case GEN8_TYPE_HF:      return "HF";
  1014.       default:                return "BAD";
  1015.       }
  1016.    }
  1017. }
  1018.  
  1019. static const char *
  1020. disasm_inst_vert_stride(const struct disasm_inst *inst, unsigned vert_stride)
  1021. {
  1022.    switch (vert_stride) {
  1023.    case GEN6_VERTSTRIDE_0:    return "0";
  1024.    case GEN6_VERTSTRIDE_1:    return "1";
  1025.    case GEN6_VERTSTRIDE_2:    return "2";
  1026.    case GEN6_VERTSTRIDE_4:    return "4";
  1027.    case GEN6_VERTSTRIDE_8:    return "8";
  1028.    case GEN6_VERTSTRIDE_16:   return "16";
  1029.    case GEN6_VERTSTRIDE_32:   return "32";
  1030.    case GEN6_VERTSTRIDE_VXH:  return "VxH";
  1031.    default:                   return "BAD";
  1032.    }
  1033. }
  1034.  
  1035. static const char *
  1036. disasm_inst_width(const struct disasm_inst *inst, unsigned width)
  1037. {
  1038.    switch (width) {
  1039.    case GEN6_WIDTH_1:   return "1";
  1040.    case GEN6_WIDTH_2:   return "2";
  1041.    case GEN6_WIDTH_4:   return "4";
  1042.    case GEN6_WIDTH_8:   return "8";
  1043.    case GEN6_WIDTH_16:  return "16";
  1044.    default:             return "BAD";
  1045.    }
  1046. }
  1047.  
  1048. static const char *
  1049. disasm_inst_horz_stride(const struct disasm_inst *inst, unsigned horz_stride)
  1050. {
  1051.    switch (horz_stride) {
  1052.    case GEN6_HORZSTRIDE_0: return "0";
  1053.    case GEN6_HORZSTRIDE_1: return "1";
  1054.    case GEN6_HORZSTRIDE_2: return "2";
  1055.    case GEN6_HORZSTRIDE_4: return "4";
  1056.    default:                return "BAD";
  1057.    }
  1058. }
  1059.  
  1060. static const char *
  1061. disasm_inst_writemask(const struct disasm_inst *inst, unsigned writemask)
  1062. {
  1063.    switch (writemask) {
  1064.    case 0x0:   return ".";
  1065.    case 0x1:   return ".x";
  1066.    case 0x2:   return ".y";
  1067.    case 0x3:   return ".xy";
  1068.    case 0x4:   return ".z";
  1069.    case 0x5:   return ".xz";
  1070.    case 0x6:   return ".yz";
  1071.    case 0x7:   return ".xyz";
  1072.    case 0x8:   return ".w";
  1073.    case 0x9:   return ".xw";
  1074.    case 0xa:   return ".yw";
  1075.    case 0xb:   return ".xyw";
  1076.    case 0xc:   return ".zw";
  1077.    case 0xd:   return ".xzw";
  1078.    case 0xe:   return ".yzw";
  1079.    case 0xf:   return "";
  1080.    default:    return ".BAD";
  1081.    }
  1082. }
  1083.  
  1084. static const char *
  1085. disasm_inst_negate(const struct disasm_inst *inst, bool negate)
  1086. {
  1087.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
  1088.       switch (inst->opcode) {
  1089.       case GEN6_OPCODE_AND:
  1090.       case GEN6_OPCODE_NOT:
  1091.       case GEN6_OPCODE_OR:
  1092.       case GEN6_OPCODE_XOR:
  1093.          return (negate) ? "~" : "";
  1094.          break;
  1095.       default:
  1096.          break;
  1097.       }
  1098.    }
  1099.  
  1100.    return (negate) ? "-" : "";
  1101. }
  1102.  
  1103. static const char *
  1104. disasm_inst_absolute(const struct disasm_inst *inst, bool absolute)
  1105. {
  1106.    return (absolute) ? "(abs)" : "";
  1107. }
  1108.  
  1109. static const char *
  1110. disasm_inst_mdesc_sampler_op(const struct disasm_inst *inst, int op)
  1111. {
  1112.    switch (op) {
  1113.    case GEN6_MSG_SAMPLER_SAMPLE:       return "sample";
  1114.    case GEN6_MSG_SAMPLER_SAMPLE_B:     return "sample_b";
  1115.    case GEN6_MSG_SAMPLER_SAMPLE_L:     return "sample_l";
  1116.    case GEN6_MSG_SAMPLER_SAMPLE_C:     return "sample_c";
  1117.    case GEN6_MSG_SAMPLER_SAMPLE_D:     return "sample_d";
  1118.    case GEN6_MSG_SAMPLER_SAMPLE_B_C:   return "sample_b_c";
  1119.    case GEN6_MSG_SAMPLER_SAMPLE_L_C:   return "sample_l_c";
  1120.    case GEN6_MSG_SAMPLER_LD:           return "ld";
  1121.    case GEN6_MSG_SAMPLER_GATHER4:      return "gather4";
  1122.    case GEN6_MSG_SAMPLER_LOD:          return "lod";
  1123.    case GEN6_MSG_SAMPLER_RESINFO:      return "resinfo";
  1124.    case GEN6_MSG_SAMPLER_SAMPLEINFO:   return "sampleinfo";
  1125.    case GEN7_MSG_SAMPLER_GATHER4_C:    return "gather4_c";
  1126.    case GEN7_MSG_SAMPLER_GATHER4_PO:   return "gather4_po";
  1127.    case GEN7_MSG_SAMPLER_GATHER4_PO_C: return "gather4_po_c";
  1128.    case GEN7_MSG_SAMPLER_SAMPLE_D_C:   return "sample_d_c";
  1129.    case GEN7_MSG_SAMPLER_SAMPLE_LZ:    return "sample_lz";
  1130.    case GEN7_MSG_SAMPLER_SAMPLE_C_LC:  return "sample_c_lc";
  1131.    case GEN7_MSG_SAMPLER_LD_LZ:        return "ld_lz";
  1132.    case GEN7_MSG_SAMPLER_LD_MCS:       return "ld_mcs";
  1133.    case GEN7_MSG_SAMPLER_LD2DMS:       return "ld2dms";
  1134.    case GEN7_MSG_SAMPLER_LD2DSS:       return "ld2dss";
  1135.    default:                            return "BAD";
  1136.    }
  1137. }
  1138.  
  1139. static const char *
  1140. disasm_inst_mdesc_sampler_simd(const struct disasm_inst *inst, int simd)
  1141. {
  1142.    switch (simd) {
  1143.    case GEN6_MSG_SAMPLER_SIMD4X2:   return "SIMD4x2";
  1144.    case GEN6_MSG_SAMPLER_SIMD8:     return "SIMD8";
  1145.    case GEN6_MSG_SAMPLER_SIMD16:    return "SIMD16";
  1146.    case GEN6_MSG_SAMPLER_SIMD32_64: return "SIMD32";
  1147.    default:                         return "BAD";
  1148.    }
  1149. }
  1150.  
  1151. static const char *
  1152. disasm_inst_mdesc_urb_op(const struct disasm_inst *inst, int op)
  1153. {
  1154.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
  1155.       switch (op) {
  1156.       case GEN7_MSG_URB_WRITE_HWORD:   return "write HWord";
  1157.       case GEN7_MSG_URB_WRITE_OWORD:   return "write OWord";
  1158.       case GEN7_MSG_URB_READ_HWORD:    return "read HWord";
  1159.       case GEN7_MSG_URB_READ_OWORD:    return "read OWord";
  1160.       case GEN7_MSG_URB_ATOMIC_MOV:    return "atomic mov";
  1161.       case GEN7_MSG_URB_ATOMIC_INC:    return "atomic inc";
  1162.       default:                         return "BAD";
  1163.       }
  1164.    } else {
  1165.       switch (op) {
  1166.       case GEN6_MSG_URB_WRITE:         return "urb_write";
  1167.       case GEN6_MSG_URB_FF_SYNC:       return "ff_sync";
  1168.       default:                         return "BAD";
  1169.       }
  1170.    }
  1171. }
  1172.  
  1173. static const char *
  1174. disasm_inst_mdesc_dp_op_gen6(const struct disasm_inst *inst,
  1175.                              int sfid, int op)
  1176. {
  1177.    ILO_DEV_ASSERT(inst->dev, 6, 6);
  1178.  
  1179.    switch (op) {
  1180.    case GEN6_MSG_DP_OWORD_BLOCK_READ:           return "OWORD block read";
  1181.    case GEN6_MSG_DP_RT_UNORM_READ:              return "RT UNORM read";
  1182.    case GEN6_MSG_DP_OWORD_DUAL_BLOCK_READ:      return "OWORD dual block read";
  1183.    case GEN6_MSG_DP_MEDIA_BLOCK_READ:           return "media block read";
  1184.    case GEN6_MSG_DP_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read";
  1185.    case GEN6_MSG_DP_DWORD_SCATTERED_READ:       return "DWORD scattered read";
  1186.    case GEN6_MSG_DP_DWORD_ATOMIC_WRITE:         return "DWORD atomic write";
  1187.    case GEN6_MSG_DP_OWORD_BLOCK_WRITE:          return "OWORD block write";
  1188.    case GEN6_MSG_DP_OWORD_DUAL_BLOCK_WRITE:     return "OWORD dual block_write";
  1189.    case GEN6_MSG_DP_MEDIA_BLOCK_WRITE:          return "media block write";
  1190.    case GEN6_MSG_DP_DWORD_SCATTERED_WRITE:      return "DWORD scattered write";
  1191.    case GEN6_MSG_DP_RT_WRITE:                   return "RT write";
  1192.    case GEN6_MSG_DP_SVB_WRITE:                  return "SVB write";
  1193.    case GEN6_MSG_DP_RT_UNORM_WRITE:             return "RT UNORM write";
  1194.    default:                                     return "BAD";
  1195.    }
  1196. }
  1197.  
  1198. static const char *
  1199. disasm_inst_mdesc_dp_op_gen7(const struct disasm_inst *inst,
  1200.                              int sfid, int op)
  1201. {
  1202.    ILO_DEV_ASSERT(inst->dev, 7, 7);
  1203.  
  1204.    switch (sfid) {
  1205.    case GEN6_SFID_DP_SAMPLER:
  1206.       switch (op) {
  1207.       case GEN7_MSG_DP_SAMPLER_UNALIGNED_OWORD_BLOCK_READ: return "OWORD block read";
  1208.       case GEN7_MSG_DP_SAMPLER_MEDIA_BLOCK_READ:         return "media block read";
  1209.       default:                                           return "BAD";
  1210.       }
  1211.    case GEN6_SFID_DP_RC:
  1212.       switch (op) {
  1213.       case GEN7_MSG_DP_RC_MEDIA_BLOCK_READ:              return "media block read";
  1214.       case GEN7_MSG_DP_RC_TYPED_SURFACE_READ:            return "typed surface read";
  1215.       case GEN7_MSG_DP_RC_TYPED_ATOMIC_OP:               return "typed atomic op";
  1216.       case GEN7_MSG_DP_RC_MEMORY_FENCE:                  return "memory fence";
  1217.       case GEN7_MSG_DP_RC_MEDIA_BLOCK_WRITE:             return "media block write";
  1218.       case GEN7_MSG_DP_RC_RT_WRITE:                      return "RT write";
  1219.       case GEN7_MSG_DP_RC_TYPED_SURFACE_WRITE:           return "typed surface write";
  1220.       default:                                           return "BAD";
  1221.       }
  1222.    case GEN6_SFID_DP_CC:
  1223.       switch (op) {
  1224.       case GEN7_MSG_DP_CC_OWORD_BLOCK_READ:              return "OWROD block read";
  1225.       case GEN7_MSG_DP_CC_UNALIGNED_OWORD_BLOCK_READ:    return "unaligned OWORD block read";
  1226.       case GEN7_MSG_DP_CC_OWORD_DUAL_BLOCK_READ:         return "OWORD dual block read";
  1227.       case GEN7_MSG_DP_CC_DWORD_SCATTERED_READ:          return "DWORD scattered read";
  1228.       default:                                           return "BAD";
  1229.       }
  1230.    case GEN7_SFID_DP_DC0:
  1231.       switch (op) {
  1232.       case GEN7_MSG_DP_DC0_OWORD_BLOCK_READ:             return "OWORD block read";
  1233.       case GEN7_MSG_DP_DC0_UNALIGNED_OWORD_BLOCK_READ:   return "unaligned OWORD block read";
  1234.       case GEN7_MSG_DP_DC0_OWORD_DUAL_BLOCK_READ:        return "OWORD dual block read";
  1235.       case GEN7_MSG_DP_DC0_DWORD_SCATTERED_READ:         return "DWORD scattered read";
  1236.       case GEN7_MSG_DP_DC0_BYTE_SCATTERED_READ:          return "BYTE scattered read";
  1237.       case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_READ:         return "untyped surface read";
  1238.       case GEN7_MSG_DP_DC0_UNTYPED_ATOMIC_OP:            return "untyped atomic op";
  1239.       case GEN7_MSG_DP_DC0_MEMORY_FENCE:                 return "memory fence";
  1240.       case GEN7_MSG_DP_DC0_OWORD_BLOCK_WRITE:            return "OWORD block write";
  1241.       case GEN7_MSG_DP_DC0_OWORD_DUAL_BLOCK_WRITE:       return "OWORD dual block write";
  1242.       case GEN7_MSG_DP_DC0_DWORD_SCATTERED_WRITE:        return "OWORD scattered write";
  1243.       case GEN7_MSG_DP_DC0_BYTE_SCATTERED_WRITE:         return "BYTE scattered write";
  1244.       case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_WRITE:        return "untyped surface write";
  1245.       default:                                           return "BAD";
  1246.       }
  1247.    default:                                              return "BAD";
  1248.    }
  1249. }
  1250.  
  1251. static const char *
  1252. disasm_inst_mdesc_dp_op_gen75(const struct disasm_inst *inst,
  1253.                               int sfid, int op)
  1254. {
  1255.    ILO_DEV_ASSERT(inst->dev, 7.5, 8);
  1256.  
  1257.    switch (sfid) {
  1258.    case GEN6_SFID_DP_SAMPLER:
  1259.       switch (op) {
  1260.       case GEN75_MSG_DP_SAMPLER_READ_SURFACE_INFO:          return "read surface info";
  1261.       case GEN75_MSG_DP_SAMPLER_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read";
  1262.       case GEN75_MSG_DP_SAMPLER_MEDIA_BLOCK_READ:           return "media block read";
  1263.       default:                                              return "BAD";
  1264.       }
  1265.  
  1266.    case GEN6_SFID_DP_RC:
  1267.       switch (op) {
  1268.       case GEN75_MSG_DP_RC_MEDIA_BLOCK_READ:                return "media block read";
  1269.       case GEN75_MSG_DP_RC_MEMORY_FENCE:                    return "memory fence";
  1270.       case GEN75_MSG_DP_RC_MEDIA_BLOCK_WRITE:               return "media block write";
  1271.       case GEN75_MSG_DP_RC_RT_WRITE:                        return "RT write";
  1272.       default:                                              return "BAD";
  1273.       }
  1274.    case GEN6_SFID_DP_CC:
  1275.       switch (op) {
  1276.       case GEN75_MSG_DP_CC_OWORD_BLOCK_READ:                return "OWROD block read";
  1277.       case GEN75_MSG_DP_CC_UNALIGNED_OWORD_BLOCK_READ:      return "unaligned OWORD block read";
  1278.       case GEN75_MSG_DP_CC_OWORD_DUAL_BLOCK_READ:           return "OWORD dual block read";
  1279.       case GEN75_MSG_DP_CC_DWORD_SCATTERED_READ:            return "DWORD scattered read";
  1280.       default:                                              return "BAD";
  1281.       }
  1282.    case GEN7_SFID_DP_DC0:
  1283.       switch (op) {
  1284.       case GEN75_MSG_DP_DC0_OWORD_BLOCK_READ:               return "OWORD block read";
  1285.       case GEN75_MSG_DP_DC0_UNALIGNED_OWORD_BLOCK_READ:     return "unaligned OWORD block read";
  1286.       case GEN75_MSG_DP_DC0_OWORD_DUAL_BLOCK_READ:          return "OWORD dual block read";
  1287.       case GEN75_MSG_DP_DC0_DWORD_SCATTERED_READ:           return "DWORD scattered read";
  1288.       case GEN75_MSG_DP_DC0_BYTE_SCATTERED_READ:            return "BYTE scattered read";
  1289.       case GEN75_MSG_DP_DC0_MEMORY_FENCE:                   return "memory fence";
  1290.       case GEN75_MSG_DP_DC0_OWORD_BLOCK_WRITE:              return "OWORD block write";
  1291.       case GEN75_MSG_DP_DC0_OWORD_DUAL_BLOCK_WRITE:         return "OWORD dual block write";
  1292.       case GEN75_MSG_DP_DC0_DWORD_SCATTERED_WRITE:          return "OWORD scattered write";
  1293.       case GEN75_MSG_DP_DC0_BYTE_SCATTERED_WRITE:           return "BYTE scattered write";
  1294.       default:                                              return "BAD";
  1295.       }
  1296.    case GEN75_SFID_DP_DC1:
  1297.       switch (op) {
  1298.       case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_READ:           return "untyped surface read";
  1299.       case GEN75_MSG_DP_DC1_UNTYPED_ATOMIC_OP:              return "DC untyped atomic op";
  1300.       case GEN75_MSG_DP_DC1_UNTYPED_ATOMIC_OP_SIMD4X2:      return "DC untyped 4x2 atomic op";
  1301.       case GEN75_MSG_DP_DC1_MEDIA_BLOCK_READ:               return "DC media block read";
  1302.       case GEN75_MSG_DP_DC1_TYPED_SURFACE_READ:             return "DC typed surface read";
  1303.       case GEN75_MSG_DP_DC1_TYPED_ATOMIC_OP:                return "DC typed atomic";
  1304.       case GEN75_MSG_DP_DC1_TYPED_ATOMIC_OP_SIMD4X2:        return "DC typed 4x2 atomic op";
  1305.       case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_WRITE:          return "DC untyped surface write";
  1306.       case GEN75_MSG_DP_DC1_MEDIA_BLOCK_WRITE:              return "DC media block write";
  1307.       case GEN75_MSG_DP_DC1_ATOMIC_COUNTER_OP:              return "DC atomic counter op";
  1308.       case GEN75_MSG_DP_DC1_ATOMIC_COUNTER_OP_SIMD4X2:      return "DC 4x2 atomic counter op";
  1309.       case GEN75_MSG_DP_DC1_TYPED_SURFACE_WRITE:            return "DC typed surface write";
  1310.       default:                                              return "BAD";
  1311.       }
  1312.    default:                                              return "BAD";
  1313.    }
  1314. }
  1315.  
  1316. static const char *
  1317. disasm_inst_mdesc_dp_op(const struct disasm_inst *inst, int sfid, int op)
  1318. {
  1319.    switch (ilo_dev_gen(inst->dev)) {
  1320.    case ILO_GEN(8):
  1321.    case ILO_GEN(7.5):   return disasm_inst_mdesc_dp_op_gen75(inst, sfid, op);
  1322.    case ILO_GEN(7):     return disasm_inst_mdesc_dp_op_gen7(inst, sfid, op);
  1323.    case ILO_GEN(6):     return disasm_inst_mdesc_dp_op_gen6(inst, sfid, op);
  1324.    default:             return "BAD";
  1325.    }
  1326. }
  1327.  
  1328. static const char *
  1329. disasm_inst_mdesc_dp_untyped_surface_simd_mode(const struct disasm_inst *inst,
  1330.                                                uint32_t mdesc)
  1331. {
  1332.    switch (mdesc & GEN7_MSG_DP_UNTYPED_MODE__MASK) {
  1333.    case GEN7_MSG_DP_UNTYPED_MODE_SIMD4X2: return "SIMD4x2";
  1334.    case GEN7_MSG_DP_UNTYPED_MODE_SIMD16:  return "SIMD16";
  1335.    case GEN7_MSG_DP_UNTYPED_MODE_SIMD8:   return "SIMD8";
  1336.    default:                               return "BAD";
  1337.    }
  1338. }
  1339.  
  1340. static const char *
  1341. disasm_inst_mdesc_dp_rt_write_simd_mode(const struct disasm_inst *inst,
  1342.                                         uint32_t mdesc)
  1343. {
  1344.    switch (mdesc & GEN6_MSG_DP_RT_MODE__MASK) {
  1345.    case GEN6_MSG_DP_RT_MODE_SIMD16:             return "SIMD16";
  1346.    case GEN6_MSG_DP_RT_MODE_SIMD16_REPDATA:     return "SIMD16/RepData";
  1347.    case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_LO:   return "SIMD8/DualSrcLow";
  1348.    case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_HI:   return "SIMD8/DualSrcHigh";
  1349.    case GEN6_MSG_DP_RT_MODE_SIMD8_LO:           return "SIMD8";
  1350.    case GEN6_MSG_DP_RT_MODE_SIMD8_IMAGE_WR:     return "SIMD8/ImageWrite";
  1351.    default:                                     return "BAD";
  1352.    }
  1353. }
  1354.  
  1355. static bool
  1356. disasm_inst_is_null(const struct disasm_inst *inst,
  1357.                     const struct disasm_operand *operand)
  1358. {
  1359.    return (operand->file == GEN6_FILE_ARF && operand->reg == GEN6_ARF_NULL);
  1360. }
  1361.  
  1362. static int
  1363. disasm_inst_type_size(const struct disasm_inst *inst,
  1364.                       const struct disasm_operand *operand)
  1365. {
  1366.    assert(operand->file != GEN6_FILE_IMM);
  1367.  
  1368.    switch (operand->type) {
  1369.    case GEN6_TYPE_UD:      return 4;
  1370.    case GEN6_TYPE_D:       return 4;
  1371.    case GEN6_TYPE_UW:      return 2;
  1372.    case GEN6_TYPE_W:       return 2;
  1373.    case GEN6_TYPE_UB:      return 1;
  1374.    case GEN6_TYPE_B:       return 1;
  1375.    case GEN7_TYPE_DF:      return 8;
  1376.    case GEN6_TYPE_F:       return 4;
  1377.    default:                return 1;
  1378.    }
  1379. }
  1380.  
  1381. static void
  1382. disasm_printer_reset(struct disasm_printer *printer)
  1383. {
  1384.    printer->buf[0] = '\0';
  1385.    printer->len = 0;
  1386. }
  1387.  
  1388. static const char *
  1389. disasm_printer_get_string(struct disasm_printer *printer)
  1390. {
  1391.    return printer->buf;
  1392. }
  1393.  
  1394. static void _util_printf_format(2, 3)
  1395. disasm_printer_add(struct disasm_printer *printer, const char *format, ...)
  1396. {
  1397.    const size_t avail = sizeof(printer->buf) - printer->len;
  1398.    va_list ap;
  1399.    int written;
  1400.  
  1401.    va_start(ap, format);
  1402.    written = vsnprintf(printer->buf + printer->len, avail, format, ap);
  1403.    va_end(ap);
  1404.  
  1405.    /* truncated */
  1406.    if (written < 0 || written >= avail) {
  1407.       memcpy(printer->buf + sizeof(printer->buf) - 4, "...", 4);
  1408.       printer->len = sizeof(printer->buf) - 1;
  1409.    } else {
  1410.       printer->len += written;
  1411.    }
  1412. }
  1413.  
  1414. /**
  1415.  * Pad to the specified column.
  1416.  */
  1417. static void
  1418. disasm_printer_column(struct disasm_printer *printer, int col)
  1419. {
  1420.    int len = DISASM_PRINTER_COLUMN_WIDTH * col;
  1421.  
  1422.    if (len <= printer->len) {
  1423.       if (!printer->len)
  1424.          return;
  1425.  
  1426.       /* at least one space */
  1427.       len = printer->len + 1;
  1428.    }
  1429.  
  1430.    if (len >= sizeof(printer->buf)) {
  1431.       len = sizeof(printer->buf) - 1;
  1432.  
  1433.       if (len <= printer->len)
  1434.          return;
  1435.    }
  1436.  
  1437.    memset(printer->buf + printer->len, ' ', len - printer->len);
  1438.    printer->len = len;
  1439.    printer->buf[printer->len] = '\0';
  1440. }
  1441.  
  1442. static void
  1443. disasm_printer_add_op(struct disasm_printer *printer,
  1444.                       const struct disasm_inst *inst)
  1445. {
  1446.    if (inst->pred_ctrl != GEN6_PREDCTRL_NONE) {
  1447.       disasm_printer_add(printer, "(%c%s%s) ",
  1448.             disasm_inst_pred_inv(inst),
  1449.             disasm_inst_flag_reg(inst),
  1450.             disasm_inst_pred_ctrl(inst));
  1451.    }
  1452.  
  1453.    disasm_printer_add(printer, "%s%s%s%s",
  1454.          disasm_inst_opcode(inst),
  1455.          disasm_inst_saturate(inst),
  1456.          disasm_inst_debug_ctrl(inst),
  1457.          disasm_inst_cond_modifier(inst));
  1458.  
  1459.    if (inst->cond_modifier != GEN6_COND_NONE) {
  1460.       switch (inst->opcode) {
  1461.       case GEN6_OPCODE_SEL:
  1462.       case GEN6_OPCODE_IF:
  1463.       case GEN6_OPCODE_WHILE:
  1464.          /* these do not update flag registers */
  1465.          break;
  1466.       default:
  1467.          disasm_printer_add(printer, ".%s", disasm_inst_flag_reg(inst));
  1468.          break;
  1469.       }
  1470.    }
  1471.  
  1472.    if (inst->opcode == GEN6_OPCODE_MATH)
  1473.       disasm_printer_add(printer, " %s", disasm_inst_fc(inst));
  1474.    if (inst->opcode != GEN6_OPCODE_NOP)
  1475.       disasm_printer_add(printer, "(%s)", disasm_inst_exec_size(inst));
  1476. }
  1477.  
  1478. static void
  1479. disasm_printer_add_operand(struct disasm_printer *printer,
  1480.                            const struct disasm_inst *inst,
  1481.                            const struct disasm_operand *operand)
  1482. {
  1483.    const char *name;
  1484.    bool multi_regs;
  1485.  
  1486.    name = disasm_inst_file(inst, operand, &multi_regs);
  1487.    if (!multi_regs) {
  1488.       disasm_printer_add(printer, "%s", name);
  1489.       return;
  1490.    }
  1491.  
  1492.    if (operand->file == GEN6_FILE_IMM) {
  1493.       switch (operand->type) {
  1494.       case GEN6_TYPE_UD:
  1495.          disasm_printer_add(printer, "0x%08xUD", inst->u.ud);
  1496.          break;
  1497.       case GEN6_TYPE_D:
  1498.          disasm_printer_add(printer, "%dD", inst->u.d);
  1499.          break;
  1500.       case GEN6_TYPE_UW:
  1501.          disasm_printer_add(printer, "0x%04xUW", inst->u.uw);
  1502.          break;
  1503.       case GEN6_TYPE_W:
  1504.          disasm_printer_add(printer, "%dW", inst->u.w);
  1505.          break;
  1506.       case GEN6_TYPE_UV_IMM:
  1507.          disasm_printer_add(printer, "0x%08xUV", inst->u.ud);
  1508.          break;
  1509.       case GEN6_TYPE_VF_IMM:
  1510.          disasm_printer_add(printer, "Vector Float");
  1511.          break;
  1512.       case GEN6_TYPE_V_IMM:
  1513.          disasm_printer_add(printer, "0x%08xV", inst->u.ud);
  1514.          break;
  1515.       case GEN6_TYPE_F:
  1516.          disasm_printer_add(printer, "%-gF", uif(inst->u.f));
  1517.          break;
  1518.       default:
  1519.          disasm_printer_add(printer, "BAD");
  1520.          break;
  1521.       }
  1522.  
  1523.       return;
  1524.    }
  1525.  
  1526.    if (operand->addr_mode == GEN6_ADDRMODE_DIRECT) {
  1527.       unsigned reg, subreg;
  1528.  
  1529.       reg = operand->reg;
  1530.       if (operand->file == GEN6_FILE_ARF)
  1531.          reg &= 0xf;
  1532.  
  1533.       subreg = operand->subreg / disasm_inst_type_size(inst, operand);
  1534.  
  1535.       if (subreg)
  1536.          disasm_printer_add(printer, "%s%d.%d", name, reg, subreg);
  1537.       else
  1538.          disasm_printer_add(printer, "%s%d", name, reg);
  1539.    } else {
  1540.       disasm_printer_add(printer, "%s[a0.%d %d]",
  1541.             name, operand->addr_subreg, operand->addr_imm);
  1542.    }
  1543. }
  1544.  
  1545. static void
  1546. disasm_printer_add_dst(struct disasm_printer *printer,
  1547.                        const struct disasm_inst *inst,
  1548.                        const struct disasm_dst_operand *dst)
  1549. {
  1550.    disasm_printer_add_operand(printer, inst, &dst->base);
  1551.  
  1552.    /* dst is an immediate when in EU_INSTRUCTION_BRANCH_CONDITIONAL form */
  1553.    if (disasm_inst_is_null(inst, &dst->base) ||
  1554.        dst->base.file == GEN6_FILE_IMM)
  1555.       return;
  1556.  
  1557.    disasm_printer_add(printer, "<%s>%s%s",
  1558.          disasm_inst_horz_stride(inst, dst->horz_stride),
  1559.          disasm_inst_writemask(inst, dst->writemask),
  1560.          disasm_inst_type(inst, &dst->base));
  1561. }
  1562.  
  1563. static void
  1564. disasm_printer_add_src(struct disasm_printer *printer,
  1565.                        const struct disasm_inst *inst,
  1566.                        const struct disasm_src_operand *src)
  1567. {
  1568.    static const char swizzle_chars[4] = { 'x', 'y', 'z', 'w' };
  1569.    char swizzle[5];
  1570.  
  1571.    disasm_printer_add(printer, "%s%s",
  1572.          disasm_inst_negate(inst, src->negate),
  1573.          disasm_inst_absolute(inst, src->absolute));
  1574.  
  1575.    disasm_printer_add_operand(printer, inst, &src->base);
  1576.  
  1577.    if (disasm_inst_is_null(inst, &src->base) ||
  1578.        src->base.file == GEN6_FILE_IMM)
  1579.       return;
  1580.  
  1581.    if (src->swizzle_x == 0 && src->swizzle_y == 1 &&
  1582.        src->swizzle_z == 2 && src->swizzle_w == 3) {
  1583.       swizzle[0] = '\0';
  1584.    } else if (src->swizzle_x == src->swizzle_y &&
  1585.               src->swizzle_x == src->swizzle_z &&
  1586.               src->swizzle_x == src->swizzle_w) {
  1587.       swizzle[0] = swizzle_chars[src->swizzle_x];
  1588.       swizzle[1] = '\0';
  1589.    } else {
  1590.       swizzle[0] = swizzle_chars[src->swizzle_x];
  1591.       swizzle[1] = swizzle_chars[src->swizzle_y];
  1592.       swizzle[2] = swizzle_chars[src->swizzle_z];
  1593.       swizzle[3] = swizzle_chars[src->swizzle_w];
  1594.       swizzle[4] = '\0';
  1595.    }
  1596.  
  1597.    disasm_printer_add(printer, "<%s,%s,%s>%s%s",
  1598.          disasm_inst_vert_stride(inst, src->vert_stride),
  1599.          disasm_inst_width(inst, src->width),
  1600.          disasm_inst_horz_stride(inst, src->horz_stride),
  1601.          swizzle,
  1602.          disasm_inst_type(inst, &src->base));
  1603. }
  1604.  
  1605. static void
  1606. disasm_printer_add_ctrl(struct disasm_printer *printer,
  1607.                         const struct disasm_inst *inst)
  1608. {
  1609.    if (inst->opcode == GEN6_OPCODE_NOP) {
  1610.       disasm_printer_add(printer, ";");
  1611.       return;
  1612.    }
  1613.  
  1614.    disasm_printer_add(printer, "{%s%s%s%s%s%s%s%s };",
  1615.          disasm_inst_access_mode(inst),
  1616.          disasm_inst_mask_ctrl(inst),
  1617.          disasm_inst_dep_ctrl(inst),
  1618.          disasm_inst_qtr_ctrl(inst),
  1619.          disasm_inst_cmpt_ctrl(inst),
  1620.          disasm_inst_thread_ctrl(inst),
  1621.          disasm_inst_acc_wr_ctrl(inst),
  1622.          disasm_inst_eot(inst));
  1623. }
  1624.  
  1625. static void
  1626. disasm_printer_add_mdesc_sampler(struct disasm_printer *printer,
  1627.                                  const struct disasm_inst *inst,
  1628.                                  uint32_t mdesc)
  1629. {
  1630.    int op, simd;
  1631.  
  1632.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
  1633.       op = GEN_EXTRACT(mdesc, GEN7_MSG_SAMPLER_OP);
  1634.       simd = GEN_EXTRACT(mdesc, GEN7_MSG_SAMPLER_SIMD);
  1635.    } else {
  1636.       op = GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_OP);
  1637.       simd = GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_SIMD);
  1638.    }
  1639.  
  1640.    disasm_printer_add(printer,
  1641.          "%s %s samp %d surf %d",
  1642.          disasm_inst_mdesc_sampler_op(inst, op),
  1643.          disasm_inst_mdesc_sampler_simd(inst, simd),
  1644.          GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_INDEX),
  1645.          GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_SURFACE));
  1646. }
  1647.  
  1648. static void
  1649. disasm_printer_add_mdesc_urb(struct disasm_printer *printer,
  1650.                              const struct disasm_inst *inst,
  1651.                              uint32_t mdesc)
  1652. {
  1653.    int op, offset;
  1654.    bool interleaved, complete, allocate, used;
  1655.  
  1656.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
  1657.       op = GEN_EXTRACT(mdesc, GEN7_MSG_URB_OP);
  1658.       offset = GEN_EXTRACT(mdesc, GEN7_MSG_URB_GLOBAL_OFFSET);
  1659.       interleaved = mdesc & GEN7_MSG_URB_INTERLEAVED;
  1660.  
  1661.       complete = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) ?
  1662.          false : (mdesc & GEN7_MSG_URB_COMPLETE);
  1663.  
  1664.       allocate = false;
  1665.       used = false;
  1666.    } else {
  1667.       op = GEN_EXTRACT(mdesc, GEN6_MSG_URB_OP);
  1668.       offset = GEN_EXTRACT(mdesc, GEN6_MSG_URB_OFFSET);
  1669.       interleaved = mdesc & GEN6_MSG_URB_INTERLEAVED;
  1670.       complete = mdesc & GEN6_MSG_URB_COMPLETE;
  1671.  
  1672.       allocate = mdesc & GEN6_MSG_URB_ALLOCATE;
  1673.       used = mdesc & GEN6_MSG_URB_USED;
  1674.    }
  1675.  
  1676.    disasm_printer_add(printer, "%s offset %d%s%s%s%s",
  1677.          disasm_inst_mdesc_urb_op(inst, op),
  1678.          offset,
  1679.          (interleaved) ? " interleave" : "",
  1680.          (allocate) ? " allocate" : "",
  1681.          (used) ? " used" : "",
  1682.          (complete) ? " complete" : "");
  1683. }
  1684.  
  1685. static void
  1686. disasm_printer_add_mdesc_spawner(struct disasm_printer *printer,
  1687.                                  const struct disasm_inst *inst,
  1688.                                  uint32_t mdesc)
  1689. {
  1690.    const char *requester, *op;
  1691.  
  1692.    switch (mdesc & GEN6_MSG_TS_REQUESTER_TYPE__MASK) {
  1693.    case GEN6_MSG_TS_REQUESTER_TYPE_ROOT:  requester = "root";  break;
  1694.    case GEN6_MSG_TS_REQUESTER_TYPE_CHILD: requester = "child"; break;
  1695.    default:                               requester = "BAD";   break;
  1696.    }
  1697.  
  1698.    switch (mdesc & GEN6_MSG_TS_OPCODE__MASK) {
  1699.    case GEN6_MSG_TS_OPCODE_DEREF:
  1700.       op = (mdesc & GEN6_MSG_TS_RESOURCE_SELECT_NO_DEREF) ?
  1701.          "no deref" : "deref";
  1702.       break;
  1703.    case GEN6_MSG_TS_OPCODE_SPAWN:
  1704.       op = (mdesc & GEN6_MSG_TS_RESOURCE_SELECT_ROOT) ?
  1705.          "spawn root" : "spawn child";
  1706.       break;
  1707.    default:
  1708.       op = "BAD";
  1709.       break;
  1710.    }
  1711.  
  1712.    disasm_printer_add(printer, "%s thread %s", requester, op);
  1713. }
  1714.  
  1715. static void
  1716. disasm_printer_add_mdesc_dp_sampler(struct disasm_printer *printer,
  1717.                                     const struct disasm_inst *inst,
  1718.                                     uint32_t mdesc)
  1719. {
  1720.    const int op = (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) ?
  1721.       GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP) : GEN_EXTRACT(mdesc, GEN6_MSG_DP_OP);
  1722.    const bool write_commit = (ilo_dev_gen(inst->dev) == ILO_GEN(6)) ?
  1723.          (mdesc & GEN6_MSG_DP_SEND_WRITE_COMMIT) : 0;
  1724.  
  1725.    disasm_printer_add(printer, "%s block size %d commit %d surf %d",
  1726.          disasm_inst_mdesc_dp_op(inst, GEN6_SFID_DP_SAMPLER, op),
  1727.          GEN_EXTRACT(mdesc, GEN6_MSG_DP_OWORD_BLOCK_SIZE),
  1728.          write_commit,
  1729.          GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
  1730. }
  1731.  
  1732. static void
  1733. disasm_printer_add_mdesc_dp_dc0(struct disasm_printer *printer,
  1734.                                 const struct disasm_inst *inst,
  1735.                                 uint32_t mdesc)
  1736. {
  1737.    const int op = GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP);
  1738.  
  1739.    ILO_DEV_ASSERT(inst->dev, 7, 7.5);
  1740.  
  1741.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(7.5)) {
  1742.       disasm_printer_add(printer, "%s ctrl 0x%x surf %d",
  1743.             disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op),
  1744.             GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL),
  1745.             GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
  1746.    } else {
  1747.       switch (op) {
  1748.       case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_READ:
  1749.       case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_WRITE:
  1750.          disasm_printer_add(printer, "%s %s mask 0x%x surf %d",
  1751.                disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op),
  1752.                disasm_inst_mdesc_dp_untyped_surface_simd_mode(inst, mdesc),
  1753.                GEN_EXTRACT(mdesc, GEN7_MSG_DP_UNTYPED_MASK),
  1754.                GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
  1755.          break;
  1756.       default:
  1757.          disasm_printer_add(printer, "%s ctrl 0x%x surf %d",
  1758.                disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op),
  1759.                GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL),
  1760.                GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
  1761.          break;
  1762.       }
  1763.    }
  1764. }
  1765.  
  1766. static void
  1767. disasm_printer_add_mdesc_dp_dc1(struct disasm_printer *printer,
  1768.                                 const struct disasm_inst *inst,
  1769.                                 uint32_t mdesc)
  1770. {
  1771.    const int op = GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP);
  1772.  
  1773.    ILO_DEV_ASSERT(inst->dev, 7.5, 7.5);
  1774.  
  1775.    switch (op) {
  1776.    case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_READ:
  1777.    case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_WRITE:
  1778.       disasm_printer_add(printer, "%s %s mask 0x%x surf %d",
  1779.             disasm_inst_mdesc_dp_op(inst, GEN75_SFID_DP_DC1, op),
  1780.             disasm_inst_mdesc_dp_untyped_surface_simd_mode(inst, mdesc),
  1781.             GEN_EXTRACT(mdesc, GEN7_MSG_DP_UNTYPED_MASK),
  1782.             GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
  1783.       break;
  1784.    default:
  1785.       disasm_printer_add(printer, "%s ctrl 0x%x surf %d",
  1786.             disasm_inst_mdesc_dp_op(inst, GEN75_SFID_DP_DC1, op),
  1787.             GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL),
  1788.             GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
  1789.       break;
  1790.    }
  1791. }
  1792.  
  1793. static void
  1794. disasm_printer_add_mdesc_dp_rc(struct disasm_printer *printer,
  1795.                                const struct disasm_inst *inst,
  1796.                                uint32_t mdesc)
  1797. {
  1798.    const int op = (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) ?
  1799.       GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP) : GEN_EXTRACT(mdesc, GEN6_MSG_DP_OP);
  1800.    bool is_rt_write;
  1801.  
  1802.    if (ilo_dev_gen(inst->dev) >= ILO_GEN(7.5))
  1803.       is_rt_write = (op == GEN75_MSG_DP_RC_RT_WRITE);
  1804.    else if (ilo_dev_gen(inst->dev) >= ILO_GEN(7))
  1805.       is_rt_write = (op == GEN7_MSG_DP_RC_RT_WRITE);
  1806.    else
  1807.       is_rt_write = (op == GEN6_MSG_DP_RT_WRITE);
  1808.  
  1809.    disasm_printer_add(printer, "%s",
  1810.          disasm_inst_mdesc_dp_op(inst, GEN6_SFID_DP_RC, op));
  1811.  
  1812.    if (is_rt_write) {
  1813.       disasm_printer_add(printer, " %s%s%s%s",
  1814.             disasm_inst_mdesc_dp_rt_write_simd_mode(inst, mdesc),
  1815.             (mdesc & GEN6_MSG_DP_RT_SLOTGRP_HI) ? " Hi" : "",
  1816.             (mdesc & GEN6_MSG_DP_RT_LAST) ? " LastRT" : "",
  1817.             (ilo_dev_gen(inst->dev) == ILO_GEN(6) &&
  1818.              (mdesc & GEN6_MSG_DP_SEND_WRITE_COMMIT)) ? " WriteCommit" : "");
  1819.    }
  1820.  
  1821.    disasm_printer_add(printer, " surf %d",
  1822.          GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
  1823. }
  1824.  
  1825. static void
  1826. disasm_printer_add_mdesc(struct disasm_printer *printer,
  1827.                          const struct disasm_inst *inst)
  1828. {
  1829.    const uint32_t mdesc = inst->u.ud;
  1830.  
  1831.    assert(inst->opcode == GEN6_OPCODE_SEND ||
  1832.           inst->opcode == GEN6_OPCODE_SENDC);
  1833.    assert(inst->src1.base.file == GEN6_FILE_IMM);
  1834.  
  1835.    disasm_printer_add(printer, "            %s (", disasm_inst_sfid(inst));
  1836.  
  1837.    switch (inst->sfid) {
  1838.    case GEN6_SFID_SAMPLER:
  1839.       disasm_printer_add_mdesc_sampler(printer, inst, mdesc);
  1840.       break;
  1841.    case GEN6_SFID_DP_SAMPLER:
  1842.       disasm_printer_add_mdesc_dp_sampler(printer, inst, mdesc);
  1843.       break;
  1844.    case GEN6_SFID_DP_RC:
  1845.       disasm_printer_add_mdesc_dp_rc(printer, inst, mdesc);
  1846.       break;
  1847.    case GEN6_SFID_URB:
  1848.       disasm_printer_add_mdesc_urb(printer, inst, mdesc);
  1849.       break;
  1850.    case GEN6_SFID_SPAWNER:
  1851.       disasm_printer_add_mdesc_spawner(printer, inst, mdesc);
  1852.       break;
  1853.    case GEN7_SFID_DP_DC0:
  1854.       disasm_printer_add_mdesc_dp_dc0(printer, inst, mdesc);
  1855.       break;
  1856.    case GEN75_SFID_DP_DC1:
  1857.       disasm_printer_add_mdesc_dp_dc1(printer, inst, mdesc);
  1858.       break;
  1859.    case GEN6_SFID_DP_CC:
  1860.    case GEN7_SFID_PI:
  1861.    default:
  1862.       break;
  1863.    }
  1864.  
  1865.    disasm_printer_add(printer, ") mlen %d rlen %d",
  1866.          GEN_EXTRACT(mdesc, GEN6_MSG_MLEN),
  1867.          GEN_EXTRACT(mdesc, GEN6_MSG_RLEN));
  1868. }
  1869.  
  1870. static void
  1871. disasm_printer_print_inst(struct disasm_printer *printer,
  1872.                           const struct disasm_inst *inst)
  1873. {
  1874.    int col = 0;
  1875.  
  1876.    disasm_printer_reset(printer);
  1877.  
  1878.    disasm_printer_column(printer, col++);
  1879.    disasm_printer_add_op(printer, inst);
  1880.  
  1881.    if (inst->has_jip || inst->has_uip) {
  1882.       if (inst->has_jip) {
  1883.          const int32_t jip = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) ?
  1884.             inst->u.ip32.jip : inst->u.ip16.jip;
  1885.  
  1886.          disasm_printer_column(printer, col++);
  1887.          disasm_printer_add(printer, "JIP: %d", jip);
  1888.       }
  1889.  
  1890.       if (inst->has_uip) {
  1891.          const int32_t uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) ?
  1892.             inst->u.ip32.uip : inst->u.ip16.uip;
  1893.  
  1894.          disasm_printer_column(printer, col++);
  1895.          disasm_printer_add(printer, "UIP: %d", uip);
  1896.       }
  1897.    } else {
  1898.       const int src_count = disasm_opcode_table[inst->opcode].src_count;
  1899.  
  1900.       if (src_count) {
  1901.          const struct disasm_src_operand *src[3] = {
  1902.             &inst->src0, &inst->src1, &inst->u.src2
  1903.          };
  1904.          int i;
  1905.  
  1906.          disasm_printer_column(printer, col++);
  1907.          disasm_printer_add_dst(printer, inst, &inst->dst);
  1908.  
  1909.          for (i = 0; i < src_count; i++) {
  1910.             disasm_printer_column(printer, col++);
  1911.             disasm_printer_add_src(printer, inst, src[i]);
  1912.          }
  1913.       }
  1914.    }
  1915.  
  1916.    if (inst->opcode == GEN6_OPCODE_SEND ||
  1917.        inst->opcode == GEN6_OPCODE_SENDC) {
  1918.       /* start a new line */
  1919.       ilo_printf("%s\n", disasm_printer_get_string(printer));
  1920.       disasm_printer_reset(printer);
  1921.       col = 0;
  1922.  
  1923.       disasm_printer_column(printer, col++);
  1924.  
  1925.       disasm_printer_column(printer, col++);
  1926.       disasm_printer_add_mdesc(printer, inst);
  1927.    }
  1928.  
  1929.    if (col < 4)
  1930.       col = 4;
  1931.  
  1932.    disasm_printer_column(printer, col++);
  1933.    disasm_printer_add_ctrl(printer, inst);
  1934.  
  1935.    ilo_printf("%s\n", disasm_printer_get_string(printer));
  1936. }
  1937.  
  1938. static void
  1939. disasm_uncompact_3src(const struct ilo_dev *dev,
  1940.                       uint64_t compact, uint32_t *dw)
  1941. {
  1942.    const struct toy_compaction_table *tbl =
  1943.       toy_compiler_get_compaction_table(dev);
  1944.    uint32_t src[3], tmp;
  1945.    uint64_t tmp64;
  1946.  
  1947.    ILO_DEV_ASSERT(dev, 8, 8);
  1948.  
  1949.    tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_OPCODE);
  1950.    dw[0] = GEN_SHIFT32(tmp, GEN6_INST_OPCODE);
  1951.  
  1952.    /* ControlIndex */
  1953.    tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_CONTROL_INDEX);
  1954.    tmp = tbl->control_3src[tmp];
  1955.  
  1956.    dw[0] |= (tmp & 0x1fffff) << GEN6_INST_ACCESSMODE__SHIFT;
  1957.    dw[1] = (tmp >> 21) & ((ilo_dev_gen(dev) >= ILO_GEN(9)) ? 0x1f : 0x7);
  1958.  
  1959.    /* SourceIndex */
  1960.    tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SOURCE_INDEX);
  1961.    tmp64 = tbl->source_3src[tmp];
  1962.  
  1963.    dw[1] |= (tmp64 & 0x7ffff) << 5;
  1964.    src[0] = ((tmp64 >> 19) & 0xff) << 1;
  1965.    src[1] = ((tmp64 >> 27) & 0xff) << 1;
  1966.    src[2] = ((tmp64 >> 35) & 0xff) << 1;
  1967.    if (ilo_dev_gen(dev) >= ILO_GEN(9)) {
  1968.       src[0] |= ((tmp64 >> 43) & 0x3) << 19;
  1969.       src[1] |= ((tmp64 >> 45) & 0x3) << 19;
  1970.       src[2] |= ((tmp64 >> 47) & 0x3) << 19;
  1971.    } else {
  1972.       src[0] |= ((tmp64 >> 43) & 0x1) << 19;
  1973.       src[1] |= ((tmp64 >> 44) & 0x1) << 19;
  1974.       src[2] |= ((tmp64 >> 45) & 0x1) << 19;
  1975.    }
  1976.  
  1977.    tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_DST_REG);
  1978.    dw[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_DST_REG);
  1979.  
  1980.    if (compact & GEN8_COMPACT_3SRC_SRC0_REPCTRL)
  1981.       src[0] |= GEN6_3SRC_SRC_REPCTRL;
  1982.  
  1983.    assert(compact & GEN8_COMPACT_3SRC_CMPTCTRL);
  1984.  
  1985.    if (compact & GEN8_COMPACT_3SRC_DEBUGCTRL)
  1986.       dw[0] |= GEN6_INST_DEBUGCTRL;
  1987.    if (compact & GEN8_COMPACT_3SRC_SATURATE)
  1988.       dw[0] |= GEN6_INST_SATURATE;
  1989.  
  1990.    if (compact & GEN8_COMPACT_3SRC_SRC1_REPCTRL)
  1991.       src[1] |= GEN6_3SRC_SRC_REPCTRL;
  1992.    if (compact & GEN8_COMPACT_3SRC_SRC2_REPCTRL)
  1993.       src[2] |= GEN6_3SRC_SRC_REPCTRL;
  1994.  
  1995.    tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC0_SUBREG);
  1996.    src[0] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG);
  1997.    tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC1_SUBREG);
  1998.    src[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG);
  1999.    tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC2_SUBREG);
  2000.    src[2] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG);
  2001.  
  2002.    tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC0_REG);
  2003.    src[0] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG);
  2004.    tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC1_REG);
  2005.    src[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG);
  2006.    tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC2_REG);
  2007.    src[2] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG);
  2008.  
  2009.    tmp64 = (uint64_t) src[2] << 42 |
  2010.            (uint64_t) src[1] << 21 |
  2011.            (uint64_t) src[0];
  2012.    dw[2] = (uint32_t) tmp64;
  2013.    dw[3] = (uint32_t) (tmp64 >> 32);
  2014. }
  2015.  
  2016. static void
  2017. disasm_uncompact(const struct ilo_dev *dev,
  2018.                  uint64_t compact, uint32_t *dw)
  2019. {
  2020.    const struct toy_compaction_table *tbl =
  2021.       toy_compiler_get_compaction_table(dev);
  2022.    bool src_is_imm;
  2023.    uint32_t tmp;
  2024.  
  2025.    ILO_DEV_ASSERT(dev, 6, 8);
  2026.  
  2027.    tmp = GEN_EXTRACT(compact, GEN6_COMPACT_OPCODE);
  2028.    if (disasm_opcode_table[tmp].src_count == 3) {
  2029.       disasm_uncompact_3src(dev, compact, dw);
  2030.       return;
  2031.    }
  2032.  
  2033.    memset(dw, 0, sizeof(*dw) * 4);
  2034.  
  2035.    dw[0] |= GEN_SHIFT32(tmp, GEN6_INST_OPCODE);
  2036.  
  2037.    if (ilo_dev_gen(dev) >= ILO_GEN(7) && (compact & GEN6_COMPACT_DEBUGCTRL))
  2038.       dw[0] |= GEN6_INST_DEBUGCTRL;
  2039.  
  2040.    /* ControlIndex */
  2041.    tmp = GEN_EXTRACT(compact, GEN6_COMPACT_CONTROL_INDEX);
  2042.    tmp = tbl->control[tmp];
  2043.  
  2044.    dw[0] |= (tmp & 0xffff) << GEN6_INST_ACCESSMODE__SHIFT;
  2045.    if (tmp & 0x10000)
  2046.       dw[0] |= GEN6_INST_SATURATE;
  2047.  
  2048.    if (ilo_dev_gen(dev) >= ILO_GEN(7))
  2049.       dw[2] |= (tmp >> 17) << GEN6_INST_FLAG_SUBREG__SHIFT;
  2050.  
  2051.    /* DataTypeIndex */
  2052.    tmp = GEN_EXTRACT(compact, GEN6_COMPACT_DATATYPE_INDEX);
  2053.    tmp = tbl->datatype[tmp];
  2054.  
  2055.    dw[1] |= (tmp & 0x7fff) << GEN6_INST_DST_FILE__SHIFT;
  2056.    dw[1] |= (tmp >> 15) << GEN6_INST_DST_HORZSTRIDE__SHIFT;
  2057.  
  2058.    /* SubRegIndex */
  2059.    tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SUBREG_INDEX);
  2060.    tmp = tbl->subreg[tmp];
  2061.  
  2062.    dw[1] |= (tmp & 0x1f) << 16;
  2063.    dw[2] |= ((tmp >> 5) & 0x1f);
  2064.    dw[3] |= ((tmp >> 10) & 0x1f);
  2065.  
  2066.    if (compact & GEN6_COMPACT_ACCWRCTRL)
  2067.       dw[0] |= GEN6_INST_ACCWRCTRL;
  2068.  
  2069.    tmp = GEN_EXTRACT(compact, GEN6_COMPACT_CONDMODIFIER);
  2070.    dw[0] |= GEN_SHIFT32(tmp, GEN6_INST_CONDMODIFIER);
  2071.  
  2072.    if (ilo_dev_gen(dev) == ILO_GEN(6)) {
  2073.       tmp = GEN_EXTRACT(compact, GEN6_COMPACT_FLAG_SUBREG);
  2074.       dw[2] |= GEN_SHIFT32(compact, GEN6_INST_FLAG_SUBREG);
  2075.    }
  2076.  
  2077.    assert(compact & GEN6_COMPACT_CMPTCTRL);
  2078.  
  2079.    /* Src0Index */
  2080.    tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC0_INDEX);
  2081.    tmp = tbl->src[tmp];
  2082.    dw[2] |= tmp << 13;
  2083.  
  2084.    src_is_imm = (GEN_EXTRACT(dw[1], GEN6_INST_SRC0_FILE) == GEN6_FILE_IMM) ||
  2085.                 (GEN_EXTRACT(dw[1], GEN6_INST_SRC1_FILE) == GEN6_FILE_IMM);
  2086.  
  2087.    /* Src1Index */
  2088.    tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC1_INDEX);
  2089.    if (src_is_imm) {
  2090.       if (tmp & 0x10)
  2091.          tmp |= 0xfffff0;
  2092.       dw[3] |= tmp << 8;
  2093.    } else {
  2094.       tmp = tbl->src[tmp];
  2095.       dw[3] |= tmp << 13;
  2096.    }
  2097.  
  2098.    tmp = GEN_EXTRACT(compact, GEN6_COMPACT_DST_REG);
  2099.    dw[1] |= GEN_SHIFT32(tmp, GEN6_INST_DST_REG);
  2100.  
  2101.    tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC0_REG);
  2102.    dw[2] |= GEN_SHIFT32(tmp, GEN6_INST_SRC_REG);
  2103.  
  2104.    tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC1_REG);
  2105.    if (src_is_imm)
  2106.       dw[3] |= tmp;
  2107.    else
  2108.       dw[3] |= GEN_SHIFT32(tmp, GEN6_INST_SRC_REG);
  2109. }
  2110.  
  2111. void
  2112. toy_compiler_disassemble(const struct ilo_dev *dev,
  2113.                          const void *kernel, int size,
  2114.                          bool dump_hex)
  2115. {
  2116.    const uint32_t *cur = (const uint32_t *) kernel;
  2117.    const uint32_t *end = cur + size / sizeof(*cur);
  2118.    struct disasm_printer printer;
  2119.  
  2120.    disasm_printer_reset(&printer);
  2121.  
  2122.    while (cur < end) {
  2123.       struct disasm_inst inst;
  2124.       const bool compacted = (cur[0] & GEN6_INST_CMPTCTRL);
  2125.       const uint32_t *dw = cur;
  2126.       uint32_t temp[4];
  2127.  
  2128.       cur += (compacted) ? 2 : 4;
  2129.       /* incomplete instruction */
  2130.       if (cur > end)
  2131.          break;
  2132.  
  2133.       if (compacted) {
  2134.          const uint64_t compact = (uint64_t) dw[1] << 32 | dw[0];
  2135.          disasm_uncompact(dev, compact, temp);
  2136.          dw = temp;
  2137.       }
  2138.  
  2139.       if (dump_hex) {
  2140.          ilo_printf("0x%08x 0x%08x 0x%08x 0x%08x ",
  2141.                dw[0], dw[1], dw[2], dw[3]);
  2142.       }
  2143.  
  2144.       memset(&inst, 0, sizeof(inst));
  2145.       inst.dev = dev;
  2146.       disasm_inst_decode(&inst, dw);
  2147.       inst.cmpt_ctrl = compacted;
  2148.  
  2149.       disasm_printer_print_inst(&printer, &inst);
  2150.    }
  2151. }
  2152.