<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright © 2020 Google, Inc.

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 -->

<isa>

<!--
	Cat5 Instructions: texture instructions
 -->

<bitset name="#cat5-s2en-bindless-base" size="1">
	<doc>
		The BASE field is actually split across BASE_LO and BASE_HI,
		but '.baseN' should only appear in the bindless case.. the
		easiest way to accomplish that is by splitting it out into a
		bitset.  We just arbitrarily map this to BASE_LO
	</doc>
	<override>
		<expr>{BINDLESS}</expr>
		<display>
			.base{BASE}
		</display>
	</override>
	<display/>
	<field name="BASE_LO" pos="0" type="uint"/>
	<derived name="BASE" type="uint">
		<expr>({BASE_HI} * 2) | {BASE_LO}</expr>
	</derived>
	<encode type="struct ir3_instruction *">
		<map name="BASE_LO">src->cat5.tex_base &amp; 0x1</map>
	</encode>
</bitset>

<bitset name="#instruction-cat5" extends="#instruction">
	<doc>
		The "normal" case, ie. not s2en (indirect) and/or bindless
	</doc>
	<display>
		{SY}{JP}{NAME}{3D}{A}{O}{P}{SV}{1D} {TYPE}({WRMASK}){DST_HALF}{DST}{SRC1}{SRC2}{SAMP}{TEX}
	</display>
	<derived name="DST_HALF" expr="#type-half" type="bool" display="h"/>
	<field name="FULL" pos="0" type="bool"/>
	<derived name="HALF" expr="#multisrc-half" type="bool" display="h"/>
	<field name="SRC1" low="1" high="8" type="#cat5-src1">
		<param name="NUM_SRC"/>
		<param name="HALF"/>
	</field>
	<field name="SRC2" low="9" high="16" type="#cat5-src2">
		<param name="NUM_SRC"/>
		<param name="HALF"/>
		<param name="O"/>
		<param name="SRC2_IMM_OFFSET"/>
	</field>
	<!--
		TODO remainder of first 32b differ depending on s2en/bindless..
		possibly use overrides?  Need to sort-out how to display..

		Note b17 seems to show up in some blob traces (samgpN), need
		to figure out what this bit does
	 -->
	<pattern pos="17">x</pattern>

	<field name="SAMP" low="21" high="24" type="#cat5-samp">
		<param name="HAS_SAMP"/>
	</field>
	<field name="TEX" low="25" high="31" type="#cat5-tex">
		<param name="HAS_TEX"/>
	</field>

	<field name="DST" low="32" high="39" type="#reg-gpr"/>
	<field name="WRMASK" low="40" high="43" type="#wrmask"/>
	<field name="TYPE" low="44" high="46" type="#cat5-type">
		<param name="HAS_TYPE"/>
	</field>
	<assert pos="47">0</assert>    <!-- BASE_LO -->
	<field name="3D" pos="48" type="bool" display=".3d"/>
	<field name="A" pos="49" type="bool" display=".a"/>
	<field name="S2EN_BINDLESS" pos="51" type="bool"/>
	<field name="O" pos="52" type="bool" display=".o"/>
	<!-- OPC -->
	<field name="JP" pos="59" type="bool" display="(jp)"/>
	<field name="SY" pos="60" type="bool" display="(sy)"/>
	<pattern low="61" high="63">101</pattern>  <!-- cat5 -->
	<encode>
		<map name="FULL">extract_cat5_FULL(src)</map>
		<map name="TEX">src</map>
		<map name="SAMP">src</map>
		<map name="WRMASK">src->dsts[0]->wrmask</map>
		<map name="BASE">src</map>
		<map name="TYPE">src</map>
		<map name="BASE_HI">src->cat5.tex_base >> 1</map>
		<map name="3D">!!(src->flags &amp; IR3_INSTR_3D)</map>
		<map name="A">!!(src->flags &amp; IR3_INSTR_A)</map>
		<map name="S2EN_BINDLESS">!!(src->flags &amp; (IR3_INSTR_S2EN | IR3_INSTR_B))</map>
		<map name="O">!!(src->flags &amp; IR3_INSTR_O)</map>
		<map name="DESC_MODE">extract_cat5_DESC_MODE(src)</map>
		<!--
			TODO the src order is currently a bit messy due to ir3 using srcs[0]
			for s2en src in the s2en case
		 -->
		<map name="SRC1">extract_cat5_SRC(src, 0)</map>
		<map name="SRC2">extract_cat5_SRC(src, 1)</map>
		<map name="SRC3">(src->srcs_count > 0) ? src->srcs[0] : NULL</map>
	</encode>

	<derived name="SRC2_IMM_OFFSET" expr="#false" type="bool"/>
	<derived name="P" expr="#false" type="bool" display=""/>
	<derived name="1D" expr="#false" type="bool" display=""/>
</bitset>

<bitset name="#instruction-cat5-tex-base" extends="#instruction-cat5">
	<override>
		<expr>{S2EN_BINDLESS}</expr>
		<doc>
			The s2en (indirect) or bindless case
		</doc>
		<display>
			{SY}{JP}{NAME}{3D}{A}{O}{P}{SV}{S2EN}{UNIFORM}{NONUNIFORM}{BASE}{1D} {TYPE}({WRMASK}){DST_HALF}{DST}{SRC1}{SRC2}{SRC3}{A1}
		</display>
		<field name="BASE_HI" low="19" high="20" type="uint"/>
		<field name="SRC3" low="21" high="28" type="#cat5-src3">
			<param name="BINDLESS"/>
			<param name="DESC_MODE"/>
			<param name="HAS_SAMP"/>
			<param name="HAS_TEX"/>
		</field>
		<field name="DESC_MODE" low="29" high="31" type="#cat5-s2en-bindless-desc-mode"/>
		<field name="BASE" pos="47" type="#cat5-s2en-bindless-base">
			<param name="BINDLESS"/>
			<param name="BASE_HI"/>
		</field>
		<derived name="BINDLESS" expr="#cat5-s2enb-is-bindless" type="bool"/>
		<derived name="S2EN" expr="#cat5-s2enb-is-indirect" type="bool" display=".s2en"/>
		<derived name="UNIFORM" expr="#cat5-s2enb-is-uniform" type="bool" display=".uniform"/>
		<derived name="NONUNIFORM" expr="#cat5-s2enb-is-nonuniform" type="bool" display=".nonuniform"/>
		<derived name="A1" expr="#cat5-s2enb-uses_a1" type="bool" display=", a1.x"/>
	</override>

	<assert low="19" high="20">00</assert>   <!-- BASE_HI -->
</bitset>

<bitset name="#instruction-cat5-tex" extends="#instruction-cat5-tex-base">
	<pattern pos="18">0</pattern>
	<field name="SV" pos="50" type="bool" display=".s"/>
	<field name="P" pos="53" type="bool" display=".p"/>

	<encode>
		<map name="SV">!!(src->flags &amp; IR3_INSTR_S)</map>
		<map name="P">!!(src->flags &amp; IR3_INSTR_P)</map>
	</encode>
</bitset>

<bitset name="isam" extends="#instruction-cat5-tex-base">
	<pattern low="54" high="58">00000</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>

	<!-- Not sure what this field does exactly but isam.v does not work
	     without it set. The blob disassembles it as .1d when not set. -->
	<field name="1D" pos="18" type="bool_inv" display=".1d"/>
	<field name="SV" pos="50" type="bool" display=".v"/>
	<field name="SRC2_IMM_OFFSET" pos="53" type="bool"/>

	<encode>
		<map name="SV">!!(src->flags &amp; IR3_INSTR_V)</map>
		<map name="1D">!!(src->flags &amp; IR3_INSTR_INV_1D)</map>
		<map name="SRC2_IMM_OFFSET">!!(src->flags &amp; IR3_INSTR_IMM_OFFSET)</map>
	</encode>
</bitset>

<bitset name="isaml" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">00001</pattern>
	<derived name="NUM_SRC" expr="#two" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="isamm" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">00010</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="sam" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">00011</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="samb" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">00100</pattern>
	<derived name="NUM_SRC" expr="#two" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="saml" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">00101</pattern>
	<derived name="NUM_SRC" expr="#two" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="samgq" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">00110</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="getlod" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">00111</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="conv" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">01000</pattern>
	<derived name="NUM_SRC" expr="#two" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="convm" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">01001</pattern>
	<derived name="NUM_SRC" expr="#two" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="getsize" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">01010</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="getbuf" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">01011</pattern>
	<derived name="NUM_SRC" expr="#zero" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="getpos" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">01100</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="getinfo" extends="#instruction-cat5-tex">
	<doc>
		GETINFO returns 4 values, in .xyzw:

		x: A value associated with the channel type, i.e. OpenCL's
		   get_image_channel_data_type:

		   The below was RE'd on A420 and confirmed with the
		   blob's headers.

		   8_SNORM:	     0 (CLK_SNORM_INT8)
		   16_SNORM:	     1 (CLK_SNORM_INT16)
		   8_UNORM:	     2 (CLK_UNORM_INT8)
		   16_UNORM:	     3 (CLK_UNORM_INT16)
		   5_6_5_UNORM:	     4 (CLK_UNORM_SHORT_565)
		   5_5_5_1_UNORM:    5 (CLK_UNORM_SHORT_555)
		   10_10_10_2_UNORM: 6 (CLK_UNORM_INT_101010, CLK_UNORM_SHORT_101010)
		   8_SINT:	     7 (CLK_SIGNED_INT8)
		   16_SINT:	     8 (CLK_SIGNED_INT16)
		   32_SINT:	     9 (CLK_SIGNED_INT32)
		   8_UINT:	    10 (CLK_UNSIGNED_INT8)
		   16_UINT:	    11 (CLK_UNSIGNED_INT16)
		   32_UINT:	    12 (CLK_UNSIGNED_INT32)
		   16_FLOAT:	    13 (CLK_HALF_FLOAT)
		   32_FLOAT:	    14 (CLK_FLOAT)
		   9_9_9_E5_FLOAT:  15 (CLK_FLOAT_10F_11F_11F)
		   11_11_10_FLOAT:  15 (CLK_FLOAT_10F_11F_11F)
		   10_10_10_2_UINT: 16 (CLK_UNSIGNED_SHORT_101010)
		   4_4_4_4_UNORM:   17 (CLK_UNORM_INT4)
		   X8Z24_UNORM:	    18 (CLK_UNORM_INT32)

		y: A value associated with the number of components
		   and swizzle, i.e. OpenCL's get_image_channel_order:

		   The below was largely taken from the blob's headers.

		   A3xx/A4xx:

		   0:  CLK_A
		   1:  CLK_R
		   2:  CLK_Rx
		   3:  CLK_RG
		   4:  CLK_RGx
		   5:  CLK_RA
		   6:  CLK_RGB
		   7:  CLK_RGBx
		   8:  CLK_RGBA
		   9:  CLK_ARGB
		   10: CLK_BGRA
		   11: CLK_LUMINANCE
		   12: CLK_INTENSITY
		   13: CLK_ABGR
		   14: CLK_BGR
		   15: CLK_sRGB
		   16: CLK_sRGBA
		   17: CLK_DEPTH

		   A5xx/A6xx:

		   0:  CLK_A
		   1:  CLK_R
		   2:  CLK_RX
		   3:  CLK_RG
		   4:  CLK_RGX
		   5:  CLK_RA
		   6:  CLK_RGB
		   7:  CLK_RGBX
		   8:  CLK_RGBA
		   9:  CLK_ARGB
		   10: CLK_BGRA
		   11: CLK_INTENSITY
		   12: CLK_LUMINANCE
		   13: CLK_ABGR
		   14: CLK_DEPTH
		   15: CLK_sRGB
		   16: CLK_sRGBx
		   17: CLK_sRGBA
		   18: CLK_sBGRA
		   19: CLK_sARGB
		   20: CLK_sABGR
		   21: CLK_BGR

		z: Number of levels

		w: Number of samples
	</doc>
	<pattern low="54" high="58">01101</pattern>
	<derived name="NUM_SRC" expr="#zero" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="dsx" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">01110</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#false" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="dsy" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">01111</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#false" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="gather4r" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">10000</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="gather4g" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">10001</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="gather4b" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">10010</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="gather4a" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">10011</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="samgp0" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">10100</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="samgp1" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">10101</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="samgp2" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">10110</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="samgp3" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">10111</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#true" type="bool"/>
	<derived name="HAS_TEX" expr="#true" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="dsxpp.1" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">11000</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#false" type="bool"/>
	<derived name="HAS_TYPE" expr="#false" type="bool"/>
</bitset>

<bitset name="dsypp.1" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">11001</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#false" type="bool"/>
	<derived name="HAS_TYPE" expr="#false" type="bool"/>
</bitset>

<bitset name="rgetpos" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">11010</pattern>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#false" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="rgetinfo" extends="#instruction-cat5-tex">
	<pattern low="54" high="58">11011</pattern>
	<derived name="NUM_SRC" expr="#zero" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#false" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="tcinv" extends="#instruction">
	<doc>
		Texture Cache Invalidate ?
	</doc>
	<display>
		{SY}{JP}{NAME}
	</display>
	<pattern low="0"  high="31">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</pattern>
	<pattern low="32" high="53">xxxxxxxxxxxxxxxxxxxxxx</pattern>
	<pattern low="54" high="58">11100</pattern>
	<field name="JP" pos="59" type="bool" display="(jp)"/>
	<field name="SY" pos="60" type="bool" display="(sy)"/>
	<pattern low="61" high="63">101</pattern>  <!-- cat5 -->
</bitset>

<bitset name="#instruction-cat5-brcst" extends="#instruction-cat5">
	<pattern pos="18">0</pattern>
	<pattern pos="50">0</pattern>
</bitset>

<bitset name="brcst.active" extends="#instruction-cat5-brcst">
	<doc>
		The subgroup is divided into (subgroup_size / CLUSTER_SIZE)
		clusters. For each cluster brcst.active.w does:

		Given a cluster of fibers f_0, f_1, ..., f_{CLUSTER_SIZE-1} brcst
		broadcasts the SRC value from the fiber f_{CLUSTER_SIZE/2-1}
		to fibers f_{CLUSTER_SIZE/2}, ..., f_{CLUSTER_SIZE-1}. The DST reg
		in other fibers is unaffected. If fiber f_{CLUSTER_SIZE/2-1} is
		inactive the value to broadcast is taken from lower fibers
		f_{CLUSTER_SIZE/2-2}, f_{CLUSTER_SIZE/2-3}, ...
		If all fibers f_0, f_1, ..., f_{CLUSTER_SIZE/2-1} are inactive
		the DST reg remains unchanged for all fibers.

		It is necessary in order to implement arithmetic subgroup
		operations with prefix sum (https://en.wikipedia.org/wiki/Prefix_sum).

		For brcst.active.w8 without inactive fibers:
			Fiber      | 0  1  2  3  4  5  6  7  | 8  9  10  11  12  13  14  15
			SRC        | s0 s1 s2 s3 ...      s7 | s8  ...   s11 ...         s15
			DST_before | d0 d1       ...      d7 | d8  ...                   d15
			DST_after  | d0 d1 d2 d3 s3 s3 s3 s3 | d8  ...   d11 s11 s11 s11 s11

		If fibers 2 and 3 are inactive:
			Fiber      | 0  1  X  X  4  5  6  7  | ...
			SRC        | s0 s1 X  X  ...      s7 | ...
			DST_before | d0 d1       ...      d7 | ...
			DST_after  | d0 d1 X  X  s1 s1 s1 s1 | ...
	</doc>

	<gen min="600"/>

	<display>
		{SY}{JP}{NAME}.w{CLUSTER_SIZE} {TYPE}({WRMASK}){DST_HALF}{DST}{SRC1}
	</display>

	<field name="W" low="19" high="20" type="uint"/>
	<pattern low="53" high="58">111110</pattern> <!-- OPC -->

	<derived name="CLUSTER_SIZE" type="uint">
		<expr>
			2 &lt;&lt; {W}
		</expr>
	</derived>
	<derived name="NUM_SRC" expr="#one" type="uint"/>
	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#false" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>

	<encode>
		<map name="W">util_logbase2(src->cat5.cluster_size) - 1</map>
	</encode>
</bitset>

<bitset name="#instruction-cat5-quad-shuffle" extends="#instruction-cat5-brcst">
	<gen min="600"/>

	<display>
		{SY}{JP}{NAME} {TYPE}({WRMASK}){DST_HALF}{DST}{SRC1}{SRC2}
	</display>

	<pattern low="53" high="58">111111</pattern> <!-- OPC -->

	<derived name="HAS_SAMP" expr="#false" type="bool"/>
	<derived name="HAS_TEX" expr="#false" type="bool"/>
	<derived name="HAS_TYPE" expr="#true" type="bool"/>
</bitset>

<bitset name="quad_shuffle.brcst" extends="#instruction-cat5-quad-shuffle">
	<doc>subgroupQuadBroadcast</doc>

	<pattern low="19" high="20">00</pattern>   <!-- Quad-shuffle variant -->

	<derived name="NUM_SRC" expr="#two" type="uint"/>
</bitset>

<bitset name="quad_shuffle.horiz" extends="#instruction-cat5-quad-shuffle">
	<doc>subgroupQuadSwapHorizontal</doc>

	<pattern low="19" high="20">01</pattern>   <!-- Quad-shuffle variant -->

	<derived name="NUM_SRC" expr="#one" type="uint"/>
</bitset>

<bitset name="quad_shuffle.vert" extends="#instruction-cat5-quad-shuffle">
	<doc>subgroupQuadSwapVertical</doc>

	<pattern low="19" high="20">10</pattern>   <!-- Quad-shuffle variant -->

	<derived name="NUM_SRC" expr="#one" type="uint"/>
</bitset>

<bitset name="quad_shuffle.diag" extends="#instruction-cat5-quad-shuffle">
	<doc>subgroupQuadSwapDiagonal</doc>

	<pattern low="19" high="20">11</pattern>   <!-- Quad-shuffle variant -->

	<derived name="NUM_SRC" expr="#one" type="uint"/>
</bitset>

<!--
	All the magic for conditionally displaying various srcs, etc
	for the non-bindless / non-indirect case, or things that are in
	common with the bindless / indirect case
 -->

<bitset name="#cat5-src1" size="8">
	<override>
		<expr>{NUM_SRC} > 0</expr>
		<display>
			, {HALF}{SRC}
		</display>
		<field name="SRC" low="0" high="7" type="#reg-gpr"/>
	</override>
	<display/>
	<assert low="0" high="7">00000000</assert>
	<encode type="struct ir3_register *">
		<map name="SRC">src</map>
	</encode>
</bitset>

<bitset name="#cat5-src2" size="8">
	<override>
		<expr>{O} || ({NUM_SRC} > 1)</expr>
		<display>
			, {HALF}{SRC}
		</display>
		<field name="SRC" low="0" high="7" type="#reg-gpr"/>
	</override>
	<override>
		<expr>{SRC2_IMM_OFFSET}</expr>
		<display>
			{OFF}
		</display>
		<field name="OFF" low="0" high="7" type="uoffset"/>
	</override>
	<display/>
	<assert low="0" high="7">00000000</assert>
	<encode type="struct ir3_register *">
		<map name="SRC">src</map>
		<map name="OFF">extract_reg_uim(src)</map>
	</encode>
</bitset>

<bitset name="#cat5-samp" size="4">
	<override>
		<expr>{HAS_SAMP}</expr>
		<display>
			, s#{SAMP}
		</display>
		<field name="SAMP" low="0" high="3" type="uint"/>
	</override>
	<display/>
	<assert low="0" high="3">0000</assert>
	<encode type="struct ir3_instruction *">
		<map name="SAMP">src->cat5.samp</map>
	</encode>
</bitset>

<bitset name="#cat5-samp-s2en-bindless-a1" size="8">
	<doc>s2en (indirect) / bindless case with tex in a1.x</doc>
	<override>
		<expr>{HAS_SAMP}</expr>
		<display>
			, s#{SAMP}
		</display>
		<field name="SAMP" low="0" high="7" type="uint"/>
	</override>
	<display/>
	<assert low="0" high="7">00000000</assert>
	<encode type="struct ir3_instruction *">
		<map name="SAMP">src->cat5.samp</map>
	</encode>
</bitset>

<bitset name="#cat5-tex-s2en-bindless-a1" size="8">
	<doc>s2en (indirect) / bindless case with samp in a1.x</doc>
	<override>
		<expr>{HAS_TEX}</expr>
		<display>
			, t#{TEX}
		</display>
		<field name="TEX" low="0" high="7" type="uint"/>
	</override>
	<display/>
	<assert low="0" high="7">00000000</assert>
	<encode type="struct ir3_instruction *">
		<map name="TEX">src->cat5.tex</map>
	</encode>
</bitset>

<bitset name="#cat5-tex" size="7">
	<override>
		<expr>{HAS_TEX}</expr>
		<display>
			, t#{TEX}
		</display>
		<field name="TEX" low="0" high="6" type="uint"/>
	</override>
	<display/>
	<assert low="0" high="6">0000000</assert>
	<encode type="struct ir3_instruction *">
		<map name="TEX">src->cat5.tex</map>
	</encode>
</bitset>

<bitset name="#cat5-tex-s2en-bindless" size="4">
	<doc>s2en (indirect) / bindless case only has 4b tex</doc>
	<override>
		<expr>{HAS_TEX}</expr>
		<display>
			, t#{TEX}
		</display>
		<field name="TEX" low="0" high="3" type="uint"/>
	</override>
	<display/>
	<assert low="0" high="3">0000</assert>
	<encode type="struct ir3_instruction *">
		<map name="TEX">src->cat5.tex</map>
	</encode>
</bitset>

<bitset name="#cat5-type" size="3">
	<display/>
	<override>
		<expr>{HAS_TYPE}</expr>
		<display>
			({TYPE})
		</display>
	</override>
	<field name="TYPE" low="0" high="2" type="#type"/>
	<encode type="struct ir3_instruction *">
		<!--
			Normally we only encode fields that have visible impact on
			the decoded disasm, but the type field is one of those
			special exceptions
		 -->
		<map name="TYPE" force="true">src->cat5.type</map>
	</encode>
</bitset>

<!--
	Helpers/bitsets/etc for dealing with the bindless/indirect case:
 -->

<enum name="#cat5-s2en-bindless-desc-mode">
	<doc>
		We don't actually display this enum, but it is useful to
		document the various cases

		TODO we should probably have an option for uniforms w/out
		display strings, but which have 'C' names that can be used
		to generate header that the compiler can use
	</doc>
	<value val="0" display="CAT5_UNIFORM">
		<doc>
			Use traditional GL binding model, get texture and sampler index
			from src3 which is presumed to be uniform on a4xx+ (a3xx doesn't
			have the other modes, but does handle non-uniform indexing).
		</doc>
	</value>
	<value val="1" display="CAT5_BINDLESS_A1_UNIFORM">
		<doc>
			The sampler base comes from the low 3 bits of a1.x, and the sampler
			and texture index come from src3 which is presumed to be uniform.
		</doc>
	</value>
	<value val="2" display="CAT5_BINDLESS_NONUNIFORM">
		<doc>
			The texture and sampler share the same base, and the sampler and
			texture index come from src3 which is *not* presumed to be uniform.
		</doc>
	</value>
	<value val="3" display="CAT5_BINDLESS_A1_NONUNIFORM">
		<doc>
			The sampler base comes from the low 3 bits of a1.x, and the sampler
			and texture index come from src3 which is *not* presumed to be
			uniform.
		</doc>
	</value>
	<value val="4" display="CAT5_NONUNIFORM">
		<doc>
			Use traditional GL binding model, get texture and sampler index
			from src3 which is *not* presumed to be uniform.
		</doc>
	</value>
	<value val="5" display="CAT5_BINDLESS_UNIFORM">
		<doc>
			The texture and sampler share the same base, and the sampler and
			texture index come from src3 which is presumed to be uniform.
		</doc>
	</value>
	<value val="6" display="CAT5_BINDLESS_IMM">
		<doc>
			The texture and sampler share the same base, get sampler index from low
			4 bits of src3 and texture index from high 4 bits.
		</doc>
	</value>
	<value val="7" display="CAT5_BINDLESS_A1_IMM">
		<doc>
			The sampler base comes from the low 3 bits of a1.x, and the texture
			index comes from the next 8 bits of a1.x. The sampler index is an
			immediate in src3.
		</doc>
	</value>
</enum>

<!-- Helper to map s2en/bindless DESC_MODE to whether it is an indirect mode -->
<expr name="#cat5-s2enb-is-indirect">
	{DESC_MODE} &lt; 6  /* CAT5_BINDLESS_IMM */
</expr>

<!-- Helper to map s2en/bindless DESC_MODE to whether it is a bindless mode -->
<expr name="#cat5-s2enb-is-bindless">
	({DESC_MODE} == 1) /* CAT5_BINDLESS_A1_UNIFORM */ ||
	({DESC_MODE} == 2) /* CAT5_BINDLESS_NONUNIFORM */ ||
	({DESC_MODE} == 3) /* CAT5_BINDLESS_A1_NONUNIFORM */ ||
	({DESC_MODE} == 5) /* CAT5_BINDLESS_UNIFORM */ ||
	({DESC_MODE} == 6) /* CAT5_BINDLESS_IMM */ ||
	({DESC_MODE} == 7) /* CAT5_BINDLESS_A1_IMM */
</expr>

<!-- Helper to map s2en/bindless DESC_MODE to whether it uses a1.x -->
<expr name="#cat5-s2enb-uses_a1">
	({DESC_MODE} == 1) /* CAT5_BINDLESS_A1_UNIFORM */ ||
	({DESC_MODE} == 3) /* CAT5_BINDLESS_A1_NONUNIFORM */ ||
	({DESC_MODE} == 7) /* CAT5_BINDLESS_A1_IMM */
</expr>

<expr name="#cat5-s2enb-uses_a1-gen6">
	ISA_GPU_ID() &gt;= 600 &amp;&amp; ISA_GPU_ID() &lt; 700 &amp;&amp;
	(({DESC_MODE} == 1) /* CAT5_BINDLESS_A1_UNIFORM */ ||
	 ({DESC_MODE} == 3) /* CAT5_BINDLESS_A1_NONUNIFORM */ ||
	 ({DESC_MODE} == 7))/* CAT5_BINDLESS_A1_IMM */
</expr>

<expr name="#cat5-s2enb-uses_a1-gen7">
	ISA_GPU_ID() &gt;= 700 &amp;&amp;
	(({DESC_MODE} == 1) /* CAT5_BINDLESS_A1_UNIFORM */ ||
	 ({DESC_MODE} == 3) /* CAT5_BINDLESS_A1_NONUNIFORM */ ||
	 ({DESC_MODE} == 7))/* CAT5_BINDLESS_A1_IMM */
</expr>

<!-- Helper to map s2en/bindless DESC_MODE to whether it is uniform (flow control) mode -->
<expr name="#cat5-s2enb-is-uniform">
	({DESC_MODE} == 0) /* CAT5_UNIFORM */ ||
	({DESC_MODE} == 1) /* CAT5_BINDLESS_A1_UNIFORM */ ||
	({DESC_MODE} == 5) /* CAT5_BINDLESS_UNIFORM */
</expr>

<!-- Helper to map s2en/bindless DESC_MODE to whether it is non-uniform mode. -->
<expr name="#cat5-s2enb-is-nonuniform">
	({DESC_MODE} == 2) /* CAT5_BINDLESS_NONUNIFORM */ ||
	({DESC_MODE} == 3) /* CAT5_BINDLESS_A1_NONUNIFORM */ ||
	({DESC_MODE} == 4) /* CAT5_NONUNIFORM */
</expr>

<bitset name="#cat5-src3" size="8">
	<doc>bindless/indirect src3, which can either be GPR or samp/tex</doc>
	<override expr="#cat5-s2enb-is-indirect">
		<display>
			, {SRC_HALF}{SRC}
		</display>
		<field name="SRC" low="0" high="7" type="#reg-gpr"/>
		<derived name="SRC_HALF" type="bool" display="h">
			<expr>!{BINDLESS}</expr>
		</derived>
	</override>
	<override expr="#cat5-s2enb-uses_a1-gen6">
		<doc>
			In the case that a1.x is used, all 8 bits encode sampler
		</doc>
		<display>
			{SAMP}
		</display>
		<field name="SAMP" low="0" high="7" type="#cat5-samp-s2en-bindless-a1">
			<param name="HAS_SAMP"/>
		</field>
	</override>
	<override expr="#cat5-s2enb-uses_a1-gen7">
		<doc>
			In the case that a1.x is used, all 8 bits encode texture
		</doc>
		<display>
			{TEX}
		</display>
		<field name="TEX" low="0" high="7" type="#cat5-tex-s2en-bindless-a1">
			<param name="HAS_TEX"/>
		</field>
	</override>
	<display>
		{SAMP}{TEX}
	</display>
	<field name="SAMP" low="0" high="3" type="#cat5-samp">
		<param name="HAS_SAMP"/>
	</field>
	<field name="TEX" low="4" high="7" type="#cat5-tex-s2en-bindless">
		<param name="HAS_TEX"/>
	</field>
	<encode type="struct ir3_register *">
		<map name="SAMP">s->instr</map>
		<map name="TEX">s->instr</map>
		<map name="SRC">src</map>
	</encode>
</bitset>

</isa>
