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

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>

<bitset name="#instruction" size="32">
	<doc>
		Encoding of an afuc instruction.  All instructions are 32b.
	</doc>
	<encode type="struct afuc_instr *" case-prefix="OPC_">
		<map name="XMOV">src->xmov</map>
		<map name="DST">src->dst</map>
		<map name="SRC1">src->src1</map>
		<map name="SRC2">src->src2</map>
		<map name="IMMED">src->immed</map>
		<map name="BIT">src->bit</map>
		<!-- RIMMED is an alias of IMMED for immediates that might be a GPU register -->
		<map name="RIMMED">src->immed</map>
	</encode>
	<decode/>
</bitset>

<enum name="#specialsrc">
	<doc>special registers for operands used as a source</doc>
	<value val="0x1c" display="$rem"/>
	<value val="0x1d" display="$memdata"/>
	<value val="0x1e" display="$regdata"/>
	<value val="0x1f" display="$data"/>
</enum>

<enum name="#specialdst">
	<doc>special registers for operands used as a destination</doc>
	<value val="0x1c" display="$rem"/>
	<value val="0x1d" display="$addr"/>
	<value val="0x1e" display="$usraddr"/>
	<value val="0x1f" display="$data"/>
</enum>

<!-- TODO add support for padding integers so this doesn't have to be an enum -->
<enum name="#reg">
	<value val="0x00" display="$00"/>
	<value val="0x01" display="$01"/>
	<value val="0x02" display="$02"/>
	<value val="0x03" display="$03"/>
	<value val="0x04" display="$04"/>
	<value val="0x05" display="$05"/>
	<value val="0x06" display="$06"/>
	<value val="0x07" display="$07"/>
	<value val="0x08" display="$08"/>
	<value val="0x09" display="$09"/>
	<value val="0x0a" display="$0a"/>
	<value val="0x0b" display="$0b"/>
	<value val="0x0c" display="$0c"/>
	<value val="0x0d" display="$0d"/>
	<value val="0x0e" display="$0e"/>
	<value val="0x0f" display="$0f"/>
	<value val="0x10" display="$10"/>
	<value val="0x11" display="$11"/>
	<value val="0x12" display="$12"/>
	<value val="0x13" display="$13"/>
	<value val="0x14" display="$14"/>
	<value val="0x15" display="$15"/>
	<value val="0x16" display="$16"/>
	<value val="0x17" display="$17"/>
	<value val="0x18" display="$18"/>
	<value val="0x19" display="$19"/>
	<value val="0x1a" display="$sp"/>
	<value val="0x1b" display="$lr"/>
</enum>

<expr name="#reg-special">
	{SPECIALREG} >= 0x1c
</expr>

<bitset name="#src" size="5">
	<override expr="#reg-special">
		<display>
			{SPECIALREG}
		</display>
		<field name="SPECIALREG" low="0" high="4" type="#specialsrc"/>
	</override>
	<display>
		{REG}
	</display>
	<field name="REG" low="0" high="4" type="#reg"/>

	<encode type="uint8_t">
		<map name="REG">src</map>
		<map name="SPECIALREG">src</map>
	</encode>
	<decode/>
</bitset>

<bitset name="#dst" size="5">
	<override expr="#reg-special">
		<display>
			{SPECIALREG}
		</display>
		<field name="SPECIALREG" low="0" high="4" type="#specialdst"/>
	</override>
	<display>
		{REG}
	</display>
	<field name="REG" low="0" high="4" type="#reg"/>

	<encode type="uint8_t">
		<map name="REG">src</map>
		<map name="SPECIALREG">src</map>
	</encode>
	<decode/>
</bitset>

<bitset name="#instruction-rep" extends="#instruction">
	<field name="REP" pos="26" type="bool" display="(rep)"/>

	<encode>
		<map name="REP">src->rep</map>
	</encode>
</bitset>

<enum name="#xmov">
	<doc>Execute eXtra mov's based on $rem</doc>
	<value val="0" display=""/>
	<value val="1" display="(xmov1)"/>
	<value val="2" display="(xmov2)"/>
	<value val="3" display="(xmov3)"/>
</enum>

<bitset name="#alu-2src" extends="#instruction-rep">
	<display>
		{REP}{XMOV}{PEEK}{NAME} {DST}, {SRC1}, {SRC2}
	</display>

	<pattern low="5" high="7">xxx</pattern>
	<field name="PEEK" pos="8" type="bool" display="(peek)"/>
	<field name="XMOV" low="9" high="10" type="#xmov"/>
	<field name="DST" low="11" high="15" type="#dst"/>
	<field name="SRC2" low="16" high="20" type="#src"/>
	<field name="SRC1" low="21" high="25" type="#src"/>
	<pattern low="27" high="31">10011</pattern>

	<encode>
		<map name="PEEK">src->peek</map>
	</encode>
</bitset>

<bitset name="#alu-1src" extends="#instruction-rep">
	<display>
		{REP}{XMOV}{NAME} {DST}, {SRC1}
	</display>

	<pattern low="5" high="8">xxxx</pattern>
	<field name="XMOV" low="9" high="10" type="#xmov"/>
	<field name="DST" low="11" high="15" type="#dst"/>
	<field name="SRC1" low="16" high="20" type="#src"/>
	<pattern low="21" high="25">xxxxx</pattern> <!-- SRC1 unused -->
	<pattern low="27" high="31">10011</pattern>
</bitset>

<bitset name="#alu-2src-immed" extends="#instruction-rep">
	<display>
		{REP}{NAME} {DST}, {SRC1}, 0x{RIMMED}
	</display>

	<field name="RIMMED" low="0" high="15" type="hex"/>
	<field name="DST" low="16" high="20" type="#dst"/>
	<field name="SRC1" low="21" high="25" type="#src"/>
</bitset>

<bitset name="#alu-2src-immed12" extends="#instruction-rep">
	<display>
		{REP}{NAME} {DST}, {SRC1}, 0x{RIMMED}
	</display>

	<field name="RIMMED" low="0" high="11" type="hex"/>
	<field name="DST" low="16" high="20" type="#dst"/>
	<field name="SRC1" low="21" high="25" type="#src"/>
	<pattern low="27" high="31">10010</pattern>
</bitset>

<bitset name="#alu-1src-immed" extends="#instruction-rep">
	<display>
		{REP}{NAME} {DST}, 0x{IMMED}
	</display>

	<field name="IMMED" low="0" high="15" type="hex"/>
	<field name="DST" low="16" high="20" type="#dst"/>
	<pattern low="21" high="25">xxxxx</pattern> <!-- SRC1 unused -->
</bitset>

<bitset name="add" extends="#alu-2src">
	<doc>add and write carry flag</doc>
	<pattern low="0" high="4">00001</pattern>
</bitset>

<bitset name="addi" displayname="add" extends="#alu-2src-immed">
	<pattern low="27" high="31">00001</pattern>
</bitset>

<bitset name="addhi" extends="#alu-2src">
	<doc>Perform high 32 bits of 64-bit addition, using carry flag written by add</doc>
	<pattern low="0" high="4">00010</pattern>
</bitset>

<bitset name="addhii" displayname="addhi" extends="#alu-2src-immed">
	<pattern low="27" high="31">00010</pattern>
</bitset>

<bitset name="sub" extends="#alu-2src">
	<doc>subtract and write carry flag</doc>
	<pattern low="0" high="4">00011</pattern>
</bitset>

<bitset name="subi" displayname="sub" extends="#alu-2src-immed">
	<pattern low="27" high="31">00011</pattern>
</bitset>

<bitset name="subhi" extends="#alu-2src">
	<doc>Perform high 32 bits of 64-bit subtraction, using carry flag written by sub</doc>
	<pattern low="0" high="4">00100</pattern>
</bitset>

<bitset name="subhii" displayname="subhi" extends="#alu-2src-immed">
	<pattern low="27" high="31">00100</pattern>
</bitset>

<bitset name="and" extends="#alu-2src">
	<pattern low="0" high="4">00101</pattern>
</bitset>

<bitset name="andi" displayname="and" extends="#alu-2src-immed">
	<pattern low="27" high="31">00101</pattern>
</bitset>

<bitset name="or" extends="#alu-2src">
	<!-- mov of a register is encoded as or with $00 -->
	<override>
		<expr>{SRC1} == 0</expr>
		<display>
			{REP}{XMOV}{PEEK}mov {DST}, {SRC2}
		</display>
	</override>
	<pattern low="0" high="4">00110</pattern>
</bitset>

<bitset name="ori" displayname="or" extends="#alu-2src-immed">
	<pattern low="27" high="31">00110</pattern>
</bitset>

<bitset name="xor" extends="#alu-2src">
	<pattern low="0" high="4">00111</pattern>
</bitset>

<bitset name="xori" displayname="xor" extends="#alu-2src-immed">
	<pattern low="27" high="31">00111</pattern>
</bitset>

<bitset name="not" extends="#alu-1src">
	<pattern low="0" high="4">01000</pattern>
</bitset>

<bitset name="noti" displayname="not" extends="#alu-1src-immed">
	<pattern low="27" high="31">01000</pattern>
</bitset>

<bitset name="shl" extends="#alu-2src">
	<gen max="6"/>
	<pattern low="0" high="4">01001</pattern>
</bitset>

<bitset name="shli" displayname="shl" extends="#alu-2src-immed">
	<gen max="6"/>
	<pattern low="27" high="31">01001</pattern>
</bitset>

<bitset name="shl" extends="#alu-2src">
	<gen min="7"/>
	<pattern low="0" high="4">10010</pattern>
</bitset>

<bitset name="shli" displayname="shl" extends="#alu-2src-immed12">
	<gen min="7"/>
	<pattern low="12" high="15">0010</pattern>
</bitset>

<bitset name="ushr" extends="#alu-2src">
	<doc>0-extending right shift</doc>
	<gen max="6"/>
	<pattern low="0" high="4">01010</pattern>
</bitset>

<bitset name="ushri" displayname="ushr" extends="#alu-2src-immed">
	<gen max="6"/>
	<pattern low="27" high="31">01010</pattern>
</bitset>

<bitset name="ushr" extends="#alu-2src">
	<gen min="7"/>
	<pattern low="0" high="4">10011</pattern>
</bitset>

<bitset name="ushri" displayname="ushr" extends="#alu-2src-immed12">
	<gen min="7"/>
	<pattern low="12" high="15">0011</pattern>
</bitset>

<bitset name="ishr" extends="#alu-2src">
	<doc>sign-extending right shift</doc>
	<gen max="6"/>
	<pattern low="0" high="4">01011</pattern>
</bitset>

<bitset name="ishri" displayname="ishr" extends="#alu-2src-immed">
	<gen max="6"/>
	<pattern low="27" high="31">01011</pattern>
</bitset>

<bitset name="ishr" extends="#alu-2src">
	<gen min="7"/>
	<pattern low="0" high="4">10100</pattern>
</bitset>

<bitset name="ishri" displayname="ishr" extends="#alu-2src-immed12">
	<gen min="7"/>
	<pattern low="12" high="15">0100</pattern>
</bitset>

<bitset name="rot" extends="#alu-2src">
	<doc>Rotate left (left shift with wraparound)</doc>
	<gen max="6"/>
	<pattern low="0" high="4">01100</pattern>
</bitset>

<bitset name="roti" displayname="rot" extends="#alu-2src-immed">
	<gen max="6"/>
	<pattern low="27" high="31">01100</pattern>
</bitset>

<bitset name="rot" extends="#alu-2src">
	<gen min="7"/>
	<pattern low="0" high="4">10101</pattern>
</bitset>

<bitset name="roti" displayname="rot" extends="#alu-2src-immed12">
	<gen min="7"/>
	<pattern low="12" high="15">0101</pattern>
</bitset>

<bitset name="mul8" extends="#alu-2src">
	<doc>Multiply low 8 bits of each source to produce a 16-bit result</doc>
	<gen max="6"/>
	<pattern low="0" high="4">01101</pattern>
</bitset>

<bitset name="mul8i" displayname="mul8" extends="#alu-2src-immed">
	<gen max="6"/>
	<pattern low="27" high="31">01101</pattern>
</bitset>

<bitset name="mul8" extends="#alu-2src">
	<gen min="7"/>
	<pattern low="0" high="4">01100</pattern>
</bitset>

<bitset name="mul8i" displayname="mul8" extends="#alu-2src-immed">
	<gen min="7"/>
	<pattern low="27" high="31">01100</pattern>
</bitset>

<bitset name="min" extends="#alu-2src">
	<doc>Unsigned minimum</doc>
	<gen max="6"/>
	<pattern low="0" high="4">01110</pattern>
</bitset>

<bitset name="mini" displayname="min" extends="#alu-2src-immed">
	<gen max="6"/>
	<pattern low="27" high="31">01110</pattern>
</bitset>

<bitset name="min" extends="#alu-2src">
	<gen min="7"/>
	<pattern low="0" high="4">01010</pattern>
</bitset>

<bitset name="mini" displayname="min" extends="#alu-2src-immed">
	<gen min="7"/>
	<pattern low="27" high="31">01010</pattern>
</bitset>

<bitset name="max" extends="#alu-2src">
	<doc>Unsigned maximum</doc>
	<gen max="6"/>
	<pattern low="0" high="4">01111</pattern>
</bitset>

<bitset name="maxi" displayname="max" extends="#alu-2src-immed">
	<gen max="6"/>
	<pattern low="27" high="31">01111</pattern>
</bitset>

<bitset name="max" extends="#alu-2src">
	<gen min="7"/>
	<pattern low="0" high="4">01011</pattern>
</bitset>

<bitset name="maxi" displayname="max" extends="#alu-2src-immed">
	<gen min="7"/>
	<pattern low="27" high="31">01011</pattern>
</bitset>

<bitset name="cmp" extends="#alu-2src">
	<doc>
		Compare two sources and produce a bitfield:
		- 0x00 if src1 &gt; src2
		- 0x2b if src1 == src2
		- 0x1e if src1 &lt; src2 
		Often a "branch on bit set/unset" instruction is used on the
		result to implement a compare-and-branch macro.
	</doc>
	<gen max="6"/>
	<pattern low="0" high="4">10000</pattern>
</bitset>

<bitset name="cmpi" displayname="cmp" extends="#alu-2src-immed">
	<gen max="6"/>
	<pattern low="27" high="31">10000</pattern>
</bitset>

<bitset name="cmp" extends="#alu-2src">
	<gen min="7"/>
	<pattern low="0" high="4">01101</pattern>
</bitset>

<bitset name="cmpi" displayname="cmp" extends="#alu-2src-immed">
	<gen min="7"/>
	<pattern low="27" high="31">01101</pattern>
</bitset>

<bitset name="bic" extends="#alu-2src">
	<gen min="7"/>
	<pattern low="0" high="4">01001</pattern>
</bitset>

<bitset name="bici" displayname="bic" extends="#alu-2src-immed">
	<gen min="7"/>
	<pattern low="27" high="31">01001</pattern>
</bitset>

<bitset name="msb" extends="#alu-1src">
	<doc>Return the most-significant bit of src2, or 0 if src2 == 0</doc>
	<gen max="6"/>
	<pattern low="0" high="4">10100</pattern>
</bitset>

<bitset name="msb" extends="#alu-1src">
	<gen min="7"/>
	<pattern low="0" high="4">11001</pattern>
</bitset>

<bitset name="#setclrbit6" extends="#instruction-rep">
	<display>
		{REP}{NAME} {DST}, {SRC}, b{BIT}
	</display>

	<field name="BIT" low="1" high="5" type="uint"/>
	<pattern low="6" high="15">xxxxxxxxxx</pattern>
	<field name="DST" low="16" high="20" type="#dst"/>
	<field name="SRC" low="21" high="25" type="#src"/>
	<pattern low="27" high="31">10010</pattern>

	<encode>
		<map name="SRC">src->src1</map>
	</encode>
</bitset>

<bitset name="#setclrbit7" extends="#instruction-rep">
	<display>
		{REP}{NAME} {DST}, {SRC}, b{BIT}
	</display>

	<field name="BIT" low="1" high="5" type="uint"/>
	<pattern low="6" high="11">xxxxxx</pattern>
	<pattern low="12" high="15">0110</pattern>
	<field name="DST" low="16" high="20" type="#dst"/>
	<field name="SRC" low="21" high="25" type="#src"/>
	<pattern low="27" high="31">10010</pattern>

	<encode>
		<map name="SRC">src->src1</map>
	</encode>
</bitset>

<bitset name="setbiti" displayname="setbit" extends="#setclrbit6">
	<doc>Set a given bit to 1</doc>
	<gen max="6"/>
	<pattern pos="0">1</pattern>
</bitset>

<bitset name="clrbit" extends="#setclrbit6">
	<doc>Clear a given bit, i.e. set it to 0</doc>
	<gen max="6"/>
	<pattern pos="0">0</pattern>
</bitset>

<bitset name="setbiti" displayname="setbit" extends="#setclrbit7">
	<gen min="7"/>
	<pattern pos="0">1</pattern>
</bitset>

<bitset name="clrbit" extends="#setclrbit7">
	<gen min="7"/>
	<pattern pos="0">0</pattern>
</bitset>

<bitset name="setbit" extends="#alu-2src">
	<doc>
		Set or clear a given bit. This is the non-immediate form of
		setbit/clrbit. Bits 1-5 of src2 are the bit to set, bit 0 is the
		value to set it to.
	</doc>
	<gen min="7"/>
	<pattern low="0" high="4">10110</pattern>
</bitset>

<bitset name="#bitfield-immed" extends="#instruction-rep">
	<display>
		{REP}{NAME} {DST}, {SRC}, b{LO}, b{HI}
	</display>

	<field name="LO" low="0" high="4" type="uint"/>
	<field name="HI" low="5" high="9" type="uint"/>
	<pattern low="10" high="11">xx</pattern>
	<field name="DST" low="16" high="20" type="#dst"/>
	<field name="SRC" low="21" high="25" type="#src"/>
	<pattern low="27" high="31">10010</pattern>

	<encode>
		<map name="LO">src->bit</map>
		<map name="HI">src->immed</map>
		<map name="SRC">src->src1</map>
	</encode>
</bitset>

<bitset name="ubfx" extends="#bitfield-immed">
	<doc>Unsigned BitField eXtract</doc>
	<gen min="7"/>
	<pattern low="12" high="15">0111</pattern>
</bitset>

<bitset name="bfi" extends="#bitfield-immed">
	<doc>BitField Insert</doc>
	<gen min="7"/>
	<pattern low="12" high="15">1000</pattern>
</bitset>

<bitset name="#movi" extends="#instruction-rep">
	<doc>Special move-immediate instruction with a shift</doc>
	<override>
		<expr>{SHIFT} == 0</expr>
		<display>
			{REP}mov {DST}, 0x{RIMMED}
		</display>
	</override>
	<display>
		{REP}mov {DST}, 0x{RIMMED} &lt;&lt; {SHIFT}
	</display>

	<field name="RIMMED" low="0" high="15" type="hex"/>
	<field name="DST" low="16" high="20" type="#dst"/>
	<field name="SHIFT" low="21" high="25" type="uint"/>

	<encode>
		<map name="SHIFT">src->shift</map>
	</encode>
</bitset>

<bitset name="movi" extends="#movi">
	<gen max="6"/>
	<pattern low="27" high="31">10001</pattern>
</bitset>

<bitset name="movi" extends="#movi">
	<gen min="7"/>
	<pattern low="27" high="31">01110</pattern>
</bitset>

<enum name="#sds">
	<doc>
		Used in combination with writing @DRAW_STATE_SET, the source is
		read the specified number of times and used to set the draw
		state base.
	</doc>
	<value val="0" display=""/>
	<value val="1" display="(sds1)"/>
	<value val="2" display="(sds2)"/>
	<value val="3" display="(sds3)"/>
</enum>

<bitset name="#control" extends="#instruction-rep">
	<field name="PREINCREMENT" pos="14" type="bool" display="!"/>
	<field name="OFFSET" low="21" high="25" type="#src"/>

	<encode>
		<map name="PREINCREMENT">src->preincrement</map>
	</encode>
</bitset>

<bitset name="#store" extends="#control">
	<display>
		{REP}store {SRC}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}
	</display>

	<doc>
		Store to memory directly. Mainly used by preemption to avoid
		disturbing FIFO state before it is saved and after it is
		restored.
	</doc>

	<pattern low="12" high="13">00</pattern>
	<field name="IMMED" low="0" high="11" type="hex"/>
	<field name="SRC" low="16" high="20" type="#src"/>

	<encode>
		<map name="SRC">src->src1</map>
		<map name="OFFSET">src->src2</map>
	</encode>
</bitset>

<bitset name="store" extends="#store">
	<gen max="5"/>
	<pattern low="27" high="31">10101</pattern>
	<pattern pos="15">0</pattern>
</bitset>

<bitset name="store" extends="#store">
	<gen min="6"/>
	<pattern pos="15">0</pattern>
	<pattern low="27" high="31">10100</pattern>
</bitset>

<expr name="#pre-increment">
	{PREINCREMENT}
</expr>

<bitset name="#control-base" size="12">
	<!--
		In pre-increment mode, the register is usually in the offset
		instead of the base, so always print it as an immediate.
	-->
	<override expr="#pre-increment">
		<display>
			0x{IMMED}
		</display>
		<field name="IMMED" low="0" high="11" type="hex"/>
	</override>
	<display>
		{CONTROLREG}
	</display>
	<field name="CONTROLREG" low="0" high="11" type="custom"/>
	<encode type="uint32_t">
		<map name="IMMED">src</map>
		<map name="CONTROLREG">src</map>
	</encode>
	<decode/>
</bitset>

<bitset name="#cwrite" extends="#control">
	<doc>Write to a control register.</doc>
	<display>
		{REP}{SDS}cwrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}
	</display>

	<field name="BASE" low="0" high="11" type="#control-base">
		<param name="PREINCREMENT"/>
	</field>
	<field name="SDS" low="12" high="13" type="#sds"/>
	<field name="SRC" low="16" high="20" type="#src"/>
	<pattern low="27" high="31">10101</pattern>

	<encode>
		<map name="SDS">src->sds</map>
		<map name="SRC">src->src1</map>
		<map name="OFFSET">src->src2</map>
		<map name="BASE">src->immed</map>
	</encode>
</bitset>

<bitset name="cwrite" extends="#cwrite">
	<pattern pos="15">1</pattern>
	<gen max="5"/>
</bitset>

<bitset name="cwrite" extends="#cwrite">
	<pattern pos="15">0</pattern>
	<gen min="6"/>
</bitset>

<bitset name="#sqe-base" size="12">
	<override expr="#pre-increment">
		<display>
			0x{IMMED}
		</display>
		<field name="IMMED" low="0" high="11" type="uint"/>
	</override>
	<display>
		{SQEREG}
	</display>
	<field name="SQEREG" low="0" high="11" type="custom"/>
	<encode type="uint32_t">
		<map name="IMMED">src</map>
		<map name="SQEREG">src</map>
	</encode>
</bitset>

<bitset name="swrite" extends="#control">
	<doc>Write to a SQE register.</doc>
	<gen min="6"/>
	<display>
		{REP}swrite {SRC}, [{OFFSET} + {BASE}]{PREINCREMENT}
	</display>

	<field name="BASE" low="0" high="11" type="#sqe-base">
		<param name="PREINCREMENT"/>
	</field>
	<pattern low="12" high="13">00</pattern>
	<field name="SRC" low="16" high="20" type="#src"/>
	<pattern pos="15">1</pattern>
	<pattern low="27" high="31">10101</pattern>

	<encode>
		<map name="SRC">src->src1</map>
		<map name="OFFSET">src->src2</map>
		<map name="BASE">src->immed</map>
	</encode>
</bitset>

<bitset name="load" extends="#control">
	<gen min="6"/>
	<doc>
		Load from memory directly. Mainly used by preemption to avoid
		disturbing FIFO state before it is saved and after it is
		restored.
	</doc>
	<display>
		{REP}load {DST}, [{OFFSET} + 0x{IMMED}]{PREINCREMENT}
	</display>

	<field name="IMMED" low="0" high="11" type="hex"/>
	<pattern low="12" high="13">00</pattern>
	<pattern pos="15">0</pattern>
	<field name="DST" low="16" high="20" type="#dst"/>
	<pattern low="27" high="31">10110</pattern>

	<encode>
		<map name="OFFSET">src->src1</map>
	</encode>
</bitset>

<bitset name="#cread" extends="#control">
	<doc>Read from a control register.</doc>
	<display>
		{REP}cread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}
	</display>

	<field name="BASE" low="0" high="11" type="#control-base">
		<param name="PREINCREMENT"/>
	</field>
	<pattern low="12" high="13">00</pattern>
	<field name="DST" low="16" high="20" type="#dst"/>

	<encode>
		<map name="OFFSET">src->src1</map>
		<map name="BASE">src->immed</map>
	</encode>
</bitset>

<bitset name="cread" extends="#cread">
	<gen max="5"/>
	<pattern pos="15">1</pattern>
	<pattern low="27" high="31">10110</pattern>
</bitset>

<bitset name="cread" extends="#cread">
	<gen min="6"/>
	<pattern pos="15">0</pattern>
	<!-- a6xx shuffled around the cread opcode -->
	<pattern low="27" high="31">10111</pattern>
</bitset>

<bitset name="sread" extends="#control">
	<doc>Read from a SQE register.</doc>
	<gen min="6"/>
	<display>
		{REP}{XREG}sread {DST}, [{OFFSET} + {BASE}]{PREINCREMENT}
	</display>

	<field name="BASE" low="0" high="11" type="#sqe-base">
		<param name="PREINCREMENT"/>
	</field>
	<pattern low="12" high="13">00</pattern>
	<field name="DST" low="16" high="20" type="#dst"/>

	<encode>
		<map name="OFFSET">src->src1</map>
		<map name="BASE">src->immed</map>
	</encode>

	<pattern pos="15">1</pattern>
	<pattern low="27" high="31">10111</pattern>
</bitset>

<bitset name="#branch" extends="#instruction">
	<field name="OFFSET" low="0" high="15" type="branch"/>
	<field name="SRC" low="21" high="25" type="#src"/>

	<encode>
		<map name="OFFSET">src->offset</map>
		<map name="SRC">src->src1</map>
	</encode>
</bitset>

<bitset name="#branch-immed" extends="#branch">
	<display>
		{NAME} {SRC}, 0x{IMMED}, #{OFFSET}
	</display>
	<field name="IMMED" low="16" high="20" type="hex"/>
</bitset>

<bitset name="#branch-bit" extends="#branch">
	<display>
		{NAME} {SRC}, b{BIT}, #{OFFSET}
	</display>
	<field name="BIT" low="16" high="20" type="uint"/>
</bitset>

<bitset name="brnei" displayname="brne" extends="#branch-immed">
	<doc>Branch if not equal to an immediate.</doc>
	<pattern low="26" high="31">110000</pattern>
</bitset>

<bitset name="breqi" displayname="breq" extends="#branch-immed">
	<doc>Branch if equal to an immediate.</doc>
	<pattern low="26" high="31">110001</pattern>
</bitset>

<bitset name="brneb" displayname="brne" extends="#branch-bit">
	<doc>Branch if a bit is not set.</doc>
	<override>
		<!-- jump #label is encoded as brne $00, b0, #label -->
		<expr>
			({BIT} == 0) &amp;&amp; ({SRC} == 0)
		</expr>
		<display>
			jump #{OFFSET}
		</display>
	</override>
	<pattern low="26" high="31">110010</pattern>
</bitset>

<bitset name="breqb" displayname="breq" extends="#branch-bit">
	<doc>Branch if a bit is set.</doc>
	<pattern low="26" high="31">110011</pattern>
</bitset>

<bitset name="#instruction-no-args" extends="#instruction">
	<display>
		{NAME}
	</display>
	<pattern low="0" high="25">xxxxxxxxxxxxxxxxxxxxxxxxxx</pattern>
</bitset>

<bitset name="#ret" extends="#instruction">
	<display>
		{NAME}
	</display>
	<pattern low="26" high="31">110100</pattern>
	<pattern low="0" high="24">xxxxxxxxxxxxxxxxxxxxxxxxx</pattern>
</bitset>

<bitset name="ret" extends="#ret">
	<pattern low="25" high="25">0</pattern>
</bitset>

<bitset name="iret" extends="#ret">
	<doc>Return from preemption interrupt handler.</doc>
	<pattern low="25" high="25">1</pattern>
</bitset>

<bitset name="call" extends="#instruction">
	<display>
		call #{TARGET}
	</display>

	<field name="TARGET" low="0" high="25" type="absbranch" call="true"/>
	<pattern low="26" high="31">110101</pattern>

	<encode>
		<map name="TARGET">src->literal</map>
	</encode>
</bitset>

<bitset name="jumpa" extends="#instruction">
	<display>
		jumpa #{TARGET}
	</display>

	<gen min="7"/>

	<field name="TARGET" low="0" high="25" type="absbranch"/>
	<pattern low="26" high="31">111001</pattern>

	<encode>
		<map name="TARGET">src->literal</map>
	</encode>
</bitset>

<bitset name="waitin" extends="#instruction-no-args">
	<doc>
		A special branch instruction that parses the next PM4 packet
		header in $data and jumps to the packet handler routine. By
		convention the delay slot always contains a "mov $01, $data"
		instruction, so that $01 contains the packet header when
		processing the next packet.
	</doc>
	<display>
		waitin
	</display>
	<pattern low="26" high="31">110110</pattern>
</bitset>

<bitset name="bl" extends="#instruction">
	<doc>
		Jump to the target and store a return address in $lr.
	</doc>
	<display>
		bl #{TARGET}
	</display>

	<field name="TARGET" low="0" high="25" type="absbranch" call="true"/>
	<pattern low="26" high="31">111000</pattern>

	<encode>
		<map name="TARGET">src->literal</map>
	</encode>
</bitset>

<expr name="#three">
	3
</expr>

<bitset name="setsecure" extends="#instruction-no-args">
	<doc>
		Call the zap shader fw to switch into/out of secure mode. Skips
		the next two instructions if successful.
	</doc>
	<display>
		setsecure $02, #{TARGET}
	</display>

	<pattern low="26" high="31">111011</pattern>
	<derived name="TARGET" expr="#three" width="16" type="branch"/>
</bitset>

<bitset name="nop" extends="#instruction-rep">
	<gen max="5"/>
	<display>
		{REP}nop
	</display>
	<pattern low="0" high="25">00000000000000000000000000</pattern>
	<pattern low="27" high="31">00000</pattern>
</bitset>

<!-- a6xx changed the default nop pattern and all 0's is now illegal -->
<bitset name="nop" extends="#instruction-rep">
	<gen min="6"/>
	<display>
		{REP}nop
	</display>
	<pattern low="0" high="25">01000000000000000000000000</pattern>
	<pattern low="27" high="31">00000</pattern>
</bitset>

<bitset name="#jump-a7xx" extends="#instruction">
	<gen min="7"/>
	<pattern low="26" high="31">110111</pattern>
</bitset>

<bitset name="jumpr" extends="#jump-a7xx">
	<doc>
                Indirect jump instruction. Jump to the given offset.
                Used as a return instruction together with bl:

			bl #fxn
			...

			fxn:
			...
			jump $lr
			nop

		However this is only used by hand-crafted assembly
		routines that make sure to never use any stack space. Otherwise
		sret is used.
	</doc>

	<display>
		jump {SRC1}
	</display>

	<pattern low="20" high="25">110111</pattern>
	<pattern low="5" high="19">000000000000000</pattern>
	<field name="SRC1" low="0" high="4" type="#src"/>
</bitset>

<bitset name="sret" extends="#jump-a7xx">
	<doc>
		Seems to be equivalent to "jump $lr". This seems to be used by
		the compiled code, and is always immediately followed by a
		"sub $sp, $sp, imm" instruction to restore the stack frame. It's
		therefore possible this also includes a stack overflow check.
	</doc>

	<display>
		sret
	</display>

	<pattern low="20" high="25">110110</pattern>
	<pattern low="0" high="19">00000000000000000000</pattern>
</bitset>

</isa>
