summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Gmeiner <cgmeiner@igalia.com>2021-07-26 06:37:25 +0200
committerMarge Bot <emma+marge@anholt.net>2023-12-16 14:34:18 +0000
commitfa0ff0849c5d96534195d276658aa8211d115076 (patch)
tree2dbffdd4ee42dc7f39cfcf1a451cb70667e58390
parenta8a33ac5ae75a76d640d0bed909a3a21a6d68219 (diff)
etnaviv: Add isaspec support
This commit adds etnaviv.xml which describes the used ISA. Quite some time was spend to to get it into that shape by creating a big collection of shader asm generated by the binary blob. These shaders are used as basis for test driven development for this ISA specification. The xml has some black spots but the internal disasm is used by developers so that should be no problem. Some refinement will happen during normal development. This commit adds only disasm support. Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com> Reviewed-by: Rob Clark <robdclark@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20144>
-rw-r--r--.clang-format-include1
-rw-r--r--.gitlab-ci/test-source-dep.yml1
-rw-r--r--src/etnaviv/ci/gitlab-ci.yml1
-rw-r--r--src/etnaviv/isa/.clang-format7
-rw-r--r--src/etnaviv/isa/disasm.c33
-rw-r--r--src/etnaviv/isa/etnaviv.xml1246
-rw-r--r--src/etnaviv/isa/isa.h11
-rw-r--r--src/etnaviv/isa/meson.build48
-rw-r--r--src/etnaviv/isa/tests/disasm.cpp311
-rw-r--r--src/etnaviv/isa/tests/meson.build14
-rw-r--r--src/etnaviv/meson.build1
11 files changed, 1674 insertions, 0 deletions
diff --git a/.clang-format-include b/.clang-format-include
index be36b4ffb33..63e032dc5d8 100644
--- a/.clang-format-include
+++ b/.clang-format-include
@@ -5,3 +5,4 @@ src/gallium/drivers/i915
src/amd/vulkan/**/*
src/amd/compiler/**/*
src/egl/**/*
+src/etnaviv/isa/**/*
diff --git a/.gitlab-ci/test-source-dep.yml b/.gitlab-ci/test-source-dep.yml
index 4a2bed11b27..bee4d9c5772 100644
--- a/.gitlab-ci/test-source-dep.yml
+++ b/.gitlab-ci/test-source-dep.yml
@@ -253,6 +253,7 @@
- src/egl/**/*
- src/amd/vulkan/**/*
- src/amd/compiler/**/*
+ - src/etnaviv/isa/**/*
when: on_success
allow_failure: false
# in other pipelines, formatting checks are allowed to fail
diff --git a/src/etnaviv/ci/gitlab-ci.yml b/src/etnaviv/ci/gitlab-ci.yml
index 947869d2c53..94c84cce6e9 100644
--- a/src/etnaviv/ci/gitlab-ci.yml
+++ b/src/etnaviv/ci/gitlab-ci.yml
@@ -13,6 +13,7 @@
- src/etnaviv/ci/$GPU_VERSION-skips.txt
- src/etnaviv/drm/**/*
- src/etnaviv/drm-shim/**/*
+ - src/etnaviv/isa/**/*
- src/gallium/drivers/etnaviv/**/*
- src/gallium/winsys/etnaviv/**/*
- src/gallium/auxiliary/renderonly/**/*
diff --git a/src/etnaviv/isa/.clang-format b/src/etnaviv/isa/.clang-format
new file mode 100644
index 00000000000..b1a43d91fe2
--- /dev/null
+++ b/src/etnaviv/isa/.clang-format
@@ -0,0 +1,7 @@
+
+BasedOnStyle: InheritParentConfig
+DisableFormat: false
+
+AlignConsecutiveBitFields: true
+ColumnLimit: 100
+BreakStringLiterals: false
diff --git a/src/etnaviv/isa/disasm.c b/src/etnaviv/isa/disasm.c
new file mode 100644
index 00000000000..88710f663c3
--- /dev/null
+++ b/src/etnaviv/isa/disasm.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2023 Igalia S.L.
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <stdio.h>
+
+#include "util/os_file.h"
+
+#include "isa.h"
+
+static void
+pre_instr_cb(void *d, unsigned n, void *instr)
+{
+ uint32_t *dwords = (uint32_t *)instr;
+ printf("%03d [%08x %08x %08x %08x] ", n, dwords[0], dwords[1], dwords[2], dwords[3]);
+}
+
+int
+main(int argc, char *argv[])
+{
+ size_t sz;
+ void *raw = os_read_file(argv[1], &sz);
+
+ isa_disasm(raw, sz, stdout,
+ &(struct isa_decode_options){
+ .show_errors = true,
+ .branch_labels = true,
+ .pre_instr_cb = pre_instr_cb,
+ });
+
+ return 0;
+}
diff --git a/src/etnaviv/isa/etnaviv.xml b/src/etnaviv/isa/etnaviv.xml
new file mode 100644
index 00000000000..b09c0a4609f
--- /dev/null
+++ b/src/etnaviv/isa/etnaviv.xml
@@ -0,0 +1,1246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright © 2023 Igalia S.L.
+SPDX-License-Identifier: MIT
+ -->
+
+<isa>
+
+<template name="INSTR_ALU">
+ {NAME}{SAT}{COND}{TYPE}{PMODE}{THREAD}{RMODE}
+</template>
+
+<template name="INSTR_TEX">
+ {NAME}{TEX_SWIZ}
+</template>
+
+<template name="INSTR_CF">
+ {NAME}{COND}{TYPE}
+</template>
+
+<template name="INSTR_LOAD_STORE">
+ {NAME}{COND}{SKPHP}{DENORM}{LOCAL}{TYPE}{PMODE}
+</template>
+
+<template name="INSTR_LOAD_STORE_WITH_LEFT_SHIFT">
+ {NAME}{COND}{SKPHP}{DENORM}{LOCAL}.ls{LEFT_SHIFT}{TYPE}{PMODE}
+</template>
+
+<enum name="#cond">
+ <value val="0" name=".true" display=""/>
+ <value val="1" display=".gt"/>
+ <value val="2" display=".lt"/>
+ <value val="3" display=".ge"/>
+ <value val="4" display=".le"/>
+ <value val="5" display=".eq"/>
+ <value val="6" display=".ne"/>
+ <value val="7" display=".and"/>
+ <value val="8" display=".or"/>
+ <value val="9" display=".xor"/>
+ <value val="10" display=".not"/>
+ <value val="11" display=".nz"/>
+ <value val="12" display=".gez"/>
+ <value val="13" display=".gz"/>
+ <value val="14" display=".lez"/>
+ <value val="15" display=".lz"/>
+ <value val="22" display=".0x16"/>
+</enum>
+
+<enum name="#swiz">
+ <value val="0" display="x"/>
+ <value val="1" display="y"/>
+ <value val="2" display="z"/>
+ <value val="3" display="w"/>
+</enum>
+
+<enum name="#type">
+ <value val="0" name=".f32" display=""/>
+ <value val="1" display=".s32"/>
+ <value val="2" display=".s8"/>
+ <value val="3" display=".u16"/>
+ <value val="4" display=".f16"/>
+ <value val="5" display=".s16"/>
+ <value val="6" display=".u32"/>
+ <value val="7" display=".u8"/>
+</enum>
+
+<enum name="#reg_group">
+ <value val="0" display="t"/>
+ <value val="2" display="u"/>
+ <value val="3" display="u2"/>
+ <value val="4" display="th"/>
+ <value val="7" name="immed" display=""/>
+</enum>
+
+<enum name="#reg_addressing_mode">
+ <value val="0" display=""/>
+ <value val="1" display="[a.x]"/>
+ <value val="2" display="[a.y]"/>
+ <value val="3" display="[a.z]"/>
+ <value val="4" display="[a.w]"/>
+</enum>
+
+<enum name="#rounding">
+ <value val="0" display=""/>
+ <value val="1" display=".rtz"/>
+ <value val="2" display=".rtne"/>
+ <value val="3" display=".unkown"/>
+ <value val="4" display=".unkown2"/>
+</enum>
+
+<enum name="#wrmask">
+ <value val="0" display=".____"/>
+ <value val="1" display=".x___"/>
+ <value val="2" display="._y__"/>
+ <value val="3" display=".xy__"/>
+ <value val="4" display=".__z_"/>
+ <value val="5" display=".zx"/>
+ <value val="6" display=".zy"/>
+ <value val="7" display=".xyz_"/>
+ <value val="8" display=".___w"/>
+ <value val="9" display=".x__w"/>
+ <value val="10" display="._y_w"/>
+ <value val="11" display=".xy_w"/>
+ <value val="12" display=".__zw"/>
+ <value val="13" display=".x_zw"/>
+ <value val="14" display="._yzw"/>
+ <value val="15" display=""/> <!-- xyzw -->
+</enum>
+
+<bitset name="#instruction-dst" size="14">
+ <override>
+ <expr>
+ {DST_USE} == 0
+ </expr>
+ <display>
+ void
+ </display>
+ </override>
+
+ <display>
+ t{REG}{AMODE}{COMPS}
+ </display>
+
+ <field name="AMODE" low="0" high="2" type="#reg_addressing_mode"/>
+ <field name="REG" low="3" high="9" type="uint"/>
+ <field name="COMPS" low="10" high="13" type="#wrmask"/>
+</bitset>
+
+<bitset name="#instruction" size="128">
+ <field name="COND" low="6" high="10" type="#cond"/>
+ <field name="SAT" pos="11" type="bool" display=".sat"/>
+
+ <field name="TYPE_BIT2" pos="53" type="uint"/>
+ <pattern low="65" high="66">00</pattern>
+ <field name="TYPE_BIT01" low="94" high="95" type="int"/>
+
+ <derived name="TYPE" type="#type">
+ <expr>{TYPE_BIT2} &lt;&lt; 2 | {TYPE_BIT01}</expr>
+ </derived>
+</bitset>
+
+<bitset name="#src-swizzle" size="8">
+ <display>
+ .{SWIZ_X}{SWIZ_Y}{SWIZ_Z}{SWIZ_W}
+ </display>
+
+ <field name="SWIZ_X" low="0" high="1" type="#swiz"/>
+ <field name="SWIZ_Y" low="2" high="3" type="#swiz"/>
+ <field name="SWIZ_Z" low="4" high="5" type="#swiz"/>
+ <field name="SWIZ_W" low="6" high="7" type="#swiz"/>
+</bitset>
+
+<enum name="#thread">
+ <value val="0" display=""/>
+ <value val="1" display=".t0"/>
+ <value val="2" display=".t1"/>
+</enum>
+
+<bitset name="#instruction-alu-base" extends="#instruction">
+ <field name="DST_USE" pos="12" type="bool"/>
+ <field name="DST" low="13" high="26" type="#instruction-dst">
+ <param name="DST_USE"/>
+ <param name="COMPS"/>
+ </field>
+ <pattern low="27" high="31">00000</pattern> <!-- TEX_ID -->
+ <field name="RMODE" low="32" high="33" type="#rounding"/>
+ <field name="PMODE" pos="34" type="bool_inv" display=".pack"/>
+
+ <field name="LOW_HALF" pos="109" type="bool"/>
+ <field name="HIGH_HALF" pos="120" type="bool"/>
+
+ <derived name="THREAD" type="#thread">
+ <expr>{HIGH_HALF} &lt;&lt; 1 | {LOW_HALF}</expr>
+ </derived>
+
+ <field name="DST_FULL" pos="127" type="bool" display=".hp"/>
+</bitset>
+
+<bitset name="#instruction-alu" extends="#instruction-alu-base">
+ <pattern low="35" high="42">00000000</pattern><!-- TEX_SWIZ -->
+</bitset>
+
+<bitset name="#instruction-src" size="10">
+ <display>
+ {SRC_NEG}{SRC_ABS}{SRC_RGROUP}{SRC_REG}{SRC_AMODE}{SRC_SWIZ}{SRC_ABS}
+ </display>
+
+ <field name="SRC_SWIZ" low="0" high="7" type="#src-swizzle"/>
+ <field name="SRC_NEG" pos="8" type="bool" display="-"/>
+ <field name="SRC_ABS" pos="9" type="bool" display="|"/>
+
+ <derived name="IMMED_TYPE" type="uint">
+ <expr>({SRC_AMODE} &gt;&gt; 1)</expr> <!-- lowest bit is the sign bit -->
+ </derived>
+
+ <override>
+ <expr>
+ (({SRC_RGROUP} == 7) &amp; ({IMMED_TYPE} == 0))
+ </expr>
+
+ <display>
+ {IMMED}
+ </display>
+
+ <derived name="IMMED" type="float" width="32">
+ <expr>
+ (((({SRC_AMODE} &amp; 0x1) &lt;&lt; 19) |
+ ({SRC_ABS} &lt;&lt; 18) |
+ ({SRC_NEG} &lt;&lt; 17) |
+ ({SRC_SWIZ} &lt;&lt; 9) |
+ {SRC_REG}) &lt;&lt; 12)
+ </expr>
+ </derived>
+ </override>
+
+ <override>
+ <expr>
+ (({SRC_RGROUP} == 7) &amp; ({IMMED_TYPE} == 1))
+ </expr>
+
+ <display>
+ {IMMED}
+ </display>
+
+ <derived name="IMMED" type="int" width="20">
+ <expr>
+ ((({SRC_AMODE} &amp; 0x1) &lt;&lt; 19) |
+ ({SRC_ABS} &lt;&lt; 18) |
+ ({SRC_NEG} &lt;&lt; 17) |
+ ({SRC_SWIZ} &lt;&lt; 9) |
+ {SRC_REG})
+ </expr>
+ </derived>
+ </override>
+
+ <override>
+ <expr>
+ (({SRC_RGROUP} == 7) &amp; ({IMMED_TYPE} == 2))
+ </expr>
+
+ <display>
+ {IMMED}
+ </display>
+
+ <derived name="IMMED" type="uint" width="20">
+ <expr>
+ ((({SRC_AMODE} &amp; 0x1) &lt;&lt; 19) |
+ ({SRC_ABS} &lt;&lt; 18) |
+ ({SRC_NEG} &lt;&lt; 17) |
+ ({SRC_SWIZ} &lt;&lt; 9) |
+ {SRC_REG})
+ </expr>
+ </derived>
+ </override>
+
+ <override>
+ <expr>
+ (({SRC_RGROUP} == 7) &amp; ({IMMED_TYPE} == 3))
+ </expr>
+
+ <display>
+ {IMMED}
+ </display>
+
+ <derived name="IMMED" type="float" width="16">
+ <expr>
+ ((({SRC_AMODE} &amp; 0x1) &lt;&lt; 19) |
+ ({SRC_ABS} &lt;&lt; 18) |
+ ({SRC_NEG} &lt;&lt; 17) |
+ ({SRC_SWIZ} &lt;&lt; 9) |
+ {SRC_REG})
+ </expr>
+ </derived>
+ </override>
+</bitset>
+
+<bitset name="#instruction-alu-atomic" extends="#instruction-alu-base">
+ <display>
+ {INSTR_ALU} {DST:align=18}, {SRC0}, {SRC1}, {SRC2}
+ </display>
+
+ <pattern low="35" high="42">xxxxxxxx</pattern><!-- TEX_SWIZ -->
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">1</pattern> <!-- SRC1_USE -->
+ <field name="SRC1_REG" low="71" high="79" type="uint"/>
+ <field name="SRC1" low="81" high="90" type="#instruction-src">
+ <param name="SRC1_REG" as="SRC_REG"/>
+ <param name="SRC1_AMODE" as="SRC_AMODE"/>
+ <param name="SRC1_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC1_AMODE" low="91" high="93" type="#reg_addressing_mode"/>
+ <field name="SRC1_RGROUP" low="96" high="98" type="#reg_group"/>
+
+ <!-- SRC2 -->
+ <pattern pos="99">1</pattern> <!-- SRC2_USE -->
+ <field name="SRC2_REG" low="100" high="108" type="uint"/>
+ <field name="SRC2" low="110" high="119" type="#instruction-src">
+ <param name="SRC2_REG" as="SRC_REG"/>
+ <param name="SRC2_AMODE" as="SRC_AMODE"/>
+ <param name="SRC2_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC2_AMODE" low="121" high="123" type="#reg_addressing_mode"/>
+ <field name="SRC2_RGROUP" low="124" high="126" type="#reg_group"/>
+</bitset>
+
+<bitset name="#instruction-alu-atomic" extends="#instruction-alu-base">
+ <display>
+ {INSTR_ALU} {DST:align=18}, {SRC0}, {SRC1}, {SRC2}
+ </display>
+
+ <pattern low="35" high="42">xxxxxxxx</pattern>
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">1</pattern> <!-- SRC1_USE -->
+ <field name="SRC1_REG" low="71" high="79" type="uint"/>
+ <field name="SRC1" low="81" high="90" type="#instruction-src">
+ <param name="SRC1_REG" as="SRC_REG"/>
+ <param name="SRC1_AMODE" as="SRC_AMODE"/>
+ <param name="SRC1_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC1_AMODE" low="91" high="93" type="#reg_addressing_mode"/>
+ <field name="SRC1_RGROUP" low="96" high="98" type="#reg_group"/>
+
+ <!-- SRC2 -->
+ <pattern pos="99">1</pattern> <!-- SRC2_USE -->
+ <field name="SRC2_REG" low="100" high="108" type="uint"/>
+ <field name="SRC2" low="110" high="119" type="#instruction-src">
+ <param name="SRC2_REG" as="SRC_REG"/>
+ <param name="SRC2_AMODE" as="SRC_AMODE"/>
+ <param name="SRC2_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC2_AMODE" low="121" high="123" type="#reg_addressing_mode"/>
+ <field name="SRC2_RGROUP" low="124" high="126" type="#reg_group"/>
+</bitset>
+
+<bitset name="#instruction-alu-no-src" extends="#instruction-alu">
+ <display>
+ {NAME} {DST:align=18}{DST_FULL}, void, void, void
+ </display>
+
+ <!-- SRC0 -->
+ <pattern pos="43">0</pattern> <!-- SRC0_USE -->
+ <pattern low="44" high="52">000000000</pattern> <!-- SRC0_REG -->
+ <pattern low="54" high="61">00000000</pattern> <!-- SRC0_SWIZ -->
+ <pattern pos="62">0</pattern> <!-- SRC0_NEG -->
+ <pattern pos="63">0</pattern> <!-- SRC0_ABS -->
+ <pattern pos="64">0</pattern> <!-- SRC0_AMODE -->
+ <pattern low="67" high="69">000</pattern> <!-- SRC0_RGROUP -->
+
+ <!-- SRC1 -->
+ <pattern pos="70">0</pattern> <!-- SRC1_USE -->
+ <pattern low="71" high="79">000000000</pattern> <!-- SRC1_REG -->
+ <pattern low="81" high="88">00000000</pattern> <!-- SRC1_SWIZ -->
+ <pattern pos="89">0</pattern> <!-- SRC1_NEG -->
+ <pattern pos="90">0</pattern> <!-- SRC1_ABS -->
+ <pattern low="91" high="93">000</pattern> <!-- SRC1_AMODE -->
+ <pattern low="96" high="98">000</pattern> <!-- SRC1_RGROUP -->
+
+ <!-- SRC2 -->
+ <pattern pos="99">0</pattern> <!-- SRC2_USE -->
+ <pattern low="100" high="108">000000000</pattern> <!-- SRC2_REG -->
+ <pattern low="110" high="117">00000000</pattern> <!-- SRC2_SWIZ -->
+ <pattern pos="118">0</pattern> <!-- SRC2_NEG -->
+ <pattern pos="119">0</pattern> <!-- SRC2_ABS -->
+ <pattern low="121" high="123">000</pattern> <!-- SRC2_AMODE -->
+ <pattern low="124" high="126">000</pattern> <!-- SRC2_RGROUP -->
+</bitset>
+
+<expr name="#instruction-alu-no-dst-has-src0-src1">
+ ({SRC0_USE} != 0) &amp;&amp; ({SRC1_USE} != 0)
+</expr>
+
+<bitset name="#instruction-alu-no-dst-maybe-src1-src2" extends="#instruction-alu">
+ <doc>Needed for texkill</doc>
+ <display>
+ {NAME}{COND}{TYPE}{PMODE}{THREAD}{RMODE} {DST:align=18}{DST_FULL}, void, void, void
+ </display>
+
+ <override expr="#instruction-alu-no-dst-has-src0-src1">
+ <display>
+ {NAME}{COND}{TYPE}{PMODE}{THREAD}{RMODE} {DST:align=18}, {SRC0}, {SRC1}, void
+ </display>
+ </override>
+
+ <!-- SRC0 -->
+ <field name="SRC0_USE" pos="43" type="bool"/>
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <field name="SRC1_USE" pos="70" type="bool"/>
+ <field name="SRC1_REG" low="71" high="79" type="uint"/>
+ <field name="SRC1" low="81" high="90" type="#instruction-src">
+ <param name="SRC1_REG" as="SRC_REG"/>
+ <param name="SRC1_AMODE" as="SRC_AMODE"/>
+ <param name="SRC1_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC1_AMODE" low="91" high="93" type="#reg_addressing_mode"/>
+ <field name="SRC1_RGROUP" low="96" high="98" type="#reg_group"/>
+
+ <!-- SRC2 -->
+ <pattern pos="99">0</pattern> <!-- SRC2_USE -->
+ <pattern low="100" high="108">000000000</pattern> <!-- SRC2_REG -->
+ <pattern low="110" high="117">00000000</pattern> <!-- SRC2_SWIZ -->
+ <pattern pos="118">0</pattern> <!-- SRC2_NEG -->
+ <pattern pos="119">0</pattern> <!-- SRC2_ABS -->
+ <pattern low="121" high="123">000</pattern> <!-- SRC2_AMODE -->
+ <pattern low="124" high="126">000</pattern> <!-- SRC2_RGROUP -->
+</bitset>
+
+<bitset name="#instruction-alu-src0" extends="#instruction-alu">
+ <display>
+ {INSTR_ALU} {DST:align=18}, {SRC0}, void, void
+ </display>
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">0</pattern> <!-- SRC1_USE -->
+ <pattern low="71" high="79">000000000</pattern> <!-- SRC1_REG -->
+ <pattern low="81" high="88">00000000</pattern> <!-- SRC1_SWIZ -->
+ <pattern pos="89">0</pattern> <!-- SRC1_NEG -->
+ <pattern pos="90">0</pattern> <!-- SRC1_ABS -->
+ <pattern low="91" high="93">000</pattern> <!-- SRC1_AMODE -->
+ <pattern low="96" high="98">000</pattern> <!-- SRC1_RGROUP -->
+
+ <!-- SRC2 -->
+ <pattern pos="99">0</pattern> <!-- SRC2_USE -->
+ <pattern low="100" high="108">000000000</pattern> <!-- SRC2_REG -->
+ <pattern low="110" high="117">00000000</pattern> <!-- SRC2_SWIZ -->
+ <pattern pos="118">0</pattern> <!-- SRC2_NEG -->
+ <pattern pos="119">0</pattern> <!-- SRC2_ABS -->
+ <pattern low="121" high="123">000</pattern> <!-- SRC2_AMODE -->
+ <pattern low="124" high="126">000</pattern> <!-- SRC2_RGROUP -->
+</bitset>
+
+<bitset name="#instruction-alu-src2" extends="#instruction-alu">
+ <display>
+ {INSTR_ALU} {DST:align=18}, void, void, {SRC2}
+ </display>
+
+ <!-- SRC0 -->
+ <pattern pos="43">0</pattern> <!-- SRC0_USE -->
+ <pattern low="44" high="52">000000000</pattern> <!-- SRC0_REG -->
+ <pattern low="54" high="61">00000000</pattern> <!-- SRC0_SWIZ -->
+ <pattern pos="62">0</pattern> <!-- SRC0_NEG -->
+ <pattern pos="63">0</pattern> <!-- SRC0_ABS -->
+ <pattern pos="64">0</pattern> <!-- SRC0_AMODE -->
+ <pattern low="67" high="69">000</pattern> <!-- SRC0_RGROUP -->
+
+ <!-- SRC1 -->
+ <pattern pos="70">0</pattern> <!-- SRC1_USE -->
+ <pattern low="71" high="79">000000000</pattern> <!-- SRC1_REG -->
+ <pattern low="81" high="88">00000000</pattern> <!-- SRC1_SWIZ -->
+ <pattern pos="89">0</pattern> <!-- SRC1_NEG -->
+ <pattern pos="90">0</pattern> <!-- SRC1_ABS -->
+ <pattern low="91" high="93">000</pattern> <!-- SRC1_AMODE -->
+ <pattern low="96" high="98">000</pattern> <!-- SRC1_RGROUP -->
+
+ <!-- SRC2 -->
+ <pattern pos="99">1</pattern> <!-- SRC2_USE -->
+ <field name="SRC2_REG" low="100" high="108" type="uint"/>
+ <field name="SRC2" low="110" high="119" type="#instruction-src">
+ <param name="SRC2_REG" as="SRC_REG"/>
+ <param name="SRC2_AMODE" as="SRC_AMODE"/>
+ <param name="SRC2_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC2_AMODE" low="121" high="123" type="#reg_addressing_mode"/>
+ <field name="SRC2_RGROUP" low="124" high="126" type="#reg_group"/>
+</bitset>
+
+<bitset name="#instruction-alu-src0-src1" extends="#instruction-alu">
+ <display>
+ {INSTR_ALU} {DST:align=18}, {SRC0}, {SRC1}, void
+ </display>
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">1</pattern> <!-- SRC1_USE -->
+ <field name="SRC1_REG" low="71" high="79" type="uint"/>
+ <field name="SRC1" low="81" high="90" type="#instruction-src">
+ <param name="SRC1_REG" as="SRC_REG"/>
+ <param name="SRC1_AMODE" as="SRC_AMODE"/>
+ <param name="SRC1_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC1_AMODE" low="91" high="93" type="#reg_addressing_mode"/>
+ <field name="SRC1_RGROUP" low="96" high="98" type="#reg_group"/>
+
+ <!-- SRC2 -->
+ <pattern pos="99">0</pattern> <!-- SRC2_USE -->
+ <pattern low="100" high="108">000000000</pattern> <!-- SRC2_REG -->
+ <pattern low="110" high="117">00000000</pattern> <!-- SRC2_SWIZ -->
+ <pattern pos="118">0</pattern> <!-- SRC2_NEG -->
+ <pattern pos="119">0</pattern> <!-- SRC2_ABS -->
+ <pattern low="121" high="123">000</pattern> <!-- SRC2_AMODE -->
+ <pattern low="124" high="126">000</pattern> <!-- SRC2_RGROUP -->
+</bitset>
+
+<bitset name="#instruction-alu-src0-src2" extends="#instruction-alu">
+ <display>
+ {INSTR_ALU} {DST:align=18}, {SRC0}, void, {SRC2}
+ </display>
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">0</pattern> <!-- SRC1_USE -->
+ <pattern low="71" high="79">000000000</pattern> <!-- SRC1_REG -->
+ <pattern low="81" high="88">00000000</pattern> <!-- SRC1_SWIZ -->
+ <pattern pos="89">0</pattern> <!-- SRC1_NEG -->
+ <pattern pos="90">0</pattern> <!-- SRC1_ABS -->
+ <pattern low="91" high="93">000</pattern> <!-- SRC1_AMODE -->
+ <pattern low="96" high="98">000</pattern> <!-- SRC1_RGROUP -->
+
+ <!-- SRC2 -->
+ <pattern pos="99">1</pattern> <!-- SRC2_USE -->
+ <field name="SRC2_REG" low="100" high="108" type="uint"/>
+ <field name="SRC2" low="110" high="119" type="#instruction-src">
+ <param name="SRC2_REG" as="SRC_REG"/>
+ <param name="SRC2_AMODE" as="SRC_AMODE"/>
+ <param name="SRC2_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC2_AMODE" low="121" high="123" type="#reg_addressing_mode"/>
+ <field name="SRC2_RGROUP" low="124" high="126" type="#reg_group"/>
+</bitset>
+
+<bitset name="#instruction-alu-src0-src1-src2" extends="#instruction-alu">
+ <display>
+ {INSTR_ALU} {DST:align=18}, {SRC0}, {SRC1}, {SRC2}
+ </display>
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">1</pattern> <!-- SRC1_USE -->
+ <field name="SRC1_REG" low="71" high="79" type="uint"/>
+ <field name="SRC1" low="81" high="90" type="#instruction-src">
+ <param name="SRC1_REG" as="SRC_REG"/>
+ <param name="SRC1_AMODE" as="SRC_AMODE"/>
+ <param name="SRC1_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC1_AMODE" low="91" high="93" type="#reg_addressing_mode"/>
+ <field name="SRC1_RGROUP" low="96" high="98" type="#reg_group"/>
+
+ <!-- SRC2 -->
+ <pattern pos="99">1</pattern> <!-- SRC2_USE -->
+ <field name="SRC2_REG" low="100" high="108" type="uint"/>
+ <field name="SRC2" low="110" high="119" type="#instruction-src">
+ <param name="SRC2_REG" as="SRC_REG"/>
+ <param name="SRC2_AMODE" as="SRC_AMODE"/>
+ <param name="SRC2_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC2_AMODE" low="121" high="123" type="#reg_addressing_mode"/>
+ <field name="SRC2_RGROUP" low="124" high="126" type="#reg_group"/>
+</bitset>
+
+<bitset name="#instruction-tex" extends="#instruction">
+ <field name="DST_USE" pos="12" type="bool"/>
+ <field name="DST" low="13" high="26" type="#instruction-dst">
+ <param name="DST_USE"/>
+ <param name="COMPS"/>
+ </field>
+ <field name="TEX_ID" low="27" high="31" type="uint"/>
+ <field name="RMODE" low="32" high="34" type="#reg_addressing_mode"/>
+ <field name="TEX_SWIZ" low="35" high="42" type="#src-swizzle"/>
+
+ <pattern pos="109">0</pattern>
+ <pattern pos="120">0</pattern>
+ <pattern pos="127">0</pattern>
+</bitset>
+
+<bitset name="#instruction-tex-src0" extends="#instruction-tex">
+ <display>
+ {INSTR_TEX} {DST:align=18}, tex{TEX_ID}, {SRC0}, void, void
+ </display>
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">0</pattern> <!-- SRC1_USE -->
+ <pattern low="71" high="79">000000000</pattern> <!-- SRC1_REG -->
+ <pattern low="81" high="88">00000000</pattern> <!-- SRC1_SWIZ -->
+ <pattern pos="89">0</pattern> <!-- SRC1_NEG -->
+ <pattern pos="90">0</pattern> <!-- SRC1_ABS -->
+ <pattern low="91" high="93">000</pattern> <!-- SRC1_AMODE -->
+ <pattern low="96" high="98">000</pattern> <!-- SRC1_RGROUP -->
+
+ <!-- SRC2 -->
+ <pattern pos="99">0</pattern> <!-- SRC2_USE -->
+ <pattern low="100" high="108">000000000</pattern> <!-- SRC2_REG -->
+ <pattern low="110" high="117">00000000</pattern> <!-- SRC2_SWIZ -->
+ <pattern pos="118">0</pattern> <!-- SRC2_NEG -->
+ <pattern pos="119">0</pattern> <!-- SRC2_ABS -->
+ <pattern low="121" high="123">000</pattern> <!-- SRC2_AMODE -->
+ <pattern low="124" high="126">000</pattern> <!-- SRC2_RGROUP -->
+</bitset>
+
+<bitset name="#instruction-tex-src0-src1-src2" extends="#instruction-tex">
+ <display>
+ {INSTR_TEX} {DST:align=18}, tex{TEX_ID}, {SRC0}, {SRC1}, {SRC2}
+ </display>
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">1</pattern> <!-- SRC1_USE -->
+ <field name="SRC1_REG" low="71" high="79" type="uint"/>
+ <field name="SRC1" low="81" high="90" type="#instruction-src">
+ <param name="SRC2_REG" as="SRC_REG"/>
+ <param name="SRC2_AMODE" as="SRC_AMODE"/>
+ <param name="SRC2_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC1_AMODE" low="91" high="93" type="#reg_addressing_mode"/>
+ <field name="SRC1_RGROUP" low="96" high="98" type="#reg_group"/>
+
+ <!-- SRC2 -->
+ <pattern pos="99">1</pattern> <!-- SRC2_USE -->
+ <field name="SRC2_REG" low="100" high="108" type="uint"/>
+ <field name="SRC2" low="110" high="119" type="#instruction-src">
+ <param name="SRC2_REG" as="SRC_REG"/>
+ <param name="SRC2_AMODE" as="SRC_AMODE"/>
+ <param name="SRC2_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC2_AMODE" low="121" high="123" type="#reg_addressing_mode"/>
+ <field name="SRC2_RGROUP" low="124" high="126" type="#reg_group"/>
+</bitset>
+
+<bitset name="#instruction-cf" extends="#instruction">
+ <pattern low="12" high="31">00000000000000000000</pattern>
+
+ <pattern low="32" high="33">00</pattern> <!-- RMODE -->
+ <pattern pos="34">x</pattern><!-- PMODE -->
+ <pattern low="35" high="42">00000000</pattern><!-- TEX_SWIZ -->
+
+ <pattern low="99" high="102">0000</pattern>
+ <field name="TARGET" low="103" high="117" type="absbranch"/>
+ <pattern low="118" high="127">0000000000</pattern>
+</bitset>
+
+<bitset name="#instruction-cf-no-src" extends="#instruction-cf">
+ <display>
+ {INSTR_CF} {:align=18}void, void, void, {TARGET}
+ </display>
+
+ <pattern low="43" high="52">0000000000</pattern>
+ <pattern low="54" high="63">0000000000</pattern>
+
+ <pattern pos="64">0</pattern>
+ <pattern low="67" high="79">0000000000000</pattern>
+ <pattern low="81" high="93">0000000000000</pattern>
+ <pattern low="96" high="98">000</pattern>
+</bitset>
+
+<bitset name="#instruction-cf-src1-src2" extends="#instruction-cf">
+ <display>
+ {INSTR_CF} {:align=18}void, {SRC0}, {SRC1}, {TARGET}
+ </display>
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">1</pattern> <!-- SRC1_USE -->
+ <field name="SRC1_REG" low="71" high="79" type="uint"/>
+ <field name="SRC1" low="81" high="90" type="#instruction-src">
+ <param name="SRC1_REG" as="SRC_REG"/>
+ <param name="SRC1_AMODE" as="SRC_AMODE"/>
+ <param name="SRC1_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC1_AMODE" low="91" high="93" type="#reg_addressing_mode"/>
+ <field name="SRC1_RGROUP" low="96" high="98" type="#reg_group"/>
+</bitset>
+
+<expr name="#instruction-has-left-shift">
+ ({LEFT_SHIFT} != 0)
+</expr>
+
+<bitset name="#instruction-load" extends="#instruction">
+ <field name="DST_USE" pos="12" type="bool"/>
+ <field name="DST" low="13" high="26" type="#instruction-dst">
+ <param name="DST_USE"/>
+ <param name="COMPS"/>
+ </field>
+
+ <pattern low="27" high="31">00000</pattern> <!-- TEX_ID -->
+ <pattern low="32" high="33">00</pattern> <!-- RMODE -->
+ <field name="PMODE" pos="34" type="bool_inv" display=".pack"/>
+ <field name="LEFT_SHIFT" low="35" high="36" type="uint"/>
+ <pattern low="37" high="38">00</pattern>
+ <field name="SKPHP" pos="39" type="bool" display=".skpHp"/>
+ <field name="LOCAL" pos="40" type="bool" display=".local"/>
+ <pattern pos="41">0</pattern>
+ <field name="DENORM" pos="42" type="bool" display=".denorm"/>
+
+ <field name="LOW_HALF" pos="109" type="bool"/>
+ <field name="HIGH_HALF" pos="120" type="bool"/>
+
+ <derived name="THREAD" type="#thread">
+ <expr>{HIGH_HALF} &lt;&lt; 1 | {LOW_HALF}</expr>
+ </derived>
+
+ <field name="DST_FULL" pos="127" type="bool" display=".hp"/>
+
+ <display>
+ {INSTR_LOAD_STORE} {DST:align=18}, {SRC0}, {SRC1}, void
+ </display>
+
+ <override expr="#instruction-has-left-shift">
+ <display>
+ {INSTR_LOAD_STORE_WITH_LEFT_SHIFT} {DST:align=18}, {SRC0}, {SRC1}, void
+ </display>
+ </override>
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">1</pattern> <!-- SRC1_USE -->
+ <field name="SRC1_REG" low="71" high="79" type="uint"/>
+ <field name="SRC1" low="81" high="90" type="#instruction-src">
+ <param name="SRC1_REG" as="SRC_REG"/>
+ <param name="SRC1_AMODE" as="SRC_AMODE"/>
+ <param name="SRC1_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC1_AMODE" low="91" high="93" type="#reg_addressing_mode"/>
+ <field name="SRC1_RGROUP" low="96" high="98" type="#reg_group"/>
+
+ <!-- SRC2 -->
+ <pattern pos="99">0</pattern> <!-- SRC2_USE -->
+ <pattern low="100" high="108">000000000</pattern> <!-- SRC2_REG -->
+ <pattern low="110" high="117">00000000</pattern> <!-- SRC2_SWIZ -->
+ <pattern pos="118">0</pattern> <!-- SRC2_NEG -->
+ <pattern pos="119">0</pattern> <!-- SRC2_ABS -->
+ <pattern low="121" high="123">000</pattern> <!-- SRC2_AMODE -->
+ <pattern low="124" high="126">000</pattern> <!-- SRC2_RGROUP -->
+</bitset>
+
+<bitset name="#instruction-store" extends="#instruction">
+ <pattern low="12" high="16">xxxxx</pattern>
+ <pattern pos="17">x</pattern>
+ <pattern low="18" high="22">xxxxx</pattern>
+ <field name="COMPS" low="23" high="26" type="#wrmask"/>
+ <pattern low="27" high="31">xxxxx</pattern>
+ <pattern low="32" high="33">xx</pattern>
+ <field name="PMODE" pos="34" type="bool_inv" display=".pack"/>
+ <field name="LEFT_SHIFT" low="35" high="36" type="uint"/>
+ <pattern low="37" high="38">00</pattern>
+ <field name="SKPHP" pos="39" type="bool" display=".skpHp"/>
+ <field name="LOCAL" pos="40" type="bool" display=".local"/>
+ <pattern low="41" high="41">x</pattern>
+ <field name="DENORM" pos="42" type="bool" display=".denorm"/>
+
+ <field name="LOW_HALF" pos="109" type="bool"/>
+ <field name="HIGH_HALF" pos="120" type="bool"/>
+
+ <derived name="THREAD" type="#thread">
+ <expr>{HIGH_HALF} &lt;&lt; 1 | {LOW_HALF}</expr>
+ </derived>
+
+ <field name="DST_FULL" pos="127" type="bool" display=".hp"/>
+
+ <display>
+ {INSTR_LOAD_STORE} {:align=18}mem{COMPS}, {SRC0}, {SRC1}, {SRC2}
+ </display>
+
+ <override expr="#instruction-has-left-shift">
+ <display>
+ {INSTR_LOAD_STORE_WITH_LEFT_SHIFT} {:align=18}mem{COMPS}, {SRC0}, {SRC1}, {SRC2}
+ </display>
+ </override>
+
+ <!-- SRC0 -->
+ <pattern pos="43">1</pattern> <!-- SRC0_USE -->
+ <field name="SRC0_REG" low="44" high="52" type="uint"/>
+ <field name="SRC0" low="54" high="63" type="#instruction-src">
+ <param name="SRC0_REG" as="SRC_REG"/>
+ <param name="SRC0_AMODE" as="SRC_AMODE"/>
+ <param name="SRC0_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC0_AMODE" pos="64" type="#reg_addressing_mode"/>
+ <field name="SRC0_RGROUP" low="67" high="69" type="#reg_group"/>
+
+ <!-- SRC1 -->
+ <pattern pos="70">1</pattern> <!-- SRC1_USE -->
+ <field name="SRC1_REG" low="71" high="79" type="uint"/>
+ <field name="SRC1" low="81" high="90" type="#instruction-src">
+ <param name="SRC1_REG" as="SRC_REG"/>
+ <param name="SRC1_AMODE" as="SRC_AMODE"/>
+ <param name="SRC1_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC1_AMODE" low="91" high="93" type="#reg_addressing_mode"/>
+ <field name="SRC1_RGROUP" low="96" high="98" type="#reg_group"/>
+
+ <!-- SRC2 -->
+ <pattern pos="99">1</pattern> <!-- SRC2_USE -->
+ <field name="SRC2_REG" low="100" high="108" type="uint"/>
+ <field name="SRC2" low="110" high="119" type="#instruction-src">
+ <param name="SRC2_REG" as="SRC_REG"/>
+ <param name="SRC2_AMODE" as="SRC_AMODE"/>
+ <param name="SRC2_RGROUP" as="SRC_RGROUP"/>
+ </field>
+ <field name="SRC2_AMODE" low="121" high="123" type="#reg_addressing_mode"/>
+ <field name="SRC2_RGROUP" low="124" high="126" type="#reg_group"/>
+</bitset>
+
+<!-- opcocdes sorted by opc number -->
+
+<bitset name="nop" extends="#instruction-alu-no-src">
+ <pattern low="0" high="5">000000</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="add" extends="#instruction-alu-src0-src2">
+ <pattern low="0" high="5">000001</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="mad" extends="#instruction-alu-src0-src1-src2">
+ <pattern low="0" high="5">000010</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="mul" extends="#instruction-alu-src0-src1">
+ <pattern low="0" high="5">000011</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- dst -->
+
+<bitset name="dp2" extends="#instruction-alu-src0-src1">
+ <pattern low="0" high="5">000100</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="dp3" extends="#instruction-alu-src0-src1">
+ <pattern low="0" high="5">000101</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="dp4" extends="#instruction-alu-src0-src1">
+ <pattern low="0" high="5">000110</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- dsx -->
+<!-- dsy -->
+
+<bitset name="mov" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">001001</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- movar -->
+<!-- movaf -->
+
+<bitset name="rcp" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">001100</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="rsq" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">001101</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- litp -->
+
+<bitset name="select" extends="#instruction-alu-src0-src1-src2">
+ <pattern low="0" high="5">001111</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="set" extends="#instruction-alu-src0-src1">
+ <pattern low="0" high="5">010000</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="exp" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">010001</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="log" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">010010</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- frc -->
+
+<bitset name="call" extends="#instruction-cf-no-src">
+ <pattern low="0" high="5">010100</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="ret" extends="#instruction-alu-no-src">
+ <pattern low="0" high="5">010101</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="branch" extends="#instruction-cf-no-src">
+ <pattern low="0" high="5">010110</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="branch_if" extends="#instruction-cf-src1-src2" displayname="branch">
+ <pattern low="0" high="5">010110</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="texkill" extends="#instruction-alu-no-dst-maybe-src1-src2">
+ <pattern low="0" high="5">010111</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="texld" extends="#instruction-tex-src0">
+ <pattern low="0" high="5">011000</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+
+<!-- 0x7800000f 0x9011007c 0x00200804 0x0100100c -->
+
+<!-- texldd -->
+<!-- texldl -->
+<!-- texldpcf -->
+<!-- rep -->
+<!-- endrep -->
+<!-- loop -->
+<!-- endloop -->
+
+<bitset name="sqrt" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">100001</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="sin" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">100010</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="cos" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">100011</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- branch2 -->
+
+<bitset name="floor" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">100101</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="ceil" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">100110</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="sign" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">100111</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- addlo -->
+<!-- mullo -->
+
+<bitset name="barrier" extends="#instruction-alu-no-src">
+ <pattern low="0" high="5">101010</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- swizzle -->
+
+<bitset name="i2i" extends="#instruction-alu-src0-src1">
+ <pattern low="0" high="5">101100</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="i2f" extends="#instruction-alu-src0">
+ <pattern low="0" high="5">101101</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="f2i" extends="#instruction-alu-src0">
+ <pattern low="0" high="5">101110</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="f2irnd" extends="#instruction-alu-src0">
+ <pattern low="0" high="5">101111</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- f2i7 -->
+
+<bitset name="cmp" extends="#instruction-alu-src0-src1-src2">
+ <pattern low="0" high="5">110001</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="load" extends="#instruction-load">
+ <pattern low="0" high="5">110010</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="store" extends="#instruction-store">
+ <pattern low="0" high="5">110011</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="iaddsat" extends="#instruction-alu-src0-src2">
+ <pattern low="0" high="5">111011</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="imullo0" extends="#instruction-alu-src0-src1">
+ <pattern low="0" high="5">111100</pattern> <!-- OPC -->
+ <pattern pos="80">0</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- imullo1 -->
+<!-- imullosat0 -->
+<!-- imullosat1 -->
+
+<bitset name="imulhi0" extends="#instruction-alu-src0-src1">
+ <pattern low="0" high="5">000000</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<!-- imulhi1 -->
+
+<bitset name="idiv0" extends="#instruction-alu-src0-src1">
+ <pattern low="0" high="5">000100</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="imod" extends="#instruction-alu-src0-src1">
+ <pattern low="0" high="5">001000</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="imadlo0" extends="#instruction-alu-src0-src1-src2">
+ <pattern low="0" high="5">001100</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="imadlosat0" extends="#instruction-alu-src0-src1-src2">
+ <pattern low="0" high="5">001110</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="or" extends="#instruction-alu-src0-src2">
+ <pattern low="0" high="5">011100</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="and" extends="#instruction-alu-src0-src2">
+ <pattern low="0" high="5">011101</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="xor" extends="#instruction-alu-src0-src2">
+ <pattern low="0" high="5">011110</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="not" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">011111</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="popcount" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">100001</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="iabs" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">010111</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="leadzero" extends="#instruction-alu-src2">
+ <pattern low="0" high="5">011000</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="lshift" extends="#instruction-alu-src0-src2">
+ <pattern low="0" high="5">011001</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="rshift" extends="#instruction-alu-src0-src2">
+ <pattern low="0" high="5">011010</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="rotate" extends="#instruction-alu-src0-src2">
+ <pattern low="0" high="5">011011</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="atomic_add" extends="#instruction-alu-atomic">
+ <pattern low="0" high="5">100101</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="atomic_xchg" extends="#instruction-alu-atomic">
+ <pattern low="0" high="5">100110</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="atomic_cmp_xchg" extends="#instruction-alu-atomic">
+ <pattern low="0" high="5">100111</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="atomic_min" extends="#instruction-alu-atomic">
+ <pattern low="0" high="5">101000</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="atomic_max" extends="#instruction-alu-atomic">
+ <pattern low="0" high="5">101001</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="atomic_or" extends="#instruction-alu-atomic">
+ <pattern low="0" high="5">101010</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="atomic_and" extends="#instruction-alu-atomic">
+ <pattern low="0" high="5">101011</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="atomic_xor" extends="#instruction-alu-atomic">
+ <pattern low="0" high="5">101100</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+<bitset name="texldlpcf" extends="#instruction-tex-src0-src1-src2">
+ <pattern low="0" high="5">101111</pattern> <!-- OPC -->
+ <pattern pos="80">1</pattern> <!-- OPCODE_BIT6 -->
+</bitset>
+
+</isa>
diff --git a/src/etnaviv/isa/isa.h b/src/etnaviv/isa/isa.h
new file mode 100644
index 00000000000..6214bc154ec
--- /dev/null
+++ b/src/etnaviv/isa/isa.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright © 2023 Igalia S.L.
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef _ISA_H_
+#define _ISA_H_
+
+#include "compiler/isaspec/isaspec.h"
+
+#endif /* _ISA_H_ */
diff --git a/src/etnaviv/isa/meson.build b/src/etnaviv/isa/meson.build
new file mode 100644
index 00000000000..a191f76ac5d
--- /dev/null
+++ b/src/etnaviv/isa/meson.build
@@ -0,0 +1,48 @@
+#
+# Copyright © 2023 Igalia S.L.
+# SPDX-License-Identifier: MIT
+#
+
+isa_depend_files = [
+ 'etnaviv.xml',
+]
+
+etnaviv_isa = custom_target(
+ 'etnaviv-isa',
+ input: ['etnaviv.xml'],
+ output: ['etnaviv-isa.c', 'etnaviv-isa.h'],
+ command: [
+ prog_isaspec_decode, '--xml', '@INPUT@',
+ '--out-c', '@OUTPUT0@', '--out-h', '@OUTPUT1@',
+ ],
+ depend_files: isa_depend_files,
+)
+
+decode_files = [
+ etnaviv_isa,
+ 'isa.h',
+]
+
+libetnaviv_decode = static_library(
+ 'etnaviv_decode',
+ decode_files,
+ dependencies: [idep_mesautil, idep_isaspec_decode],
+ include_directories: [
+ inc_include,
+ inc_src,
+ ],
+ gnu_symbol_visibility: 'hidden',
+)
+
+disasm = executable(
+ 'etnaviv-disasm',
+ ['disasm.c'],
+ link_with: libetnaviv_decode,
+ build_by_default: with_tools.contains('etnaviv'),
+ include_directories: [
+ inc_src,
+ ],
+ install: false,
+)
+
+subdir('tests')
diff --git a/src/etnaviv/isa/tests/disasm.cpp b/src/etnaviv/isa/tests/disasm.cpp
new file mode 100644
index 00000000000..09f3b478d04
--- /dev/null
+++ b/src/etnaviv/isa/tests/disasm.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright © 2023 Igalia S.L.
+ * SPDX-License-Identifier: MIT
+ */
+
+/* Unit test for disassembly of instructions.
+ *
+ * The goal is to take instructions we've seen the blob produce, and test that
+ * we can disassemble them correctly.
+ */
+
+#include "compiler/isaspec/isaspec.h"
+#include <gtest/gtest.h>
+
+struct disasm_state {
+ uint32_t bin[4];
+ const char *disasm;
+
+ friend std::ostream &operator<<(std::ostream &os, const disasm_state &obj)
+ {
+ // clang-format off
+ return os
+ << "binary: "
+ << std::showbase << std::internal << std::setfill('0') << std::setw(8) << std::hex << obj.bin[0] << " "
+ << std::showbase << std::internal << std::setfill('0') << std::setw(8) << std::hex << obj.bin[1] << " "
+ << std::showbase << std::internal << std::setfill('0') << std::setw(8) << std::hex << obj.bin[2] << " "
+ << std::showbase << std::internal << std::setfill('0') << std::setw(8) << std::hex << obj.bin[3] << " "
+ << "disasm: " << obj.disasm;
+ // clang-format on
+ }
+};
+
+struct DisasmTest : testing::Test, testing::WithParamInterface<disasm_state> {
+ char *disasm_output;
+
+ DisasmTest()
+ {
+ static const struct isa_decode_options options = {.show_errors = true,
+ .branch_labels = false};
+
+ constexpr int output_size = 4096;
+ disasm_output = (char *)malloc(output_size);
+ FILE *fdisasm = fmemopen(disasm_output, output_size, "w+");
+
+ if (!fdisasm) {
+ return;
+ }
+
+ isa_disasm((void *)GetParam().bin, 16, fdisasm, &options);
+ fflush(fdisasm);
+ }
+};
+
+TEST_P(DisasmTest, basicOpCodes)
+{
+ auto as = GetParam();
+ EXPECT_STREQ(as.disasm, disasm_output);
+}
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(Default, DisasmTest,
+ testing::Values(
+ disasm_state{ {0x00000000, 0x00000000, 0x00000000, 0x00000000}, "nop void, void, void, void\n" },
+ disasm_state{ {0x07811018, 0x15001f20, 0x00000000, 0x00000000}, "texld.xyzw t1, tex0, t1.xyyy, void, void\n" },
+ disasm_state{ {0x07831018, 0x39003f20, 0x00000000, 0x00000000}, "texld.xyzw t3, tex0, t3.xyzw, void, void\n" },
+ disasm_state{ {0x07811009, 0x00000000, 0x00000000, 0x20390008}, "mov.pack t1, void, void, u0.xyzw\n" },
+ disasm_state{ {0x01821009, 0x00000000, 0x00000000, 0x00150028}, "mov.pack t2.xy__, void, void, t2.xyyy\n"},
+ disasm_state{ {0x01821009, 0x00000000, 0x00000000, 0x00550028}, "mov.pack t2.xy__, void, void, -t2.xyyy\n"},
+ disasm_state{ {0x01821009, 0x00000000, 0x00000000, 0x00950028}, "mov.pack t2.xy__, void, void, |t2.xyyy|\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(OperandTypes, DisasmTest,
+ testing::Values(
+ disasm_state{ {0x01821009, 0x00000000, 0x00000000, 0x00150028}, "mov.pack t2.xy__, void, void, t2.xyyy\n"},
+ disasm_state{ {0x01821009, 0x00000000, 0x40000000, 0x00150028}, "mov.s32.pack t2.xy__, void, void, t2.xyyy\n"},
+ disasm_state{ {0x01821009, 0x00000000, 0x80000000, 0x00150028}, "mov.s8.pack t2.xy__, void, void, t2.xyyy\n"},
+ disasm_state{ {0x01821009, 0x00000000, 0xc0000000, 0x00150028}, "mov.u16.pack t2.xy__, void, void, t2.xyyy\n"},
+ disasm_state{ {0x01821009, 0x00200000, 0x00000000, 0x00150028}, "mov.f16.pack t2.xy__, void, void, t2.xyyy\n"},
+ disasm_state{ {0x01821009, 0x00200000, 0x40000000, 0x00150028}, "mov.s16.pack t2.xy__, void, void, t2.xyyy\n"},
+ disasm_state{ {0x01821009, 0x00200000, 0x80000000, 0x00150028}, "mov.u32.pack t2.xy__, void, void, t2.xyyy\n"},
+ disasm_state{ {0x01821009, 0x00200000, 0xc0000000, 0x00150028}, "mov.u8.pack t2.xy__, void, void, t2.xyyy\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(Opcodes, DisasmTest,
+ testing::Values(
+ // GC3000
+ disasm_state{ {0x00000000, 0x00000000, 0x00000000, 0x00000000}, "nop void, void, void, void\n" },
+ disasm_state{ {0x00801001, 0x00001804, 0x00000000, 0x00000008}, "add t0.x___, t1.xxxx, void, t0.xxxx\n" },
+ disasm_state{ {0x07801002, 0x39002805, 0x01c800c0, 0x00390038}, "mad.rtz t0, t2.xyzw, t1.xyzw, t3.xyzw\n" },
+ disasm_state{ {0x00801003, 0x00001804, 0x00000040, 0x00000000}, "mul t0.x___, t1.xxxx, t0.xxxx, void\n" },
+ disasm_state{ {0x00801005, 0x09000802, 0x00000040, 0x00000002}, "dp3.pack.rtne t0.x___, t0.xyzx, u0.xxxx, void\n" },
+ disasm_state{ {0x00801006, 0x39001804, 0x01c800c0, 0x00000000}, "dp4 t0.x___, t1.xyzw, t1.xyzw, void\n" },
+ disasm_state{ {0x01821009, 0x00000000, 0x00000000, 0x00150028}, "mov.pack t2.xy__, void, void, t2.xyyy\n"},
+ disasm_state{ {0x0081100c, 0x00000000, 0x00000000, 0x00000018}, "rcp.pack t1.x___, void, void, t1.xxxx\n" },
+ disasm_state{ {0x0080100d, 0x00000004, 0x00000000, 0x00000008}, "rsq t0.x___, void, void, t0.xxxx\n" },
+ disasm_state{ {0x0783108f, 0x39002800, 0x05c800c0, 0x00390028}, "select.lt.pack t3, t2.xyzw, |t1.xyzw|, t2.xyzw\n"},
+ disasm_state{ {0x008010d0, 0x00000800, 0x00000040, 0x00000002}, "set.ge.pack t0.x___, t0.xxxx, u0.xxxx, void\n" },
+ disasm_state{ {0x01001011, 0x00000004, 0x00000000, 0x00154008}, "exp t0._y__, void, void, t0.yyyy\n" },
+ disasm_state{ {0x01801012, 0x00000005, 0x00000000, 0x00000008}, "log.rtz t0.xy__, void, void, t0.xxxx\n" },
+ disasm_state{ {0x00000014, 0x00000000, 0x00000000, 0x00000380}, "call void, void, void, 7\n" },
+ disasm_state{ {0x00000015, 0x00000000, 0x00000000, 0x00000000}, "ret void, void, void, void\n" },
+ disasm_state{ {0x00000016, 0x00000000, 0x00000000, 0x00001080}, "branch void, void, void, 33\n"},
+ disasm_state{ {0x00000017, 0x00000000, 0x00000000, 0x00000000}, "texkill.pack void, void, void, void\n" },
+ disasm_state{ {0x00000057, 0x00002800, 0x00000040, 0x00000002}, "texkill.gt.pack void, t2.xxxx, u0.xxxx, void\n" },
+ disasm_state{ {0x07811018, 0x15001f20, 0x00000000, 0x00000000}, "texld.xyzw t1, tex0, t1.xyyy, void, void\n" },
+ disasm_state{ {0x00801021, 0x00000004, 0x00000000, 0x00000008}, "sqrt t0.x___, void, void, t0.xxxx\n" },
+ disasm_state{ {0x03001022, 0x00000005, 0x00000000, 0x00154008}, "sin.rtz t0.zy, void, void, t0.yyyy\n" },
+ disasm_state{ {0x01801023, 0x00000005, 0x00000000, 0x00000008}, "cos.rtz t0.xy__, void, void, t0.xxxx\n" },
+ disasm_state{ {0x00801025, 0x00000004, 0x00000000, 0x00000008}, "floor t0.x___, void, void, t0.xxxx\n"},
+ disasm_state{ {0x00801026, 0x00000004, 0x00000000, 0x00000008}, "ceil t0.x___, void, void, t0.xxxx\n"},
+ disasm_state{ {0x00801027, 0x00000004, 0x00000000, 0x00000008}, "sign t0.x___, void, void, t0.xxxx\n" },
+ disasm_state{ {0x0000002a, 0x00000000, 0x00000000, 0x00000000}, "barrier void, void, void, void\n" },
+ disasm_state{ {0x0080102c, 0x00200804, 0x50001040, 0x00000007}, "i2i.s16 t0.x___, t0.xxxx, 32, void\n" },
+ disasm_state{ {0x0381102d, 0x00201804, 0x40000000, 0x00000000}, "i2f.s16 t1.xyz_, t1.xxxx, void, void\n"},
+ disasm_state{ {0x0101102e, 0x00201804, 0x80000020, 0x00002000}, "f2i.u32.t0 t1._y__, th1.xxxx, void, void\n"},
+ disasm_state{ {0x0081102f, 0x00000806, 0x40000000, 0x00000000}, "f2irnd.s32.rtne t1.x___, t0.xxxx, void, void\n"},
+ disasm_state{ {0x00811131, 0x80001800, 0x00aa0040, 0x202a800a}, "cmp.le.pack t1.x___, |t1.xxxx|, u0.yyyy, u0.zzzz\n"},
+ disasm_state{ {0x00801032, 0x00000c04, 0x10000050, 0x00000007}, "load.denorm t0.x___, u0.xxxx, 0, void\n"},
+ disasm_state{ {0x00800033, 0x00000c84, 0x10000050, 0x0000000f}, "store.skpHp.denorm mem.x___, u0.xxxx, 0, t0.xxxx\n"},
+ disasm_state{ {0x0080103b, 0x00001804, 0x40000000, 0x00400028}, "iaddsat.s32 t0.x___, t1.xxxx, void, -t2.xxxx\n"},
+ disasm_state{ {0x01001008, 0x15400804, 0xd00100c0, 0x00000007}, "imod.u16 t0._y__, t0.yyyy, 1, void\n"},
+ disasm_state{ {0x0080103c, 0x00001804, 0x40000140, 0x00000000}, "imullo0.s32 t0.x___, t1.xxxx, t2.xxxx, void\n"},
+ disasm_state{ {0x00801000, 0x00001804, 0x40010140, 0x00000000}, "imulhi0.s32 t0.x___, t1.xxxx, t2.xxxx, void\n"},
+ disasm_state{ {0x00801004, 0x00201804, 0x40010040, 0x00000000}, "idiv0.s16 t0.x___, t1.xxxx, t0.xxxx, void\n"},
+ disasm_state{ {0x0080100e, 0x00001804, 0x40010140, 0x00000038}, "imadlosat0.s32 t0.x___, t1.xxxx, t2.xxxx, t3.xxxx\n"},
+ disasm_state{ {0x0082101c, 0x00001804, 0x40010000, 0x00000008}, "or.s32 t2.x___, t1.xxxx, void, t0.xxxx\n"},
+ disasm_state{ {0x0082101d, 0x00001804, 0x40010000, 0x00000008}, "and.s32 t2.x___, t1.xxxx, void, t0.xxxx\n"},
+ disasm_state{ {0x0080101e, 0x00001804, 0x40010000, 0x00000008}, "xor.s32 t0.x___, t1.xxxx, void, t0.xxxx\n"},
+ disasm_state{ {0x0080101f, 0x00000004, 0x40010000, 0x00000018}, "not.s32 t0.x___, void, void, t1.xxxx\n"},
+ disasm_state{ {0x00801021, 0x00000004, 0x00010000, 0x00000008}, "popcount t0.x___, void, void, t0.xxxx\n"},
+ disasm_state{ {0x00801017, 0x00000004, 0x40010000, 0x00000018}, "iabs.s32 t0.x___, void, void, t1.xxxx\n"},
+ disasm_state{ {0x00801018, 0x00000004, 0x40010000, 0x00000008}, "leadzero.s32 t0.x___, void, void, t0.xxxx\n"},
+ disasm_state{ {0x00801019, 0x15400804, 0x40010000, 0x74000028}, "lshift.s32 t0.x___, t0.yyyy, void, 2\n"},
+ disasm_state{ {0x0080101a, 0x00001804, 0x40010000, 0x78000018}, "rshift.s32 t0.x___, t1.xxxx, void, 1\n"},
+ disasm_state{ {0x0080101b, 0x00001804, 0x40010000, 0x00000008}, "rotate.s32 t0.x___, t1.xxxx, void, t0.xxxx\n"},
+ disasm_state{ {0x01061025, 0x2aa00804, 0xa0010050, 0x7800001f}, "atomic_add.u32 t6._y__, u0.zzzz, 0, 1\n"},
+ disasm_state{ {0x00801025, 0x2a800884, 0x50010050, 0x0000000f}, "atomic_add.s32 t0.x___, u0.zzzz, 0, t0.xxxx\t; dontcare bits in atomic_add: 00000000000000000000008000000000\n"},
+ disasm_state{ {0x00821026, 0x2a800884, 0x50010050, 0x0000001f}, "atomic_xchg.s32 t2.x___, u0.zzzz, 0, t1.xxxx\t; dontcare bits in atomic_xchg: 00000000000000000000008000000000\n"},
+ disasm_state{ {0x00801027, 0x2a800884, 0x50010050, 0x0015000f}, "atomic_cmp_xchg.s32 t0.x___, u0.zzzz, 0, t0.xyyy\t; dontcare bits in atomic_cmp_xchg: 00000000000000000000008000000000\n"},
+ disasm_state{ {0x00821028, 0x2a800884, 0x50010050, 0x0000001f}, "atomic_min.s32 t2.x___, u0.zzzz, 0, t1.xxxx\t; dontcare bits in atomic_min: 00000000000000000000008000000000\n"},
+ disasm_state{ {0x00821029, 0x2a800884, 0x50010050, 0x0000000f}, "atomic_max.s32 t2.x___, u0.zzzz, 0, t0.xxxx\t; dontcare bits in atomic_max: 00000000000000000000008000000000\n"},
+ disasm_state{ {0x0080102a, 0x2a800884, 0x50010050, 0x0000000f}, "atomic_or.s32 t0.x___, u0.zzzz, 0, t0.xxxx\t; dontcare bits in atomic_or: 00000000000000000000008000000000\n"},
+ disasm_state{ {0x0082102b, 0x2a800884, 0x50010050, 0x0000001f}, "atomic_and.s32 t2.x___, u0.zzzz, 0, t1.xxxx\t; dontcare bits in atomic_and: 00000000000000000000008000000000\n"},
+ disasm_state{ {0x0080102c, 0x2a800884, 0x50010050, 0x0000001f}, "atomic_xor.s32 t0.x___, u0.zzzz, 0, t1.xxxx\t; dontcare bits in atomic_xor: 00000000000000000000008000000000\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(Branch, DisasmTest,
+ testing::Values(
+ // taken from deqp2 run on GC2000
+ disasm_state{ {0x00000016, 0x00000000, 0x00000000, 0x00001080}, "branch void, void, void, 33\n"},
+ disasm_state{ {0x00000056, 0x00000800, 0x000000d0, 0x00000280}, "branch.gt void, u0.xxxx, t1.xxxx, 5\n"},
+ disasm_state{ {0x00000056, 0x00000800, 0x000000d0, 0x00000280}, "branch.gt void, u0.xxxx, t1.xxxx, 5\n"},
+ disasm_state{ {0x00000096, 0x15402800, 0x00000040, 0x00000082}, "branch.lt void, t2.yyyy, u0.xxxx, 1\n"},
+ disasm_state{ {0x000000d6, 0x00001800, 0x01540250, 0x00000980}, "branch.ge void, u1.xxxx, t4.zzzz, 19\n"},
+ disasm_state{ {0x00000116, 0x3fc01800, 0x000000c0, 0x00000482}, "branch.le void, t1.wwww, u1.xxxx, 9\n"},
+ disasm_state{ {0x00000156, 0x39001800, 0x000002c0, 0x00001282}, "branch.eq void, t1.xyzw, u5.xxxx, 37\n"},
+ disasm_state{ {0x00000196, 0x15401800, 0x00aa0040, 0x00000382}, "branch.ne void, t1.yyyy, u0.yyyy, 7\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(Abs, DisasmTest,
+ testing::Values(
+ // taken from deqp2 run on GC2000
+ disasm_state{ {0x00811131, 0x80001800, 0x00aa0040, 0x202a800a}, "cmp.le.pack t1.x___, |t1.xxxx|, u0.yyyy, u0.zzzz\n"},
+ disasm_state{ {0x0783108f, 0x39002800, 0x05c800c0, 0x00390028}, "select.lt.pack t3, t2.xyzw, |t1.xyzw|, t2.xyzw\n"},
+ disasm_state{ {0x0383108f, 0xa9001800, 0x05480140, 0x00a90018}, "select.lt.pack t3.xyz_, |t1.xyzz|, |t2.xyzz|, |t1.xyzz|\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(Minus, DisasmTest,
+ testing::Values(
+ // taken from deqp2 run on GC2000
+ disasm_state{ {0x01021001, 0x3fc00800, 0x00000010, 0x00554018}, "add.pack t2._y__, u0.wwww, void, -t1.yyyy\n"},
+ disasm_state{ {0x00821001, 0x40001800, 0x00000000, 0x00554018}, "add.pack t2.x___, -t1.xxxx, void, -t1.yyyy\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(AddressRegister, DisasmTest,
+ testing::Values(
+ // taken from deqp2 run on GC2000
+ disasm_state{ {0x00823009, 0x00000000, 0x00000000, 0x00000018}, "mov.pack t2[a.x].x___, void, void, t1.xxxx\n"},
+ disasm_state{ {0x00825009, 0x00000000, 0x00000000, 0x00154028}, "mov.pack t2[a.y].x___, void, void, t2.yyyy\n"},
+ disasm_state{ {0x00827009, 0x00000000, 0x00000000, 0x00000018}, "mov.pack t2[a.z].x___, void, void, t1.xxxx\n"},
+ disasm_state{ {0x00829009, 0x00000000, 0x00000000, 0x00000018}, "mov.pack t2[a.w].x___, void, void, t1.xxxx\n"},
+ disasm_state{ {0x00801009, 0x00000000, 0x00000000, 0x02000028}, "mov.pack t0.x___, void, void, t2[a.x].xxxx\n"},
+ disasm_state{ {0x01031009, 0x00000000, 0x00000000, 0x043fc018}, "mov.pack t3._y__, void, void, t1[a.y].wwww\n"},
+ disasm_state{ {0x02031009, 0x00000000, 0x00000000, 0x063fc018}, "mov.pack t3.__z_, void, void, t1[a.z].wwww\n"},
+ disasm_state{ {0x01811001, 0x15001800, 0x00000000, 0x28150018}, "add.pack t1.xy__, t1.xyyy, void, u1[a.w].xyyy\n"},
+ disasm_state{ {0x01011001, 0x00001800, 0x00000001, 0x04000018}, "add.pack t1._y__, t1[a.x].xxxx, void, t1[a.y].xxxx\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(Threads, DisasmTest,
+ testing::Values(
+ // taken from deqp3 run on GC3000
+ disasm_state{ {0x01011001, 0x00001804, 0x00000020, 0xa0402008}, "add.t0 t1._y__, th1.xxxx, void, -u0.xxxx\n"},
+ disasm_state{ {0x01021001, 0x00002804, 0x00000020, 0xa1400008}, "add.t1 t2._y__, th2.xxxx, void, -u0.xxxx\n"},
+
+ // full dual-16 shader from a deqp3 run on GC3000
+ disasm_state{ {0x0101102e, 0x00201804, 0x80000020, 0x00002000}, "f2i.u32.t0 t1._y__, th1.xxxx, void, void\n"},
+ disasm_state{ {0x0101102e, 0x00202804, 0x80000020, 0x01000000}, "f2i.u32.t1 t1._y__, th2.xxxx, void, void\n"},
+ disasm_state{ {0x00811171, 0x15601804, 0x80000040, 0x76fffffa}, "cmp.eq.u32.t0 t1.x___, t1.yyyy, u0.xxxx, -1\n"},
+ disasm_state{ {0x00811171, 0x15601804, 0x80000040, 0x77ffdffa}, "cmp.eq.u32.t1 t1.x___, t1.yyyy, u0.xxxx, -1\n"},
+ disasm_state{ {0x0081158f, 0x00201804, 0x700000c0, 0x7c00000f}, "select.0x16.s16 t1.x___, t1.xxxx, 0.000000, 0.000000\n"},
+ disasm_state{ {0x0381102d, 0x00201804, 0x40000000, 0x00000000}, "i2f.s16 t1.xyz_, t1.xxxx, void, void\n"},
+ disasm_state{ {0x04011009, 0x00000004, 0x00000000, 0x20154008}, "mov t1.___w, void, void, u0.yyyy\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(ImmediateValues, DisasmTest,
+ testing::Values(
+ // taken from deqp3 run on GC3000
+ disasm_state{ {0x00801001, 0x7e000805, 0x00000038, 0x00800008}, "add.rtz t0.x___, 0.500000, void, |t0.xxxx|\n"}, /* type: 0 */
+ disasm_state{ {0x00811131, 0x95401804, 0x00aa0060, 0x76fffffa}, "cmp.le.t0 t1.x___, |th1.yyyy|, u0.yyyy, -1\n"}, /* type: 1 */
+ disasm_state{ {0x0080101a, 0x00001804, 0x40010000, 0x78000018}, "rshift.s32 t0.x___, t1.xxxx, void, 1\n"}, /* type: 2*/
+ disasm_state{ {0x020211b1, 0x00001804, 0x01fe0040, 0x7c1fdffa}, "cmp.ne t2.__z_, t1.xxxx, u0.wwww, -nan\n"} /* type: 3 */
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(LoadStore, DisasmTest,
+ testing::Values(
+ // full opencl shader on GC3000
+ disasm_state{ {0x00801032, 0x00000c04, 0x10000050, 0x00000007}, "load.denorm t0.x___, u0.xxxx, 0, void\n"},
+ disasm_state{ {0x00811032, 0x15400c04, 0x10000050, 0x00000007}, "load.denorm t1.x___, u0.yyyy, 0, void\n"},
+ disasm_state{ {0x00801001, 0x00001804, 0x00000000, 0x00000008}, "add t0.x___, t1.xxxx, void, t0.xxxx\n"},
+ disasm_state{ {0x00800033, 0x00000c84, 0x10000050, 0x0000000f}, "store.skpHp.denorm mem.x___, u0.xxxx, 0, t0.xxxx\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(Rounding, DisasmTest,
+ testing::Values(
+ // taken from opencl shader on GC3000
+ disasm_state{ {0x0081102f, 0x00000806, 0x40000000, 0x00000000}, "f2irnd.s32.rtne t1.x___, t0.xxxx, void, void\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(CLRoundShader, DisasmTest,
+ testing::Values(
+ // taken from opencl shader on GC3000
+ disasm_state{ {0x00801032, 0x15400c04, 0x10000050, 0x00000007}, "load.denorm t0.x___, u0.yyyy, 0, void\n"},
+ disasm_state{ {0x00811027, 0x00000004, 0x00000000, 0x00000008}, "sign t1.x___, void, void, t0.xxxx\n"},
+ disasm_state{ {0x00801001, 0x7e000805, 0x00000038, 0x00800008}, "add.rtz t0.x___, 0.500000, void, |t0.xxxx|\n"},
+ disasm_state{ {0x00801025, 0x00000004, 0x00000000, 0x00000008}, "floor t0.x___, void, void, t0.xxxx\n"},
+ disasm_state{ {0x00801003, 0x00001805, 0x00000040, 0x00000000}, "mul.rtz t0.x___, t1.xxxx, t0.xxxx, void\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(TFShader, DisasmTest,
+ testing::Values(
+ // taken from transform shader on GC2000
+ disasm_state{ {0x0081102e, 0x00000800, 0x40000020, 0x00000000}, "f2i.s32.pack t1.x___, th0.xxxx, void, void\n"},
+ disasm_state{ {0x07821009, 0x00000000, 0x00000000, 0x00390008}, "mov.pack t2, void, void, t0.xyzw\n"},
+ disasm_state{ {0x01831009, 0x00000000, 0x00000000, 0x00150008}, "mov.pack t3.xy__, void, void, t0.xyyy\n"},
+ disasm_state{ {0x03841009, 0x00000000, 0x00000000, 0x00290008}, "mov.pack t4.xyz_, void, void, t0.xyzz\n"},
+ disasm_state{ {0x0201102d, 0x00000800, 0x40000010, 0x00000000}, "i2f.s32.pack t1.__z_, u0.xxxx, void, void\n"},
+ disasm_state{ {0x00000156, 0x2a801800, 0x01540040, 0x00000402}, "branch.eq void, t1.zzzz, u0.zzzz, 8\n"},
+ disasm_state{ {0x0081100c, 0x3fc00800, 0x400100d0, 0x20154008}, "imadlo0.s32.pack t1.x___, u0.wwww, t1.xxxx, u0.yyyy\n"},
+ disasm_state{ {0x07820033, 0x00001800, 0x01540040, 0x0039002a}, "store.pack mem, t1.xxxx, u0.zzzz, t2.xyzw\t; dontcare bits in store: 00000000000000000000000000020000\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(texldlpcf, DisasmTest,
+ testing::Values(
+ // taken from dEQP-GLES3.functional.shaders.texture_functions.texturelod.sampler2dshadow_vertex (GC7000)
+ disasm_state{ {0x04011809, 0x00000004, 0x00000000, 0x002a8018}, "mov.sat t1.___w, void, void, t1.zzzz\n"},
+ disasm_state{ {0x0081102f, 0x29001800, 0x00010140, 0x003fc018}, "texldlpcf.xxxx t1.x___, tex0, t1.xyzz, t1.xxxx, t1.wwww\n"},
+ disasm_state{ {0x07011009, 0x00000004, 0x00000000, 0x20390018}, "mov t1._yzw, void, void, u1.xyzw\n"}
+ )
+);
+// clang-format on
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(LoadStoreVariants, DisasmTest,
+ testing::Values(
+ // seen on GC7000
+ disasm_state{ {0x01001032, 0x15400c14, 0x00000050, 0x00000000}, "load.denorm.ls2 t0._y__, u0.yyyy, t0.xxxx, void\n"},
+ disasm_state{ {0x01001032, 0x15400d14, 0x00000040, 0x00000000}, "load.denorm.local.ls2 t0._y__, t0.yyyy, t0.xxxx, void\n"},
+ disasm_state{ {0x00800033, 0x00000c14, 0x00000050, 0x00154008}, "store.denorm.ls2 mem.x___, u0.xxxx, t0.xxxx, t0.yyyy\n"},
+ disasm_state{ {0x00861033, 0x15400d04, 0x100efe40, 0x7085860f}, "store.denorm.local mem.x___, t0.yyyy, 4092, 99.000000\t; dontcare bits in store: 00000000000000000000000000061000\n"}
+ )
+);
+// clang-format on
diff --git a/src/etnaviv/isa/tests/meson.build b/src/etnaviv/isa/tests/meson.build
new file mode 100644
index 00000000000..afb13bf5cec
--- /dev/null
+++ b/src/etnaviv/isa/tests/meson.build
@@ -0,0 +1,14 @@
+#
+# Copyright © 2023 Igalia S.L.
+# SPDX-License-Identifier: MIT
+#
+
+test(
+ 'etnaviv_isa_disasm',
+ executable(
+ 'etnaviv_disasm', 'disasm.cpp',
+ link_with: [libetnaviv_decode],
+ include_directories: [inc_etnaviv, inc_src],
+ dependencies : [idep_gtest],
+ )
+)
diff --git a/src/etnaviv/meson.build b/src/etnaviv/meson.build
index f2292c6dd12..2150aae1b3b 100644
--- a/src/etnaviv/meson.build
+++ b/src/etnaviv/meson.build
@@ -21,6 +21,7 @@
inc_etnaviv = include_directories(['.'])
subdir('drm')
+subdir('isa')
if with_tools.contains('drm-shim')
subdir('drm-shim')