whatcanGOwrong

This commit is contained in:
2024-09-19 21:38:24 -04:00
commit d0ae4d841d
17908 changed files with 4096831 additions and 0 deletions
@@ -0,0 +1,458 @@
# arm instruction description version 0.01.
# https://golang.org/x/arch/arm
#
# This file contains a block of comment lines, each beginning with #,
# followed by entries in CSV format. All the # comments are at the top
# of the file, so a reader can skip past the comments and hand the
# rest of the file to a standard CSV reader.
#
# Each line in the CSV section contains 5 fields:
#
# mask value mnemonic encoding tags
#
# The mnemonic and encoding correspond to the notation used in the
# ARM Architecture Reference Manual.
#
# A particular instruction word w matches a line if w&mask == value.
# The mask and value are computed from a combination of the encodings
# and the additional pseudocode restrictions given in the manual
# for each instruction.
#
# Multiple lines may match a particular instruction word.
# The tags specify which line takes priority in these cases,
# as a partial order. Eventually the plan is that a tag of the form
# 'name:x' marks a line with the name x, and a tag of the form
# 'except:x' says that the line on which the tag appears is of lower
# priority than the ones marked with name x.
# For now, however, a tag of the form 'SEE XXX' is taken from the
# manual and is like 'except:x' but without a rigorous resolution for
# the x. So far we've been able to just sort instructions into two classes:
# those with SEE and those without.
#
# The tag 'pseudo' indicates that this instruction is an alternate name
# for another encoding and should be ignored during disassembly.
#
# This file was generated by a program reading the PDF version of
# the manual, but it was then hand edited to make corrections.
# The eventual plan is for the generator to write the
# file directly, using the PDF and a list of modifications, but
# no hand editing. Then, when a new version of the manual comes out,
# updating the list should be as easy as downloading the new PDF
# and invoking the generator. However, we are not there yet.
#
"0x0fe00000","0x02a00000","ADC{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|1|0|1|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00a00010","ADC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00a00000","ADC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fe00000","0x02800000","ADD{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|1|0|0|S|Rn:4|Rd:4|imm12:12","SEE ADR SEE ADD (SP plus immediate) SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00800010","ADD{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00800000","ADD{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions SEE ADD (SP plus register)"
"0x0fef0000","0x028d0000","ADD{S}<c> <Rd>,SP,#<const>","cond:4|0|0|1|0|1|0|0|S|1|1|0|1|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fef0010","0x008d0000","ADD{S}<c> <Rd>,SP,<Rm>{,<shift>}","cond:4|0|0|0|0|1|0|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fff0000","0x028f0000","ADR<c> <Rd>,<label+12>","cond:4|0|0|1|0|1|0|0|0|1|1|1|1|Rd:4|imm12:12","pseudo"
"0x0fff0000","0x024f0000","ADR<c> <Rd>,<label-12>","cond:4|0|0|1|0|0|1|0|0|1|1|1|1|Rd:4|imm12:12","pseudo"
"0x0fe00000","0x02000000","AND{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|0|0|0|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00000010","AND{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00000000","AND{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fef0070","0x01a00040","ASR{S}<c> <Rd>,<Rm>,#<imm5_32>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|0|0|Rm:4",""
"0x0fef00f0","0x01a00050","ASR{S}<c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|0|1|Rn:4",""
"0x0f000000","0x0a000000","B<c> <label24>","cond:4|1|0|1|0|imm24:24",""
"0x0fe0007f","0x07c0001f","BFC<c> <Rd>,#<lsb>,#<width>","cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|1|1|1|1",""
"0x0fe00070","0x07c00010","BFI<c> <Rd>,<Rn>,#<lsb>,#<width>","cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|Rn:4","SEE BFC"
"0x0fe00000","0x03c00000","BIC{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|1|1|1|0|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x01c00010","BIC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x01c00000","BIC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0ff000f0","0x01200070","BKPT<c> #<imm12+4>","cond:4|0|0|0|1|0|0|1|0|imm12:12|0|1|1|1|imm4:4",""
"0x0f000000","0x0b000000","BL<c> <label24>","cond:4|1|0|1|1|imm24:24",""
"0xfe000000","0xfa000000","BLX <label24H>","1|1|1|1|1|0|1|H|imm24:24",""
"0x0ffffff0","0x012fff30","BLX<c> <Rm>","cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0ffffff0","0x012fff10","BX<c> <Rm>","cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ffffff0","0x012fff20","BXJ<c> <Rm>","cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4",""
"0xffffffff","0xf57ff01f","CLREX","1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1)",""
"0x0fff0ff0","0x016f0f10","CLZ<c> <Rd>,<Rm>","cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff0f000","0x03700000","CMN<c> <Rn>,#<const>","cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12",""
"0x0ff0f090","0x01700010","CMN<c> <Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4",""
"0x0ff0f010","0x01700000","CMN<c> <Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4",""
"0x0ff0f000","0x03500000","CMP<c> <Rn>,#<const>","cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12",""
"0x0ff0f090","0x01500010","CMP<c> <Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4",""
"0x0ff0f010","0x01500000","CMP<c> <Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4",""
"0x0ffffff0","0x0320f0f0","DBG<c> #<option>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|1|1|1|1|option:4",""
"0xfffffff0","0xf57ff050","DMB #<option>","1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|1|option:4",""
"0xfffffff0","0xf57ff040","DSB #<option>","1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|0|option:4",""
"0x0fe00000","0x02200000","EOR{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|0|0|1|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00200010","EOR{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|0|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00200000","EOR{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|0|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0xfffffff0","0xf57ff060","ISB #<option>","1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|1|0|option:4",""
"0x0fd00000","0x08900000","LDM<c> <Rn>{!},<registers>","cond:4|1|0|0|0|1|0|W|1|Rn:4|register_list:16","SEE POP"
"0x0fd00000","0x08100000","LDMDA<c> <Rn>{!},<registers>","cond:4|1|0|0|0|0|0|W|1|Rn:4|register_list:16",""
"0x0fd00000","0x09100000","LDMDB<c> <Rn>{!},<registers>","cond:4|1|0|0|1|0|0|W|1|Rn:4|register_list:16",""
"0x0fd00000","0x09900000","LDMIB<c> <Rn>{!},<registers>","cond:4|1|0|0|1|1|0|W|1|Rn:4|register_list:16",""
"0x0f7f0000","0x051f0000","LDR<c> <Rt>,<label+/-12>","cond:4|0|1|0|(1)|U|0|(0)|1|1|1|1|1|Rt:4|imm12:12",""
"0x0e500010","0x06100000","LDR<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!}","cond:4|0|1|1|P|U|0|W|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4","SEE LDRT"
"0x0e500000","0x04100000","LDR<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!}","cond:4|0|1|0|P|U|0|W|1|Rn:4|Rt:4|imm12:12","SEE LDR (literal) SEE LDRT SEE POP"
"0x0f7f0000","0x055f0000","LDRB<c> <Rt>,<label+/-12>","cond:4|0|1|0|(1)|U|1|(0)|1|1|1|1|1|Rt:4|imm12:12",""
"0x0e500010","0x06500000","LDRB<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!}","cond:4|0|1|1|P|U|1|W|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4","SEE LDRBT"
"0x0e500000","0x04500000","LDRB<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!}","cond:4|0|1|0|P|U|1|W|1|Rn:4|Rt:4|imm12:12","SEE LDRB (literal) SEE LDRBT"
"0x0f700000","0x04700000","LDRBT<c> <Rt>,[<Rn>],#+/-<imm12>","cond:4|0|1|0|0|U|1|1|1|Rn:4|Rt:4|imm12:12",""
"0x0f700010","0x06700000","LDRBT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>}","cond:4|0|1|1|0|U|1|1|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4",""
"0x0f7f10f0","0x014f00d0","LDRD<c> <Rt1>,<Rt2>,<label+/-4+4>","cond:4|0|0|0|(1)|U|1|(0)|0|1|1|1|1|Rt:4|imm4H:4|1|1|0|1|imm4L:4","pseudo"
"0x0e500ff0","0x000000d0","LDRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|0|1|Rm:4",""
"0x0e5000f0","0x004000d0","LDRD<c> <Rt1>,<Rt2>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4","SEE LDRD (literal)"
"0x0ff00fff","0x01900f9f","LDREX<c> <Rt>,[<Rn>]","cond:4|0|0|0|1|1|0|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)",""
"0x0ff00fff","0x01d00f9f","LDREXB<c> <Rt>, [<Rn>]","cond:4|0|0|0|1|1|1|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)",""
"0x0ff00fff","0x01b00f9f","LDREXD<c> <Rt1>,<Rt2>,[<Rn>]","cond:4|0|0|0|1|1|0|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)",""
"0x0ff00fff","0x01f00f9f","LDREXH<c> <Rt>, [<Rn>]","cond:4|0|0|0|1|1|1|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)",""
"0x0f7f00f0","0x015f00b0","LDRH<c> <Rt>,<label+/-4+4>","cond:4|0|0|0|1|U|1|0|1|1|1|1|1|Rt:4|imm4H:4|1|0|1|1|imm4L:4","pseudo"
"0x0e500ff0","0x001000b0","LDRH<c> <Rt>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4","SEE LDRHT"
"0x0e5000f0","0x005000b0","LDRH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4","SEE LDRH literal SEE LDRHT"
"0x0f7000f0","0x007000b0","LDRHT<c> <Rt>, [<Rn>] {,#+/-<imm8>}","cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4",""
"0x0f700ff0","0x003000b0","LDRHT<c> <Rt>, [<Rn>], +/-<Rm>","cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4",""
"0x0f7f00f0","0x015f00d0","LDRSB<c> <Rt>,<label+/-4+4>","cond:4|0|0|0|1|U|1|0|1|1|1|1|1|Rt:4|imm4H:4|1|1|0|1|imm4L:4","pseudo"
"0x0e500ff0","0x001000d0","LDRSB<c> <Rt>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|1|0|1|Rm:4","SEE LDRSBT"
"0x0e5000f0","0x005000d0","LDRSB<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4","SEE LDRSB literal SEE LDRSBT"
"0x0f7000f0","0x007000d0","LDRSBT<c> <Rt>, [<Rn>] {,#+/-<imm8>}","cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4",""
"0x0f700ff0","0x003000d0","LDRSBT<c> <Rt>, [<Rn>], +/-<Rm>","cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|1|0|1|Rm:4",""
"0x0f7f00f0","0x015f00f0","LDRSH<c> <Rt>,<label+/-4+4>","cond:4|0|0|0|1|U|1|0|1|1|1|1|1|Rt:4|imm4H:4|1|1|1|1|imm4L:4","pseudo"
"0x0e500ff0","0x001000f0","LDRSH<c> <Rt>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|1|1|1|Rm:4","SEE LDRSHT"
"0x0e5000f0","0x005000f0","LDRSH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4","SEE LDRSH literal SEE LDRSHT"
"0x0f7000f0","0x007000f0","LDRSHT<c> <Rt>, [<Rn>] {,#+/-<imm8>}","cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4",""
"0x0f700ff0","0x003000f0","LDRSHT<c> <Rt>, [<Rn>], +/-<Rm>","cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|1|1|1|Rm:4",""
"0x0f700000","0x04300000","LDRT<c> <Rt>, [<Rn>] {,#+/-<imm12>}","cond:4|0|1|0|0|U|0|1|1|Rn:4|Rt:4|imm12:12",""
"0x0f700010","0x06300000","LDRT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>}","cond:4|0|1|1|0|U|0|1|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4",""
"0x0fef0070","0x01a00000","LSL{S}<c> <Rd>,<Rm>,#<imm5_nz>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|0|0|0|Rm:4","SEE MOV register"
"0x0fef00f0","0x01a00010","LSL{S}<c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|0|0|1|Rn:4",""
"0x0fef0070","0x01a00020","LSR{S}<c> <Rd>,<Rm>,#<imm5_32>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|0|1|0|Rm:4",""
"0x0fef00f0","0x01a00030","LSR{S}<c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|0|1|1|Rn:4",""
"0x0fe000f0","0x00200090","MLA{S}<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|0|0|0|0|0|1|S|Rd:4|Ra:4|Rm:4|1|0|0|1|Rn:4",""
"0x0ff000f0","0x00600090","MLS<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|0|0|0|0|1|1|0|Rd:4|Ra:4|Rm:4|1|0|0|1|Rn:4",""
"0x0ff00000","0x03400000","MOVT<c> <Rd>,#<imm12+4>","cond:4|0|0|1|1|0|1|0|0|imm4:4|Rd:4|imm12:12",""
"0x0ff00000","0x03000000","MOVW<c> <Rd>,#<imm12+4>","cond:4|0|0|1|1|0|0|0|0|imm4:4|Rd:4|imm12:12",""
"0x0fef0000","0x03a00000","MOV{S}<c> <Rd>,#<const>","cond:4|0|0|1|1|1|0|1|S|0|0|0|0|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fef0ff0","0x01a00000","MOV{S}<c> <Rd>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|0|0|0|0|0|0|0|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fff0fff","0x010f0000","MRS<c> <Rd>,APSR","cond:4|0|0|0|1|0|0|0|0|(1)|(1)|(1)|(1)|Rd:4|(0)|(0)|(0)|(0)|0|0|0|0|(0)|(0)|(0)|(0)",""
"0x0ffffff0","0x012cf000","MSR<c> APSR,<Rn>","cond:4|0|0|0|1|0|0|1|0|1|1|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|Rn:4",""
"0x0ffff000","0x032cf000","MSR<c> APSR,#<const>","cond:4|0|0|1|1|0|0|1|0|1|1|0|0|(1)|(1)|(1)|(1)|imm12:12",""
"0x0fe0f0f0","0x00000090","MUL{S}<c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|0|0|0|0|S|Rd:4|(0)|(0)|(0)|(0)|Rm:4|1|0|0|1|Rn:4",""
"0x0fef0000","0x03e00000","MVN{S}<c> <Rd>,#<const>","cond:4|0|0|1|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fef0090","0x01e00010","MVN{S}<c> <Rd>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fef0010","0x01e00000","MVN{S}<c> <Rd>,<Rm>{,<shift>}","cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fffffff","0x0320f000","NOP<c>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|0",""
"0x0fe00000","0x03800000","ORR{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|1|1|0|0|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x01800010","ORR{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x01800000","ORR{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0ff00030","0x06800010","PKH<BT,TB><c> <Rd>,<Rn>,<Rm>{,LSL #<imm5>}","cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|imm5:5|tb|0|1|Rm:4",""
"0xff7ff000","0xf55ff000","PLD <label+/-12>","1|1|1|1|0|1|0|1|U|(1)|0|1|1|1|1|1|(1)|(1)|(1)|(1)|imm12:12",""
"0xff30f000","0xf510f000","PLD{W} [<Rn>,#+/-<imm12>]","1|1|1|1|0|1|0|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12","SEE PLD (literal)"
"0xff30f010","0xf710f000","PLD{W} [<Rn>,+/-<Rm>{, <shift>}]","1|1|1|1|0|1|1|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4",""
"0xff70f000","0xf450f000","PLI [<Rn>,#+/-<imm12>]","1|1|1|1|0|1|0|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12",""
"0xff70f010","0xf650f000","PLI [<Rn>,+/-<Rm>{, <shift>}]","1|1|1|1|0|1|1|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4",""
"0x0fff0000","0x08bd0000","POP<c> <registers2>","cond:4|1|0|0|0|1|0|1|1|1|1|0|1|register_list:16",""
"0x0fff0fff","0x049d0004","POP<c> <registers1>","cond:4|0|1|0|0|1|0|0|1|1|1|0|1|Rt:4|0|0|0|0|0|0|0|0|0|1|0|0",""
"0x0fff0000","0x092d0000","PUSH<c> <registers2>","cond:4|1|0|0|1|0|0|1|0|1|1|0|1|register_list:16",""
"0x0fff0fff","0x052d0004","PUSH<c> <registers1>","cond:4|0|1|0|1|0|0|1|0|1|1|0|1|Rt:4|0|0|0|0|0|0|0|0|0|1|0|0",""
"0x0ff00ff0","0x06200f10","QADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06200f90","QADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x01000050","QADD<c> <Rd>,<Rm>,<Rn>","cond:4|0|0|0|1|0|0|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06200f30","QASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0ff00ff0","0x01400050","QDADD<c> <Rd>,<Rm>,<Rn>","cond:4|0|0|0|1|0|1|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x01600050","QDSUB<c> <Rd>,<Rm>,<Rn>","cond:4|0|0|0|1|0|1|1|0|Rn:4|Rd:4|0|0|0|0|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06200f50","QSAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06200f70","QSUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06200ff0","QSUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0ff00ff0","0x01200050","QSUB<c> <Rd>,<Rm>,<Rn>","cond:4|0|0|0|1|0|0|1|0|Rn:4|Rd:4|0|0|0|0|0|1|0|1|Rm:4",""
"0x0fff0ff0","0x06ff0f30","RBIT<c> <Rd>,<Rm>","cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0fff0ff0","0x06bf0fb0","REV16<c> <Rd>,<Rm>","cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4",""
"0x0fff0ff0","0x06bf0f30","REV<c> <Rd>,<Rm>","cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0fff0ff0","0x06ff0fb0","REVSH<c> <Rd>,<Rm>","cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4",""
"0x0fef0070","0x01a00060","ROR{S}<c> <Rd>,<Rm>,#<imm5>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|1|0|Rm:4","SEE RRX"
"0x0fef00f0","0x01a00070","ROR{S}<c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|1|1|Rn:4",""
"0x0fef0ff0","0x01a00060","RRX{S}<c> <Rd>,<Rm>","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|0|0|0|0|0|1|1|0|Rm:4",""
"0x0fe00000","0x02600000","RSB{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|0|1|1|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00600010","RSB{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|0|1|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00600000","RSB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|0|1|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fe00000","0x02e00000","RSC{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|1|1|1|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00e00010","RSC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|1|1|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00e00000","RSC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|1|1|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0ff00ff0","0x06100f10","SADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06100f90","SADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x06100f30","SASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0fe00000","0x02c00000","SBC{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|1|1|0|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00c00010","SBC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00c00000","SBC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0fe00070","0x07a00050","SBFX<c> <Rd>,<Rn>,#<lsb>,#<widthm1>","cond:4|0|1|1|1|1|0|1|widthm1:5|Rd:4|lsb:5|1|0|1|Rn:4",""
"0x0ff0f0f0","0x0710f010","SDIV<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|1|0|0|0|1|Rd:4|(1)|(1)|(1)|(1)|Rm:4|0|0|0|1|Rn:4",""
"0x0ff00ff0","0x06800fb0","SEL<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4",""
"0xfffffdff","0xf1010000","SETEND <endian_specifier>","1|1|1|1|0|0|0|1|0|0|0|0|0|0|0|1|0|0|0|0|0|0|E|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)",""
"0x0fffffff","0x0320f004","SEV<c>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|1|0|0",""
"0x0ff00ff0","0x06300f10","SHADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06300f90","SHADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x06300f30","SHASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0ff00ff0","0x06300f50","SHSAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06300f70","SHSUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06300ff0","SHSUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0ff00090","0x01000080","SMLA<x><y><c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|0|0|1|0|0|0|0|Rd:4|Ra:4|Rm:4|1|M|N|0|Rn:4",""
"0x0ff000d0","0x07000010","SMLAD{X}<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|1|1|1|0|0|0|0|Rd:4|Ra:4|Rm:4|0|0|M|1|Rn:4","SEE SMUAD"
"0x0ff00090","0x01400080","SMLAL<x><y><c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|1|M|N|0|Rn:4",""
"0x0ff000d0","0x07400010","SMLALD{X}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|1|1|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|0|0|M|1|Rn:4",""
"0x0fe000f0","0x00e00090","SMLAL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|0|1|1|1|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4",""
"0x0ff000b0","0x01200080","SMLAW<y><c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|0|0|1|0|0|1|0|Rd:4|Ra:4|Rm:4|1|M|0|0|Rn:4",""
"0x0ff000d0","0x07000050","SMLSD{X}<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|1|1|1|0|0|0|0|Rd:4|Ra:4|Rm:4|0|1|M|1|Rn:4","SEE SMUSD"
"0x0ff000d0","0x07400050","SMLSLD{X}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|1|1|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|0|1|M|1|Rn:4",""
"0x0ff000d0","0x07500010","SMMLA{R}<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|1|1|1|0|1|0|1|Rd:4|Ra:4|Rm:4|0|0|R|1|Rn:4","SEE SMMUL"
"0x0ff000d0","0x075000d0","SMMLS{R}<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|1|1|1|0|1|0|1|Rd:4|Ra:4|Rm:4|1|1|R|1|Rn:4",""
"0x0ff0f0d0","0x0750f010","SMMUL{R}<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|1|0|1|0|1|Rd:4|1|1|1|1|Rm:4|0|0|R|1|Rn:4",""
"0x0ff0f0d0","0x0700f010","SMUAD{X}<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|1|0|0|0|0|Rd:4|1|1|1|1|Rm:4|0|0|M|1|Rn:4",""
"0x0ff0f090","0x01600080","SMUL<x><y><c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|0|1|1|0|Rd:4|0|0|0|0|Rm:4|1|M|N|0|Rn:4",""
"0x0fe000f0","0x00c00090","SMULL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|0|1|1|0|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4",""
"0x0ff0f0b0","0x012000a0","SMULW<y><c> <Rd>,<Rn>,<Rm>","cond:4|0|0|0|1|0|0|1|0|Rd:4|0|0|0|0|Rm:4|1|M|1|0|Rn:4",""
"0x0ff0f0d0","0x0700f050","SMUSD{X}<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|1|0|0|0|0|Rd:4|1|1|1|1|Rm:4|0|1|M|1|Rn:4",""
"0x0ff00ff0","0x06a00f30","SSAT16<c> <Rd>,#<sat_imm4m1>,<Rn>","cond:4|0|1|1|0|1|0|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4",""
"0x0fe00030","0x06a00010","SSAT<c> <Rd>,#<sat_imm5m1>,<Rn>{,<shift>}","cond:4|0|1|1|0|1|0|1|sat_imm:5|Rd:4|imm5:5|sh|0|1|Rn:4",""
"0x0ff00ff0","0x06100f50","SSAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06100f70","SSUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06100ff0","SSUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0fd00000","0x08800000","STM<c> <Rn>{!},<registers>","cond:4|1|0|0|0|1|0|W|0|Rn:4|register_list:16",""
"0x0fd00000","0x08000000","STMDA<c> <Rn>{!},<registers>","cond:4|1|0|0|0|0|0|W|0|Rn:4|register_list:16",""
"0x0fd00000","0x09000000","STMDB<c> <Rn>{!},<registers>","cond:4|1|0|0|1|0|0|W|0|Rn:4|register_list:16","SEE PUSH"
"0x0fd00000","0x09800000","STMIB<c> <Rn>{!},<registers>","cond:4|1|0|0|1|1|0|W|0|Rn:4|register_list:16",""
"0x0e500018","0x06000000","STR<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!}","cond:4|0|1|1|P|U|0|W|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4","SEE STRT"
"0x0e500000","0x04000000","STR<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!}","cond:4|0|1|0|P|U|0|W|0|Rn:4|Rt:4|imm12:12","SEE STRT SEE PUSH"
"0x0e500010","0x06400000","STRB<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!}","cond:4|0|1|1|P|U|1|W|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4","SEE STRBT"
"0x0e500000","0x04400000","STRB<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!}","cond:4|0|1|0|P|U|1|W|0|Rn:4|Rt:4|imm12:12","SEE STRBT"
"0x0f700000","0x04600000","STRBT<c> <Rt>,[<Rn>],#+/-<imm12>","cond:4|0|1|0|0|U|1|1|0|Rn:4|Rt:4|imm12:12",""
"0x0f700010","0x06600000","STRBT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>}","cond:4|0|1|1|0|U|1|1|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4",""
"0x0e500ff0","0x000000f0","STRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|1|1|Rm:4",""
"0x0e5000f0","0x004000f0","STRD<c> <Rt1>,<Rt2>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4",""
"0x0ff00ff0","0x01800f90","STREX<c> <Rd>,<Rt>,[<Rn>]","cond:4|0|0|0|1|1|0|0|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4",""
"0x0ff00ff0","0x01c00f90","STREXB<c> <Rd>,<Rt>,[<Rn>]","cond:4|0|0|0|1|1|1|0|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4",""
"0x0ff00ff0","0x01a00f90","STREXD<c> <Rd>,<Rt1>,<Rt2>,[<Rn>]","cond:4|0|0|0|1|1|0|1|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4",""
"0x0ff00ff0","0x01e00f90","STREXH<c> <Rd>,<Rt>,[<Rn>]","cond:4|0|0|0|1|1|1|1|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4",""
"0x0e500ff0","0x000000b0","STRH<c> <Rt>,[<Rn>,+/-<Rm>]{!}","cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4","SEE STRHT"
"0x0e5000f0","0x004000b0","STRH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!}","cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4","SEE STRHT"
"0x0f7000f0","0x006000b0","STRHT<c> <Rt>, [<Rn>] {,#+/-<imm8>}","cond:4|0|0|0|0|U|1|1|0|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4",""
"0x0f700ff0","0x002000b0","STRHT<c> <Rt>, [<Rn>], +/-<Rm>","cond:4|0|0|0|0|U|0|1|0|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4",""
"0x0f700000","0x04200000","STRT<c> <Rt>, [<Rn>] {,#+/-<imm12>}","cond:4|0|1|0|0|U|0|1|0|Rn:4|Rt:4|imm12:12",""
"0x0f700010","0x06200000","STRT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>}","cond:4|0|1|1|0|U|0|1|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4",""
"0x0fe00000","0x02400000","SUB{S}<c> <Rd>,<Rn>,#<const>","cond:4|0|0|1|0|0|1|0|S|Rn:4|Rd:4|imm12:12","SEE ADR SEE SUB (SP minus immediate) SEE SUBS PC, LR and related instructions"
"0x0fe00090","0x00400010","SUB{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|0|0|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4",""
"0x0fe00010","0x00400000","SUB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>}","cond:4|0|0|0|0|0|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions SEE SUB (SP minus register)"
"0x0fef0000","0x024d0000","SUB{S}<c> <Rd>,SP,#<const>","cond:4|0|0|1|0|0|1|0|S|1|1|0|1|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions"
"0x0fef0010","0x004d0000","SUB{S}<c> <Rd>,SP,<Rm>{,<shift>}","cond:4|0|0|0|0|0|1|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions"
"0x0f000000","0x0f000000","SVC<c> #<imm24>","cond:4|1|1|1|1|imm24:24",""
"0x0fb00ff0","0x01000090","SWP{B}<c> <Rt>,<Rm>,[<Rn>]","cond:4|0|0|0|1|0|B|0|0|Rn:4|Rt:4|0|0|0|0|1|0|0|1|Rm:4",""
"0x0ff003f0","0x06800070","SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE SXTB16"
"0x0ff003f0","0x06a00070","SXTAB<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|1|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE SXTB"
"0x0ff003f0","0x06b00070","SXTAH<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|1|1|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE SXTH"
"0x0fff03f0","0x068f0070","SXTB16<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|0|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0x0fff03f0","0x06af0070","SXTB<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|1|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0x0fff03f0","0x06bf0070","SXTH<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|0|1|1|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0x0ff0f000","0x03300000","TEQ<c> <Rn>,#<const>","cond:4|0|0|1|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12",""
"0x0ff0f090","0x01300010","TEQ<c> <Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4",""
"0x0ff0f010","0x01300000","TEQ<c> <Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4",""
"0x0ff0f000","0x03100000","TST<c> <Rn>,#<const>","cond:4|0|0|1|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12",""
"0x0ff0f090","0x01100010","TST<c> <Rn>,<Rm>,<type> <Rs>","cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4",""
"0x0ff0f010","0x01100000","TST<c> <Rn>,<Rm>{,<shift>}","cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4",""
"0x0ff00ff0","0x06500f10","UADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06500f90","UADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x06500f30","UASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0fe00070","0x07e00050","UBFX<c> <Rd>,<Rn>,#<lsb>,#<widthm1>","cond:4|0|1|1|1|1|1|1|widthm1:5|Rd:4|lsb:5|1|0|1|Rn:4",""
"0x0ff0f0f0","0x0730f010","UDIV<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|1|0|0|1|1|Rd:4|(1)|(1)|(1)|(1)|Rm:4|0|0|0|1|Rn:4",""
"0x0ff00ff0","0x06700f10","UHADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06700f90","UHADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x06700f30","UHASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0ff00ff0","0x06700f50","UHSAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06700f70","UHSUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06700ff0","UHSUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0ff000f0","0x00400090","UMAAL<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|0|0|1|0|0|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4",""
"0x0fe000f0","0x00a00090","UMLAL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|0|1|0|1|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4",""
"0x0fe000f0","0x00800090","UMULL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm>","cond:4|0|0|0|0|1|0|0|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4",""
"0x0ff00ff0","0x06600f10","UQADD16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4",""
"0x0ff00ff0","0x06600f90","UQADD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4",""
"0x0ff00ff0","0x06600f30","UQASX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4",""
"0x0ff00ff0","0x06600f50","UQSAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06600f70","UQSUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06600ff0","UQSUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0ff0f0f0","0x0780f010","USAD8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|1|1|0|0|0|Rd:4|1|1|1|1|Rm:4|0|0|0|1|Rn:4",""
"0x0ff000f0","0x07800010","USADA8<c> <Rd>,<Rn>,<Rm>,<Ra>","cond:4|0|1|1|1|1|0|0|0|Rd:4|Ra:4|Rm:4|0|0|0|1|Rn:4","SEE USAD8"
"0x0ff00ff0","0x06e00f30","USAT16<c> <Rd>,#<sat_imm4>,<Rn>","cond:4|0|1|1|0|1|1|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4",""
"0x0fe00030","0x06e00010","USAT<c> <Rd>,#<sat_imm5>,<Rn>{,<shift>}","cond:4|0|1|1|0|1|1|1|sat_imm:5|Rd:4|imm5:5|sh|0|1|Rn:4",""
"0x0ff00ff0","0x06500f50","USAX<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4",""
"0x0ff00ff0","0x06500f70","USUB16<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4",""
"0x0ff00ff0","0x06500ff0","USUB8<c> <Rd>,<Rn>,<Rm>","cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4",""
"0x0ff003f0","0x06c00070","UXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|0|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE UXTB16"
"0x0ff003f0","0x06e00070","UXTAB<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|1|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE UXTB"
"0x0ff003f0","0x06f00070","UXTAH<c> <Rd>,<Rn>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|1|1|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4","SEE UXTH"
"0x0fff03f0","0x06cf0070","UXTB16<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|0|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0x0fff03f0","0x06ef0070","UXTB<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|1|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0x0fff03f0","0x06ff0070","UXTH<c> <Rd>,<Rm>{,<rotation>}","cond:4|0|1|1|0|1|1|1|1|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4",""
"0xff800f10","0xf3000110","V<BIF,BIT,BSL> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|op:2|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4","SEE VEOR"
"0xffb00c10","0xf3b00800","V<TBL,TBX>.8 <Dd>, <list_len>, <Dm>","1|1|1|1|0|0|1|1|1|D|1|1|Vn:4|Vd:4|1|0|len:2|N|op|M|0|Vm:4",""
"0xfe800a50","0xf2800040","V<MLA,MLS>.<dt> <Qd>, <Qn>, <Dm[x]>","1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|0|op|0|F|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xfe800f00","0xf2000600","V<MAX,MIN>.<dt> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|1|0|N|Q|M|op|Vm:4",""
"0xfe800f10","0xf2000900","V<MLA,MLS>.<dt> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|op|0|D|size:2|Vn:4|Vd:4|1|0|0|1|N|Q|M|0|Vm:4",""
"0xff800f10","0xf2000d10","V<MLA,MLS>.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|op|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|1|Vm:4",""
"0xff800f10","0xf2000f00","V<MAX,MIN>.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|op|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|0|Vm:4",""
"0xff800f10","0xf3000e10","VAC<GE,GT>.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|op|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|1|Vm:4",""
"0x0fb00e10","0x0e000a00","V<MLA,MLS><c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|0|0|Vn:4|Vd:4|1|0|1|sz|N|op|M|0|Vm:4","vfp"
"0xfe801d50","0xf2800800","V<MLA,MLS>L.<dt> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|1|0|op|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xfe801b50","0xf2800240","V<MLA,MLS>L.<dt> <Qd>, <Dn>, <Dm[x]>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|op|1|0|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xfe800f10","0xf2000710","VABA.<dt_Usize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|1|1|N|Q|M|1|Vm:4",""
"0xfe801f50","0xf2800500","VABAL.<dt_Usize> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|1|0|1|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xfe800f10","0xf2000700","VABD.<dt_Usize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|1|1|N|Q|M|0|Vm:4",""
"0xffa00f10","0xf3200d00","VABD.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|1|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4",""
"0xfe801f50","0xf2800700","VABDL.<dt_Usize> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|1|1|1|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xffb30b90","0xf3b10300","VABS.<dt_Fsize> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|1|1|0|Q|M|0|Vm:4",""
"0x0fbf0ed0","0x0eb00ac0","VABS<c>.F<32,64> <Sd,Dd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|0|0|0|Vd:4|1|0|1|sz|1|1|M|0|Vm:4","vfp"
"0xff800f10","0xf2000800","VADD.<dt_Isize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|0|Vm:4",""
"0xffa00f10","0xf2000d00","VADD.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|0|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4",""
"0x0fb00e50","0x0e300a00","VADD<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|1|1|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4","vfp"
"0xff810f51","0xf2800400","VADDHN.<dt_Isize> <Dd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|0|1|0|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xfe801e50","0xf2800000","VADDL.<dt_Usize> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|0|0|op|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xffb00f10","0xf2000110","VAND <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|0|0|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4",""
"0xffb00f10","0xf2100110","VBIC <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|0|1|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4",""
"0xfeb800b0","0xf2800030","VBIC.<dt_simd> <Qd>, #<imm_simd1>","1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|1|1|imm4:4","SEE “Related encodings”"
"0xffb30b90","0xf3b10100","VCEQ.<dt_Fsize> <Qd>, <Qm>, #0","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|1|0|Q|M|0|Vm:4",""
"0xff800f10","0xf3000810","VCEQ.<dt_Isize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|1|Vm:4",""
"0xffa00f10","0xf2000e00","VCEQ.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|0|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|0|Vm:4",""
"0xffb30b90","0xf3b10080","VCGE.<dt_Fsize> <Qd>, <Qm>, #0","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|0|1|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000310","VCGE.<dt_Isize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|1|1|N|Q|M|1|Vm:4",""
"0xffa00f10","0xf3000e00","VCGE.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|0|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|0|Vm:4",""
"0xffb30b90","0xf3b10000","VCGT.<dt_Fsize> <Qd>, <Qm>, #0","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|0|0|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000300","VCGT.<dt_Isize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|1|1|N|Q|M|0|Vm:4",""
"0xffa00f10","0xf3200e00","VCGT.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|1|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|0|Vm:4",""
"0xffb30b90","0xf3b10180","VCLE.<dt_Fsize> <Qd>, <Qm>, #0","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|1|1|Q|M|0|Vm:4",""
"0xffb30f90","0xf3b00400","VCLS.<dt_Isize> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|0|0|Q|M|0|Vm:4",""
"0xffb30b90","0xf3b10200","VCLT.<dt_Fsize> <Qd>, <Qm>, #0","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|1|0|0|Q|M|0|Vm:4",""
"0xffb30f90","0xf3b00480","VCLZ.<dt_Isize> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|0|1|Q|M|0|Vm:4",""
"0x0fbf0e7f","0x0eb50a40","VCMP{E}<c>.F<32,64> <Sd,Dd>, #0.0","cond:4|1|1|1|0|1|D|1|1|0|1|0|1|Vd:4|1|0|1|sz|E|1|0|0|(0)|(0)|(0)|(0)","vfp"
"0x0fbf0e50","0x0eb40a40","VCMP{E}<c>.F<32,64> <Sd,Dd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|1|0|0|Vd:4|1|0|1|sz|E|1|M|0|Vm:4","vfp"
"0xffbf0f90","0xf3b00500","VCNT.8 <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|1|0|Q|M|0|Vm:4",""
"0xffbf0e10","0xf3bb0600","VCVT.<Td>.<Tm_1> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|1|Vd:4|0|1|1|op:2|Q|M|0|Vm:4",""
"0xfea00e90","0xf2a00e10","VCVT.<Td>.<Tm_2> <Qd>, <Qm>, #<fbits>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|1|1|op|0|Q|M|1|Vm:4","SEE “Related encodings”"
"0x0fbe0e50","0x0eba0a40","VCVT<c>.F<32,64>.FX<S,U><16,32> <Sd,Dd>, <Sd,Dd>, #<fbits>","cond:4|1|1|1|0|1|D|1|1|1|0|1|U|Vd:4|1|0|1|sz|sx|1|i|0|imm4:4","vfp"
"0x0fbe0e50","0x0ebe0a40","VCVT<c>.FX<S,U><16,32>.F<32,64> <Sd,Dd>, <Sd,Dd>, #<fbits>","cond:4|1|1|1|0|1|D|1|1|1|1|1|U|Vd:4|1|0|1|sz|sx|1|i|0|imm4:4","vfp"
"0xffbf0ed0","0xf3b60600","VCVT.F32.F16 <Qd>, <Dm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|1|1|op|0|0|M|0|Vm:4",""
"0x0fbf0ed0","0x0eb70ac0","VCVT<c>.<F64.F32,F32.F64> <Dd,Sd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|1|1|1|Vd:4|1|0|1|sz|1|1|M|0|Vm:4","vfp"
"0x0fbe0f50","0x0eb20a40","VCVT<B,T><c>.<F32.F16,F16.F32> <Sd>, <Sm>","cond:4|1|1|1|0|1|D|1|1|0|0|1|op|Vd:4|1|0|1|0|T|1|M|0|Vm:4","vfp"
"0x0fbf0e50","0x0eb80a40","VCVT<c>.F<32,64>.<U,S>32 <Sd,Dd>, <Sm>","cond:4|1|1|1|0|1|D|1|1|1|0|0|0|Vd:4|1|0|1|sz|op|1|M|0|Vm:4","vfp"
"0x0fbe0e50","0x0ebc0a40","VCVT<R,><c>.<U,S>32.F<32,64> <Sd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|1|1|0|signed|Vd:4|1|0|1|sz|op|1|M|0|Vm:4","vfp"
"0x0fb00e50","0x0e800a00","VDIV<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|1|D|0|0|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4","vfp"
"0xffb00f90","0xf3b00c00","VDUP.<size_x> <Qd>, <Dm[size_x]>","1|1|1|1|0|0|1|1|1|D|1|1|imm4:4|Vd:4|1|1|0|0|0|Q|M|0|Vm:4",""
"0x0f900f5f","0x0e800b10","VDUP<c>.<size_be> <Qd>, <Rt>","cond:4|1|1|1|0|1|b|Q|0|Vd:4|Rt:4|1|0|1|1|D|0|e|1|(0)|(0)|(0)|(0)",""
"0xffb00f10","0xf3000110","VEOR <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|0|0|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4",""
"0xffb00010","0xf2b00000","VEXT.8 <Qd>, <Qn>, <Qm>, #<imm4>","1|1|1|1|0|0|1|0|1|D|1|1|Vn:4|Vd:4|imm4:4|N|Q|M|0|Vm:4",""
"0xfe800d10","0xf2000000","VH<ADD,SUB> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|op|0|N|Q|M|0|Vm:4",""
"0xffb00200","0xf4200200","VLD1.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00f00","0xf4a00c00","VLD1.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|0|0|size:2|T|a|Rm:4",""
"0xffb00300","0xf4a00000","VLD1.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|0|0|index_align:4|Rm:4","SEE VLD1 (single element to all lanes)"
"0xffb00400","0xf4200000","VLD2.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00f00","0xf4a00d00","VLD2.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|0|1|size:2|T|a|Rm:4",""
"0xffb00300","0xf4a00100","VLD2.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|0|1|index_align:4|Rm:4","SEE VLD2 (single 2-element structure to all lanes)"
"0xffb00f10","0xf4a00e00","VLD3.<size> <list3t>, [<Rn>]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|1|0|size:2|T|a|Rm:4",""
"0xffb00310","0xf4a00200","VLD3.<size> <list3>, [<Rn>]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|1|0|index_align:4|Rm:4","SEE VLD3 (single 3-element structure to all lanes)"
"0xffb00e20","0xf4200400","VLD3.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00f00","0xf4a00f00","VLD4.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|1|1|size:2|T|a|Rm:4",""
"0xffb00e00","0xf4200000","VLD4.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00300","0xf4a00300","VLD4.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|1|1|index_align:4|Rm:4","SEE VLD4 (single 4-element structure to all lanes)"
"0x0f300e00","0x0d100a00","VLDR<c> <Sd,Dd>, [<Rn>{,#+/-<imm8>}]","cond:4|1|1|0|1|U|D|0|1|Rn:4|Vd:4|1|0|1|sz|imm8:8","vfp"
"0x0fe00fd0","0x0c400b10","VMOV<c> <Dm>, <Rt>, <Rt2>","cond:4|1|1|0|0|0|1|0|op|Rt2:4|Rt:4|1|0|1|1|0|0|M|1|Vm:4",""
"0xffb00f10","0xf2200110","VMOV <Qd>, <Qm>","1|1|1|1|0|0|1|0|0|D|1|0|Vm:4|Vd:4|0|0|0|1|M|Q|M|1|Vm:4","SEE VORR (register)"
"0x0fe00fd0","0x0c400a10","VMOV<c> <Sm>, <Sm1>, <Rt>, <Rt2>","cond:4|1|1|0|0|0|1|0|op|Rt2:4|Rt:4|1|0|1|0|0|0|M|1|Vm:4",""
"0x0ff00f7f","0x0e000a10","VMOV<c> <Sn>, <Rt>","cond:4|1|1|1|0|0|0|0|0|Vn:4|Rt:4|1|0|1|0|N|0|0|1|0|0|0|0","vfp"
"0x0ff00f7f","0x0e100a10","VMOV<c> <Rt>, <Sn>","cond:4|1|1|1|0|0|0|0|1|Vn:4|Rt:4|1|0|1|0|N|0|0|1|0|0|0|0","vfp"
"0xfeb80090","0xf2800010","VMOV.<dt_simd> <Qd>, #<imm_simd>","1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|op|1|imm4:4","SEE VORR (immediate) SEE “Related encodings”"
"0x0fd00f7f","0x0e100b10","VMOV<c>.32 <Rt>, <Dn[x]>","cond:4|1|1|1|0|0|0|opc1|1|Vn:4|Rt:4|1|0|1|1|N|0|0|1|0|0|0|0","vfp"
"0x0fd00f7f","0x0e000b10","VMOV<c>.32 <Dd[x]>, <Rt>","cond:4|1|1|1|0|0|0|opc1|0|Vd:4|Rt:4|1|0|1|1|D|0|0|1|0|0|0|0","vfp"
"0x0fb00ef0","0x0eb00a00","VMOV<c>.F<32,64> <Sd,Dd>, #<imm_vfp>","cond:4|1|1|1|0|1|D|1|1|imm4H:4|Vd:4|1|0|1|sz|0|0|0|0|imm4L:4","vfp"
"0x0fbf0ed0","0x0eb00a40","VMOV<c>.F<32,64> <Sd,Dd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|0|0|0|Vd:4|1|0|1|sz|0|1|M|0|Vm:4","vfp"
"0xfe871fd0","0xf2800a10","VMOVL.<dt> <Qd>, <Dm>","1|1|1|1|0|0|1|U|1|D|imm3:3|0|0|0|Vd:4|1|0|1|0|0|0|M|1|Vm:4","SEE “Related encodings” SEE VSHLL"
"0xffb30fd1","0xf3b20200","VMOVN.<dt> <Dd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|1|0|0|0|M|0|Vm:4",""
"0x0fff0fff","0x0ef10a10","VMRS<c> <Rt_nzcv>, FPSCR","cond:4|1|1|1|0|1|1|1|1|0|0|0|1|Rt:4|1|0|1|0|0|0|0|1|0|0|0|0","vfp"
"0x0fff0fff","0x0ee10a10","VMSR<c> FPSCR, <Rt>","cond:4|1|1|1|0|1|1|1|0|0|0|0|1|Rt:4|1|0|1|0|0|0|0|1|0|0|0|0","vfp"
"0xfe800e50","0xf2800840","VMUL.<dt> <Qd>, <Qn>, <Dm[x]>","1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|1|0|0|F|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xfe800f10","0xf2000910","VMUL.<dt> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|op|0|D|size:2|Vn:4|Vd:4|1|0|0|1|N|Q|M|1|Vm:4",""
"0xffa00f10","0xf3000d10","VMUL.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|0|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|1|Vm:4",""
"0x0fb00e50","0x0e200a00","VMUL<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|1|0|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4","vfp"
"0xfe801d50","0xf2800c00","VMULL.<dt> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|1|1|op|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xfe801f50","0xf2800a40","VMULL.<dt> <Qd>, <Dn>, <Dm[x]>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|1|0|1|0|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xffbf0f90","0xf3b00580","VMVN <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|1|1|Q|M|0|Vm:4",""
"0xfeb800b0","0xf2800030","VMVN.<dt> <Qd>, #<imm3>","1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|1|1|imm4:4","SEE “Related encodings”"
"0xffb30b90","0xf3b10380","VNEG.<dt> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|1|1|1|Q|M|0|Vm:4",""
"0x0fbf0ed0","0x0eb10a40","VNEG<c>.F<32,64> <Sd,Dd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|0|0|1|Vd:4|1|0|1|sz|0|1|M|0|Vm:4","vfp"
"0x0fb00e10","0x0e100a00","VN<MLS,MLA><c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|0|1|Vn:4|Vd:4|1|0|1|sz|N|op|M|0|Vm:4","vfp"
"0x0fb00e50","0x0e200a40","VNMUL<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|1|0|Vn:4|Vd:4|1|0|1|sz|N|1|M|0|Vm:4","vfp"
"0xffb00f10","0xf2300110","VORN <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|1|1|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4",""
"0xffb00f10","0xf2200110","VORR <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|1|0|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4","SEE VMOV (register)"
"0xfeb800b0","0xf2800010","VORR.<dt> <Qd>, #<imm3>","1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|0|1|imm4:4","SEE VMOV (immediate)"
"0xfe800f00","0xf2000a00","VP<MIN,MAX>.<dt> <Dd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|1|0|1|0|N|Q|M|op|Vm:4",""
"0xff800f10","0xf3000f00","VP<MIN,MAX>.F32 <Dd>, <Dn>, <Dm>","1|1|1|1|0|0|1|1|0|D|op|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|0|Vm:4",""
"0xffb30f10","0xf3b00600","VPADAL.<dt> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|1|0|op|Q|M|0|Vm:4",""
"0xff800f10","0xf2000b10","VPADD.<dt> <Dd>, <Dn>, <Dm>","1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|1|1|N|Q|M|1|Vm:4",""
"0xffa00f10","0xf3000d00","VPADD.F32 <Dd>, <Dn>, <Dm>","1|1|1|1|0|0|1|1|0|D|0|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4",""
"0xffb30f10","0xf3b00200","VPADDL.<dt> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|0|1|0|op|Q|M|0|Vm:4",""
"0x0fbf0f00","0x0cbd0a00","VPOP <vlist32>","cond:4|1|1|0|0|1|D|1|1|1|1|0|1|Vd:4|1|0|1|0|imm8:8",""
"0x0fbf0f00","0x0cbd0b00","VPOP <vlist64>","cond:4|1|1|0|0|1|D|1|1|1|1|0|1|Vd:4|1|0|1|1|imm8:8",""
"0x0fbf0f00","0x0d2d0a00","VPUSH<c> <vlist32>","cond:4|1|1|0|1|0|D|1|0|1|1|0|1|Vd:4|1|0|1|0|imm8:8",""
"0x0fbf0f00","0x0d2d0b00","VPUSH<c> <vlist64>","cond:4|1|1|0|1|0|D|1|0|1|1|0|1|Vd:4|1|0|1|1|imm8:8",""
"0xffb30f90","0xf3b00700","VQABS.<dt> <Qd>,<Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|1|1|0|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000010","VQADD.<dt> <Qd>,<Qn>,<Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|0|0|N|Q|M|1|Vm:4",""
"0xff801d50","0xf2800900","VQD<MLAL,MLSL>.<dt> <Qd>,<Dn>,<Dm>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|1|0|op|1|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xff801b50","0xf2800340","VQD<MLAL,MLSL>.<dt> <Qd>,<Dn>,<Dm[x]>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|0|op|1|1|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xfe800f50","0xf2800c40","VQDMULH.<dt> <Qd>,<Qn>,<Dm[x]>","1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|1|1|0|0|N|1|M|0|Vm:4",""
"0xff800f10","0xf2000b00","VQDMULH.<dt> <Qd>,<Qn>,<Qm>","1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|1|1|N|Q|M|0|Vm:4",""
"0xff801f50","0xf2800d00","VQDMULL.<dt> <Qd>,<Dn>,<Dm>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|1|1|0|1|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xff801f50","0xf2800b40","VQDMULL.<dt> <Qd>,<Dn>,<Dm[x]>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|1|0|1|1|N|1|M|0|Vm:4","SEE “Related encodings”"
"0xffb30f11","0xf3b20200","VQMOV{U}N.<type><size> <Dd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|1|0|op:2|M|0|Vm:4","SEE VMOVN"
"0xffb30f90","0xf3b00780","VQNEG.<dt> <Qd>,<Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|1|1|1|Q|M|0|Vm:4",""
"0xfe800f50","0xf2800d40","VQRDMULH.<dt> <Qd>,<Qn>,<Dm[x]>","1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|1|1|0|1|N|1|M|0|Vm:4",""
"0xff800f10","0xf3000b00","VQRDMULH.<dt> <Qd>,<Qn>,<Qm>","1|1|1|1|0|0|1|1|0|D|size:2|Vn:4|Vd:4|1|0|1|1|N|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000510","VQRSHL.<type><size> <Qd>,<Qm>,<Qn>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|1|N|Q|M|1|Vm:4",""
"0xfe800ed1","0xf2800850","VQRSHR{U}N.<type><size> <Dd>,<Qm>,#<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|0|0|op|0|1|M|1|Vm:4","SEE “Related encodings” SEE VRSHRN"
"0xfe800f10","0xf2000410","VQSHL.<type><size> <Qd>,<Qm>,<Qn>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|0|N|Q|M|1|Vm:4",""
"0xfe800e90","0xf2800690","VQSHL{U}.<type><size> <Qd>,<Qm>,#<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|1|1|op|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xfe800ed1","0xf2800810","VQSHR{U}N.<type><size> <Dd>,<Qm>,#<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|0|0|op|0|0|M|1|Vm:4","SEE “Related encodings” SEE VSHRN"
"0xfe800f10","0xf2000210","VQSUB.<type><size> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|1|0|N|Q|M|1|Vm:4",""
"0xff810f51","0xf3800400","VRADDHN.<dt> <Dd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|1|D|size:2|Vn:4|Vd:4|0|1|0|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xffbf0e90","0xf3bb0400","VRECPE.<dt> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|1|Vd:4|0|1|0|F|0|Q|M|0|Vm:4",""
"0xffa00f10","0xf2000f10","VRECPS.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|0|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|1|Vm:4",""
"0xffb30e10","0xf3b00000","VREV<n>.<size> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|0|0|op:2|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000100","VRHADD <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|0|1|N|Q|M|0|Vm:4",""
"0xfe800f10","0xf2000500","VRSHL.<type><size> <Qd>, <Qm>, <Qn>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|1|N|Q|M|0|Vm:4",""
"0xfe800f90","0xf2800290","VRSHR.<type><size> <Qd>, <Qm>, #<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|1|0|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xff800fd1","0xf2800850","VRSHRN.I<size> <Dd>, <Qm>, #<imm6>","1|1|1|1|0|0|1|0|1|D|imm6:6|Vd:4|1|0|0|0|0|1|M|1|Vm:4","SEE “Related encodings”"
"0xffbf0e90","0xf3bb0480","VRSQRTE.<dt> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|1|Vd:4|0|1|0|F|1|Q|M|0|Vm:4",""
"0xffa00f10","0xf2200f10","VRSQRTS.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|1|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|1|Vm:4",""
"0xfe800f90","0xf2800390","VRSRA.<type><size> <Qd>, <Qm>, #<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|1|1|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xff810f51","0xf3800600","VRSUBHN.<dt> <Dd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|1|D|size:2|Vn:4|Vd:4|0|1|1|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xff800f90","0xf2800590","VSHL.I<size> <Qd>, <Qm>, #<imm6>","1|1|1|1|0|0|1|0|1|D|imm6:6|Vd:4|0|1|0|1|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xfe800f10","0xf2000400","VSHL.I<size> <Qd>, <Qm>, <Qn>","1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|0|N|Q|M|0|Vm:4",""
"0xffb31fd0","0xf3b20300","VSHLL.<type><size> <Qd>, <Dm>, #<immsize>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|1|1|0|0|M|0|Vm:4",""
"0xfe801fd0","0xf2800a10","VSHLL.<type><size> <Qd>, <Dm>, #<imm6>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|0|1|0|0|0|M|1|Vm:4","SEE “Related encodings” SEE VMOVL"
"0xfe800f90","0xf2800090","VSHR.<type><size_vs> <Qd>, <Qm>, #<imm_vs>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|0|0|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xff800fd1","0xf2800810","VSHRN.I<size_vsn> <Dd>, <Qm>, #<imm_vsn>","1|1|1|1|0|0|1|0|1|D|imm6:6|Vd:4|1|0|0|0|0|0|M|1|Vm:4","SEE “Related encodings”"
"0xff800f90","0xf3800590","VSLI.<size_vs> <Qd>, <Qm>, #<imm_vs>","1|1|1|1|0|0|1|1|1|D|imm6:6|Vd:4|0|1|0|1|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0x0fbf0ed0","0x0eb10ac0","VSQRT<c>.F<32,64> <Sd,Dd>, <Sm,Dm>","cond:4|1|1|1|0|1|D|1|1|0|0|0|1|Vd:4|1|0|1|sz|1|1|M|0|Vm:4","vfp"
"0xfe800f90","0xf2800190","VSRA.<type_U><size_vs> <Qd>, <Qm>, #<imm_vs>","1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|0|1|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xff800f90","0xf3800490","VSRI.<size_vs> <Qd>, <Qm>, #<imm_vs>","1|1|1|1|0|0|1|1|1|D|imm6:6|Vd:4|0|1|0|0|L|Q|M|1|Vm:4","SEE “Related encodings”"
"0xffb00200","0xf4000200","VST1.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00300","0xf4800000","VST1.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|0|0|index_align:4|Rm:4",""
"0xffb00400","0xf4000000","VST2.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00300","0xf4800100","VST2.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|0|1|index_align:4|Rm:4",""
"0xffb00300","0xf4800200","VST3.<size> <list4>, [<Rn>]{!}","1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|1|0|index_align:4|Rm:4",""
"0xffb00e20","0xf4000400","VST3.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00e00","0xf4000000","VST4.<size> <list4>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4","SEE “Related encodings”"
"0xffb00300","0xf4800300","VST4.<size> <list1>, [<Rn>{@<align>}]{!}","1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|1|1|index_align:4|Rm:4",""
"0x0f300e00","0x0d000a00","VSTR<c> <Sd,Dd>, [<Rn>{,#+/-<imm8>}]","cond:4|1|1|0|1|U|D|0|0|Rn:4|Vd:4|1|0|1|sz|imm8:8","vfp"
"0xff800f10","0xf3000800","VSUB.<dt_Isize> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|1|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|0|Vm:4",""
"0xffa00f10","0xf2200d00","VSUB.F32 <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|1|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4",""
"0x0fb00e50","0x0e300a40","VSUB<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm>","cond:4|1|1|1|0|0|D|1|1|Vn:4|Vd:4|1|0|1|sz|N|1|M|0|Vm:4","vfp"
"0xff810f51","0xf2800600","VSUBHN.<dt_Isize> <Dd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|0|1|1|0|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xfe801e50","0xf2800200","VSUBL.<dt_Usize> <Qd>, <Dn>, <Dm>","1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|0|1|op|N|0|M|0|Vm:4","SEE “Related encodings”"
"0xffbf0f90","0xf3b20000","VSWP <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|0|0|Q|M|0|Vm:4",""
"0xffb30f90","0xf3b20080","VTRN.<size_n> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|0|1|Q|M|0|Vm:4",""
"0xff800f10","0xf2000810","VTST.<size_n> <Qd>, <Qn>, <Qm>","1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|1|Vm:4",""
"0xffb30f90","0xf3b20100","VUZP.<size_n> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|1|0|Q|M|0|Vm:4",""
"0xffb30f90","0xf3b20180","VZIP.<size_n> <Qd>, <Qm>","1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|1|1|Q|M|0|Vm:4",""
"0x0fffffff","0x0320f002","WFE<c>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|0",""
"0x0fffffff","0x0320f003","WFI<c>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|1",""
"0x0fffffff","0x0320f001","YIELD<c>","cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|1",""
"0xffffffff","0xf7fabcfd","UNDEF","1|1|1|1|0|1|1|1|1|1|1|1|1|0|1|0|1|0|1|1|1|1|0|0|1|1|1|1|1|1|0|1",""
1 # arm instruction description version 0.01.
2 # https://golang.org/x/arch/arm
3 #
4 # This file contains a block of comment lines each beginning with #
5 # followed by entries in CSV format. All the # comments are at the top
6 # of the file so a reader can skip past the comments and hand the
7 # rest of the file to a standard CSV reader.
8 #
9 # Each line in the CSV section contains 5 fields:
10 #
11 # mask value mnemonic encoding tags
12 #
13 # The mnemonic and encoding correspond to the notation used in the
14 # ARM Architecture Reference Manual.
15 #
16 # A particular instruction word w matches a line if w&mask == value.
17 # The mask and value are computed from a combination of the encodings
18 # and the additional pseudocode restrictions given in the manual
19 # for each instruction.
20 #
21 # Multiple lines may match a particular instruction word.
22 # The tags specify which line takes priority in these cases
23 # as a partial order. Eventually the plan is that a tag of the form
24 # 'name:x' marks a line with the name x and a tag of the form
25 # 'except:x' says that the line on which the tag appears is of lower
26 # priority than the ones marked with name x.
27 # For now however a tag of the form 'SEE XXX' is taken from the
28 # manual and is like 'except:x' but without a rigorous resolution for
29 # the x. So far we've been able to just sort instructions into two classes:
30 # those with SEE and those without.
31 #
32 # The tag 'pseudo' indicates that this instruction is an alternate name
33 # for another encoding and should be ignored during disassembly.
34 #
35 # This file was generated by a program reading the PDF version of
36 # the manual but it was then hand edited to make corrections.
37 # The eventual plan is for the generator to write the
38 # file directly using the PDF and a list of modifications but
39 # no hand editing. Then when a new version of the manual comes out
40 # updating the list should be as easy as downloading the new PDF
41 # and invoking the generator. However we are not there yet.
42 #
43 0x0fe00000 0x02a00000 ADC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|0|1|S|Rn:4|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
44 0x0fe00090 0x00a00010 ADC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
45 0x0fe00010 0x00a00000 ADC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
46 0x0fe00000 0x02800000 ADD{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|0|0|S|Rn:4|Rd:4|imm12:12 SEE ADR SEE ADD (SP plus immediate) SEE SUBS PC, LR and related instructions
47 0x0fe00090 0x00800010 ADD{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
48 0x0fe00010 0x00800000 ADD{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions SEE ADD (SP plus register)
49 0x0fef0000 0x028d0000 ADD{S}<c> <Rd>,SP,#<const> cond:4|0|0|1|0|1|0|0|S|1|1|0|1|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
50 0x0fef0010 0x008d0000 ADD{S}<c> <Rd>,SP,<Rm>{,<shift>} cond:4|0|0|0|0|1|0|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
51 0x0fff0000 0x028f0000 ADR<c> <Rd>,<label+12> cond:4|0|0|1|0|1|0|0|0|1|1|1|1|Rd:4|imm12:12 pseudo
52 0x0fff0000 0x024f0000 ADR<c> <Rd>,<label-12> cond:4|0|0|1|0|0|1|0|0|1|1|1|1|Rd:4|imm12:12 pseudo
53 0x0fe00000 0x02000000 AND{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|0|0|S|Rn:4|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
54 0x0fe00090 0x00000010 AND{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
55 0x0fe00010 0x00000000 AND{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
56 0x0fef0070 0x01a00040 ASR{S}<c> <Rd>,<Rm>,#<imm5_32> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|0|0|Rm:4
57 0x0fef00f0 0x01a00050 ASR{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|0|1|Rn:4
58 0x0f000000 0x0a000000 B<c> <label24> cond:4|1|0|1|0|imm24:24
59 0x0fe0007f 0x07c0001f BFC<c> <Rd>,#<lsb>,#<width> cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|1|1|1|1
60 0x0fe00070 0x07c00010 BFI<c> <Rd>,<Rn>,#<lsb>,#<width> cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|Rn:4 SEE BFC
61 0x0fe00000 0x03c00000 BIC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|1|1|1|0|S|Rn:4|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
62 0x0fe00090 0x01c00010 BIC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
63 0x0fe00010 0x01c00000 BIC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
64 0x0ff000f0 0x01200070 BKPT<c> #<imm12+4> cond:4|0|0|0|1|0|0|1|0|imm12:12|0|1|1|1|imm4:4
65 0x0f000000 0x0b000000 BL<c> <label24> cond:4|1|0|1|1|imm24:24
66 0xfe000000 0xfa000000 BLX <label24H> 1|1|1|1|1|0|1|H|imm24:24
67 0x0ffffff0 0x012fff30 BLX<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
68 0x0ffffff0 0x012fff10 BX<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
69 0x0ffffff0 0x012fff20 BXJ<c> <Rm> cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4
70 0xffffffff 0xf57ff01f CLREX 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1)
71 0x0fff0ff0 0x016f0f10 CLZ<c> <Rd>,<Rm> cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
72 0x0ff0f000 0x03700000 CMN<c> <Rn>,#<const> cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
73 0x0ff0f090 0x01700010 CMN<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
74 0x0ff0f010 0x01700000 CMN<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
75 0x0ff0f000 0x03500000 CMP<c> <Rn>,#<const> cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
76 0x0ff0f090 0x01500010 CMP<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
77 0x0ff0f010 0x01500000 CMP<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
78 0x0ffffff0 0x0320f0f0 DBG<c> #<option> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|1|1|1|1|option:4
79 0xfffffff0 0xf57ff050 DMB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|1|option:4
80 0xfffffff0 0xf57ff040 DSB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|0|0|option:4
81 0x0fe00000 0x02200000 EOR{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|0|1|S|Rn:4|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
82 0x0fe00090 0x00200010 EOR{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
83 0x0fe00010 0x00200000 EOR{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
84 0xfffffff0 0xf57ff060 ISB #<option> 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|1|1|0|option:4
85 0x0fd00000 0x08900000 LDM<c> <Rn>{!},<registers> cond:4|1|0|0|0|1|0|W|1|Rn:4|register_list:16 SEE POP
86 0x0fd00000 0x08100000 LDMDA<c> <Rn>{!},<registers> cond:4|1|0|0|0|0|0|W|1|Rn:4|register_list:16
87 0x0fd00000 0x09100000 LDMDB<c> <Rn>{!},<registers> cond:4|1|0|0|1|0|0|W|1|Rn:4|register_list:16
88 0x0fd00000 0x09900000 LDMIB<c> <Rn>{!},<registers> cond:4|1|0|0|1|1|0|W|1|Rn:4|register_list:16
89 0x0f7f0000 0x051f0000 LDR<c> <Rt>,<label+/-12> cond:4|0|1|0|(1)|U|0|(0)|1|1|1|1|1|Rt:4|imm12:12
90 0x0e500010 0x06100000 LDR<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|0|W|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4 SEE LDRT
91 0x0e500000 0x04100000 LDR<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|0|W|1|Rn:4|Rt:4|imm12:12 SEE LDR (literal) SEE LDRT SEE POP
92 0x0f7f0000 0x055f0000 LDRB<c> <Rt>,<label+/-12> cond:4|0|1|0|(1)|U|1|(0)|1|1|1|1|1|Rt:4|imm12:12
93 0x0e500010 0x06500000 LDRB<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|1|W|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4 SEE LDRBT
94 0x0e500000 0x04500000 LDRB<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|1|W|1|Rn:4|Rt:4|imm12:12 SEE LDRB (literal) SEE LDRBT
95 0x0f700000 0x04700000 LDRBT<c> <Rt>,[<Rn>],#+/-<imm12> cond:4|0|1|0|0|U|1|1|1|Rn:4|Rt:4|imm12:12
96 0x0f700010 0x06700000 LDRBT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|1|1|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
97 0x0f7f10f0 0x014f00d0 LDRD<c> <Rt1>,<Rt2>,<label+/-4+4> cond:4|0|0|0|(1)|U|1|(0)|0|1|1|1|1|Rt:4|imm4H:4|1|1|0|1|imm4L:4 pseudo
98 0x0e500ff0 0x000000d0 LDRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|0|1|Rm:4
99 0x0e5000f0 0x004000d0 LDRD<c> <Rt1>,<Rt2>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4 SEE LDRD (literal)
100 0x0ff00fff 0x01900f9f LDREX<c> <Rt>,[<Rn>] cond:4|0|0|0|1|1|0|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
101 0x0ff00fff 0x01d00f9f LDREXB<c> <Rt>, [<Rn>] cond:4|0|0|0|1|1|1|0|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
102 0x0ff00fff 0x01b00f9f LDREXD<c> <Rt1>,<Rt2>,[<Rn>] cond:4|0|0|0|1|1|0|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
103 0x0ff00fff 0x01f00f9f LDREXH<c> <Rt>, [<Rn>] cond:4|0|0|0|1|1|1|1|1|Rn:4|Rt:4|(1)|(1)|(1)|(1)|1|0|0|1|(1)|(1)|(1)|(1)
104 0x0f7f00f0 0x015f00b0 LDRH<c> <Rt>,<label+/-4+4> cond:4|0|0|0|1|U|1|0|1|1|1|1|1|Rt:4|imm4H:4|1|0|1|1|imm4L:4 pseudo
105 0x0e500ff0 0x001000b0 LDRH<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4 SEE LDRHT
106 0x0e5000f0 0x005000b0 LDRH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4 SEE LDRH literal SEE LDRHT
107 0x0f7000f0 0x007000b0 LDRHT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4
108 0x0f700ff0 0x003000b0 LDRHT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4
109 0x0f7f00f0 0x015f00d0 LDRSB<c> <Rt>,<label+/-4+4> cond:4|0|0|0|1|U|1|0|1|1|1|1|1|Rt:4|imm4H:4|1|1|0|1|imm4L:4 pseudo
110 0x0e500ff0 0x001000d0 LDRSB<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|1|0|1|Rm:4 SEE LDRSBT
111 0x0e5000f0 0x005000d0 LDRSB<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4 SEE LDRSB literal SEE LDRSBT
112 0x0f7000f0 0x007000d0 LDRSBT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|1|0|1|imm4L:4
113 0x0f700ff0 0x003000d0 LDRSBT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|1|0|1|Rm:4
114 0x0f7f00f0 0x015f00f0 LDRSH<c> <Rt>,<label+/-4+4> cond:4|0|0|0|1|U|1|0|1|1|1|1|1|Rt:4|imm4H:4|1|1|1|1|imm4L:4 pseudo
115 0x0e500ff0 0x001000f0 LDRSH<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|1|Rn:4|Rt:4|0|0|0|0|1|1|1|1|Rm:4 SEE LDRSHT
116 0x0e5000f0 0x005000f0 LDRSH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|1|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4 SEE LDRSH literal SEE LDRSHT
117 0x0f7000f0 0x007000f0 LDRSHT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|1|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4
118 0x0f700ff0 0x003000f0 LDRSHT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|1|Rn:4|Rt:4|0|0|0|0|1|1|1|1|Rm:4
119 0x0f700000 0x04300000 LDRT<c> <Rt>, [<Rn>] {,#+/-<imm12>} cond:4|0|1|0|0|U|0|1|1|Rn:4|Rt:4|imm12:12
120 0x0f700010 0x06300000 LDRT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|0|1|1|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
121 0x0fef0070 0x01a00000 LSL{S}<c> <Rd>,<Rm>,#<imm5_nz> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|0|0|0|Rm:4 SEE MOV register
122 0x0fef00f0 0x01a00010 LSL{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|0|0|1|Rn:4
123 0x0fef0070 0x01a00020 LSR{S}<c> <Rd>,<Rm>,#<imm5_32> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|0|1|0|Rm:4
124 0x0fef00f0 0x01a00030 LSR{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|0|1|1|Rn:4
125 0x0fe000f0 0x00200090 MLA{S}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|0|0|0|1|S|Rd:4|Ra:4|Rm:4|1|0|0|1|Rn:4
126 0x0ff000f0 0x00600090 MLS<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|0|0|1|1|0|Rd:4|Ra:4|Rm:4|1|0|0|1|Rn:4
127 0x0ff00000 0x03400000 MOVT<c> <Rd>,#<imm12+4> cond:4|0|0|1|1|0|1|0|0|imm4:4|Rd:4|imm12:12
128 0x0ff00000 0x03000000 MOVW<c> <Rd>,#<imm12+4> cond:4|0|0|1|1|0|0|0|0|imm4:4|Rd:4|imm12:12
129 0x0fef0000 0x03a00000 MOV{S}<c> <Rd>,#<const> cond:4|0|0|1|1|1|0|1|S|0|0|0|0|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
130 0x0fef0ff0 0x01a00000 MOV{S}<c> <Rd>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|0|0|0|0|0|0|0|0|Rm:4 SEE SUBS PC, LR and related instructions
131 0x0fff0fff 0x010f0000 MRS<c> <Rd>,APSR cond:4|0|0|0|1|0|0|0|0|(1)|(1)|(1)|(1)|Rd:4|(0)|(0)|(0)|(0)|0|0|0|0|(0)|(0)|(0)|(0)
132 0x0ffffff0 0x012cf000 MSR<c> APSR,<Rn> cond:4|0|0|0|1|0|0|1|0|1|1|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|Rn:4
133 0x0ffff000 0x032cf000 MSR<c> APSR,#<const> cond:4|0|0|1|1|0|0|1|0|1|1|0|0|(1)|(1)|(1)|(1)|imm12:12
134 0x0fe0f0f0 0x00000090 MUL{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|0|0|0|0|S|Rd:4|(0)|(0)|(0)|(0)|Rm:4|1|0|0|1|Rn:4
135 0x0fef0000 0x03e00000 MVN{S}<c> <Rd>,#<const> cond:4|0|0|1|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
136 0x0fef0090 0x01e00010 MVN{S}<c> <Rd>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|Rs:4|0|type:2|1|Rm:4
137 0x0fef0010 0x01e00000 MVN{S}<c> <Rd>,<Rm>{,<shift>} cond:4|0|0|0|1|1|1|1|S|(0)|(0)|(0)|(0)|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
138 0x0fffffff 0x0320f000 NOP<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|0
139 0x0fe00000 0x03800000 ORR{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|1|1|0|0|S|Rn:4|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
140 0x0fe00090 0x01800010 ORR{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
141 0x0fe00010 0x01800000 ORR{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
142 0x0ff00030 0x06800010 PKH<BT,TB><c> <Rd>,<Rn>,<Rm>{,LSL #<imm5>} cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|imm5:5|tb|0|1|Rm:4
143 0xff7ff000 0xf55ff000 PLD <label+/-12> 1|1|1|1|0|1|0|1|U|(1)|0|1|1|1|1|1|(1)|(1)|(1)|(1)|imm12:12
144 0xff30f000 0xf510f000 PLD{W} [<Rn>,#+/-<imm12>] 1|1|1|1|0|1|0|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12 SEE PLD (literal)
145 0xff30f010 0xf710f000 PLD{W} [<Rn>,+/-<Rm>{, <shift>}] 1|1|1|1|0|1|1|1|U|R|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4
146 0xff70f000 0xf450f000 PLI [<Rn>,#+/-<imm12>] 1|1|1|1|0|1|0|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm12:12
147 0xff70f010 0xf650f000 PLI [<Rn>,+/-<Rm>{, <shift>}] 1|1|1|1|0|1|1|0|U|1|0|1|Rn:4|(1)|(1)|(1)|(1)|imm5:5|type:2|0|Rm:4
148 0x0fff0000 0x08bd0000 POP<c> <registers2> cond:4|1|0|0|0|1|0|1|1|1|1|0|1|register_list:16
149 0x0fff0fff 0x049d0004 POP<c> <registers1> cond:4|0|1|0|0|1|0|0|1|1|1|0|1|Rt:4|0|0|0|0|0|0|0|0|0|1|0|0
150 0x0fff0000 0x092d0000 PUSH<c> <registers2> cond:4|1|0|0|1|0|0|1|0|1|1|0|1|register_list:16
151 0x0fff0fff 0x052d0004 PUSH<c> <registers1> cond:4|0|1|0|1|0|0|1|0|1|1|0|1|Rt:4|0|0|0|0|0|0|0|0|0|1|0|0
152 0x0ff00ff0 0x06200f10 QADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
153 0x0ff00ff0 0x06200f90 QADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
154 0x0ff00ff0 0x01000050 QADD<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|0|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4
155 0x0ff00ff0 0x06200f30 QASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
156 0x0ff00ff0 0x01400050 QDADD<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|1|0|0|Rn:4|Rd:4|(0)|(0)|(0)|(0)|0|1|0|1|Rm:4
157 0x0ff00ff0 0x01600050 QDSUB<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|1|1|0|Rn:4|Rd:4|0|0|0|0|0|1|0|1|Rm:4
158 0x0ff00ff0 0x06200f50 QSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
159 0x0ff00ff0 0x06200f70 QSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
160 0x0ff00ff0 0x06200ff0 QSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
161 0x0ff00ff0 0x01200050 QSUB<c> <Rd>,<Rm>,<Rn> cond:4|0|0|0|1|0|0|1|0|Rn:4|Rd:4|0|0|0|0|0|1|0|1|Rm:4
162 0x0fff0ff0 0x06ff0f30 RBIT<c> <Rd>,<Rm> cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
163 0x0fff0ff0 0x06bf0fb0 REV16<c> <Rd>,<Rm> cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
164 0x0fff0ff0 0x06bf0f30 REV<c> <Rd>,<Rm> cond:4|0|1|1|0|1|0|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
165 0x0fff0ff0 0x06ff0fb0 REVSH<c> <Rd>,<Rm> cond:4|0|1|1|0|1|1|1|1|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
166 0x0fef0070 0x01a00060 ROR{S}<c> <Rd>,<Rm>,#<imm5> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|1|0|Rm:4 SEE RRX
167 0x0fef00f0 0x01a00070 ROR{S}<c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|1|1|Rn:4
168 0x0fef0ff0 0x01a00060 RRX{S}<c> <Rd>,<Rm> cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|0|0|0|0|0|1|1|0|Rm:4
169 0x0fe00000 0x02600000 RSB{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|1|1|S|Rn:4|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
170 0x0fe00090 0x00600010 RSB{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|1|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
171 0x0fe00010 0x00600000 RSB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|1|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
172 0x0fe00000 0x02e00000 RSC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|1|1|S|Rn:4|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
173 0x0fe00090 0x00e00010 RSC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|1|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
174 0x0fe00010 0x00e00000 RSC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|1|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
175 0x0ff00ff0 0x06100f10 SADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
176 0x0ff00ff0 0x06100f90 SADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
177 0x0ff00ff0 0x06100f30 SASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
178 0x0fe00000 0x02c00000 SBC{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|1|1|0|S|Rn:4|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
179 0x0fe00090 0x00c00010 SBC{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
180 0x0fe00010 0x00c00000 SBC{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
181 0x0fe00070 0x07a00050 SBFX<c> <Rd>,<Rn>,#<lsb>,#<widthm1> cond:4|0|1|1|1|1|0|1|widthm1:5|Rd:4|lsb:5|1|0|1|Rn:4
182 0x0ff0f0f0 0x0710f010 SDIV<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|0|0|1|Rd:4|(1)|(1)|(1)|(1)|Rm:4|0|0|0|1|Rn:4
183 0x0ff00ff0 0x06800fb0 SEL<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|1|1|Rm:4
184 0xfffffdff 0xf1010000 SETEND <endian_specifier> 1|1|1|1|0|0|0|1|0|0|0|0|0|0|0|1|0|0|0|0|0|0|E|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)|(0)
185 0x0fffffff 0x0320f004 SEV<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|1|0|0
186 0x0ff00ff0 0x06300f10 SHADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
187 0x0ff00ff0 0x06300f90 SHADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
188 0x0ff00ff0 0x06300f30 SHASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
189 0x0ff00ff0 0x06300f50 SHSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
190 0x0ff00ff0 0x06300f70 SHSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
191 0x0ff00ff0 0x06300ff0 SHSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
192 0x0ff00090 0x01000080 SMLA<x><y><c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|1|0|0|0|0|Rd:4|Ra:4|Rm:4|1|M|N|0|Rn:4
193 0x0ff000d0 0x07000010 SMLAD{X}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|0|0|0|Rd:4|Ra:4|Rm:4|0|0|M|1|Rn:4 SEE SMUAD
194 0x0ff00090 0x01400080 SMLAL<x><y><c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|1|M|N|0|Rn:4
195 0x0ff000d0 0x07400010 SMLALD{X}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|1|1|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|0|0|M|1|Rn:4
196 0x0fe000f0 0x00e00090 SMLAL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|1|1|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
197 0x0ff000b0 0x01200080 SMLAW<y><c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|0|0|1|0|0|1|0|Rd:4|Ra:4|Rm:4|1|M|0|0|Rn:4
198 0x0ff000d0 0x07000050 SMLSD{X}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|0|0|0|Rd:4|Ra:4|Rm:4|0|1|M|1|Rn:4 SEE SMUSD
199 0x0ff000d0 0x07400050 SMLSLD{X}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|1|1|1|0|1|0|0|RdHi:4|RdLo:4|Rm:4|0|1|M|1|Rn:4
200 0x0ff000d0 0x07500010 SMMLA{R}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|1|0|1|Rd:4|Ra:4|Rm:4|0|0|R|1|Rn:4 SEE SMMUL
201 0x0ff000d0 0x075000d0 SMMLS{R}<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|0|1|0|1|Rd:4|Ra:4|Rm:4|1|1|R|1|Rn:4
202 0x0ff0f0d0 0x0750f010 SMMUL{R}<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|1|0|1|Rd:4|1|1|1|1|Rm:4|0|0|R|1|Rn:4
203 0x0ff0f0d0 0x0700f010 SMUAD{X}<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|0|0|0|Rd:4|1|1|1|1|Rm:4|0|0|M|1|Rn:4
204 0x0ff0f090 0x01600080 SMUL<x><y><c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|0|1|1|0|Rd:4|0|0|0|0|Rm:4|1|M|N|0|Rn:4
205 0x0fe000f0 0x00c00090 SMULL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|1|0|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
206 0x0ff0f0b0 0x012000a0 SMULW<y><c> <Rd>,<Rn>,<Rm> cond:4|0|0|0|1|0|0|1|0|Rd:4|0|0|0|0|Rm:4|1|M|1|0|Rn:4
207 0x0ff0f0d0 0x0700f050 SMUSD{X}<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|0|0|0|Rd:4|1|1|1|1|Rm:4|0|1|M|1|Rn:4
208 0x0ff00ff0 0x06a00f30 SSAT16<c> <Rd>,#<sat_imm4m1>,<Rn> cond:4|0|1|1|0|1|0|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4
209 0x0fe00030 0x06a00010 SSAT<c> <Rd>,#<sat_imm5m1>,<Rn>{,<shift>} cond:4|0|1|1|0|1|0|1|sat_imm:5|Rd:4|imm5:5|sh|0|1|Rn:4
210 0x0ff00ff0 0x06100f50 SSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
211 0x0ff00ff0 0x06100f70 SSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
212 0x0ff00ff0 0x06100ff0 SSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|0|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
213 0x0fd00000 0x08800000 STM<c> <Rn>{!},<registers> cond:4|1|0|0|0|1|0|W|0|Rn:4|register_list:16
214 0x0fd00000 0x08000000 STMDA<c> <Rn>{!},<registers> cond:4|1|0|0|0|0|0|W|0|Rn:4|register_list:16
215 0x0fd00000 0x09000000 STMDB<c> <Rn>{!},<registers> cond:4|1|0|0|1|0|0|W|0|Rn:4|register_list:16 SEE PUSH
216 0x0fd00000 0x09800000 STMIB<c> <Rn>{!},<registers> cond:4|1|0|0|1|1|0|W|0|Rn:4|register_list:16
217 0x0e500018 0x06000000 STR<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|0|W|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4 SEE STRT
218 0x0e500000 0x04000000 STR<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|0|W|0|Rn:4|Rt:4|imm12:12 SEE STRT SEE PUSH
219 0x0e500010 0x06400000 STRB<c> <Rt>,[<Rn>,+/-<Rm>{, <shift>}]{!} cond:4|0|1|1|P|U|1|W|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4 SEE STRBT
220 0x0e500000 0x04400000 STRB<c> <Rt>,[<Rn>{,#+/-<imm12>}]{!} cond:4|0|1|0|P|U|1|W|0|Rn:4|Rt:4|imm12:12 SEE STRBT
221 0x0f700000 0x04600000 STRBT<c> <Rt>,[<Rn>],#+/-<imm12> cond:4|0|1|0|0|U|1|1|0|Rn:4|Rt:4|imm12:12
222 0x0f700010 0x06600000 STRBT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|1|1|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
223 0x0e500ff0 0x000000f0 STRD<c> <Rt1>,<Rt2>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|(0)|(0)|(0)|(0)|1|1|1|1|Rm:4
224 0x0e5000f0 0x004000f0 STRD<c> <Rt1>,<Rt2>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|1|1|1|imm4L:4
225 0x0ff00ff0 0x01800f90 STREX<c> <Rd>,<Rt>,[<Rn>] cond:4|0|0|0|1|1|0|0|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
226 0x0ff00ff0 0x01c00f90 STREXB<c> <Rd>,<Rt>,[<Rn>] cond:4|0|0|0|1|1|1|0|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
227 0x0ff00ff0 0x01a00f90 STREXD<c> <Rd>,<Rt1>,<Rt2>,[<Rn>] cond:4|0|0|0|1|1|0|1|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
228 0x0ff00ff0 0x01e00f90 STREXH<c> <Rd>,<Rt>,[<Rn>] cond:4|0|0|0|1|1|1|1|0|Rn:4|Rd:4|1|1|1|1|1|0|0|1|Rt:4
229 0x0e500ff0 0x000000b0 STRH<c> <Rt>,[<Rn>,+/-<Rm>]{!} cond:4|0|0|0|P|U|0|W|0|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4 SEE STRHT
230 0x0e5000f0 0x004000b0 STRH<c> <Rt>,[<Rn>{,#+/-<imm8>}]{!} cond:4|0|0|0|P|U|1|W|0|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4 SEE STRHT
231 0x0f7000f0 0x006000b0 STRHT<c> <Rt>, [<Rn>] {,#+/-<imm8>} cond:4|0|0|0|0|U|1|1|0|Rn:4|Rt:4|imm4H:4|1|0|1|1|imm4L:4
232 0x0f700ff0 0x002000b0 STRHT<c> <Rt>, [<Rn>], +/-<Rm> cond:4|0|0|0|0|U|0|1|0|Rn:4|Rt:4|0|0|0|0|1|0|1|1|Rm:4
233 0x0f700000 0x04200000 STRT<c> <Rt>, [<Rn>] {,#+/-<imm12>} cond:4|0|1|0|0|U|0|1|0|Rn:4|Rt:4|imm12:12
234 0x0f700010 0x06200000 STRT<c> <Rt>,[<Rn>],+/-<Rm>{, <shift>} cond:4|0|1|1|0|U|0|1|0|Rn:4|Rt:4|imm5:5|type:2|0|Rm:4
235 0x0fe00000 0x02400000 SUB{S}<c> <Rd>,<Rn>,#<const> cond:4|0|0|1|0|0|1|0|S|Rn:4|Rd:4|imm12:12 SEE ADR SEE SUB (SP minus immediate) SEE SUBS PC, LR and related instructions
236 0x0fe00090 0x00400010 SUB{S}<c> <Rd>,<Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|0|0|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4
237 0x0fe00010 0x00400000 SUB{S}<c> <Rd>,<Rn>,<Rm>{,<shift>} cond:4|0|0|0|0|0|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions SEE SUB (SP minus register)
238 0x0fef0000 0x024d0000 SUB{S}<c> <Rd>,SP,#<const> cond:4|0|0|1|0|0|1|0|S|1|1|0|1|Rd:4|imm12:12 SEE SUBS PC, LR and related instructions
239 0x0fef0010 0x004d0000 SUB{S}<c> <Rd>,SP,<Rm>{,<shift>} cond:4|0|0|0|0|0|1|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4 SEE SUBS PC, LR and related instructions
240 0x0f000000 0x0f000000 SVC<c> #<imm24> cond:4|1|1|1|1|imm24:24
241 0x0fb00ff0 0x01000090 SWP{B}<c> <Rt>,<Rm>,[<Rn>] cond:4|0|0|0|1|0|B|0|0|Rn:4|Rt:4|0|0|0|0|1|0|0|1|Rm:4
242 0x0ff003f0 0x06800070 SXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|0|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4 SEE SXTB16
243 0x0ff003f0 0x06a00070 SXTAB<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4 SEE SXTB
244 0x0ff003f0 0x06b00070 SXTAH<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|1|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4 SEE SXTH
245 0x0fff03f0 0x068f0070 SXTB16<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|0|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
246 0x0fff03f0 0x06af0070 SXTB<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
247 0x0fff03f0 0x06bf0070 SXTH<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|0|1|1|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
248 0x0ff0f000 0x03300000 TEQ<c> <Rn>,#<const> cond:4|0|0|1|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
249 0x0ff0f090 0x01300010 TEQ<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
250 0x0ff0f010 0x01300000 TEQ<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|0|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
251 0x0ff0f000 0x03100000 TST<c> <Rn>,#<const> cond:4|0|0|1|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12
252 0x0ff0f090 0x01100010 TST<c> <Rn>,<Rm>,<type> <Rs> cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4
253 0x0ff0f010 0x01100000 TST<c> <Rn>,<Rm>{,<shift>} cond:4|0|0|0|1|0|0|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4
254 0x0ff00ff0 0x06500f10 UADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
255 0x0ff00ff0 0x06500f90 UADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
256 0x0ff00ff0 0x06500f30 UASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
257 0x0fe00070 0x07e00050 UBFX<c> <Rd>,<Rn>,#<lsb>,#<widthm1> cond:4|0|1|1|1|1|1|1|widthm1:5|Rd:4|lsb:5|1|0|1|Rn:4
258 0x0ff0f0f0 0x0730f010 UDIV<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|0|0|1|1|Rd:4|(1)|(1)|(1)|(1)|Rm:4|0|0|0|1|Rn:4
259 0x0ff00ff0 0x06700f10 UHADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
260 0x0ff00ff0 0x06700f90 UHADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
261 0x0ff00ff0 0x06700f30 UHASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
262 0x0ff00ff0 0x06700f50 UHSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
263 0x0ff00ff0 0x06700f70 UHSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
264 0x0ff00ff0 0x06700ff0 UHSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
265 0x0ff000f0 0x00400090 UMAAL<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|0|1|0|0|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
266 0x0fe000f0 0x00a00090 UMLAL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|0|1|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
267 0x0fe000f0 0x00800090 UMULL{S}<c> <RdLo>,<RdHi>,<Rn>,<Rm> cond:4|0|0|0|0|1|0|0|S|RdHi:4|RdLo:4|Rm:4|1|0|0|1|Rn:4
268 0x0ff00ff0 0x06600f10 UQADD16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4
269 0x0ff00ff0 0x06600f90 UQADD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|0|0|1|Rm:4
270 0x0ff00ff0 0x06600f30 UQASX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4
271 0x0ff00ff0 0x06600f50 UQSAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
272 0x0ff00ff0 0x06600f70 UQSUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
273 0x0ff00ff0 0x06600ff0 UQSUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|1|0|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
274 0x0ff0f0f0 0x0780f010 USAD8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|1|1|0|0|0|Rd:4|1|1|1|1|Rm:4|0|0|0|1|Rn:4
275 0x0ff000f0 0x07800010 USADA8<c> <Rd>,<Rn>,<Rm>,<Ra> cond:4|0|1|1|1|1|0|0|0|Rd:4|Ra:4|Rm:4|0|0|0|1|Rn:4 SEE USAD8
276 0x0ff00ff0 0x06e00f30 USAT16<c> <Rd>,#<sat_imm4>,<Rn> cond:4|0|1|1|0|1|1|1|0|sat_imm:4|Rd:4|(1)|(1)|(1)|(1)|0|0|1|1|Rn:4
277 0x0fe00030 0x06e00010 USAT<c> <Rd>,#<sat_imm5>,<Rn>{,<shift>} cond:4|0|1|1|0|1|1|1|sat_imm:5|Rd:4|imm5:5|sh|0|1|Rn:4
278 0x0ff00ff0 0x06500f50 USAX<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|0|1|Rm:4
279 0x0ff00ff0 0x06500f70 USUB16<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|0|1|1|1|Rm:4
280 0x0ff00ff0 0x06500ff0 USUB8<c> <Rd>,<Rn>,<Rm> cond:4|0|1|1|0|0|1|0|1|Rn:4|Rd:4|(1)|(1)|(1)|(1)|1|1|1|1|Rm:4
281 0x0ff003f0 0x06c00070 UXTAB16<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|0|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4 SEE UXTB16
282 0x0ff003f0 0x06e00070 UXTAB<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|0|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4 SEE UXTB
283 0x0ff003f0 0x06f00070 UXTAH<c> <Rd>,<Rn>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|1|Rn:4|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4 SEE UXTH
284 0x0fff03f0 0x06cf0070 UXTB16<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|0|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
285 0x0fff03f0 0x06ef0070 UXTB<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|0|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
286 0x0fff03f0 0x06ff0070 UXTH<c> <Rd>,<Rm>{,<rotation>} cond:4|0|1|1|0|1|1|1|1|1|1|1|1|Rd:4|rotate:2|0|0|0|1|1|1|Rm:4
287 0xff800f10 0xf3000110 V<BIF,BIT,BSL> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|0|D|op:2|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4 SEE VEOR
288 0xffb00c10 0xf3b00800 V<TBL,TBX>.8 <Dd>, <list_len>, <Dm> 1|1|1|1|0|0|1|1|1|D|1|1|Vn:4|Vd:4|1|0|len:2|N|op|M|0|Vm:4
289 0xfe800a50 0xf2800040 V<MLA,MLS>.<dt> <Qd>, <Qn>, <Dm[x]> 1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|0|op|0|F|N|1|M|0|Vm:4 SEE “Related encodings”
290 0xfe800f00 0xf2000600 V<MAX,MIN>.<dt> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|1|0|N|Q|M|op|Vm:4
291 0xfe800f10 0xf2000900 V<MLA,MLS>.<dt> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|op|0|D|size:2|Vn:4|Vd:4|1|0|0|1|N|Q|M|0|Vm:4
292 0xff800f10 0xf2000d10 V<MLA,MLS>.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|op|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|1|Vm:4
293 0xff800f10 0xf2000f00 V<MAX,MIN>.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|op|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|0|Vm:4
294 0xff800f10 0xf3000e10 VAC<GE,GT>.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|0|D|op|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|1|Vm:4
295 0x0fb00e10 0x0e000a00 V<MLA,MLS><c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|0|0|Vn:4|Vd:4|1|0|1|sz|N|op|M|0|Vm:4 vfp
296 0xfe801d50 0xf2800800 V<MLA,MLS>L.<dt> <Qd>, <Dn>, <Dm> 1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|1|0|op|0|N|0|M|0|Vm:4 SEE “Related encodings”
297 0xfe801b50 0xf2800240 V<MLA,MLS>L.<dt> <Qd>, <Dn>, <Dm[x]> 1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|op|1|0|N|1|M|0|Vm:4 SEE “Related encodings”
298 0xfe800f10 0xf2000710 VABA.<dt_Usize> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|1|1|N|Q|M|1|Vm:4
299 0xfe801f50 0xf2800500 VABAL.<dt_Usize> <Qd>, <Dn>, <Dm> 1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|1|0|1|N|0|M|0|Vm:4 SEE “Related encodings”
300 0xfe800f10 0xf2000700 VABD.<dt_Usize> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|1|1|N|Q|M|0|Vm:4
301 0xffa00f10 0xf3200d00 VABD.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|0|D|1|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4
302 0xfe801f50 0xf2800700 VABDL.<dt_Usize> <Qd>, <Dn>, <Dm> 1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|1|1|1|N|0|M|0|Vm:4 SEE “Related encodings”
303 0xffb30b90 0xf3b10300 VABS.<dt_Fsize> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|1|1|0|Q|M|0|Vm:4
304 0x0fbf0ed0 0x0eb00ac0 VABS<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|0|Vd:4|1|0|1|sz|1|1|M|0|Vm:4 vfp
305 0xff800f10 0xf2000800 VADD.<dt_Isize> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|0|Vm:4
306 0xffa00f10 0xf2000d00 VADD.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|0|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4
307 0x0fb00e50 0x0e300a00 VADD<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|1|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4 vfp
308 0xff810f51 0xf2800400 VADDHN.<dt_Isize> <Dd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|0|1|0|0|N|0|M|0|Vm:4 SEE “Related encodings”
309 0xfe801e50 0xf2800000 VADDL.<dt_Usize> <Qd>, <Dn>, <Dm> 1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|0|0|op|N|0|M|0|Vm:4 SEE “Related encodings”
310 0xffb00f10 0xf2000110 VAND <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|0|0|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4
311 0xffb00f10 0xf2100110 VBIC <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|0|1|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4
312 0xfeb800b0 0xf2800030 VBIC.<dt_simd> <Qd>, #<imm_simd1> 1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|1|1|imm4:4 SEE “Related encodings”
313 0xffb30b90 0xf3b10100 VCEQ.<dt_Fsize> <Qd>, <Qm>, #0 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|1|0|Q|M|0|Vm:4
314 0xff800f10 0xf3000810 VCEQ.<dt_Isize> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|1|Vm:4
315 0xffa00f10 0xf2000e00 VCEQ.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|0|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|0|Vm:4
316 0xffb30b90 0xf3b10080 VCGE.<dt_Fsize> <Qd>, <Qm>, #0 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|0|1|Q|M|0|Vm:4
317 0xfe800f10 0xf2000310 VCGE.<dt_Isize> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|1|1|N|Q|M|1|Vm:4
318 0xffa00f10 0xf3000e00 VCGE.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|0|D|0|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|0|Vm:4
319 0xffb30b90 0xf3b10000 VCGT.<dt_Fsize> <Qd>, <Qm>, #0 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|0|0|Q|M|0|Vm:4
320 0xfe800f10 0xf2000300 VCGT.<dt_Isize> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|1|1|N|Q|M|0|Vm:4
321 0xffa00f10 0xf3200e00 VCGT.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|0|D|1|sz|Vn:4|Vd:4|1|1|1|0|N|Q|M|0|Vm:4
322 0xffb30b90 0xf3b10180 VCLE.<dt_Fsize> <Qd>, <Qm>, #0 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|0|1|1|Q|M|0|Vm:4
323 0xffb30f90 0xf3b00400 VCLS.<dt_Isize> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|0|0|Q|M|0|Vm:4
324 0xffb30b90 0xf3b10200 VCLT.<dt_Fsize> <Qd>, <Qm>, #0 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|1|0|0|Q|M|0|Vm:4
325 0xffb30f90 0xf3b00480 VCLZ.<dt_Isize> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|0|1|Q|M|0|Vm:4
326 0x0fbf0e7f 0x0eb50a40 VCMP{E}<c>.F<32,64> <Sd,Dd>, #0.0 cond:4|1|1|1|0|1|D|1|1|0|1|0|1|Vd:4|1|0|1|sz|E|1|0|0|(0)|(0)|(0)|(0) vfp
327 0x0fbf0e50 0x0eb40a40 VCMP{E}<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|1|0|0|Vd:4|1|0|1|sz|E|1|M|0|Vm:4 vfp
328 0xffbf0f90 0xf3b00500 VCNT.8 <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|1|0|Q|M|0|Vm:4
329 0xffbf0e10 0xf3bb0600 VCVT.<Td>.<Tm_1> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|1|Vd:4|0|1|1|op:2|Q|M|0|Vm:4
330 0xfea00e90 0xf2a00e10 VCVT.<Td>.<Tm_2> <Qd>, <Qm>, #<fbits> 1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|1|1|op|0|Q|M|1|Vm:4 SEE “Related encodings”
331 0x0fbe0e50 0x0eba0a40 VCVT<c>.F<32,64>.FX<S,U><16,32> <Sd,Dd>, <Sd,Dd>, #<fbits> cond:4|1|1|1|0|1|D|1|1|1|0|1|U|Vd:4|1|0|1|sz|sx|1|i|0|imm4:4 vfp
332 0x0fbe0e50 0x0ebe0a40 VCVT<c>.FX<S,U><16,32>.F<32,64> <Sd,Dd>, <Sd,Dd>, #<fbits> cond:4|1|1|1|0|1|D|1|1|1|1|1|U|Vd:4|1|0|1|sz|sx|1|i|0|imm4:4 vfp
333 0xffbf0ed0 0xf3b60600 VCVT.F32.F16 <Qd>, <Dm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|1|1|op|0|0|M|0|Vm:4
334 0x0fbf0ed0 0x0eb70ac0 VCVT<c>.<F64.F32,F32.F64> <Dd,Sd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|1|1|1|Vd:4|1|0|1|sz|1|1|M|0|Vm:4 vfp
335 0x0fbe0f50 0x0eb20a40 VCVT<B,T><c>.<F32.F16,F16.F32> <Sd>, <Sm> cond:4|1|1|1|0|1|D|1|1|0|0|1|op|Vd:4|1|0|1|0|T|1|M|0|Vm:4 vfp
336 0x0fbf0e50 0x0eb80a40 VCVT<c>.F<32,64>.<U,S>32 <Sd,Dd>, <Sm> cond:4|1|1|1|0|1|D|1|1|1|0|0|0|Vd:4|1|0|1|sz|op|1|M|0|Vm:4 vfp
337 0x0fbe0e50 0x0ebc0a40 VCVT<R,><c>.<U,S>32.F<32,64> <Sd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|1|1|0|signed|Vd:4|1|0|1|sz|op|1|M|0|Vm:4 vfp
338 0x0fb00e50 0x0e800a00 VDIV<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|1|D|0|0|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4 vfp
339 0xffb00f90 0xf3b00c00 VDUP.<size_x> <Qd>, <Dm[size_x]> 1|1|1|1|0|0|1|1|1|D|1|1|imm4:4|Vd:4|1|1|0|0|0|Q|M|0|Vm:4
340 0x0f900f5f 0x0e800b10 VDUP<c>.<size_be> <Qd>, <Rt> cond:4|1|1|1|0|1|b|Q|0|Vd:4|Rt:4|1|0|1|1|D|0|e|1|(0)|(0)|(0)|(0)
341 0xffb00f10 0xf3000110 VEOR <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|0|D|0|0|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4
342 0xffb00010 0xf2b00000 VEXT.8 <Qd>, <Qn>, <Qm>, #<imm4> 1|1|1|1|0|0|1|0|1|D|1|1|Vn:4|Vd:4|imm4:4|N|Q|M|0|Vm:4
343 0xfe800d10 0xf2000000 VH<ADD,SUB> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|op|0|N|Q|M|0|Vm:4
344 0xffb00200 0xf4200200 VLD1.<size> <list4>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4 SEE “Related encodings”
345 0xffb00f00 0xf4a00c00 VLD1.<size> <list1>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|0|0|size:2|T|a|Rm:4
346 0xffb00300 0xf4a00000 VLD1.<size> <list1>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|0|0|index_align:4|Rm:4 SEE VLD1 (single element to all lanes)
347 0xffb00400 0xf4200000 VLD2.<size> <list4>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4 SEE “Related encodings”
348 0xffb00f00 0xf4a00d00 VLD2.<size> <list1>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|0|1|size:2|T|a|Rm:4
349 0xffb00300 0xf4a00100 VLD2.<size> <list1>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|0|1|index_align:4|Rm:4 SEE VLD2 (single 2-element structure to all lanes)
350 0xffb00f10 0xf4a00e00 VLD3.<size> <list3t>, [<Rn>]{!} 1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|1|0|size:2|T|a|Rm:4
351 0xffb00310 0xf4a00200 VLD3.<size> <list3>, [<Rn>]{!} 1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|1|0|index_align:4|Rm:4 SEE VLD3 (single 3-element structure to all lanes)
352 0xffb00e20 0xf4200400 VLD3.<size> <list4>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4 SEE “Related encodings”
353 0xffb00f00 0xf4a00f00 VLD4.<size> <list4>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|1|1|1|1|size:2|T|a|Rm:4
354 0xffb00e00 0xf4200000 VLD4.<size> <list1>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|0|D|1|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4 SEE “Related encodings”
355 0xffb00300 0xf4a00300 VLD4.<size> <list1>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|1|D|1|0|Rn:4|Vd:4|size:2|1|1|index_align:4|Rm:4 SEE VLD4 (single 4-element structure to all lanes)
356 0x0f300e00 0x0d100a00 VLDR<c> <Sd,Dd>, [<Rn>{,#+/-<imm8>}] cond:4|1|1|0|1|U|D|0|1|Rn:4|Vd:4|1|0|1|sz|imm8:8 vfp
357 0x0fe00fd0 0x0c400b10 VMOV<c> <Dm>, <Rt>, <Rt2> cond:4|1|1|0|0|0|1|0|op|Rt2:4|Rt:4|1|0|1|1|0|0|M|1|Vm:4
358 0xffb00f10 0xf2200110 VMOV <Qd>, <Qm> 1|1|1|1|0|0|1|0|0|D|1|0|Vm:4|Vd:4|0|0|0|1|M|Q|M|1|Vm:4 SEE VORR (register)
359 0x0fe00fd0 0x0c400a10 VMOV<c> <Sm>, <Sm1>, <Rt>, <Rt2> cond:4|1|1|0|0|0|1|0|op|Rt2:4|Rt:4|1|0|1|0|0|0|M|1|Vm:4
360 0x0ff00f7f 0x0e000a10 VMOV<c> <Sn>, <Rt> cond:4|1|1|1|0|0|0|0|0|Vn:4|Rt:4|1|0|1|0|N|0|0|1|0|0|0|0 vfp
361 0x0ff00f7f 0x0e100a10 VMOV<c> <Rt>, <Sn> cond:4|1|1|1|0|0|0|0|1|Vn:4|Rt:4|1|0|1|0|N|0|0|1|0|0|0|0 vfp
362 0xfeb80090 0xf2800010 VMOV.<dt_simd> <Qd>, #<imm_simd> 1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|op|1|imm4:4 SEE VORR (immediate) SEE “Related encodings”
363 0x0fd00f7f 0x0e100b10 VMOV<c>.32 <Rt>, <Dn[x]> cond:4|1|1|1|0|0|0|opc1|1|Vn:4|Rt:4|1|0|1|1|N|0|0|1|0|0|0|0 vfp
364 0x0fd00f7f 0x0e000b10 VMOV<c>.32 <Dd[x]>, <Rt> cond:4|1|1|1|0|0|0|opc1|0|Vd:4|Rt:4|1|0|1|1|D|0|0|1|0|0|0|0 vfp
365 0x0fb00ef0 0x0eb00a00 VMOV<c>.F<32,64> <Sd,Dd>, #<imm_vfp> cond:4|1|1|1|0|1|D|1|1|imm4H:4|Vd:4|1|0|1|sz|0|0|0|0|imm4L:4 vfp
366 0x0fbf0ed0 0x0eb00a40 VMOV<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|0|Vd:4|1|0|1|sz|0|1|M|0|Vm:4 vfp
367 0xfe871fd0 0xf2800a10 VMOVL.<dt> <Qd>, <Dm> 1|1|1|1|0|0|1|U|1|D|imm3:3|0|0|0|Vd:4|1|0|1|0|0|0|M|1|Vm:4 SEE “Related encodings” SEE VSHLL
368 0xffb30fd1 0xf3b20200 VMOVN.<dt> <Dd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|1|0|0|0|M|0|Vm:4
369 0x0fff0fff 0x0ef10a10 VMRS<c> <Rt_nzcv>, FPSCR cond:4|1|1|1|0|1|1|1|1|0|0|0|1|Rt:4|1|0|1|0|0|0|0|1|0|0|0|0 vfp
370 0x0fff0fff 0x0ee10a10 VMSR<c> FPSCR, <Rt> cond:4|1|1|1|0|1|1|1|0|0|0|0|1|Rt:4|1|0|1|0|0|0|0|1|0|0|0|0 vfp
371 0xfe800e50 0xf2800840 VMUL.<dt> <Qd>, <Qn>, <Dm[x]> 1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|1|0|0|F|N|1|M|0|Vm:4 SEE “Related encodings”
372 0xfe800f10 0xf2000910 VMUL.<dt> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|op|0|D|size:2|Vn:4|Vd:4|1|0|0|1|N|Q|M|1|Vm:4
373 0xffa00f10 0xf3000d10 VMUL.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|0|D|0|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|1|Vm:4
374 0x0fb00e50 0x0e200a00 VMUL<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|0|Vn:4|Vd:4|1|0|1|sz|N|0|M|0|Vm:4 vfp
375 0xfe801d50 0xf2800c00 VMULL.<dt> <Qd>, <Dn>, <Dm> 1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|1|1|op|0|N|0|M|0|Vm:4 SEE “Related encodings”
376 0xfe801f50 0xf2800a40 VMULL.<dt> <Qd>, <Dn>, <Dm[x]> 1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|1|0|1|0|N|1|M|0|Vm:4 SEE “Related encodings”
377 0xffbf0f90 0xf3b00580 VMVN <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|0|1|1|Q|M|0|Vm:4
378 0xfeb800b0 0xf2800030 VMVN.<dt> <Qd>, #<imm3> 1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|1|1|imm4:4 SEE “Related encodings”
379 0xffb30b90 0xf3b10380 VNEG.<dt> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|1|Vd:4|0|F|1|1|1|Q|M|0|Vm:4
380 0x0fbf0ed0 0x0eb10a40 VNEG<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|1|Vd:4|1|0|1|sz|0|1|M|0|Vm:4 vfp
381 0x0fb00e10 0x0e100a00 VN<MLS,MLA><c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|0|1|Vn:4|Vd:4|1|0|1|sz|N|op|M|0|Vm:4 vfp
382 0x0fb00e50 0x0e200a40 VNMUL<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|0|Vn:4|Vd:4|1|0|1|sz|N|1|M|0|Vm:4 vfp
383 0xffb00f10 0xf2300110 VORN <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|1|1|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4
384 0xffb00f10 0xf2200110 VORR <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|1|0|Vn:4|Vd:4|0|0|0|1|N|Q|M|1|Vm:4 SEE VMOV (register)
385 0xfeb800b0 0xf2800010 VORR.<dt> <Qd>, #<imm3> 1|1|1|1|0|0|1|i|1|D|0|0|0|imm3:3|Vd:4|cmode:4|0|Q|0|1|imm4:4 SEE VMOV (immediate)
386 0xfe800f00 0xf2000a00 VP<MIN,MAX>.<dt> <Dd>, <Dn>, <Dm> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|1|0|1|0|N|Q|M|op|Vm:4
387 0xff800f10 0xf3000f00 VP<MIN,MAX>.F32 <Dd>, <Dn>, <Dm> 1|1|1|1|0|0|1|1|0|D|op|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|0|Vm:4
388 0xffb30f10 0xf3b00600 VPADAL.<dt> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|1|0|op|Q|M|0|Vm:4
389 0xff800f10 0xf2000b10 VPADD.<dt> <Dd>, <Dn>, <Dm> 1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|1|1|N|Q|M|1|Vm:4
390 0xffa00f10 0xf3000d00 VPADD.F32 <Dd>, <Dn>, <Dm> 1|1|1|1|0|0|1|1|0|D|0|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4
391 0xffb30f10 0xf3b00200 VPADDL.<dt> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|0|1|0|op|Q|M|0|Vm:4
392 0x0fbf0f00 0x0cbd0a00 VPOP <vlist32> cond:4|1|1|0|0|1|D|1|1|1|1|0|1|Vd:4|1|0|1|0|imm8:8
393 0x0fbf0f00 0x0cbd0b00 VPOP <vlist64> cond:4|1|1|0|0|1|D|1|1|1|1|0|1|Vd:4|1|0|1|1|imm8:8
394 0x0fbf0f00 0x0d2d0a00 VPUSH<c> <vlist32> cond:4|1|1|0|1|0|D|1|0|1|1|0|1|Vd:4|1|0|1|0|imm8:8
395 0x0fbf0f00 0x0d2d0b00 VPUSH<c> <vlist64> cond:4|1|1|0|1|0|D|1|0|1|1|0|1|Vd:4|1|0|1|1|imm8:8
396 0xffb30f90 0xf3b00700 VQABS.<dt> <Qd>,<Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|1|1|0|Q|M|0|Vm:4
397 0xfe800f10 0xf2000010 VQADD.<dt> <Qd>,<Qn>,<Qm> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|0|0|N|Q|M|1|Vm:4
398 0xff801d50 0xf2800900 VQD<MLAL,MLSL>.<dt> <Qd>,<Dn>,<Dm> 1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|1|0|op|1|N|0|M|0|Vm:4 SEE “Related encodings”
399 0xff801b50 0xf2800340 VQD<MLAL,MLSL>.<dt> <Qd>,<Dn>,<Dm[x]> 1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|0|op|1|1|N|1|M|0|Vm:4 SEE “Related encodings”
400 0xfe800f50 0xf2800c40 VQDMULH.<dt> <Qd>,<Qn>,<Dm[x]> 1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|1|1|0|0|N|1|M|0|Vm:4
401 0xff800f10 0xf2000b00 VQDMULH.<dt> <Qd>,<Qn>,<Qm> 1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|1|1|N|Q|M|0|Vm:4
402 0xff801f50 0xf2800d00 VQDMULL.<dt> <Qd>,<Dn>,<Dm> 1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|1|1|0|1|N|0|M|0|Vm:4 SEE “Related encodings”
403 0xff801f50 0xf2800b40 VQDMULL.<dt> <Qd>,<Dn>,<Dm[x]> 1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|1|0|1|1|N|1|M|0|Vm:4 SEE “Related encodings”
404 0xffb30f11 0xf3b20200 VQMOV{U}N.<type><size> <Dd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|1|0|op:2|M|0|Vm:4 SEE VMOVN
405 0xffb30f90 0xf3b00780 VQNEG.<dt> <Qd>,<Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|1|1|1|1|Q|M|0|Vm:4
406 0xfe800f50 0xf2800d40 VQRDMULH.<dt> <Qd>,<Qn>,<Dm[x]> 1|1|1|1|0|0|1|Q|1|D|size:2|Vn:4|Vd:4|1|1|0|1|N|1|M|0|Vm:4
407 0xff800f10 0xf3000b00 VQRDMULH.<dt> <Qd>,<Qn>,<Qm> 1|1|1|1|0|0|1|1|0|D|size:2|Vn:4|Vd:4|1|0|1|1|N|Q|M|0|Vm:4
408 0xfe800f10 0xf2000510 VQRSHL.<type><size> <Qd>,<Qm>,<Qn> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|1|N|Q|M|1|Vm:4
409 0xfe800ed1 0xf2800850 VQRSHR{U}N.<type><size> <Dd>,<Qm>,#<imm6> 1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|0|0|op|0|1|M|1|Vm:4 SEE “Related encodings” SEE VRSHRN
410 0xfe800f10 0xf2000410 VQSHL.<type><size> <Qd>,<Qm>,<Qn> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|0|N|Q|M|1|Vm:4
411 0xfe800e90 0xf2800690 VQSHL{U}.<type><size> <Qd>,<Qm>,#<imm6> 1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|1|1|op|L|Q|M|1|Vm:4 SEE “Related encodings”
412 0xfe800ed1 0xf2800810 VQSHR{U}N.<type><size> <Dd>,<Qm>,#<imm6> 1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|0|0|op|0|0|M|1|Vm:4 SEE “Related encodings” SEE VSHRN
413 0xfe800f10 0xf2000210 VQSUB.<type><size> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|1|0|N|Q|M|1|Vm:4
414 0xff810f51 0xf3800400 VRADDHN.<dt> <Dd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|1|D|size:2|Vn:4|Vd:4|0|1|0|0|N|0|M|0|Vm:4 SEE “Related encodings”
415 0xffbf0e90 0xf3bb0400 VRECPE.<dt> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|1|Vd:4|0|1|0|F|0|Q|M|0|Vm:4
416 0xffa00f10 0xf2000f10 VRECPS.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|0|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|1|Vm:4
417 0xffb30e10 0xf3b00000 VREV<n>.<size> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|0|0|Vd:4|0|0|0|op:2|Q|M|0|Vm:4
418 0xfe800f10 0xf2000100 VRHADD <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|0|0|1|N|Q|M|0|Vm:4
419 0xfe800f10 0xf2000500 VRSHL.<type><size> <Qd>, <Qm>, <Qn> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|1|N|Q|M|0|Vm:4
420 0xfe800f90 0xf2800290 VRSHR.<type><size> <Qd>, <Qm>, #<imm6> 1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|1|0|L|Q|M|1|Vm:4 SEE “Related encodings”
421 0xff800fd1 0xf2800850 VRSHRN.I<size> <Dd>, <Qm>, #<imm6> 1|1|1|1|0|0|1|0|1|D|imm6:6|Vd:4|1|0|0|0|0|1|M|1|Vm:4 SEE “Related encodings”
422 0xffbf0e90 0xf3bb0480 VRSQRTE.<dt> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|1|Vd:4|0|1|0|F|1|Q|M|0|Vm:4
423 0xffa00f10 0xf2200f10 VRSQRTS.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|1|sz|Vn:4|Vd:4|1|1|1|1|N|Q|M|1|Vm:4
424 0xfe800f90 0xf2800390 VRSRA.<type><size> <Qd>, <Qm>, #<imm6> 1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|1|1|L|Q|M|1|Vm:4 SEE “Related encodings”
425 0xff810f51 0xf3800600 VRSUBHN.<dt> <Dd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|1|D|size:2|Vn:4|Vd:4|0|1|1|0|N|0|M|0|Vm:4 SEE “Related encodings”
426 0xff800f90 0xf2800590 VSHL.I<size> <Qd>, <Qm>, #<imm6> 1|1|1|1|0|0|1|0|1|D|imm6:6|Vd:4|0|1|0|1|L|Q|M|1|Vm:4 SEE “Related encodings”
427 0xfe800f10 0xf2000400 VSHL.I<size> <Qd>, <Qm>, <Qn> 1|1|1|1|0|0|1|U|0|D|size:2|Vn:4|Vd:4|0|1|0|0|N|Q|M|0|Vm:4
428 0xffb31fd0 0xf3b20300 VSHLL.<type><size> <Qd>, <Dm>, #<immsize> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|1|1|0|0|M|0|Vm:4
429 0xfe801fd0 0xf2800a10 VSHLL.<type><size> <Qd>, <Dm>, #<imm6> 1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|1|0|1|0|0|0|M|1|Vm:4 SEE “Related encodings” SEE VMOVL
430 0xfe800f90 0xf2800090 VSHR.<type><size_vs> <Qd>, <Qm>, #<imm_vs> 1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|0|0|L|Q|M|1|Vm:4 SEE “Related encodings”
431 0xff800fd1 0xf2800810 VSHRN.I<size_vsn> <Dd>, <Qm>, #<imm_vsn> 1|1|1|1|0|0|1|0|1|D|imm6:6|Vd:4|1|0|0|0|0|0|M|1|Vm:4 SEE “Related encodings”
432 0xff800f90 0xf3800590 VSLI.<size_vs> <Qd>, <Qm>, #<imm_vs> 1|1|1|1|0|0|1|1|1|D|imm6:6|Vd:4|0|1|0|1|L|Q|M|1|Vm:4 SEE “Related encodings”
433 0x0fbf0ed0 0x0eb10ac0 VSQRT<c>.F<32,64> <Sd,Dd>, <Sm,Dm> cond:4|1|1|1|0|1|D|1|1|0|0|0|1|Vd:4|1|0|1|sz|1|1|M|0|Vm:4 vfp
434 0xfe800f90 0xf2800190 VSRA.<type_U><size_vs> <Qd>, <Qm>, #<imm_vs> 1|1|1|1|0|0|1|U|1|D|imm6:6|Vd:4|0|0|0|1|L|Q|M|1|Vm:4 SEE “Related encodings”
435 0xff800f90 0xf3800490 VSRI.<size_vs> <Qd>, <Qm>, #<imm_vs> 1|1|1|1|0|0|1|1|1|D|imm6:6|Vd:4|0|1|0|0|L|Q|M|1|Vm:4 SEE “Related encodings”
436 0xffb00200 0xf4000200 VST1.<size> <list4>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4 SEE “Related encodings”
437 0xffb00300 0xf4800000 VST1.<size> <list1>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|0|0|index_align:4|Rm:4
438 0xffb00400 0xf4000000 VST2.<size> <list4>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4 SEE “Related encodings”
439 0xffb00300 0xf4800100 VST2.<size> <list1>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|0|1|index_align:4|Rm:4
440 0xffb00300 0xf4800200 VST3.<size> <list4>, [<Rn>]{!} 1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|1|0|index_align:4|Rm:4
441 0xffb00e20 0xf4000400 VST3.<size> <list1>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4 SEE “Related encodings”
442 0xffb00e00 0xf4000000 VST4.<size> <list4>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|0|D|0|0|Rn:4|Vd:4|type:4|size:2|align:2|Rm:4 SEE “Related encodings”
443 0xffb00300 0xf4800300 VST4.<size> <list1>, [<Rn>{@<align>}]{!} 1|1|1|1|0|1|0|0|1|D|0|0|Rn:4|Vd:4|size:2|1|1|index_align:4|Rm:4
444 0x0f300e00 0x0d000a00 VSTR<c> <Sd,Dd>, [<Rn>{,#+/-<imm8>}] cond:4|1|1|0|1|U|D|0|0|Rn:4|Vd:4|1|0|1|sz|imm8:8 vfp
445 0xff800f10 0xf3000800 VSUB.<dt_Isize> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|1|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|0|Vm:4
446 0xffa00f10 0xf2200d00 VSUB.F32 <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|1|sz|Vn:4|Vd:4|1|1|0|1|N|Q|M|0|Vm:4
447 0x0fb00e50 0x0e300a40 VSUB<c>.F<32,64> <Sd,Dd>, <Sn,Dn>, <Sm,Dm> cond:4|1|1|1|0|0|D|1|1|Vn:4|Vd:4|1|0|1|sz|N|1|M|0|Vm:4 vfp
448 0xff810f51 0xf2800600 VSUBHN.<dt_Isize> <Dd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|1|D|size:2|Vn:4|Vd:4|0|1|1|0|N|0|M|0|Vm:4 SEE “Related encodings”
449 0xfe801e50 0xf2800200 VSUBL.<dt_Usize> <Qd>, <Dn>, <Dm> 1|1|1|1|0|0|1|U|1|D|size:2|Vn:4|Vd:4|0|0|1|op|N|0|M|0|Vm:4 SEE “Related encodings”
450 0xffbf0f90 0xf3b20000 VSWP <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|0|0|Q|M|0|Vm:4
451 0xffb30f90 0xf3b20080 VTRN.<size_n> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|0|1|Q|M|0|Vm:4
452 0xff800f10 0xf2000810 VTST.<size_n> <Qd>, <Qn>, <Qm> 1|1|1|1|0|0|1|0|0|D|size:2|Vn:4|Vd:4|1|0|0|0|N|Q|M|1|Vm:4
453 0xffb30f90 0xf3b20100 VUZP.<size_n> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|1|0|Q|M|0|Vm:4
454 0xffb30f90 0xf3b20180 VZIP.<size_n> <Qd>, <Qm> 1|1|1|1|0|0|1|1|1|D|1|1|size:2|1|0|Vd:4|0|0|0|1|1|Q|M|0|Vm:4
455 0x0fffffff 0x0320f002 WFE<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|0
456 0x0fffffff 0x0320f003 WFI<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|1|1
457 0x0fffffff 0x0320f001 YIELD<c> cond:4|0|0|1|1|0|0|1|0|0|0|0|0|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|0|0|0|0|1
458 0xffffffff 0xf7fabcfd UNDEF 1|1|1|1|0|1|1|1|1|1|1|1|1|0|1|0|1|0|1|1|1|1|0|0|1|1|1|1|1|1|0|1
@@ -0,0 +1,2 @@
tables.go: ../armmap/map.go ../arm.csv
go run ../armmap/map.go -fmt=decoder ../arm.csv >_tables.go && gofmt _tables.go >tables.go && rm _tables.go
@@ -0,0 +1,569 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package armasm
import (
"encoding/binary"
"fmt"
)
// An instFormat describes the format of an instruction encoding.
// An instruction with 32-bit value x matches the format if x&mask == value
// and the condition matches.
// The condition matches if x>>28 == 0xF && value>>28==0xF
// or if x>>28 != 0xF and value>>28 == 0.
// If x matches the format, then the rest of the fields describe how to interpret x.
// The opBits describe bits that should be extracted from x and added to the opcode.
// For example opBits = 0x1234 means that the value
//
// (2 bits at offset 1) followed by (4 bits at offset 3)
//
// should be added to op.
// Finally the args describe how to decode the instruction arguments.
// args is stored as a fixed-size array; if there are fewer than len(args) arguments,
// args[i] == 0 marks the end of the argument list.
type instFormat struct {
mask uint32
value uint32
priority int8
op Op
opBits uint64
args instArgs
}
type instArgs [4]instArg
var (
errMode = fmt.Errorf("unsupported execution mode")
errShort = fmt.Errorf("truncated instruction")
errUnknown = fmt.Errorf("unknown instruction")
)
var decoderCover []bool
// Decode decodes the leading bytes in src as a single instruction.
func Decode(src []byte, mode Mode) (inst Inst, err error) {
if mode != ModeARM {
return Inst{}, errMode
}
if len(src) < 4 {
return Inst{}, errShort
}
if decoderCover == nil {
decoderCover = make([]bool, len(instFormats))
}
x := binary.LittleEndian.Uint32(src)
// The instFormat table contains both conditional and unconditional instructions.
// Considering only the top 4 bits, the conditional instructions use mask=0, value=0,
// while the unconditional instructions use mask=f, value=f.
// Prepare a version of x with the condition cleared to 0 in conditional instructions
// and then assume mask=f during matching.
const condMask = 0xf0000000
xNoCond := x
if x&condMask != condMask {
xNoCond &^= condMask
}
var priority int8
Search:
for i := range instFormats {
f := &instFormats[i]
if xNoCond&(f.mask|condMask) != f.value || f.priority <= priority {
continue
}
delta := uint32(0)
deltaShift := uint(0)
for opBits := f.opBits; opBits != 0; opBits >>= 16 {
n := uint(opBits & 0xFF)
off := uint((opBits >> 8) & 0xFF)
delta |= (x >> off) & (1<<n - 1) << deltaShift
deltaShift += n
}
op := f.op + Op(delta)
// Special case: BKPT encodes with condition but cannot have one.
if op&^15 == BKPT_EQ && op != BKPT {
continue Search
}
var args Args
for j, aop := range f.args {
if aop == 0 {
break
}
arg := decodeArg(aop, x)
if arg == nil { // cannot decode argument
continue Search
}
args[j] = arg
}
decoderCover[i] = true
inst = Inst{
Op: op,
Args: args,
Enc: x,
Len: 4,
}
priority = f.priority
continue Search
}
if inst.Op != 0 {
return inst, nil
}
return Inst{}, errUnknown
}
// An instArg describes the encoding of a single argument.
// In the names used for arguments, _p_ means +, _m_ means -,
// _pm_ means ± (usually keyed by the U bit).
// The _W suffix indicates a general addressing mode based on the P and W bits.
// The _offset and _postindex suffixes force the given addressing mode.
// The rest should be somewhat self-explanatory, at least given
// the decodeArg function.
type instArg uint8
const (
_ instArg = iota
arg_APSR
arg_FPSCR
arg_Dn_half
arg_R1_0
arg_R1_12
arg_R2_0
arg_R2_12
arg_R_0
arg_R_12
arg_R_12_nzcv
arg_R_16
arg_R_16_WB
arg_R_8
arg_R_rotate
arg_R_shift_R
arg_R_shift_imm
arg_SP
arg_Sd
arg_Sd_Dd
arg_Dd_Sd
arg_Sm
arg_Sm_Dm
arg_Sn
arg_Sn_Dn
arg_const
arg_endian
arg_fbits
arg_fp_0
arg_imm24
arg_imm5
arg_imm5_32
arg_imm5_nz
arg_imm_12at8_4at0
arg_imm_4at16_12at0
arg_imm_vfp
arg_label24
arg_label24H
arg_label_m_12
arg_label_p_12
arg_label_pm_12
arg_label_pm_4_4
arg_lsb_width
arg_mem_R
arg_mem_R_pm_R_W
arg_mem_R_pm_R_postindex
arg_mem_R_pm_R_shift_imm_W
arg_mem_R_pm_R_shift_imm_offset
arg_mem_R_pm_R_shift_imm_postindex
arg_mem_R_pm_imm12_W
arg_mem_R_pm_imm12_offset
arg_mem_R_pm_imm12_postindex
arg_mem_R_pm_imm8_W
arg_mem_R_pm_imm8_postindex
arg_mem_R_pm_imm8at0_offset
arg_option
arg_registers
arg_registers1
arg_registers2
arg_satimm4
arg_satimm5
arg_satimm4m1
arg_satimm5m1
arg_widthm1
)
// decodeArg decodes the arg described by aop from the instruction bits x.
// It returns nil if x cannot be decoded according to aop.
func decodeArg(aop instArg, x uint32) Arg {
switch aop {
default:
return nil
case arg_APSR:
return APSR
case arg_FPSCR:
return FPSCR
case arg_R_0:
return Reg(x & (1<<4 - 1))
case arg_R_8:
return Reg((x >> 8) & (1<<4 - 1))
case arg_R_12:
return Reg((x >> 12) & (1<<4 - 1))
case arg_R_16:
return Reg((x >> 16) & (1<<4 - 1))
case arg_R_12_nzcv:
r := Reg((x >> 12) & (1<<4 - 1))
if r == R15 {
return APSR_nzcv
}
return r
case arg_R_16_WB:
mode := AddrLDM
if (x>>21)&1 != 0 {
mode = AddrLDM_WB
}
return Mem{Base: Reg((x >> 16) & (1<<4 - 1)), Mode: mode}
case arg_R_rotate:
Rm := Reg(x & (1<<4 - 1))
typ, count := decodeShift(x)
// ROR #0 here means ROR #0, but decodeShift rewrites to RRX #1.
if typ == RotateRightExt {
return Rm
}
return RegShift{Rm, typ, count}
case arg_R_shift_R:
Rm := Reg(x & (1<<4 - 1))
Rs := Reg((x >> 8) & (1<<4 - 1))
typ := Shift((x >> 5) & (1<<2 - 1))
return RegShiftReg{Rm, typ, Rs}
case arg_R_shift_imm:
Rm := Reg(x & (1<<4 - 1))
typ, count := decodeShift(x)
if typ == ShiftLeft && count == 0 {
return Reg(Rm)
}
return RegShift{Rm, typ, count}
case arg_R1_0:
return Reg((x & (1<<4 - 1)))
case arg_R1_12:
return Reg(((x >> 12) & (1<<4 - 1)))
case arg_R2_0:
return Reg((x & (1<<4 - 1)) | 1)
case arg_R2_12:
return Reg(((x >> 12) & (1<<4 - 1)) | 1)
case arg_SP:
return SP
case arg_Sd_Dd:
v := (x >> 12) & (1<<4 - 1)
vx := (x >> 22) & 1
sz := (x >> 8) & 1
if sz != 0 {
return D0 + Reg(vx<<4+v)
} else {
return S0 + Reg(v<<1+vx)
}
case arg_Dd_Sd:
return decodeArg(arg_Sd_Dd, x^(1<<8))
case arg_Sd:
v := (x >> 12) & (1<<4 - 1)
vx := (x >> 22) & 1
return S0 + Reg(v<<1+vx)
case arg_Sm_Dm:
v := (x >> 0) & (1<<4 - 1)
vx := (x >> 5) & 1
sz := (x >> 8) & 1
if sz != 0 {
return D0 + Reg(vx<<4+v)
} else {
return S0 + Reg(v<<1+vx)
}
case arg_Sm:
v := (x >> 0) & (1<<4 - 1)
vx := (x >> 5) & 1
return S0 + Reg(v<<1+vx)
case arg_Dn_half:
v := (x >> 16) & (1<<4 - 1)
vx := (x >> 7) & 1
return RegX{D0 + Reg(vx<<4+v), int((x >> 21) & 1)}
case arg_Sn_Dn:
v := (x >> 16) & (1<<4 - 1)
vx := (x >> 7) & 1
sz := (x >> 8) & 1
if sz != 0 {
return D0 + Reg(vx<<4+v)
} else {
return S0 + Reg(v<<1+vx)
}
case arg_Sn:
v := (x >> 16) & (1<<4 - 1)
vx := (x >> 7) & 1
return S0 + Reg(v<<1+vx)
case arg_const:
v := x & (1<<8 - 1)
rot := (x >> 8) & (1<<4 - 1) * 2
if rot > 0 && v&3 == 0 {
// could rotate less
return ImmAlt{uint8(v), uint8(rot)}
}
if rot >= 24 && ((v<<(32-rot))&0xFF)>>(32-rot) == v {
// could wrap around to rot==0.
return ImmAlt{uint8(v), uint8(rot)}
}
return Imm(v>>rot | v<<(32-rot))
case arg_endian:
return Endian((x >> 9) & 1)
case arg_fbits:
return Imm((16 << ((x >> 7) & 1)) - ((x&(1<<4-1))<<1 | (x>>5)&1))
case arg_fp_0:
return Imm(0)
case arg_imm24:
return Imm(x & (1<<24 - 1))
case arg_imm5:
return Imm((x >> 7) & (1<<5 - 1))
case arg_imm5_32:
x = (x >> 7) & (1<<5 - 1)
if x == 0 {
x = 32
}
return Imm(x)
case arg_imm5_nz:
x = (x >> 7) & (1<<5 - 1)
if x == 0 {
return nil
}
return Imm(x)
case arg_imm_4at16_12at0:
return Imm((x>>16)&(1<<4-1)<<12 | x&(1<<12-1))
case arg_imm_12at8_4at0:
return Imm((x>>8)&(1<<12-1)<<4 | x&(1<<4-1))
case arg_imm_vfp:
x = (x>>16)&(1<<4-1)<<4 | x&(1<<4-1)
return Imm(x)
case arg_label24:
imm := (x & (1<<24 - 1)) << 2
return PCRel(int32(imm<<6) >> 6)
case arg_label24H:
h := (x >> 24) & 1
imm := (x&(1<<24-1))<<2 | h<<1
return PCRel(int32(imm<<6) >> 6)
case arg_label_m_12:
d := int32(x & (1<<12 - 1))
return Mem{Base: PC, Mode: AddrOffset, Offset: int16(-d)}
case arg_label_p_12:
d := int32(x & (1<<12 - 1))
return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)}
case arg_label_pm_12:
d := int32(x & (1<<12 - 1))
u := (x >> 23) & 1
if u == 0 {
d = -d
}
return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)}
case arg_label_pm_4_4:
d := int32((x>>8)&(1<<4-1)<<4 | x&(1<<4-1))
u := (x >> 23) & 1
if u == 0 {
d = -d
}
return PCRel(d)
case arg_lsb_width:
lsb := (x >> 7) & (1<<5 - 1)
msb := (x >> 16) & (1<<5 - 1)
if msb < lsb || msb >= 32 {
return nil
}
return Imm(msb + 1 - lsb)
case arg_mem_R:
Rn := Reg((x >> 16) & (1<<4 - 1))
return Mem{Base: Rn, Mode: AddrOffset}
case arg_mem_R_pm_R_postindex:
// Treat [<Rn>],+/-<Rm> like [<Rn>,+/-<Rm>{,<shift>}]{!}
// by forcing shift bits to <<0 and P=0, W=0 (postindex=true).
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5|1<<24|1<<21))
case arg_mem_R_pm_R_W:
// Treat [<Rn>,+/-<Rm>]{!} like [<Rn>,+/-<Rm>{,<shift>}]{!}
// by forcing shift bits to <<0.
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5))
case arg_mem_R_pm_R_shift_imm_offset:
// Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!}
// by forcing P=1, W=0 (index=false, wback=false).
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<21)|1<<24)
case arg_mem_R_pm_R_shift_imm_postindex:
// Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!}
// by forcing P=0, W=0 (postindex=true).
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<24|1<<21))
case arg_mem_R_pm_R_shift_imm_W:
Rn := Reg((x >> 16) & (1<<4 - 1))
Rm := Reg(x & (1<<4 - 1))
typ, count := decodeShift(x)
u := (x >> 23) & 1
w := (x >> 21) & 1
p := (x >> 24) & 1
if p == 0 && w == 1 {
return nil
}
sign := int8(+1)
if u == 0 {
sign = -1
}
mode := AddrMode(uint8(p<<1) | uint8(w^1))
return Mem{Base: Rn, Mode: mode, Sign: sign, Index: Rm, Shift: typ, Count: count}
case arg_mem_R_pm_imm12_offset:
// Treat [<Rn>,#+/-<imm12>] like [<Rn>{,#+/-<imm12>}]{!}
// by forcing P=1, W=0 (index=false, wback=false).
return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<21)|1<<24)
case arg_mem_R_pm_imm12_postindex:
// Treat [<Rn>],#+/-<imm12> like [<Rn>{,#+/-<imm12>}]{!}
// by forcing P=0, W=0 (postindex=true).
return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<24|1<<21))
case arg_mem_R_pm_imm12_W:
Rn := Reg((x >> 16) & (1<<4 - 1))
u := (x >> 23) & 1
w := (x >> 21) & 1
p := (x >> 24) & 1
if p == 0 && w == 1 {
return nil
}
sign := int8(+1)
if u == 0 {
sign = -1
}
imm := int16(x & (1<<12 - 1))
mode := AddrMode(uint8(p<<1) | uint8(w^1))
return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm}
case arg_mem_R_pm_imm8_postindex:
// Treat [<Rn>],#+/-<imm8> like [<Rn>{,#+/-<imm8>}]{!}
// by forcing P=0, W=0 (postindex=true).
return decodeArg(arg_mem_R_pm_imm8_W, x&^(1<<24|1<<21))
case arg_mem_R_pm_imm8_W:
Rn := Reg((x >> 16) & (1<<4 - 1))
u := (x >> 23) & 1
w := (x >> 21) & 1
p := (x >> 24) & 1
if p == 0 && w == 1 {
return nil
}
sign := int8(+1)
if u == 0 {
sign = -1
}
imm := int16((x>>8)&(1<<4-1)<<4 | x&(1<<4-1))
mode := AddrMode(uint8(p<<1) | uint8(w^1))
return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm}
case arg_mem_R_pm_imm8at0_offset:
Rn := Reg((x >> 16) & (1<<4 - 1))
u := (x >> 23) & 1
sign := int8(+1)
if u == 0 {
sign = -1
}
imm := int16(x&(1<<8-1)) << 2
return Mem{Base: Rn, Mode: AddrOffset, Offset: int16(sign) * imm}
case arg_option:
return Imm(x & (1<<4 - 1))
case arg_registers:
return RegList(x & (1<<16 - 1))
case arg_registers2:
x &= 1<<16 - 1
n := 0
for i := 0; i < 16; i++ {
if x>>uint(i)&1 != 0 {
n++
}
}
if n < 2 {
return nil
}
return RegList(x)
case arg_registers1:
Rt := (x >> 12) & (1<<4 - 1)
return RegList(1 << Rt)
case arg_satimm4:
return Imm((x >> 16) & (1<<4 - 1))
case arg_satimm5:
return Imm((x >> 16) & (1<<5 - 1))
case arg_satimm4m1:
return Imm((x>>16)&(1<<4-1) + 1)
case arg_satimm5m1:
return Imm((x>>16)&(1<<5-1) + 1)
case arg_widthm1:
return Imm((x>>16)&(1<<5-1) + 1)
}
}
// decodeShift decodes the shift-by-immediate encoded in x.
func decodeShift(x uint32) (Shift, uint8) {
count := (x >> 7) & (1<<5 - 1)
typ := Shift((x >> 5) & (1<<2 - 1))
switch typ {
case ShiftRight, ShiftRightSigned:
if count == 0 {
count = 32
}
case RotateRight:
if count == 0 {
typ = RotateRightExt
count = 1
}
}
return typ, uint8(count)
}
@@ -0,0 +1,69 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package armasm
import (
"encoding/hex"
"io/ioutil"
"strconv"
"strings"
"testing"
)
func TestDecode(t *testing.T) {
data, err := ioutil.ReadFile("testdata/decode.txt")
if err != nil {
t.Fatal(err)
}
all := string(data)
for strings.Contains(all, "\t\t") {
all = strings.Replace(all, "\t\t", "\t", -1)
}
for _, line := range strings.Split(all, "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
f := strings.SplitN(line, "\t", 4)
i := strings.Index(f[0], "|")
if i < 0 {
t.Errorf("parsing %q: missing | separator", f[0])
continue
}
if i%2 != 0 {
t.Errorf("parsing %q: misaligned | separator", f[0])
}
size := i / 2
code, err := hex.DecodeString(f[0][:i] + f[0][i+1:])
if err != nil {
t.Errorf("parsing %q: %v", f[0], err)
continue
}
mode, err := strconv.Atoi(f[1])
if err != nil {
t.Errorf("invalid mode %q in: %s", f[1], line)
continue
}
syntax, asm := f[2], f[3]
inst, err := Decode(code, Mode(mode))
var out string
if err != nil {
out = "error: " + err.Error()
} else {
switch syntax {
case "gnu":
out = GNUSyntax(inst)
case "plan9": // [sic]
out = GoSyntax(inst, 0, nil, nil)
default:
t.Errorf("unknown syntax %q", syntax)
continue
}
}
if out != asm || inst.Len != size {
t.Errorf("Decode(%s) [%s] = %s, %d, want %s, %d", f[0], syntax, out, inst.Len, asm, size)
}
}
}
@@ -0,0 +1,615 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Support for testing against external disassembler program.
// Copied and simplified from ../../x86/x86asm/ext_test.go.
package armasm
import (
"bufio"
"bytes"
"encoding/hex"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"math/rand"
"os"
"os/exec"
"regexp"
"runtime"
"strings"
"testing"
"time"
)
var (
printTests = flag.Bool("printtests", false, "print test cases that exercise new code paths")
dumpTest = flag.Bool("dump", false, "dump all encodings")
mismatch = flag.Bool("mismatch", false, "log allowed mismatches")
longTest = flag.Bool("long", false, "long test")
keep = flag.Bool("keep", false, "keep object files around")
debug = false
)
// An ExtInst represents a single decoded instruction parsed
// from an external disassembler's output.
type ExtInst struct {
addr uint32
enc [4]byte
nenc int
text string
}
func (r ExtInst) String() string {
return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text)
}
// An ExtDis is a connection between an external disassembler and a test.
type ExtDis struct {
Arch Mode
Dec chan ExtInst
File *os.File
Size int
KeepFile bool
Cmd *exec.Cmd
}
// Run runs the given command - the external disassembler - and returns
// a buffered reader of its standard output.
func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) {
if *keep {
log.Printf("%s\n", strings.Join(cmd, " "))
}
ext.Cmd = exec.Command(cmd[0], cmd[1:]...)
out, err := ext.Cmd.StdoutPipe()
if err != nil {
return nil, fmt.Errorf("stdoutpipe: %v", err)
}
if err := ext.Cmd.Start(); err != nil {
return nil, fmt.Errorf("exec: %v", err)
}
b := bufio.NewReaderSize(out, 1<<20)
return b, nil
}
// Wait waits for the command started with Run to exit.
func (ext *ExtDis) Wait() error {
return ext.Cmd.Wait()
}
// testExtDis tests a set of byte sequences against an external disassembler.
// The disassembler is expected to produce the given syntax and be run
// in the given architecture mode (16, 32, or 64-bit).
// The extdis function must start the external disassembler
// and then parse its output, sending the parsed instructions on ext.Dec.
// The generate function calls its argument f once for each byte sequence
// to be tested. The generate function itself will be called twice, and it must
// make the same sequence of calls to f each time.
// When a disassembly does not match the internal decoding,
// allowedMismatch determines whether this mismatch should be
// allowed, or else considered an error.
func testExtDis(
t *testing.T,
syntax string,
arch Mode,
extdis func(ext *ExtDis) error,
generate func(f func([]byte)),
allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool,
) {
start := time.Now()
ext := &ExtDis{
Dec: make(chan ExtInst),
Arch: arch,
}
errc := make(chan error)
// First pass: write instructions to input file for external disassembler.
file, f, size, err := writeInst(generate)
if err != nil {
t.Fatal(err)
}
ext.Size = size
ext.File = f
defer func() {
f.Close()
if !*keep {
os.Remove(file)
}
}()
// Second pass: compare disassembly against our decodings.
var (
totalTests = 0
totalSkips = 0
totalErrors = 0
errors = make([]string, 0, 100) // sampled errors, at most cap
)
go func() {
errc <- extdis(ext)
}()
generate(func(enc []byte) {
dec, ok := <-ext.Dec
if !ok {
t.Errorf("decoding stream ended early")
return
}
inst, text := disasm(syntax, arch, pad(enc))
totalTests++
if *dumpTest {
fmt.Printf("%x -> %s [%d]\n", enc[:len(enc)], dec.text, dec.nenc)
}
if text != dec.text || inst.Len != dec.nenc {
suffix := ""
if allowedMismatch(text, size, &inst, dec) {
totalSkips++
if !*mismatch {
return
}
suffix += " (allowed mismatch)"
}
totalErrors++
if len(errors) >= cap(errors) {
j := rand.Intn(totalErrors)
if j >= cap(errors) {
return
}
errors = append(errors[:j], errors[j+1:]...)
}
errors = append(errors, fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s", enc, text, inst.Len, dec.text, dec.nenc, suffix))
}
})
if *mismatch {
totalErrors -= totalSkips
}
for _, b := range errors {
t.Log(b)
}
if totalErrors > 0 {
t.Fail()
}
t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds())
if err := <-errc; err != nil {
t.Fatalf("external disassembler: %v", err)
}
}
const start = 0x8000 // start address of text
// writeInst writes the generated byte sequences to a new file
// starting at offset start. That file is intended to be the input to
// the external disassembler.
func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) {
f, err = ioutil.TempFile("", "armasm")
if err != nil {
return
}
file = f.Name()
f.Seek(start, io.SeekStart)
w := bufio.NewWriter(f)
defer w.Flush()
size = 0
generate(func(x []byte) {
if len(x) > 4 {
x = x[:4]
}
if debug {
fmt.Printf("%#x: %x%x\n", start+size, x, zeros[len(x):])
}
w.Write(x)
w.Write(zeros[len(x):])
size += len(zeros)
})
return file, f, size, nil
}
var zeros = []byte{0, 0, 0, 0}
// pad pads the code sequence with pops.
func pad(enc []byte) []byte {
if len(enc) < 4 {
enc = append(enc[:len(enc):len(enc)], zeros[:4-len(enc)]...)
}
return enc
}
// disasm returns the decoded instruction and text
// for the given source bytes, using the given syntax and mode.
func disasm(syntax string, mode Mode, src []byte) (inst Inst, text string) {
// If printTests is set, we record the coverage value
// before and after, and we write out the inputs for which
// coverage went up, in the format expected in testdata/decode.text.
// This produces a fairly small set of test cases that exercise nearly
// all the code.
var cover float64
if *printTests {
cover -= coverage()
}
inst, err := Decode(src, mode)
if err != nil {
text = "error: " + err.Error()
} else {
text = inst.String()
switch syntax {
//case "arm":
// text = ARMSyntax(inst)
case "gnu":
text = GNUSyntax(inst)
//case "plan9": // [sic]
// text = GoSyntax(inst, 0, nil)
default:
text = "error: unknown syntax " + syntax
}
}
if *printTests {
cover += coverage()
if cover > 0 {
max := len(src)
if max > 4 && inst.Len <= 4 {
max = 4
}
fmt.Printf("%x|%x\t%d\t%s\t%s\n", src[:inst.Len], src[inst.Len:max], mode, syntax, text)
}
}
return
}
// coverage returns a floating point number denoting the
// test coverage until now. The number increases when new code paths are exercised,
// both in the Go program and in the decoder byte code.
func coverage() float64 {
/*
testing.Coverage is not in the main distribution.
The implementation, which must go in package testing, is:
// Coverage reports the current code coverage as a fraction in the range [0, 1].
func Coverage() float64 {
var n, d int64
for _, counters := range cover.Counters {
for _, c := range counters {
if c > 0 {
n++
}
d++
}
}
if d == 0 {
return 0
}
return float64(n) / float64(d)
}
*/
var f float64
f += testing.Coverage()
f += decodeCoverage()
return f
}
func decodeCoverage() float64 {
n := 0
for _, t := range decoderCover {
if t {
n++
}
}
return float64(1+n) / float64(1+len(decoderCover))
}
// Helpers for writing disassembler output parsers.
// hasPrefix reports whether any of the space-separated words in the text s
// begins with any of the given prefixes.
func hasPrefix(s string, prefixes ...string) bool {
for _, prefix := range prefixes {
for s := s; s != ""; {
if strings.HasPrefix(s, prefix) {
return true
}
i := strings.Index(s, " ")
if i < 0 {
break
}
s = s[i+1:]
}
}
return false
}
// contains reports whether the text s contains any of the given substrings.
func contains(s string, substrings ...string) bool {
for _, sub := range substrings {
if strings.Contains(s, sub) {
return true
}
}
return false
}
// isHex reports whether b is a hexadecimal character (0-9A-Fa-f).
func isHex(b byte) bool { return b == '0' || unhex[b] > 0 }
// parseHex parses the hexadecimal byte dump in hex,
// appending the parsed bytes to raw and returning the updated slice.
// The returned bool signals whether any invalid hex was found.
// Spaces and tabs between bytes are okay but any other non-hex is not.
func parseHex(hex []byte, raw []byte) ([]byte, bool) {
hex = trimSpace(hex)
for j := 0; j < len(hex); {
for hex[j] == ' ' || hex[j] == '\t' {
j++
}
if j >= len(hex) {
break
}
if j+2 > len(hex) || !isHex(hex[j]) || !isHex(hex[j+1]) {
return nil, false
}
raw = append(raw, unhex[hex[j]]<<4|unhex[hex[j+1]])
j += 2
}
return raw, true
}
var unhex = [256]byte{
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
'A': 10,
'B': 11,
'C': 12,
'D': 13,
'E': 14,
'F': 15,
'a': 10,
'b': 11,
'c': 12,
'd': 13,
'e': 14,
'f': 15,
}
// index is like bytes.Index(s, []byte(t)) but avoids the allocation.
func index(s []byte, t string) int {
i := 0
for {
j := bytes.IndexByte(s[i:], t[0])
if j < 0 {
return -1
}
i = i + j
if i+len(t) > len(s) {
return -1
}
for k := 1; k < len(t); k++ {
if s[i+k] != t[k] {
goto nomatch
}
}
return i
nomatch:
i++
}
}
// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s.
// If s must be rewritten, it is rewritten in place.
func fixSpace(s []byte) []byte {
s = trimSpace(s)
for i := 0; i < len(s); i++ {
if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' {
goto Fix
}
}
return s
Fix:
b := s
w := 0
for i := 0; i < len(s); i++ {
c := s[i]
if c == '\t' || c == '\n' {
c = ' '
}
if c == ' ' && w > 0 && b[w-1] == ' ' {
continue
}
b[w] = c
w++
}
if w > 0 && b[w-1] == ' ' {
w--
}
return b[:w]
}
// trimSpace trims leading and trailing space from s, returning a subslice of s.
func trimSpace(s []byte) []byte {
j := len(s)
for j > 0 && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n') {
j--
}
i := 0
for i < j && (s[i] == ' ' || s[i] == '\t') {
i++
}
return s[i:j]
}
// pcrel matches instructions using relative addressing mode.
var (
pcrel = regexp.MustCompile(`^((?:.* )?(?:b|bl)x?(?:eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le)?) 0x([0-9a-f]+)$`)
)
// Generators.
//
// The test cases are described as functions that invoke a callback repeatedly,
// with a new input sequence each time. These helpers make writing those
// a little easier.
// condCases generates conditional instructions.
func condCases(t *testing.T) func(func([]byte)) {
return func(try func([]byte)) {
// All the strides are relatively prime to 2 and therefore to 2²⁸,
// so we will not repeat any instructions until we have tried all 2²⁸.
// Using a stride other than 1 is meant to visit the instructions in a
// pseudorandom order, which gives better variety in the set of
// test cases chosen by -printtests.
stride := uint32(10007)
n := 1 << 28 / 7
if testing.Short() {
stride = 100003
n = 1 << 28 / 1001
} else if *longTest {
stride = 200000033
n = 1 << 28
}
x := uint32(0)
for i := 0; i < n; i++ {
enc := (x%15)<<28 | x&(1<<28-1)
try([]byte{byte(enc), byte(enc >> 8), byte(enc >> 16), byte(enc >> 24)})
x += stride
}
}
}
// uncondCases generates unconditional instructions.
func uncondCases(t *testing.T) func(func([]byte)) {
return func(try func([]byte)) {
condCases(t)(func(enc []byte) {
enc[3] |= 0xF0
try(enc)
})
}
}
func countBits(x uint32) int {
n := 0
for ; x != 0; x >>= 1 {
n += int(x & 1)
}
return n
}
func expandBits(x, m uint32) uint32 {
var out uint32
for i := uint(0); i < 32; i++ {
out >>= 1
if m&1 != 0 {
out |= (x & 1) << 31
x >>= 1
}
m >>= 1
}
return out
}
func tryCondMask(mask, val uint32, try func([]byte)) {
n := countBits(^mask)
bits := uint32(0)
for i := 0; i < 1<<uint(n); i++ {
bits += 848251 // arbitrary prime
x := val | expandBits(bits, ^mask) | uint32(i)%15<<28
try([]byte{byte(x), byte(x >> 8), byte(x >> 16), byte(x >> 24)})
}
}
// vfpCases generates VFP instructions.
func vfpCases(t *testing.T) func(func([]byte)) {
const (
vfpmask uint32 = 0xFF00FE10
vfp uint32 = 0x0E009A00
)
return func(try func([]byte)) {
tryCondMask(0xff00fe10, 0x0e009a00, try) // standard VFP instruction space
tryCondMask(0xffc00f7f, 0x0e000b10, try) // VFP MOV core reg to/from float64 half
tryCondMask(0xffe00f7f, 0x0e000a10, try) // VFP MOV core reg to/from float32
tryCondMask(0xffef0fff, 0x0ee10a10, try) // VFP MOV core reg to/from cond codes
}
}
// hexCases generates the cases written in hexadecimal in the encoded string.
// Spaces in 'encoded' separate entire test cases, not individual bytes.
func hexCases(t *testing.T, encoded string) func(func([]byte)) {
return func(try func([]byte)) {
for _, x := range strings.Fields(encoded) {
src, err := hex.DecodeString(x)
if err != nil {
t.Errorf("parsing %q: %v", x, err)
}
try(src)
}
}
}
// testdataCases generates the test cases recorded in testdata/decode.txt.
// It only uses the inputs; it ignores the answers recorded in that file.
func testdataCases(t *testing.T) func(func([]byte)) {
var codes [][]byte
data, err := ioutil.ReadFile("testdata/decode.txt")
if err != nil {
t.Fatal(err)
}
for _, line := range strings.Split(string(data), "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
f := strings.Fields(line)[0]
i := strings.Index(f, "|")
if i < 0 {
t.Errorf("parsing %q: missing | separator", f)
continue
}
if i%2 != 0 {
t.Errorf("parsing %q: misaligned | separator", f)
}
code, err := hex.DecodeString(f[:i] + f[i+1:])
if err != nil {
t.Errorf("parsing %q: %v", f, err)
continue
}
codes = append(codes, code)
}
return func(try func([]byte)) {
for _, code := range codes {
try(code)
}
}
}
func caller(skip int) string {
pc, _, _, _ := runtime.Caller(skip)
f := runtime.FuncForPC(pc)
name := "?"
if f != nil {
name = f.Name()
if i := strings.LastIndex(name, "."); i >= 0 {
name = name[i+1:]
}
}
return name
}
@@ -0,0 +1,164 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package armasm
import (
"bytes"
"fmt"
"strings"
)
var saveDot = strings.NewReplacer(
".F16", "_dot_F16",
".F32", "_dot_F32",
".F64", "_dot_F64",
".S32", "_dot_S32",
".U32", "_dot_U32",
".FXS", "_dot_S",
".FXU", "_dot_U",
".32", "_dot_32",
)
// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
// This form typically matches the syntax defined in the ARM Reference Manual.
func GNUSyntax(inst Inst) string {
var buf bytes.Buffer
op := inst.Op.String()
op = saveDot.Replace(op)
op = strings.Replace(op, ".", "", -1)
op = strings.Replace(op, "_dot_", ".", -1)
op = strings.ToLower(op)
buf.WriteString(op)
sep := " "
for i, arg := range inst.Args {
if arg == nil {
break
}
text := gnuArg(&inst, i, arg)
if text == "" {
continue
}
buf.WriteString(sep)
sep = ", "
buf.WriteString(text)
}
return buf.String()
}
func gnuArg(inst *Inst, argIndex int, arg Arg) string {
switch inst.Op &^ 15 {
case LDRD_EQ, LDREXD_EQ, STRD_EQ:
if argIndex == 1 {
// second argument in consecutive pair not printed
return ""
}
case STREXD_EQ:
if argIndex == 2 {
// second argument in consecutive pair not printed
return ""
}
}
switch arg := arg.(type) {
case Imm:
switch inst.Op &^ 15 {
case BKPT_EQ:
return fmt.Sprintf("%#04x", uint32(arg))
case SVC_EQ:
return fmt.Sprintf("%#08x", uint32(arg))
}
return fmt.Sprintf("#%d", int32(arg))
case ImmAlt:
return fmt.Sprintf("#%d, %d", arg.Val, arg.Rot)
case Mem:
R := gnuArg(inst, -1, arg.Base)
X := ""
if arg.Sign != 0 {
X = ""
if arg.Sign < 0 {
X = "-"
}
X += gnuArg(inst, -1, arg.Index)
if arg.Shift == ShiftLeft && arg.Count == 0 {
// nothing
} else if arg.Shift == RotateRightExt {
X += ", rrx"
} else {
X += fmt.Sprintf(", %s #%d", strings.ToLower(arg.Shift.String()), arg.Count)
}
} else {
X = fmt.Sprintf("#%d", arg.Offset)
}
switch arg.Mode {
case AddrOffset:
if X == "#0" {
return fmt.Sprintf("[%s]", R)
}
return fmt.Sprintf("[%s, %s]", R, X)
case AddrPreIndex:
return fmt.Sprintf("[%s, %s]!", R, X)
case AddrPostIndex:
return fmt.Sprintf("[%s], %s", R, X)
case AddrLDM:
if X == "#0" {
return R
}
case AddrLDM_WB:
if X == "#0" {
return R + "!"
}
}
return fmt.Sprintf("[%s Mode(%d) %s]", R, int(arg.Mode), X)
case PCRel:
return fmt.Sprintf(".%+#x", int32(arg)+4)
case Reg:
switch inst.Op &^ 15 {
case LDREX_EQ:
if argIndex == 0 {
return fmt.Sprintf("r%d", int32(arg))
}
}
switch arg {
case R10:
return "sl"
case R11:
return "fp"
case R12:
return "ip"
}
case RegList:
var buf bytes.Buffer
fmt.Fprintf(&buf, "{")
sep := ""
for i := 0; i < 16; i++ {
if arg&(1<<uint(i)) != 0 {
fmt.Fprintf(&buf, "%s%s", sep, gnuArg(inst, -1, Reg(i)))
sep = ", "
}
}
fmt.Fprintf(&buf, "}")
return buf.String()
case RegShift:
if arg.Shift == ShiftLeft && arg.Count == 0 {
return gnuArg(inst, -1, arg.Reg)
}
if arg.Shift == RotateRightExt {
return gnuArg(inst, -1, arg.Reg) + ", rrx"
}
return fmt.Sprintf("%s, %s #%d", gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), arg.Count)
case RegShiftReg:
return fmt.Sprintf("%s, %s %s", gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), gnuArg(inst, -1, arg.RegCount))
}
return strings.ToLower(arg.String())
}
@@ -0,0 +1,438 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package armasm
import (
"bytes"
"fmt"
)
// A Mode is an instruction execution mode.
type Mode int
const (
_ Mode = iota
ModeARM
ModeThumb
)
func (m Mode) String() string {
switch m {
case ModeARM:
return "ARM"
case ModeThumb:
return "Thumb"
}
return fmt.Sprintf("Mode(%d)", int(m))
}
// An Op is an ARM opcode.
type Op uint16
// NOTE: The actual Op values are defined in tables.go.
// They are chosen to simplify instruction decoding and
// are not a dense packing from 0 to N, although the
// density is high, probably at least 90%.
func (op Op) String() string {
if op >= Op(len(opstr)) || opstr[op] == "" {
return fmt.Sprintf("Op(%d)", int(op))
}
return opstr[op]
}
// An Inst is a single instruction.
type Inst struct {
Op Op // Opcode mnemonic
Enc uint32 // Raw encoding bits.
Len int // Length of encoding in bytes.
Args Args // Instruction arguments, in ARM manual order.
}
func (i Inst) String() string {
var buf bytes.Buffer
buf.WriteString(i.Op.String())
for j, arg := range i.Args {
if arg == nil {
break
}
if j == 0 {
buf.WriteString(" ")
} else {
buf.WriteString(", ")
}
buf.WriteString(arg.String())
}
return buf.String()
}
// An Args holds the instruction arguments.
// If an instruction has fewer than 4 arguments,
// the final elements in the array are nil.
type Args [4]Arg
// An Arg is a single instruction argument, one of these types:
// Endian, Imm, Mem, PCRel, Reg, RegList, RegShift, RegShiftReg.
type Arg interface {
IsArg()
String() string
}
type Float32Imm float32
func (Float32Imm) IsArg() {}
func (f Float32Imm) String() string {
return fmt.Sprintf("#%v", float32(f))
}
type Float64Imm float32
func (Float64Imm) IsArg() {}
func (f Float64Imm) String() string {
return fmt.Sprintf("#%v", float64(f))
}
// An Imm is an integer constant.
type Imm uint32
func (Imm) IsArg() {}
func (i Imm) String() string {
return fmt.Sprintf("#%#x", uint32(i))
}
// An ImmAlt is an alternate encoding of an integer constant.
type ImmAlt struct {
Val uint8
Rot uint8
}
func (ImmAlt) IsArg() {}
func (i ImmAlt) Imm() Imm {
v := uint32(i.Val)
r := uint(i.Rot)
return Imm(v>>r | v<<(32-r))
}
func (i ImmAlt) String() string {
return fmt.Sprintf("#%#x, %d", i.Val, i.Rot)
}
// A Label is a text (code) address.
type Label uint32
func (Label) IsArg() {}
func (i Label) String() string {
return fmt.Sprintf("%#x", uint32(i))
}
// A Reg is a single register.
// The zero value denotes R0, not the absence of a register.
type Reg uint8
const (
R0 Reg = iota
R1
R2
R3
R4
R5
R6
R7
R8
R9
R10
R11
R12
R13
R14
R15
S0
S1
S2
S3
S4
S5
S6
S7
S8
S9
S10
S11
S12
S13
S14
S15
S16
S17
S18
S19
S20
S21
S22
S23
S24
S25
S26
S27
S28
S29
S30
S31
D0
D1
D2
D3
D4
D5
D6
D7
D8
D9
D10
D11
D12
D13
D14
D15
D16
D17
D18
D19
D20
D21
D22
D23
D24
D25
D26
D27
D28
D29
D30
D31
APSR
APSR_nzcv
FPSCR
SP = R13
LR = R14
PC = R15
)
func (Reg) IsArg() {}
func (r Reg) String() string {
switch r {
case APSR:
return "APSR"
case APSR_nzcv:
return "APSR_nzcv"
case FPSCR:
return "FPSCR"
case SP:
return "SP"
case PC:
return "PC"
case LR:
return "LR"
}
if R0 <= r && r <= R15 {
return fmt.Sprintf("R%d", int(r-R0))
}
if S0 <= r && r <= S31 {
return fmt.Sprintf("S%d", int(r-S0))
}
if D0 <= r && r <= D31 {
return fmt.Sprintf("D%d", int(r-D0))
}
return fmt.Sprintf("Reg(%d)", int(r))
}
// A RegX represents a fraction of a multi-value register.
// The Index field specifies the index number,
// but the size of the fraction is not specified.
// It must be inferred from the instruction and the register type.
// For example, in a VMOV instruction, RegX{D5, 1} represents
// the top 32 bits of the 64-bit D5 register.
type RegX struct {
Reg Reg
Index int
}
func (RegX) IsArg() {}
func (r RegX) String() string {
return fmt.Sprintf("%s[%d]", r.Reg, r.Index)
}
// A RegList is a register list.
// Bits at indexes x = 0 through 15 indicate whether the corresponding Rx register is in the list.
type RegList uint16
func (RegList) IsArg() {}
func (r RegList) String() string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "{")
sep := ""
for i := 0; i < 16; i++ {
if r&(1<<uint(i)) != 0 {
fmt.Fprintf(&buf, "%s%s", sep, Reg(i).String())
sep = ","
}
}
fmt.Fprintf(&buf, "}")
return buf.String()
}
// An Endian is the argument to the SETEND instruction.
type Endian uint8
const (
LittleEndian Endian = 0
BigEndian Endian = 1
)
func (Endian) IsArg() {}
func (e Endian) String() string {
if e != 0 {
return "BE"
}
return "LE"
}
// A Shift describes an ARM shift operation.
type Shift uint8
const (
ShiftLeft Shift = 0 // left shift
ShiftRight Shift = 1 // logical (unsigned) right shift
ShiftRightSigned Shift = 2 // arithmetic (signed) right shift
RotateRight Shift = 3 // right rotate
RotateRightExt Shift = 4 // right rotate through carry (Count will always be 1)
)
var shiftName = [...]string{
"LSL", "LSR", "ASR", "ROR", "RRX",
}
func (s Shift) String() string {
if s < 5 {
return shiftName[s]
}
return fmt.Sprintf("Shift(%d)", int(s))
}
// A RegShift is a register shifted by a constant.
type RegShift struct {
Reg Reg
Shift Shift
Count uint8
}
func (RegShift) IsArg() {}
func (r RegShift) String() string {
return fmt.Sprintf("%s %s #%d", r.Reg, r.Shift, r.Count)
}
// A RegShiftReg is a register shifted by a register.
type RegShiftReg struct {
Reg Reg
Shift Shift
RegCount Reg
}
func (RegShiftReg) IsArg() {}
func (r RegShiftReg) String() string {
return fmt.Sprintf("%s %s %s", r.Reg, r.Shift, r.RegCount)
}
// A PCRel describes a memory address (usually a code label)
// as a distance relative to the program counter.
// TODO(rsc): Define which program counter (PC+4? PC+8? PC?).
type PCRel int32
func (PCRel) IsArg() {}
func (r PCRel) String() string {
return fmt.Sprintf("PC%+#x", int32(r))
}
// An AddrMode is an ARM addressing mode.
type AddrMode uint8
const (
_ AddrMode = iota
AddrPostIndex // [R], X use address R, set R = R + X
AddrPreIndex // [R, X]! use address R + X, set R = R + X
AddrOffset // [R, X] use address R + X
AddrLDM // R [R] but formats as R, for LDM/STM only
AddrLDM_WB // R! - [R], X where X is instruction-specific amount, for LDM/STM only
)
// A Mem is a memory reference made up of a base R and index expression X.
// The effective memory address is R or R+X depending on AddrMode.
// The index expression is X = Sign*(Index Shift Count) + Offset,
// but in any instruction either Sign = 0 or Offset = 0.
type Mem struct {
Base Reg
Mode AddrMode
Sign int8
Index Reg
Shift Shift
Count uint8
Offset int16
}
func (Mem) IsArg() {}
func (m Mem) String() string {
R := m.Base.String()
X := ""
if m.Sign != 0 {
X = "+"
if m.Sign < 0 {
X = "-"
}
X += m.Index.String()
if m.Shift != ShiftLeft || m.Count != 0 {
X += fmt.Sprintf(", %s #%d", m.Shift, m.Count)
}
} else {
X = fmt.Sprintf("#%d", m.Offset)
}
switch m.Mode {
case AddrOffset:
if X == "#0" {
return fmt.Sprintf("[%s]", R)
}
return fmt.Sprintf("[%s, %s]", R, X)
case AddrPreIndex:
return fmt.Sprintf("[%s, %s]!", R, X)
case AddrPostIndex:
return fmt.Sprintf("[%s], %s", R, X)
case AddrLDM:
if X == "#0" {
return R
}
case AddrLDM_WB:
if X == "#0" {
return R + "!"
}
}
return fmt.Sprintf("[%s Mode(%d) %s]", R, int(m.Mode), X)
}
@@ -0,0 +1,268 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package armasm
import (
"encoding/binary"
"strings"
"testing"
)
func TestObjdumpARMTestdata(t *testing.T) { testObjdumpARM(t, testdataCases(t)) }
func TestObjdumpARMManual(t *testing.T) { testObjdumpARM(t, hexCases(t, objdumpManualTests)) }
func TestObjdumpARMCond(t *testing.T) { testObjdumpARM(t, condCases(t)) }
func TestObjdumpARMUncond(t *testing.T) { testObjdumpARM(t, uncondCases(t)) }
func TestObjdumpARMVFP(t *testing.T) { testObjdumpARM(t, vfpCases(t)) }
// objdumpManualTests holds test cases that will be run by TestObjdumpARMManual.
// If you are debugging a few cases that turned up in a longer run, it can be useful
// to list them here and then use -run=Manual, particularly with tracing enabled.
// Note that these are byte sequences, so they must be reversed from the usual
// word presentation.
var objdumpManualTests = `
002a9b1d
001b9bed
020b8ded
003a9b1d
060b8ded
fcde1100
b4de1100
bc480000
0b008de7
0b00ade7
fdbcfaf7
`
// allowedMismatchObjdump reports whether the mismatch between text and dec
// should be allowed by the test.
func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
if hasPrefix(text, "error:") {
if hasPrefix(dec.text, unsupported...) || strings.Contains(dec.text, "invalid:") || strings.HasSuffix(dec.text, "^") || strings.Contains(dec.text, "f16.f64") || strings.Contains(dec.text, "f64.f16") {
return true
}
// word 4320F02C: libopcodes says 'nopmi {44}'.
if hasPrefix(dec.text, "nop") && strings.Contains(dec.text, "{") {
return true
}
}
if hasPrefix(dec.text, "error:") && text == "undef" && inst.Enc == 0xf7fabcfd {
return true
}
// word 00f02053: libopcodes says 'noppl {0}'.
if hasPrefix(dec.text, "nop") && hasPrefix(text, "nop") && dec.text == text+" {0}" {
return true
}
// word F57FF04F. we say 'dsb #15', libopcodes says 'dsb sy'.
if hasPrefix(text, "dsb") && hasPrefix(dec.text, "dsb") {
return true
}
// word F57FF06F. we say 'isb #15', libopcodes says 'isb sy'.
if hasPrefix(text, "isb") && hasPrefix(dec.text, "isb") {
return true
}
// word F57FF053. we say 'dmb #3', libopcodes says 'dmb osh'.
if hasPrefix(text, "dmb") && hasPrefix(dec.text, "dmb") {
return true
}
// word 992D0000. push/stmdb with no registers (undefined).
// we say 'stmdbls sp!, {}', libopcodes says 'pushls {}'.
if hasPrefix(text, "stmdb") && hasPrefix(dec.text, "push") && strings.Contains(text, "{}") && strings.Contains(dec.text, "{}") {
return true
}
// word 28BD0000. pop/ldm with no registers (undefined).
// we say 'ldmcs sp!, {}', libopcodes says 'popcs {}'.
if hasPrefix(text, "ldm") && hasPrefix(dec.text, "pop") && strings.Contains(text, "{}") && strings.Contains(dec.text, "{}") {
return true
}
// word 014640F0.
// libopcodes emits #-0 for negative zero; we don't.
if strings.Replace(dec.text, "#-0", "#0", -1) == text || strings.Replace(dec.text, ", #-0", "", -1) == text {
return true
}
// word 91EF90F0. we say 'strdls r9, [pc, #0]!' but libopcodes says 'strdls r9, [pc]'.
// word D16F60F0. we say 'strdle r6, [pc, #0]!' but libopcodes says 'strdle r6, [pc, #-0]'.
if strings.Replace(text, ", #0]!", "]", -1) == strings.Replace(dec.text, ", #-0]", "]", -1) {
return true
}
// word 510F4000. we say apsr, libopcodes says CPSR.
if strings.Replace(dec.text, "CPSR", "apsr", -1) == text {
return true
}
// word 06A4B059.
// for ssat and usat, libopcodes decodes asr #0 as asr #0 but the manual seems to say it should be asr #32.
// There is never an asr #0.
if strings.Replace(dec.text, ", asr #0", ", asr #32", -1) == text {
return true
}
if len(dec.enc) >= 4 {
raw := binary.LittleEndian.Uint32(dec.enc[:4])
// word 21FFF0B5.
// the manual is clear that this is pre-indexed mode (with !) but libopcodes generates post-index (without !).
if raw&0x01200000 == 0x01200000 && strings.Replace(text, "!", "", -1) == dec.text {
return true
}
// word C100543E: libopcodes says tst, but no evidence for that.
if strings.HasPrefix(dec.text, "tst") && raw&0x0ff00000 != 0x03100000 && raw&0x0ff00000 != 0x01100000 {
return true
}
// word C3203CE8: libopcodes says teq, but no evidence for that.
if strings.HasPrefix(dec.text, "teq") && raw&0x0ff00000 != 0x03300000 && raw&0x0ff00000 != 0x01300000 {
return true
}
// word D14C552E: libopcodes says cmp but no evidence for that.
if strings.HasPrefix(dec.text, "cmp") && raw&0x0ff00000 != 0x03500000 && raw&0x0ff00000 != 0x01500000 {
return true
}
// word 2166AA4A: libopcodes says cmn but no evidence for that.
if strings.HasPrefix(dec.text, "cmn") && raw&0x0ff00000 != 0x03700000 && raw&0x0ff00000 != 0x01700000 {
return true
}
// word E70AEEEF: libopcodes says str but no evidence for that.
if strings.HasPrefix(dec.text, "str") && len(dec.text) >= 5 && (dec.text[3] == ' ' || dec.text[5] == ' ') && raw&0x0e500018 != 0x06000000 && raw&0x0e500000 != 0x0400000 {
return true
}
// word B0AF48F4: libopcodes says strd but P=0,W=1 which is unpredictable.
if hasPrefix(dec.text, "ldr", "str") && raw&0x01200000 == 0x00200000 {
return true
}
// word B6CC1C76: libopcodes inexplicably says 'uxtab16lt r1, ip, r6, ROR #24' instead of 'uxtab16lt r1, ip, r6, ror #24'
if strings.ToLower(dec.text) == text {
return true
}
// word F410FDA1: libopcodes says PLDW but the manual is clear that PLDW is F5/F7, not F4.
// word F7D0FB17: libopcodes says PLDW but the manual is clear that PLDW has 0x10 clear
if hasPrefix(dec.text, "pld") && raw&0xfd000010 != 0xf5000000 {
return true
}
// word F650FE14: libopcodes says PLI but the manual is clear that PLI has 0x10 clear
if hasPrefix(dec.text, "pli") && raw&0xff000010 != 0xf6000000 {
return true
}
}
return false
}
// Instructions known to libopcodes (or xed) but not to us.
// Most of these are floating point coprocessor instructions.
var unsupported = strings.Fields(`
abs
acs
adf
aes
asn
atn
cdp
cf
cmf
cnf
cos
cps
crc32
dvf
eret
exp
fadd
fcmp
fcpy
fcvt
fdiv
fdv
fix
fld
flt
fmac
fmd
fml
fmr
fms
fmul
fmx
fneg
fnm
frd
fsit
fsq
fst
fsu
fto
fui
hlt
hvc
lda
ldc
ldf
lfm
lgn
log
mar
mcr
mcrr
mia
mnf
mra
mrc
mrrc
mrs
msr
msr
muf
mvf
nrm
pol
pow
rdf
rfc
rfe
rfs
rmf
rnd
rpw
rsf
sdiv
sev
sfm
sha1
sha256
sin
smc
sqt
srs
stc
stf
stl
suf
tan
udf
udiv
urd
vfma
vfms
vfnma
vfnms
vrint
wfc
wfs
`)
@@ -0,0 +1,259 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Copied and simplified from ../../x86/x86asm/objdumpext_test.go.
package armasm
import (
"bytes"
"debug/elf"
"encoding/binary"
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
"testing"
)
const objdumpPath = "/usr/local/bin/arm-linux-elf-objdump"
func testObjdumpARM(t *testing.T, generate func(func([]byte))) {
testObjdumpArch(t, generate, ModeARM)
}
func testObjdumpArch(t *testing.T, generate func(func([]byte)), arch Mode) {
if testing.Short() {
t.Skip("skipping objdump test in short mode")
}
if _, err := os.Stat(objdumpPath); err != nil {
t.Skip(err)
}
testExtDis(t, "gnu", arch, objdump, generate, allowedMismatchObjdump)
}
func objdump(ext *ExtDis) error {
// File already written with instructions; add ELF header.
if ext.Arch == ModeARM {
if err := writeELF32(ext.File, ext.Size); err != nil {
return err
}
} else {
panic("unknown arch")
}
b, err := ext.Run(objdumpPath, "-d", "-z", ext.File.Name())
if err != nil {
return err
}
var (
nmatch int
reading bool
next uint32 = start
addr uint32
encbuf [4]byte
enc []byte
text string
)
flush := func() {
if addr == next {
if m := pcrel.FindStringSubmatch(text); m != nil {
targ, _ := strconv.ParseUint(m[2], 16, 64)
text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
}
if strings.HasPrefix(text, "stmia") {
text = "stm" + text[5:]
}
if strings.HasPrefix(text, "stmfd") {
text = "stmdb" + text[5:]
}
if strings.HasPrefix(text, "ldmfd") {
text = "ldm" + text[5:]
}
text = strings.Replace(text, "#0.0", "#0", -1)
if text == "undefined" && len(enc) == 4 {
text = "error: unknown instruction"
enc = nil
}
if len(enc) == 4 {
// prints as word but we want to record bytes
enc[0], enc[3] = enc[3], enc[0]
enc[1], enc[2] = enc[2], enc[1]
}
ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
encbuf = [4]byte{}
enc = nil
next += 4
}
}
var textangle = []byte("<.text>:")
for {
line, err := b.ReadSlice('\n')
if err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("reading objdump output: %v", err)
}
if bytes.Contains(line, textangle) {
reading = true
continue
}
if !reading {
continue
}
if debug {
os.Stdout.Write(line)
}
if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil {
enc = enc1
continue
}
flush()
nmatch++
addr, enc, text = parseLine(line, encbuf[:0])
if addr > next {
return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
}
}
flush()
if next != start+uint32(ext.Size) {
return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
}
if err := ext.Wait(); err != nil {
return fmt.Errorf("exec: %v", err)
}
return nil
}
var (
undefined = []byte("<UNDEFINED>")
unpredictable = []byte("<UNPREDICTABLE>")
illegalShifter = []byte("<illegal shifter operand>")
)
func parseLine(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
oline := line
i := index(line, ":\t")
if i < 0 {
log.Fatalf("cannot parse disassembly: %q", oline)
}
x, err := strconv.ParseUint(string(trimSpace(line[:i])), 16, 32)
if err != nil {
log.Fatalf("cannot parse disassembly: %q", oline)
}
addr = uint32(x)
line = line[i+2:]
i = bytes.IndexByte(line, '\t')
if i < 0 {
log.Fatalf("cannot parse disassembly: %q", oline)
}
enc, ok := parseHex(line[:i], encstart)
if !ok {
log.Fatalf("cannot parse disassembly: %q", oline)
}
line = trimSpace(line[i:])
if bytes.Contains(line, undefined) {
text = "undefined"
return
}
if bytes.Contains(line, illegalShifter) {
text = "undefined"
return
}
if false && bytes.Contains(line, unpredictable) {
text = "unpredictable"
return
}
if i := bytes.IndexByte(line, ';'); i >= 0 {
line = trimSpace(line[:i])
}
text = string(fixSpace(line))
return
}
func parseContinuation(line []byte, enc []byte) []byte {
i := index(line, ":\t")
if i < 0 {
return nil
}
line = line[i+1:]
enc, _ = parseHex(line, enc)
return enc
}
// writeELF32 writes an ELF32 header to the file,
// describing a text segment that starts at start
// and extends for size bytes.
func writeELF32(f *os.File, size int) error {
f.Seek(0, io.SeekStart)
var hdr elf.Header32
var prog elf.Prog32
var sect elf.Section32
var buf bytes.Buffer
binary.Write(&buf, binary.LittleEndian, &hdr)
off1 := buf.Len()
binary.Write(&buf, binary.LittleEndian, &prog)
off2 := buf.Len()
binary.Write(&buf, binary.LittleEndian, &sect)
off3 := buf.Len()
buf.Reset()
data := byte(elf.ELFDATA2LSB)
hdr = elf.Header32{
Ident: [16]byte{0x7F, 'E', 'L', 'F', 1, data, 1},
Type: 2,
Machine: uint16(elf.EM_ARM),
Version: 1,
Entry: start,
Phoff: uint32(off1),
Shoff: uint32(off2),
Flags: 0x05000002,
Ehsize: uint16(off1),
Phentsize: uint16(off2 - off1),
Phnum: 1,
Shentsize: uint16(off3 - off2),
Shnum: 3,
Shstrndx: 2,
}
binary.Write(&buf, binary.LittleEndian, &hdr)
prog = elf.Prog32{
Type: 1,
Off: start,
Vaddr: start,
Paddr: start,
Filesz: uint32(size),
Memsz: uint32(size),
Flags: 5,
Align: start,
}
binary.Write(&buf, binary.LittleEndian, &prog)
binary.Write(&buf, binary.LittleEndian, &sect) // NULL section
sect = elf.Section32{
Name: 1,
Type: uint32(elf.SHT_PROGBITS),
Addr: start,
Off: start,
Size: uint32(size),
Flags: uint32(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
Addralign: 4,
}
binary.Write(&buf, binary.LittleEndian, &sect) // .text
sect = elf.Section32{
Name: uint32(len("\x00.text\x00")),
Type: uint32(elf.SHT_STRTAB),
Addr: 0,
Off: uint32(off2 + (off3-off2)*3),
Size: uint32(len("\x00.text\x00.shstrtab\x00")),
Addralign: 1,
}
binary.Write(&buf, binary.LittleEndian, &sect)
buf.WriteString("\x00.text\x00.shstrtab\x00")
f.Write(buf.Bytes())
return nil
}
@@ -0,0 +1,401 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package armasm
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"math"
"strings"
)
// GoSyntax returns the Go assembler syntax for the instruction.
// The syntax was originally defined by Plan 9.
// The pc is the program counter of the instruction, used for expanding
// PC-relative addresses into absolute ones.
// The symname function queries the symbol table for the program
// being disassembled. Given a target address it returns the name and base
// address of the symbol containing the target, if any; otherwise it returns "", 0.
// The reader r should read from the text segment using text addresses
// as offsets; it is used to display pc-relative loads as constant loads.
func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string {
if symname == nil {
symname = func(uint64) (string, uint64) { return "", 0 }
}
var args []string
for _, a := range inst.Args {
if a == nil {
break
}
args = append(args, plan9Arg(&inst, pc, symname, a))
}
op := inst.Op.String()
switch inst.Op &^ 15 {
case LDR_EQ, LDRB_EQ, LDRH_EQ, LDRSB_EQ, LDRSH_EQ, VLDR_EQ:
// Check for RET
reg, _ := inst.Args[0].(Reg)
mem, _ := inst.Args[1].(Mem)
if inst.Op&^15 == LDR_EQ && reg == R15 && mem.Base == SP && mem.Sign == 0 && mem.Mode == AddrPostIndex {
return fmt.Sprintf("RET%s #%d", op[3:], mem.Offset)
}
// Check for PC-relative load.
if mem.Base == PC && mem.Sign == 0 && mem.Mode == AddrOffset && text != nil {
addr := uint32(pc) + 8 + uint32(mem.Offset)
buf := make([]byte, 8)
switch inst.Op &^ 15 {
case LDRB_EQ, LDRSB_EQ:
if _, err := text.ReadAt(buf[:1], int64(addr)); err != nil {
break
}
args[1] = fmt.Sprintf("$%#x", buf[0])
case LDRH_EQ, LDRSH_EQ:
if _, err := text.ReadAt(buf[:2], int64(addr)); err != nil {
break
}
args[1] = fmt.Sprintf("$%#x", binary.LittleEndian.Uint16(buf))
case LDR_EQ:
if _, err := text.ReadAt(buf[:4], int64(addr)); err != nil {
break
}
x := binary.LittleEndian.Uint32(buf)
if s, base := symname(uint64(x)); s != "" && uint64(x) == base {
args[1] = fmt.Sprintf("$%s(SB)", s)
} else {
args[1] = fmt.Sprintf("$%#x", x)
}
case VLDR_EQ:
switch {
case strings.HasPrefix(args[0], "D"): // VLDR.F64
if _, err := text.ReadAt(buf, int64(addr)); err != nil {
break
}
args[1] = fmt.Sprintf("$%f", math.Float64frombits(binary.LittleEndian.Uint64(buf)))
case strings.HasPrefix(args[0], "S"): // VLDR.F32
if _, err := text.ReadAt(buf[:4], int64(addr)); err != nil {
break
}
args[1] = fmt.Sprintf("$%f", math.Float32frombits(binary.LittleEndian.Uint32(buf)))
default:
panic(fmt.Sprintf("wrong FP register: %v", inst))
}
}
}
}
// Move addressing mode into opcode suffix.
suffix := ""
switch inst.Op &^ 15 {
case PLD, PLI, PLD_W:
if mem, ok := inst.Args[0].(Mem); ok {
args[0], suffix = memOpTrans(mem)
} else {
panic(fmt.Sprintf("illegal instruction: %v", inst))
}
case LDR_EQ, LDRB_EQ, LDRSB_EQ, LDRH_EQ, LDRSH_EQ, STR_EQ, STRB_EQ, STRH_EQ, VLDR_EQ, VSTR_EQ, LDREX_EQ, LDREXH_EQ, LDREXB_EQ:
if mem, ok := inst.Args[1].(Mem); ok {
args[1], suffix = memOpTrans(mem)
} else {
panic(fmt.Sprintf("illegal instruction: %v", inst))
}
case SWP_EQ, SWP_B_EQ, STREX_EQ, STREXB_EQ, STREXH_EQ:
if mem, ok := inst.Args[2].(Mem); ok {
args[2], suffix = memOpTrans(mem)
} else {
panic(fmt.Sprintf("illegal instruction: %v", inst))
}
}
// Reverse args, placing dest last.
for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
args[i], args[j] = args[j], args[i]
}
// For MLA-like instructions, the addend is the third operand.
switch inst.Op &^ 15 {
case SMLAWT_EQ, SMLAWB_EQ, MLA_EQ, MLA_S_EQ, MLS_EQ, SMMLA_EQ, SMMLS_EQ, SMLABB_EQ, SMLATB_EQ, SMLABT_EQ, SMLATT_EQ, SMLAD_EQ, SMLAD_X_EQ, SMLSD_EQ, SMLSD_X_EQ:
args = []string{args[1], args[2], args[0], args[3]}
}
// For STREX like instructions, the memory operands comes first.
switch inst.Op &^ 15 {
case STREX_EQ, STREXB_EQ, STREXH_EQ, SWP_EQ, SWP_B_EQ:
args = []string{args[1], args[0], args[2]}
}
// special process for FP instructions
op, args = fpTrans(&inst, op, args)
// LDR/STR like instructions -> MOV like
switch inst.Op &^ 15 {
case MOV_EQ:
op = "MOVW" + op[3:]
case LDR_EQ, MSR_EQ, MRS_EQ:
op = "MOVW" + op[3:] + suffix
case VMRS_EQ, VMSR_EQ:
op = "MOVW" + op[4:] + suffix
case LDRB_EQ, UXTB_EQ:
op = "MOVBU" + op[4:] + suffix
case LDRSB_EQ:
op = "MOVBS" + op[5:] + suffix
case SXTB_EQ:
op = "MOVBS" + op[4:] + suffix
case LDRH_EQ, UXTH_EQ:
op = "MOVHU" + op[4:] + suffix
case LDRSH_EQ:
op = "MOVHS" + op[5:] + suffix
case SXTH_EQ:
op = "MOVHS" + op[4:] + suffix
case STR_EQ:
op = "MOVW" + op[3:] + suffix
args[0], args[1] = args[1], args[0]
case STRB_EQ:
op = "MOVB" + op[4:] + suffix
args[0], args[1] = args[1], args[0]
case STRH_EQ:
op = "MOVH" + op[4:] + suffix
args[0], args[1] = args[1], args[0]
case VSTR_EQ:
args[0], args[1] = args[1], args[0]
default:
op = op + suffix
}
if args != nil {
op += " " + strings.Join(args, ", ")
}
return op
}
// assembler syntax for the various shifts.
// @x> is a lie; the assembler uses @> 0
// instead of @x> 1, but i wanted to be clear that it
// was a different operation (rotate right extended, not rotate right).
var plan9Shift = []string{"<<", ">>", "->", "@>", "@x>"}
func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
switch a := arg.(type) {
case Endian:
case Imm:
return fmt.Sprintf("$%d", uint32(a))
case Mem:
case PCRel:
addr := uint32(pc) + 8 + uint32(a)
if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
return fmt.Sprintf("%s(SB)", s)
}
return fmt.Sprintf("%#x", addr)
case Reg:
if a < 16 {
return fmt.Sprintf("R%d", int(a))
}
case RegList:
var buf bytes.Buffer
start := -2
end := -2
fmt.Fprintf(&buf, "[")
flush := func() {
if start >= 0 {
if buf.Len() > 1 {
fmt.Fprintf(&buf, ",")
}
if start == end {
fmt.Fprintf(&buf, "R%d", start)
} else {
fmt.Fprintf(&buf, "R%d-R%d", start, end)
}
start = -2
end = -2
}
}
for i := 0; i < 16; i++ {
if a&(1<<uint(i)) != 0 {
if i == end+1 {
end++
continue
}
start = i
end = i
} else {
flush()
}
}
flush()
fmt.Fprintf(&buf, "]")
return buf.String()
case RegShift:
return fmt.Sprintf("R%d%s$%d", int(a.Reg), plan9Shift[a.Shift], int(a.Count))
case RegShiftReg:
return fmt.Sprintf("R%d%sR%d", int(a.Reg), plan9Shift[a.Shift], int(a.RegCount))
}
return strings.ToUpper(arg.String())
}
// convert memory operand from GNU syntax to Plan 9 syntax, for example,
// [r5] -> (R5)
// [r6, #4080] -> 0xff0(R6)
// [r2, r0, ror #1] -> (R2)(R0@>1)
// inst [r2, -r0, ror #1] -> INST.U (R2)(R0@>1)
// input:
//
// a memory operand
//
// return values:
//
// corresponding memory operand in Plan 9 syntax
// .W/.P/.U suffix
func memOpTrans(mem Mem) (string, string) {
suffix := ""
switch mem.Mode {
case AddrOffset, AddrLDM:
// no suffix
case AddrPreIndex, AddrLDM_WB:
suffix = ".W"
case AddrPostIndex:
suffix = ".P"
}
off := ""
if mem.Offset != 0 {
off = fmt.Sprintf("%#x", mem.Offset)
}
base := fmt.Sprintf("(R%d)", int(mem.Base))
index := ""
if mem.Sign != 0 {
sign := ""
if mem.Sign < 0 {
suffix += ".U"
}
shift := ""
if mem.Count != 0 {
shift = fmt.Sprintf("%s%d", plan9Shift[mem.Shift], mem.Count)
}
index = fmt.Sprintf("(%sR%d%s)", sign, int(mem.Index), shift)
}
return off + base + index, suffix
}
type goFPInfo struct {
op Op
transArgs []int // indexes of arguments which need transformation
gnuName string // instruction name in GNU syntax
goName string // instruction name in Plan 9 syntax
}
var fpInst []goFPInfo = []goFPInfo{
{VADD_EQ_F32, []int{2, 1, 0}, "VADD", "ADDF"},
{VADD_EQ_F64, []int{2, 1, 0}, "VADD", "ADDD"},
{VSUB_EQ_F32, []int{2, 1, 0}, "VSUB", "SUBF"},
{VSUB_EQ_F64, []int{2, 1, 0}, "VSUB", "SUBD"},
{VMUL_EQ_F32, []int{2, 1, 0}, "VMUL", "MULF"},
{VMUL_EQ_F64, []int{2, 1, 0}, "VMUL", "MULD"},
{VNMUL_EQ_F32, []int{2, 1, 0}, "VNMUL", "NMULF"},
{VNMUL_EQ_F64, []int{2, 1, 0}, "VNMUL", "NMULD"},
{VMLA_EQ_F32, []int{2, 1, 0}, "VMLA", "MULAF"},
{VMLA_EQ_F64, []int{2, 1, 0}, "VMLA", "MULAD"},
{VMLS_EQ_F32, []int{2, 1, 0}, "VMLS", "MULSF"},
{VMLS_EQ_F64, []int{2, 1, 0}, "VMLS", "MULSD"},
{VNMLA_EQ_F32, []int{2, 1, 0}, "VNMLA", "NMULAF"},
{VNMLA_EQ_F64, []int{2, 1, 0}, "VNMLA", "NMULAD"},
{VNMLS_EQ_F32, []int{2, 1, 0}, "VNMLS", "NMULSF"},
{VNMLS_EQ_F64, []int{2, 1, 0}, "VNMLS", "NMULSD"},
{VDIV_EQ_F32, []int{2, 1, 0}, "VDIV", "DIVF"},
{VDIV_EQ_F64, []int{2, 1, 0}, "VDIV", "DIVD"},
{VNEG_EQ_F32, []int{1, 0}, "VNEG", "NEGF"},
{VNEG_EQ_F64, []int{1, 0}, "VNEG", "NEGD"},
{VABS_EQ_F32, []int{1, 0}, "VABS", "ABSF"},
{VABS_EQ_F64, []int{1, 0}, "VABS", "ABSD"},
{VSQRT_EQ_F32, []int{1, 0}, "VSQRT", "SQRTF"},
{VSQRT_EQ_F64, []int{1, 0}, "VSQRT", "SQRTD"},
{VCMP_EQ_F32, []int{1, 0}, "VCMP", "CMPF"},
{VCMP_EQ_F64, []int{1, 0}, "VCMP", "CMPD"},
{VCMP_E_EQ_F32, []int{1, 0}, "VCMP.E", "CMPF"},
{VCMP_E_EQ_F64, []int{1, 0}, "VCMP.E", "CMPD"},
{VLDR_EQ, []int{1}, "VLDR", "MOV"},
{VSTR_EQ, []int{1}, "VSTR", "MOV"},
{VMOV_EQ_F32, []int{1, 0}, "VMOV", "MOVF"},
{VMOV_EQ_F64, []int{1, 0}, "VMOV", "MOVD"},
{VMOV_EQ_32, []int{1, 0}, "VMOV", "MOVW"},
{VMOV_EQ, []int{1, 0}, "VMOV", "MOVW"},
{VCVT_EQ_F64_F32, []int{1, 0}, "VCVT", "MOVFD"},
{VCVT_EQ_F32_F64, []int{1, 0}, "VCVT", "MOVDF"},
{VCVT_EQ_F32_U32, []int{1, 0}, "VCVT", "MOVWF.U"},
{VCVT_EQ_F32_S32, []int{1, 0}, "VCVT", "MOVWF"},
{VCVT_EQ_S32_F32, []int{1, 0}, "VCVT", "MOVFW"},
{VCVT_EQ_U32_F32, []int{1, 0}, "VCVT", "MOVFW.U"},
{VCVT_EQ_F64_U32, []int{1, 0}, "VCVT", "MOVWD.U"},
{VCVT_EQ_F64_S32, []int{1, 0}, "VCVT", "MOVWD"},
{VCVT_EQ_S32_F64, []int{1, 0}, "VCVT", "MOVDW"},
{VCVT_EQ_U32_F64, []int{1, 0}, "VCVT", "MOVDW.U"},
}
// convert FP instructions from GNU syntax to Plan 9 syntax, for example,
// vadd.f32 s0, s3, s4 -> ADDF F0, S3, F2
// vsub.f64 d0, d2, d4 -> SUBD F0, F2, F4
// vldr s2, [r11] -> MOVF (R11), F1
// inputs: instruction name and arguments in GNU syntax
// return values: corresponding instruction name and arguments in Plan 9 syntax
func fpTrans(inst *Inst, op string, args []string) (string, []string) {
for _, fp := range fpInst {
if inst.Op&^15 == fp.op {
// remove gnu syntax suffixes
op = strings.Replace(op, ".F32", "", -1)
op = strings.Replace(op, ".F64", "", -1)
op = strings.Replace(op, ".S32", "", -1)
op = strings.Replace(op, ".U32", "", -1)
op = strings.Replace(op, ".32", "", -1)
// compose op name
if fp.op == VLDR_EQ || fp.op == VSTR_EQ {
switch {
case strings.HasPrefix(args[fp.transArgs[0]], "D"):
op = "MOVD" + op[len(fp.gnuName):]
case strings.HasPrefix(args[fp.transArgs[0]], "S"):
op = "MOVF" + op[len(fp.gnuName):]
default:
panic(fmt.Sprintf("wrong FP register: %v", inst))
}
} else {
op = fp.goName + op[len(fp.gnuName):]
}
// transform registers
for ix, ri := range fp.transArgs {
switch {
case strings.HasSuffix(args[ri], "[1]"): // MOVW Rx, Dy[1]
break
case strings.HasSuffix(args[ri], "[0]"): // Dx[0] -> Fx
args[ri] = strings.Replace(args[ri], "[0]", "", -1)
fallthrough
case strings.HasPrefix(args[ri], "D"): // Dx -> Fx
args[ri] = "F" + args[ri][1:]
case strings.HasPrefix(args[ri], "S"):
if inst.Args[ix].(Reg)&1 == 0 { // Sx -> Fy, y = x/2, if x is even
args[ri] = fmt.Sprintf("F%d", (inst.Args[ix].(Reg)-S0)/2)
}
case strings.HasPrefix(args[ri], "$"): // CMPF/CMPD $0, Fx
break
case strings.HasPrefix(args[ri], "R"): // MOVW Rx, Dy[1]
break
default:
panic(fmt.Sprintf("wrong FP register: %v", inst))
}
}
break
}
}
return op, args
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,5 @@
newdecode.txt:
cd ..; go test -cover -run 'ObjdumpARMCond' -v -timeout 10h -printtests -long 2>&1 | tee log
cd ..; go test -cover -run 'ObjdumpARMUncond' -v -timeout 10h -printtests -long 2>&1 | tee -a log
egrep ' (gnu|plan9) ' ../log |sort >newdecode.txt
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,757 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Armmap constructs the ARM opcode map from the instruction set CSV file.
//
// Usage:
//
// armmap [-fmt=format] arm.csv
//
// The known output formats are:
//
// text (default) - print decoding tree in text form
// decoder - print decoding tables for the armasm package
package main
import (
"bufio"
"encoding/csv"
"flag"
"fmt"
"log"
"os"
"sort"
"strconv"
"strings"
)
var format = flag.String("fmt", "text", "output format: text, decoder")
var inputFile string
func usage() {
fmt.Fprintf(os.Stderr, "usage: armmap [-fmt=format] x86.csv\n")
os.Exit(2)
}
func main() {
log.SetFlags(0)
log.SetPrefix("armmap: ")
flag.Usage = usage
flag.Parse()
if flag.NArg() != 1 {
usage()
}
inputFile = flag.Arg(0)
var print func(*Prog)
switch *format {
default:
log.Fatalf("unknown output format %q", *format)
case "text":
print = printText
case "decoder":
print = printDecoder
}
p, err := readCSV(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
print(p)
}
// readCSV reads the CSV file and returns the corresponding Prog.
// It may print details about problems to standard error using the log package.
func readCSV(file string) (*Prog, error) {
// Read input.
// Skip leading blank and # comment lines.
f, err := os.Open(file)
if err != nil {
return nil, err
}
b := bufio.NewReader(f)
for {
c, err := b.ReadByte()
if err != nil {
break
}
if c == '\n' {
continue
}
if c == '#' {
b.ReadBytes('\n')
continue
}
b.UnreadByte()
break
}
table, err := csv.NewReader(b).ReadAll()
if err != nil {
return nil, fmt.Errorf("parsing %s: %v", file, err)
}
if len(table) == 0 {
return nil, fmt.Errorf("empty csv input")
}
if len(table[0]) < 5 {
return nil, fmt.Errorf("csv too narrow: need at least five columns")
}
p := &Prog{}
for _, row := range table {
add(p, row[0], row[1], row[2], row[3], row[4])
}
return p, nil
}
type Prog struct {
Inst []Inst
OpRanges map[string]string
}
type Inst struct {
Text string
Encoding string
Mask uint32
Value uint32
Priority int
OpBase string
OpBits uint64
Args []string
}
type Arg struct {
Name string
Bits uint64
}
// add adds the entry from the CSV described by maskstr, valuestr, text, encoding, tags
// to the program p.
func add(p *Prog, maskstr, valuestr, text, encoding, tags string) {
if strings.Contains(tags, "pseudo") {
return
}
// For now, ignore the VFP floating point instructions.
if strings.HasPrefix(text, "V") && !strings.Contains(tags, "vfp") {
// TODO
return
}
mask, err := strconv.ParseUint(maskstr, 0, 32)
if err != nil {
log.Printf("invalid mask %q", maskstr)
return
}
value, err := strconv.ParseUint(valuestr, 0, 32)
if err != nil {
log.Printf("invalid value %q", valuestr)
return
}
// Parse encoding, building size and offset of each field.
// The first field in the encoding is the largest offset.
fuzzy := uint32(0) // mask of 'should be' bits
fieldOffset := map[string]int{}
fieldWidth := map[string]int{}
off := 32
for _, f := range strings.Split(encoding, "|") {
n := 1
if i := strings.Index(f, ":"); i >= 0 {
n, _ = strconv.Atoi(f[i+1:])
}
off -= n
fieldOffset[f] = off
fieldWidth[f] = n
if f == "(0)" || f == "(1)" {
fuzzy |= 1 << uint(off)
}
}
if off != 0 {
fmt.Fprintf(os.Stderr, "%s: counted %d bits in %s\n", text, 32-off, encoding)
}
// Track which encoding fields we found uses for.
// If we do not find a use for a field, that's an error in the input tables.
fieldUsed := map[string]bool{}
// Split text into opcode and arguments.
var op, argstr string
if i := strings.Index(text, " "); i >= 0 {
op = text[:i]
argstr = text[i:]
} else {
op = text
}
op = strings.TrimSpace(op)
argstr = strings.TrimSpace(argstr)
// Parse opcode suffixes.
i := strings.Index(op, "<")
if i < 0 {
i = len(op)
}
if j := strings.Index(op, "{"); j >= 0 && j < i {
i = j
}
op, suffix := op[:i], op[i:]
if suffix != "" && opSuffix[suffix] == "" {
fmt.Fprintf(os.Stderr, "%s: invalid op suffix %q in %s\n", text, suffix, op+suffix)
}
// Make sure fields needed by opcode suffix are available.
for _, f := range strings.Split(opSuffix[suffix], ",") {
if f != "" && fieldWidth[f] == 0 {
fmt.Fprintf(os.Stderr, "%s: opsuffix %s missing %s in encoding %s\n", text, suffix, f, encoding)
}
fieldUsed[f] = true
}
// Build list of opcodes that can be generated by this suffix.
// For example, the opcodes generated by ADD<c> are ADD.EQ, ADD.NE, etc.
// To simplify the decoding of instruction opcodes, we arrange that this
// sequence aligns with the encoding, so that decoding amounts to extracting
// the right bits, concatenating them, and adding them to the first opcode in
// the sequence. If the condition code is present, we always place it in the
// low order bits, so that x&^15 == FOO_EQ tests whether x is any of the
// conditional FOO instructions.
ops := []string{op}
opBits := uint64(0) // record of bits to extract and add to opcode base
opFields := strings.Split(opSuffix[suffix], ",")
// First the optional elements, like {S} meaning "" or ".S".
for strings.HasPrefix(suffix, "{") {
i := strings.Index(suffix, "}")
var f, option string
option, suffix = suffix[1:i], suffix[i+1:]
f, opFields = opFields[0], opFields[1:]
if option == "W" {
// The {W} option on PLD{W} uses the R bit which is !W.
ops = cross(ops, "."+option, "")
} else {
ops = cross(ops, "", "."+option)
}
if fieldWidth[f] != 1 {
fmt.Fprintf(os.Stderr, "%s: have %d bits for {%s}\n", text, fieldWidth[f], option)
}
// opBits is a sequence of 16-bit chunks describing contiguous bit sections.
// Each chunk is 8-bit offset followed by 8-bit size.
opBits = opBits<<16 | uint64(fieldOffset[f])<<8 | 1
}
// Then the true field substitutions.
haveCond := false
for strings.Contains(suffix, "<") {
var f, literal, x string
if len(opFields) == 0 {
fmt.Fprintf(os.Stderr, "%s: ran out of suffix fields for <%s>\n", text, x)
break
}
f, opFields = opFields[0], opFields[1:]
i := strings.Index(suffix, "<")
j := strings.Index(suffix, ">")
literal, x, suffix = suffix[:i], suffix[i+1:j], suffix[j+1:]
// Add leading literal text to all opcodes.
ops = cross(ops, literal)
// The <c> condition can happen anywhere in the opcode text
// but we want to generate the actual variation in the low bits
// of the list index. Remember when and where we've seen <c> and apply
// it after the loop has finished.
if x == "c" && f == "cond:4" {
haveCond = true
ops = cross(ops, "_COND_")
continue
}
// Otherwise, choices[x] lists the possible expansions of <x>.
// If <x> is of the form <A,B,C> the choices are A, B, and C.
expand := choices[x]
if expand == nil && strings.Contains(x, ",") {
expand = strings.Split(x, ",")
}
if expand == nil {
fmt.Fprintf(os.Stderr, "%s: unknown choices for <%s>\n", text, x)
expand = []string{x}
} else if len(expand) != 1<<uint(fieldWidth[f]) {
fmt.Fprintf(os.Stderr, "%s: have %d choices for <%s> but %d bits\n", text, len(expand), x, fieldWidth[f])
}
opBits = opBits<<16 | uint64(fieldOffset[f])<<8 | uint64(fieldWidth[f])
ops = cross(ops, expand...)
}
if haveCond {
// Apply condtional suffix last.
opBits = opBits<<16 | 28<<8 | 4
ops = crossCond(ops)
}
ops = cross(ops, suffix)
// Now ops is a list of opcodes generated by this opcode pattern.
// We want to make sure that we can arrange for those opcodes to
// happen consecutively in the final opcode numbering.
// Record in p.OpRanges[op] the required consecutive sequence of
// opcode that includes op. To make searches easier, we record
// the sequence as a comma-separated list of strings with commas
// on both ends: [A, B] encodes as ",A,B,".
if p.OpRanges == nil {
p.OpRanges = make(map[string]string)
}
opstr := "," + strings.Join(ops, ",") + ","
for _, op := range ops {
if old := p.OpRanges[op]; old != "" && old != opstr {
if strings.Contains(old, opstr) {
opstr = old
} else if strings.Contains(opstr, old) {
// great, do nothing
} else {
// It would also be okay if there is some subsequence s such that
// old = x+s and opstr = s+y (or vice versa), in which case we should
// record opstr = x+s+y. However, this has not come up in practice.
// Failing that, we can't satisfy the sequencing requirements.
fmt.Fprintf(os.Stderr, "%s: %s appears in both %s and %s\n", text, op, old, opstr)
}
}
}
for _, op := range strings.Split(opstr, ",") {
if op != "" {
p.OpRanges[op] = opstr
}
}
// Process the arguments, building a list of argument descriptions.
// Each argument description has the form <argument>|field@off|field@off...
// where the |field@off suffixes give the name and location of the fields
// needed by the argument. Each such string maps to a different decoding
// type in the generated table, according to the argOps map.
var args []string
for argstr != "" {
// Find longest match among argSuffixes pieces.
best := 0
for a := range argSuffixes {
if argstr == a || strings.HasPrefix(argstr, a+",") {
if best < len(a) {
best = len(a)
}
}
}
if best == 0 {
fmt.Fprintf(os.Stderr, "%s: unknown arg %s\n", text, argstr)
break
}
var arg, desc string
arg, argstr = argstr[:best], strings.TrimSpace(strings.TrimLeft(argstr[best:], ","))
desc = arg
for _, f := range strings.Split(argSuffixes[desc], ",") {
if f == "" {
continue
}
if fieldWidth[f] == 0 {
fmt.Fprintf(os.Stderr, "%s: arg %s missing %s in encoding %s\n", text, arg, f, encoding)
}
fieldUsed[f] = true
desc += fmt.Sprintf("|%s@%d", f, fieldOffset[f])
}
args = append(args, desc)
}
// Check that all encoding fields were used by suffix or argument decoding.
for f := range fieldWidth {
switch f {
case "0", "1", "(0)", "(1)":
// ok
default:
if !fieldUsed[f] {
fmt.Fprintf(os.Stderr, "%s: encoding field %s not used in %s\n", text, f, encoding)
}
}
}
// Determine decoding priority. Instructions that say 'SEE X' in the tag
// are considered lower priority than ones that don't. In theory the
// structure described by the SEE tags might be richer than that, but
// in practice it only has those two levels.
// We leave space for two more priorities according to whether the
// fuzzy bits are set correctly. The full set of priorities then is:
//
// 4 - no SEE tag, fuzzy bits all match
// 3 - no SEE tag, some fuzzy bits don't match
// 2 - SEE tag, fuzzy bits all match
// 1 - SEE tag, some fuzzy bits don't match
//
// You could argue for swapping the middle two levels but so far
// it has not been an issue.
pri := 4
if strings.Contains(tags, "SEE") {
pri = 2
}
inst := Inst{
Text: text,
Encoding: encoding,
Mask: uint32(mask),
Value: uint32(value),
Priority: pri,
OpBase: ops[0],
OpBits: opBits,
Args: args,
}
p.Inst = append(p.Inst, inst)
if fuzzy != 0 {
inst.Mask &^= fuzzy
inst.Priority--
p.Inst = append(p.Inst, inst)
}
}
// opSuffix describes the encoding fields used to resolve a given opcode suffix.
var opSuffix = map[string]string{
"<ADD,SUB>": "op",
"<BIF,BIT,BSL>": "op:2",
"<MLA,MLS><c>.F<32,64>": "op,cond:4,sz",
"<MLS,MLA><c>.F<32,64>": "op,cond:4,sz",
"<BT,TB><c>": "tb,cond:4",
"<TBL,TBX>.8": "op",
"<c>": "cond:4",
"<c>.32": "cond:4",
"<c>.F<32,64>": "cond:4,sz",
"<x><y><c>": "N,M,cond:4",
"<y><c>": "M,cond:4",
"{B}<c>": "B,cond:4",
"{E}<c>.F<32,64>": "E,cond:4,sz",
"{R}<c>": "R,cond:4",
"<c>.F<32,64>.<U,S>32": "cond:4,sz,op",
"<R,><c>.<U,S>32.F<32,64>": "op,cond:4,signed,sz",
"{S}<c>": "S,cond:4",
"{W}": "R",
"{X}<c>": "M,cond:4",
"<B,T><c>.<F32.F16,F16.F32>": "T,cond:4,op",
"<c>.<F64.F32,F32.F64>": "cond:4,sz",
"<c>.FX<S,U><16,32>.F<32,64>": "cond:4,U,sx,sz",
"<c>.F<32,64>.FX<S,U><16,32>": "cond:4,sz,U,sx",
}
// choices[x] describes the choices for filling in "<"+x+">" in an opcode suffix.
// Opcodes that end up containing ZZ take up a numeric sequence value but are
// not exported in the package API.
var choices = map[string][]string{
"c": {".EQ", ".NE", ".CS", ".CC", ".MI", ".PL", ".VS", ".VC", ".HI", ".LS", ".GE", ".LT", ".GT", ".LE", "", ".ZZ"},
"x": {"B", "T"},
"y": {"B", "T"},
}
// argOps maps from argument descriptions to internal decoder name.
var argOps = map[string]string{
// 4-bit register encodings
"<Rm>|Rm:4@0": "arg_R_0",
"<Rn>|Rn:4@0": "arg_R_0",
"<Rt>|Rt:4@0": "arg_R_0",
"<Rm>|Rm:4@8": "arg_R_8",
"<Ra>|Ra:4@12": "arg_R_12",
"<Rd>|Rd:4@12": "arg_R_12",
"<RdLo>|RdLo:4@12": "arg_R_12",
"<Rt>|Rt:4@12": "arg_R_12",
"<Rt_nzcv>|Rt:4@12": "arg_R_12_nzcv",
"<Rd>|Rd:4@16": "arg_R_16",
"<RdHi>|RdHi:4@16": "arg_R_16",
"<Rn>|Rn:4@16": "arg_R_16",
// first and second of consecutive register pair
"<Rt1>|Rt:4@0": "arg_R1_0",
"<Rt1>|Rt:4@12": "arg_R1_12",
"<Rt2>|Rt:4@0": "arg_R2_0",
"<Rt2>|Rt:4@12": "arg_R2_12",
// register arithmetic
"<Rm>,<type> <Rs>|Rm:4@0|Rs:4@8|type:2@5": "arg_R_shift_R",
"<Rm>{,<shift>}|Rm:4@0|imm5:5@7|type:2@5": "arg_R_shift_imm",
"<Rn>{,<shift>}|Rn:4@0|imm5:5@7|sh@6": "arg_R_shift_imm",
"<Rm>{,LSL #<imm5>}|Rm:4@0|imm5:5@7": "arg_R_shift_imm",
"<Rm>{,<rotation>}|Rm:4@0|rotate:2@10": "arg_R_rotate",
// memory references
"<Rn>{!}|Rn:4@16|W@21": "arg_R_16_WB",
"[<Rn>]|Rn:4@16": "arg_mem_R",
"[<Rn>,+/-<Rm>{, <shift>}]{!}|Rn:4@16|U@23|Rm:4@0|type:2@5|imm5:5@7|P@24|W@21": "arg_mem_R_pm_R_shift_imm_W",
"[<Rn>{,#+/-<imm8>}]{!}|Rn:4@16|P@24|U@23|W@21|imm4H:4@8|imm4L:4@0": "arg_mem_R_pm_imm8_W",
"[<Rn>] {,#+/-<imm8>}|Rn:4@16|U@23|imm4H:4@8|imm4L:4@0": "arg_mem_R_pm_imm8_postindex",
"[<Rn>{,#+/-<imm12>}]{!}|Rn:4@16|P@24|U@23|W@21|imm12:12@0": "arg_mem_R_pm_imm12_W",
"[<Rn>],#+/-<imm12>|Rn:4@16|imm12:12@0|U@23": "arg_mem_R_pm_imm12_postindex",
"[<Rn>,#+/-<imm12>]|Rn:4@16|U@23|imm12:12@0": "arg_mem_R_pm_imm12_offset",
"[<Rn>] {,#+/-<imm12>}|Rn:4@16|U@23|imm12:12@0": "arg_mem_R_pm_imm12_postindex",
"[<Rn>], +/-<Rm>|Rn:4@16|U@23|Rm:4@0": "arg_mem_R_pm_R_postindex",
"[<Rn>,+/-<Rm>]{!}|Rn:4@16|U@23|Rm:4@0|P@24|W@21": "arg_mem_R_pm_R_W",
"[<Rn>],+/-<Rm>{, <shift>}|Rn:4@16|Rm:4@0|imm5:5@7|type:2@5|U@23": "arg_mem_R_pm_R_shift_imm_postindex",
"[<Rn>,+/-<Rm>{, <shift>}]|Rn:4@16|U@23|Rm:4@0|type:2@5|imm5:5@7": "arg_mem_R_pm_R_shift_imm_offset",
"[<Rn>{,#+/-<imm8>}]|Rn:4@16|U@23|imm8:8@0": "arg_mem_R_pm_imm8at0_offset",
// pc-relative constants
"<label+12>|imm12:12@0": "arg_label_p_12",
"<label-12>|imm12:12@0": "arg_label_m_12",
"<label+/-12>|imm12:12@0|U@23": "arg_label_pm_12",
"<label+/-4+4>|imm4H:4@8|imm4L:4@0|U@23": "arg_label_pm_4_4",
// constants
"#<const>|imm12:12@0": "arg_const",
"#<imm5>|imm5:5@7": "arg_imm5",
"#<imm5_nz>|imm5:5@7": "arg_imm5_nz",
"#<imm5_32>|imm5:5@7": "arg_imm5_32",
"<label24>|imm24:24@0": "arg_label24",
"#<lsb>|lsb:5@7": "arg_imm5",
"#<width>|lsb:5@7|msb:5@16": "arg_lsb_width",
"#<imm12+4>|imm12:12@8|imm4:4@0": "arg_imm_12at8_4at0",
"#<imm12+4>|imm12:12@0|imm4:4@16": "arg_imm_4at16_12at0",
"<label24H>|imm24:24@0|H@24": "arg_label24H",
"#<option>|option:4@0": "arg_option",
"#<widthm1>|widthm1:5@16": "arg_widthm1",
"#<sat_imm4>|sat_imm:4@16": "arg_satimm4",
"#<sat_imm5>|sat_imm:5@16": "arg_satimm5",
"#<sat_imm4m1>|sat_imm:4@16": "arg_satimm4m1",
"#<sat_imm5m1>|sat_imm:5@16": "arg_satimm5m1",
"#<imm24>|imm24:24@0": "arg_imm24",
// special
"<registers>|register_list:16@0": "arg_registers",
"<registers2>|register_list:16@0": "arg_registers2",
"<registers1>|Rt:4@12": "arg_registers1",
"<endian_specifier>|E@9": "arg_endian",
"SP": "arg_SP",
"APSR": "arg_APSR",
"FPSCR": "arg_FPSCR",
// VFP floating point registers
"<Sd>|Vd:4@12|D@22": "arg_Sd",
"<Sd,Dd>|Vd:4@12|D@22|sz@8": "arg_Sd_Dd",
"<Dd,Sd>|Vd:4@12|D@22|sz@8": "arg_Dd_Sd",
"<Sn>|Vn:4@16|N@7": "arg_Sn",
"<Sn,Dn>|Vn:4@16|N@7|sz@8": "arg_Sn_Dn",
"<Sm>|Vm:4@0|M@5": "arg_Sm",
"<Sm,Dm>|Vm:4@0|M@5|sz@8": "arg_Sm_Dm",
"#0.0": "arg_fp_0",
"#<imm_vfp>|imm4H:4@16|imm4L:4@0|sz@8": "arg_imm_vfp",
"#<fbits>|sx@7|imm4:4@0|i@5": "arg_fbits",
"<Dn[x]>|N@7|Vn:4@16|opc1@21": "arg_Dn_half",
"<Dd[x]>|D@7|Vd:4@16|opc1@21": "arg_Dn_half",
}
// argSuffixes describes the encoding fields needed for a particular suffix.
// The set of keys in argSuffixes also drives the identification of suffix pieces.
// For example, <Rm> and <Rm>{, <type> <Rs>} are both keys in the map
// and matching is done 'longest first', so "<Rm>, <Rm>{, <type> <Rs>}" is
// parsed as just two arguments despite the extra ", ".
// The field order in the map values must match the order expected in
// the argument descriptions in argOps.
var argSuffixes = map[string]string{
"#0": "",
"#0.0": "",
"#<const>": "imm12:12",
"#<fbits>": "sx,imm4:4,i",
"#<imm12+4>": "imm12:12,imm4:4",
"#<imm24>": "imm24:24",
"#<imm3>": "imm3:3",
"#<imm4>": "imm4:4",
"#<imm5>": "imm5:5",
"#<imm5_nz>": "imm5:5",
"#<imm5_32>": "imm5:5",
"#<imm6>": "imm6:6",
"#<immsize>": "size:2",
"#<imm_vfp>": "imm4H:4,imm4L:4,sz",
"#<sat_imm4>": "sat_imm:4",
"#<sat_imm5>": "sat_imm:5",
"#<sat_imm4m1>": "sat_imm:4",
"#<sat_imm5m1>": "sat_imm:5",
"#<lsb>": "lsb:5",
"#<option>": "option:4",
"#<width>": "lsb:5,msb:5",
"#<widthm1>": "widthm1:5",
"+/-<Rm>": "Rm:4,U",
"<Dd>": "D,Vd:4",
"<Dd[x]>": "D,Vd:4,opc1",
"<Dm>": "M,Vm:4",
"<Dm[x]>": "M,Vm:4,size:2",
"<Dn>": "N,Vn:4",
"<Dn[x]>": "N,Vn:4,opc1",
"<Dm[size_x]>": "imm4:4",
"<Qd>": "D,Vd:4",
"<Qm>": "M,Vm:4",
"<Qn>": "N,Vn:4",
"<Ra>": "Ra:4",
"<Rd>": "Rd:4",
"<RdHi>": "RdHi:4",
"<RdLo>": "RdLo:4",
"<Rm>": "Rm:4",
"<Rm>{,<rotation>}": "Rm:4,rotate:2",
"<Rm>{,<shift>}": "Rm:4,imm5:5,type:2",
"<Rm>{,LSL #<imm5>}": "Rm:4,imm5:5",
"<Rn>": "Rn:4",
"<Rn>{!}": "Rn:4,W",
"<Rn>{,<shift>}": "Rn:4,imm5:5,sh",
"<Rs>": "Rs:4",
"<Rt1>": "Rt:4",
"<Rt2>": "Rt:4",
"<Rt>": "Rt:4",
"<Rt_nzcv>": "Rt:4",
"<Sd>": "Vd:4,D",
"<Sm1>": "Vm:4,M",
"<Sm>": "Vm:4,M",
"<Sn>": "Vn:4,N",
"<Sd,Dd>": "Vd:4,D,sz",
"<Dd,Sd>": "Vd:4,D,sz",
"<Sn,Dn>": "Vn:4,N,sz",
"<Sm,Dm>": "Vm:4,M,sz",
"<endian_specifier>": "E",
"<label+/-12>": "imm12:12,U",
"<label+12>": "imm12:12",
"<label-12>": "imm12:12",
"<label24>": "imm24:24",
"<label24H>": "imm24:24,H",
"<label+/-4+4>": "imm4H:4,imm4L:4,U",
"<list4>": "D,Vd:4,type:4",
"<list3>": "D,Vd:4,index_align:4",
"<list3t>": "D,Vd:4,T",
"<list1>": "D,Vd:4",
"<list_len>": "N,Vn:4,len:2",
"<vlist32>": "D,Vd:4,imm8:8",
"<vlist64>": "D,Vd:4,imm8:8",
"<registers>": "register_list:16",
"<registers2>": "register_list:16",
"<registers1>": "Rt:4",
"APSR": "",
"<Rm>,<type> <Rs>": "Rm:4,Rs:4,type:2",
"FPSCR": "",
"SP": "",
"[<Rn>,#+/-<imm12>]": "Rn:4,U,imm12:12",
"[<Rn>,+/-<Rm>]{!}": "Rn:4,U,Rm:4,P,W",
"[<Rn>,+/-<Rm>{, <shift>}]": "Rn:4,U,Rm:4,type:2,imm5:5",
"[<Rn>,+/-<Rm>{, <shift>}]{!}": "Rn:4,U,Rm:4,type:2,imm5:5,P,W",
"[<Rn>] {,#+/-<imm12>}": "Rn:4,U,imm12:12",
"[<Rn>] {,#+/-<imm8>}": "Rn:4,U,imm4H:4,imm4L:4",
"[<Rn>]": "Rn:4",
"[<Rn>],#+/-<imm12>": "Rn:4,imm12:12,U",
"[<Rn>],+/-<Rm>{, <shift>}": "Rn:4,Rm:4,imm5:5,type:2,U",
"[<Rn>]{!}": "Rn:4,Rm:4",
"[<Rn>{@<align>}]{!}": "XXX",
"[<Rn>{,#+/-<imm12>}]{!}": "Rn:4,P,U,W,imm12:12",
"[<Rn>{,#+/-<imm8>}]{!}": "Rn:4,P,U,W,imm4H:4,imm4L:4",
"[<Rn>{,#+/-<imm8>}]": "Rn:4,U,imm8:8",
"[<Rn>], +/-<Rm>": "Rn:4,U,Rm:4",
"#<imm_simd1>": "i,imm3:3,imm4:4,cmode:4",
"#<imm_simd>": "op,i,imm3:3,imm4:4,cmode:4",
"#<imm_vs>": "L,imm6:6",
"#<imm_vsn>": "imm6:6",
}
// cross returns the string concatenation cross product of xs and ys.
func cross(xs []string, ys ...string) []string {
var xys []string
for _, x := range xs {
for _, y := range ys {
xys = append(xys, x+y)
}
}
return xys
}
// crossCond returns the cross product of xs with all the possible
// conditional execution suffixes. It is assumed that each string x in xs
// contains a substring _COND_ marking where the conditional suffix
// should be placed.
func crossCond(xs []string) []string {
ys := choices["c"]
var xys []string
for _, x := range xs {
i := strings.Index(x, "_COND_")
pre, post := x[:i], x[i+6:]
for _, y := range ys {
xys = append(xys, pre+y+post)
}
}
return xys
}
// printText implements the -fmt=text mode, which is not implemented (yet?).
func printText(p *Prog) {
log.Fatal("-fmt=text not implemented")
}
// printDecoder implements the -fmt=decoder mode.
// It emits the tables.go for package armasm's decoder.
func printDecoder(p *Prog) {
fmt.Printf("package armasm\n\n")
// Build list of opcodes sorted by name
// but preserving the sequential ranges needed for opcode decoding.
haveRange := make(map[string]string)
for _, r := range p.OpRanges {
haveRange[r] = r
}
var ranges []string
for _, r := range haveRange {
ranges = append(ranges, r)
}
sort.Strings(ranges)
// Emit const definitions for opcodes.
fmt.Printf("const (\n")
iota := 0
fmt.Printf("\t_ Op = iota\n")
iota++
for _, r := range ranges {
for _, op := range strings.Split(r, ",") {
if op == "" {
continue
}
// Assume if opcode says .EQ it is the start of a 16-wide
// iteration through the conditional suffixes. If so, emit
// blank names until the assigned value is 16-aligned.
if strings.Contains(op, ".EQ") {
for iota&15 != 0 {
fmt.Printf("\t_\n")
iota++
}
}
fmt.Printf("\t%s\n", strings.Replace(op, ".", "_", -1))
iota++
}
}
fmt.Printf(")\n")
// Emit slice mapping opcode number to name string.
fmt.Printf("\nvar opstr = [...]string{\n")
for _, r := range ranges {
for _, op := range strings.Split(r, ",") {
if op == "" {
continue
}
fmt.Printf("\t%s: %q,\n", strings.Replace(op, ".", "_", -1), op)
}
}
fmt.Printf("}\n")
// Emit decoding table.
unknown := map[string]bool{}
fmt.Printf("\nvar instFormats = [...]instFormat{\n")
for _, inst := range p.Inst {
fmt.Printf("\t{%#08x, %#08x, %d, %s, %#x, instArgs{", inst.Mask, inst.Value, inst.Priority, strings.Replace(inst.OpBase, ".", "_", -1), inst.OpBits)
for i, a := range inst.Args {
if i > 0 {
fmt.Printf(", ")
}
str := argOps[a]
if str == "" && !unknown[a] {
fmt.Fprintf(os.Stderr, "%s: unknown arg %s\n", inst.Text, a)
unknown[a] = true
}
fmt.Printf("%s", str)
}
fmt.Printf("}}, // %s %s\n", inst.Text, inst.Encoding)
}
fmt.Printf("}\n")
}
@@ -0,0 +1,610 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Armspec reads the “ARM Architecture Reference Manual”
// to collect instruction encoding details and writes those details to standard output
// in JSON format.
//
// # Warning Warning Warning
//
// This program is unfinished. It is being published in this incomplete form
// for interested readers, but do not expect it to be runnable or useful.
package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"log"
"math"
"os"
"regexp"
"sort"
"strconv"
"strings"
"rsc.io/pdf"
)
type Inst struct {
Name string
ID string
Bits string
Arch string
Syntax []string
Code string
}
const debugPage = 0
var stdout *bufio.Writer
func main() {
log.SetFlags(0)
log.SetPrefix("armspec: ")
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "usage: armspec file.pdf\n")
os.Exit(2)
}
f, err := pdf.Open(os.Args[1])
if err != nil {
log.Fatal(err)
}
// Find instruction set reference in outline, to build instruction list.
instList := instHeadings(f.Outline())
if len(instList) < 200 {
log.Fatalf("only found %d instructions in table of contents", len(instList))
}
stdout = bufio.NewWriter(os.Stdout)
fmt.Fprintf(stdout, "[")
numTable := 0
defer stdout.Flush()
// Scan document looking for instructions.
// Must find exactly the ones in the outline.
n := f.NumPage()
PageLoop:
for pageNum := 1; pageNum <= n; pageNum++ {
if debugPage > 0 && pageNum != debugPage {
continue
}
if pageNum > 1127 {
break
}
p := f.Page(pageNum)
name, table := parsePage(pageNum, p)
if name == "" {
continue
}
if len(table) < 1 {
if false {
fmt.Fprintf(os.Stderr, "no encodings for instruction %q (page %d)\n", name, pageNum)
}
continue
}
for _, inst := range table {
if numTable > 0 {
fmt.Fprintf(stdout, ",")
}
numTable++
js, _ := json.Marshal(inst)
fmt.Fprintf(stdout, "\n%s", jsFix.Replace(string(js)))
}
for j, headline := range instList {
if name == headline {
instList[j] = ""
continue PageLoop
}
}
fmt.Fprintf(os.Stderr, "unexpected instruction %q (page %d)\n", name, pageNum)
}
fmt.Fprintf(stdout, "\n]\n")
stdout.Flush()
if debugPage == 0 {
for _, headline := range instList {
if headline != "" {
switch headline {
default:
fmt.Fprintf(os.Stderr, "missing instruction %q\n", headline)
case "CHKA": // ThumbEE
case "CPS": // system instruction
case "CPY": // synonym for MOV
case "ENTERX": // ThumbEE
case "F* (former VFP instruction mnemonics)": // synonyms
case "HB, HBL, HBLP, HBP": // ThumbEE
case "LEAVEX": // ThumbEE
case "MOV (shifted register)": // pseudo instruction for ASR, LSL, LSR, ROR, and RRX
case "NEG": // synonym for RSB
case "RFE": // system instruction
case "SMC (previously SMI)": // system instruction
case "SRS": // system instruction
case "SUBS PC, LR and related instructions": // system instruction
case "VAND (immediate)": // pseudo instruction
case "VCLE (register)": // pseudo instruction
case "VCLT (register)": // pseudo instruction
case "VORN (immediate)": // pseudo instruction
}
}
}
}
}
func instHeadings(outline pdf.Outline) []string {
return appendInstHeadings(outline, nil)
}
var instRE = regexp.MustCompile(`A[\d.]+ Alphabetical list of instructions`)
var childRE = regexp.MustCompile(`A[\d.]+ (.+)`)
var sectionRE = regexp.MustCompile(`^A[\d.]+$`)
var bitRE = regexp.MustCompile(`^( |[01]|\([01]\))*$`)
func appendInstHeadings(outline pdf.Outline, list []string) []string {
if instRE.MatchString(outline.Title) {
for _, child := range outline.Child {
m := childRE.FindStringSubmatch(child.Title)
if m == nil {
fmt.Fprintf(os.Stderr, "cannot parse section title: %s\n", child.Title)
continue
}
list = append(list, m[1])
}
}
for _, child := range outline.Child {
list = appendInstHeadings(child, list)
}
return list
}
const inch = 72.0
func parsePage(num int, p pdf.Page) (name string, table []Inst) {
content := p.Content()
var text []pdf.Text
for _, t := range content.Text {
if match(t, "Times-Roman", 7.2, "") {
t.FontSize = 9
}
if match(t, "Times-Roman", 6.72, "") && '0' <= t.S[0] && t.S[0] <= '9' {
t.S = string([]rune("⁰¹²³⁴⁵⁶⁷⁸⁹")[t.S[0]-'0'])
t.FontSize = 9
t.Y -= 2.28
}
if t.Font == "Gen_Arial" {
continue
}
text = append(text, t)
}
text = findWords(text)
for i, t := range text {
if t.Font == "Times" {
t.Font = "Times-Roman"
text[i] = t
}
}
if debugPage > 0 {
for _, t := range text {
fmt.Println(t)
}
for _, r := range content.Rect {
fmt.Println(r)
}
}
// Remove text we should ignore.
out := text[:0]
skip := false
for _, t := range text {
// skip page footer
if match(t, "Helvetica", 8, "A") || match(t, "Helvetica", 8, "ARM DDI") || match(t, "Helvetica-Oblique", 8, "Copyright") {
continue
}
// skip section header and body text
if match(t, "Helvetica-Bold", 12, "") && (sectionRE.MatchString(t.S) || t.S == "Alphabetical list of instructions") {
skip = true
continue
}
if skip && match(t, "Times-Roman", 9, "") {
continue
}
skip = false
out = append(out, t)
}
text = out
// Page header must say Instruction Details.
if len(text) == 0 || !match(text[0], "Helvetica-Oblique", 8, "Instruction Details") && !match(text[0], "Times-Roman", 9, "Instruction Details") {
return "", nil
}
text = text[1:]
isSection := func(text []pdf.Text, i int) int {
if i+2 <= len(text) && match(text[i], "Helvetica-Bold", 10, "") && sectionRE.MatchString(text[i].S) && match(text[i+1], "Helvetica-Bold", 10, "") {
return 2
}
if i+1 <= len(text) && match(text[i], "Helvetica-Bold", 10, "") && childRE.MatchString(text[i].S) {
return 1
}
return 0
}
// Skip dummy headlines and sections.
for d := isSection(text, 0); d != 0; d = isSection(text, 0) {
i := d
for i < len(text) && !match(text[i], "Helvetica-Bold", 9, "Encoding") && !match(text[i], "Helvetica-Bold", 10, "") {
i++
}
if isSection(text, i) == 0 {
break
}
text = text[i:]
}
// Next line is headline. Can wrap to multiple lines.
d := isSection(text, 0)
if d == 0 {
if debugPage > 0 {
fmt.Printf("non-inst-headline: %v\n", text[0])
}
checkNoEncodings(num, text)
return "", nil
}
if d == 2 {
name = text[1].S
text = text[2:]
} else if d == 1 {
m := childRE.FindStringSubmatch(text[0].S)
name = m[1]
text = text[1:]
}
for len(text) > 0 && match(text[0], "Helvetica-Bold", 10, "") {
name += " " + text[0].S
text = text[1:]
}
// Skip description.
for len(text) > 0 && (match(text[0], "Times-Roman", 9, "") || match(text[0], "LucidaSansTypewriteX", 6.48, "") || match(text[0], "Times-Bold", 10, "Note")) {
text = text[1:]
}
// Encodings follow.
warned := false
for i := 0; i < len(text); {
if match(text[i], "Helvetica-Bold", 10, "Assembler syntax") ||
match(text[i], "Helvetica-Bold", 9, "Modified operation in ThumbEE") ||
match(text[i], "Helvetica-Bold", 9, "Unallocated memory hints") ||
match(text[i], "Helvetica-Bold", 9, "Related encodings") ||
match(text[i], "Times-Roman", 9, "Figure A") ||
match(text[i], "Helvetica-Bold", 9, "Table A") ||
match(text[i], "Helvetica-Bold", 9, "VFP Instructions") ||
match(text[i], "Helvetica-Bold", 9, "VFP instructions") ||
match(text[i], "Helvetica-Bold", 9, "VFP vectors") ||
match(text[i], "Helvetica-Bold", 9, "FLDMX") ||
match(text[i], "Helvetica-Bold", 9, "FSTMX") ||
match(text[i], "Helvetica-Bold", 9, "Advanced SIMD and VFP") {
checkNoEncodings(num, text[i:])
break
}
if match(text[i], "Helvetica-Bold", 9, "Figure A") {
y := text[i].Y
i++
for i < len(text) && math.Abs(text[i].Y-y) < 2 {
i++
}
continue
}
if !match(text[i], "Helvetica-Bold", 9, "Encoding") {
if !warned {
warned = true
fmt.Fprintln(os.Stderr, "page", num, ": unexpected:", text[i])
}
i++
continue
}
inst := Inst{
Name: name,
}
enc := text[i].S
x := text[i].X
i++
// Possible subarchitecture notes.
for i < len(text) && text[i].X > x+36 {
if inst.Arch != "" {
inst.Arch += " "
}
inst.Arch += text[i].S
i++
}
// Encoding syntaxes.
for i < len(text) && (match(text[i], "LucidaSansTypewriteX", 6.48, "") || text[i].X > x+36) {
if text[i].X < x+0.25*inch {
inst.Syntax = append(inst.Syntax, text[i].S)
} else {
s := inst.Syntax[len(inst.Syntax)-1]
if !strings.Contains(s, "\t") {
s += "\t"
} else {
s += " "
}
s += text[i].S
inst.Syntax[len(inst.Syntax)-1] = s
}
i++
}
var bits, abits, aenc string
bits, i = readBitBox(inst.Name, inst.Syntax, content, text, i)
if strings.Contains(enc, " / ") {
if i < len(text) && match(text[i], "Times-Roman", 8, "") {
abits, i = readBitBox(inst.Name, inst.Syntax, content, text, i)
} else {
abits = bits
}
slash := strings.Index(enc, " / ")
aenc = "Encoding " + enc[slash+len(" / "):]
enc = enc[:slash]
}
// pseudocode
y0 := -1 * inch
tab := 0.0
for i < len(text) && match(text[i], "LucidaSansTypewriteX", 6.48, "") {
t := text[i]
i++
if math.Abs(t.Y-y0) < 3 {
// same line as last fragment, probably just two spaces
inst.Code += " " + t.S
continue
}
if inst.Code != "" {
inst.Code += "\n"
}
if t.X > x+0.1*inch {
if tab == 0 {
tab = t.X - x
}
inst.Code += strings.Repeat("\t", int((t.X-x)/tab+0.5))
} else {
tab = 0
}
inst.Code += t.S
y0 = t.Y
}
inst.ID = strings.TrimPrefix(enc, "Encoding ")
inst.Bits = bits
table = append(table, inst)
if abits != "" {
inst.ID = strings.TrimPrefix(aenc, "Encoding ")
inst.Bits = abits
table = append(table, inst)
}
}
return name, table
}
func readBitBox(name string, syntax []string, content pdf.Content, text []pdf.Text, i int) (string, int) {
// bit headings
y2 := 0.0
x1 := 0.0
x2 := 0.0
for i < len(text) && match(text[i], "Times-Roman", 8, "") {
if y2 == 0 {
y2 = text[i].Y
}
if x1 == 0 {
x1 = text[i].X
}
i++
}
// bit fields in box
y1 := 0.0
dy1 := 0.0
for i < len(text) && match(text[i], "Times-Roman", 9, "") {
if x2 < text[i].X+text[i].W {
x2 = text[i].X + text[i].W
}
y1 = text[i].Y
dy1 = text[i].FontSize
i++
}
if debugPage > 0 {
fmt.Println("encoding box", x1, y1, x2, y2)
}
// Find lines (thin rectangles) separating bit fields.
var bottom, top pdf.Rect
const (
yMargin = 0.25 * 72
xMargin = 2 * 72
)
for _, r := range content.Rect {
if r.Max.Y-r.Min.Y < 2 && x1-xMargin < r.Min.X && r.Min.X < x1 && x2 < r.Max.X && r.Max.X < x2+xMargin {
if y1-yMargin < r.Min.Y && r.Min.Y < y1 {
bottom = r
}
if y1+dy1 < r.Min.Y && r.Min.Y < y2 {
top = r
}
}
}
if debugPage > 0 {
fmt.Println("top", top, "bottom", bottom)
}
const ε = 0.1 * 72
var bars []pdf.Rect
for _, r := range content.Rect {
if r.Max.X-r.Min.X < 2 && math.Abs(r.Min.Y-bottom.Min.Y) < ε && math.Abs(r.Max.Y-top.Min.Y) < ε {
bars = append(bars, r)
}
}
sort.Sort(RectHorizontal(bars))
// There are 16-bit and 32-bit encodings.
// In practice, they are about 2.65 and 5.3 inches wide, respectively.
// Use 4 inches as a cutoff.
nbit := 32
dx := top.Max.X - top.Min.X
if top.Max.X-top.Min.X < 4*72 {
nbit = 16
}
total := 0
var buf bytes.Buffer
for i := 0; i < len(bars)-1; i++ {
if i > 0 {
fmt.Fprintf(&buf, "|")
}
var sub []pdf.Text
x1, x2 := bars[i].Min.X, bars[i+1].Min.X
for _, t := range content.Text {
tx := t.X + t.W/2
ty := t.Y + t.FontSize/2
if x1 < tx && tx < x2 && y1 < ty && ty < y2 {
sub = append(sub, t)
}
}
var str []string
for _, t := range findWords(sub) {
str = append(str, t.S)
}
s := strings.Join(str, " ")
s = strings.Replace(s, ")(", ") (", -1)
n := len(strings.Fields(s))
b := int(float64(nbit)*(x2-x1)/dx + 0.5)
if n == b {
for j, f := range strings.Fields(s) {
if j > 0 {
fmt.Fprintf(&buf, "|")
}
fmt.Fprintf(&buf, "%s", f)
}
} else {
if n != 1 {
fmt.Fprintf(os.Stderr, "%s - %s - multi-field %d-bit encoding: %s\n", name, syntax, n, s)
}
fmt.Fprintf(&buf, "%s:%d", s, b)
}
total += b
}
if total != nbit || total == 0 {
fmt.Fprintf(os.Stderr, "%s - %s - %d-bit encoding\n", name, syntax, total)
}
return buf.String(), i
}
type RectHorizontal []pdf.Rect
func (x RectHorizontal) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x RectHorizontal) Less(i, j int) bool { return x[i].Min.X < x[j].Min.X }
func (x RectHorizontal) Len() int { return len(x) }
func checkNoEncodings(num int, text []pdf.Text) {
for _, t := range text {
if match(t, "Helvetica-Bold", 9, "Encoding") {
fmt.Fprintf(os.Stderr, "page %d: unexpected encoding: %s\n", num, t.S)
}
}
}
func match(t pdf.Text, font string, size float64, substr string) bool {
return t.Font == font && math.Abs(t.FontSize-size) < 0.1 && strings.Contains(t.S, substr)
}
func findWords(chars []pdf.Text) (words []pdf.Text) {
// Sort by Y coordinate and normalize.
const nudge = 1
sort.Sort(pdf.TextVertical(chars))
old := -100000.0
for i, c := range chars {
if c.Y != old && math.Abs(old-c.Y) < nudge {
chars[i].Y = old
} else {
old = c.Y
}
}
// Sort by Y coordinate, breaking ties with X.
// This will bring letters in a single word together.
sort.Sort(pdf.TextVertical(chars))
// Loop over chars.
for i := 0; i < len(chars); {
// Find all chars on line.
j := i + 1
for j < len(chars) && chars[j].Y == chars[i].Y {
j++
}
var end float64
// Split line into words (really, phrases).
for k := i; k < j; {
ck := &chars[k]
s := ck.S
end = ck.X + ck.W
charSpace := ck.FontSize / 6
wordSpace := ck.FontSize * 2 / 3
l := k + 1
for l < j {
// Grow word.
cl := &chars[l]
if sameFont(cl.Font, ck.Font) && math.Abs(cl.FontSize-ck.FontSize) < 0.1 && cl.X <= end+charSpace {
s += cl.S
end = cl.X + cl.W
l++
continue
}
// Add space to phrase before next word.
if sameFont(cl.Font, ck.Font) && math.Abs(cl.FontSize-ck.FontSize) < 0.1 && cl.X <= end+wordSpace {
s += " " + cl.S
end = cl.X + cl.W
l++
continue
}
break
}
f := ck.Font
f = strings.TrimSuffix(f, ",Italic")
f = strings.TrimSuffix(f, "-Italic")
words = append(words, pdf.Text{f, ck.FontSize, ck.X, ck.Y, end - ck.X, s})
k = l
}
i = j
}
return words
}
func sameFont(f1, f2 string) bool {
f1 = strings.TrimSuffix(f1, ",Italic")
f1 = strings.TrimSuffix(f1, "-Italic")
f2 = strings.TrimSuffix(f1, ",Italic")
f2 = strings.TrimSuffix(f1, "-Italic")
return strings.TrimSuffix(f1, ",Italic") == strings.TrimSuffix(f2, ",Italic") || f1 == "Symbol" || f2 == "Symbol" || f1 == "TimesNewRoman" || f2 == "TimesNewRoman"
}
var jsFix = strings.NewReplacer(
// `\u003c`, `<`,
// `\u003e`, `>`,
// `\u0026`, `&`,
// `\u0009`, `\t`,
)
func printTable(name string, table []Inst) {
_ = strconv.Atoi
}
@@ -0,0 +1,223 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build ignore
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"regexp"
"strconv"
"strings"
)
var _ = os.Stdout
var _ = fmt.Sprintf
type Inst struct {
Name string
ID string
Bits string
Arch string
Syntax []string
Code string
Base uint32
Mask uint32
Prog []*Stmt
}
func main() {
data, err := ioutil.ReadFile("spec.json")
if err != nil {
log.Fatal(err)
}
var insts []Inst
if err := json.Unmarshal(data, &insts); err != nil {
log.Fatal(err)
}
var out []Inst
for _, inst := range insts {
inst.Prog = parse(inst.Name+" "+inst.ID, inst.Code)
if inst.ID[0] == 'A' && !strings.HasPrefix(inst.Syntax[0], "MSR<c>") && !strings.Contains(inst.Syntax[0], "<coproc>") && !strings.Contains(inst.Syntax[0], "VLDM") && !strings.Contains(inst.Syntax[0], "VSTM") {
out = append(out, inst)
}
}
insts = out
for i := range insts {
dosize(&insts[i])
}
var cond, special []Inst
for _, inst := range insts {
if inst.Base>>28 == 0xF {
special = append(special, inst)
} else {
cond = append(cond, inst)
}
}
fmt.Printf("special:\n")
split(special, 0xF0000000, 1)
fmt.Printf("cond:\n")
split(cond, 0xF0000000, 1)
}
func dosize(inst *Inst) {
var base, mask uint32
off := 0
for _, f := range strings.Split(inst.Bits, "|") {
if i := strings.Index(f, ":"); i >= 0 {
n, _ := strconv.Atoi(f[i+1:])
off += n
continue
}
for _, bit := range strings.Fields(f) {
switch bit {
case "0", "(0)":
mask |= 1 << uint(31-off)
case "1", "(1)":
base |= 1 << uint(31-off)
}
off++
}
}
if off != 16 && off != 32 {
log.Printf("incorrect bit count for %s %s: have %d", inst.Name, inst.Bits, off)
}
if off == 16 {
mask >>= 16
base >>= 16
}
mask |= base
inst.Mask = mask
inst.Base = base
}
func split(insts []Inst, used uint32, depth int) {
Again:
if len(insts) <= 1 {
for _, inst := range insts {
fmt.Printf("%*s%#08x %#08x %s %s %v\n", depth*2+2, "", inst.Mask, inst.Base, inst.Syntax[0], inst.Bits, seeRE.FindAllString(inst.Code, -1))
}
return
}
m := ^used
for _, inst := range insts {
m &= inst.Mask
}
if m == 0 {
fmt.Printf("«%*s%#08x masked out (%d)\n", depth*2, "", used, len(insts))
for _, inst := range insts {
fmt.Printf("%*s%#08x %#08x %s %s %v\n", depth*2+2, "", inst.Mask, inst.Base, inst.Syntax[0], inst.Bits, seeRE.FindAllString(inst.Code, -1))
}
updated := false
for i := range insts {
if updateMask(&insts[i]) {
updated = true
}
}
fmt.Printf("»\n")
if updated {
goto Again
}
fmt.Printf("%*s%#08x masked out (%d)\n", depth*2, "", used, len(insts))
for _, inst := range insts {
fmt.Printf("%*s%#08x %#08x %s %s %v\n", depth*2+2, "", inst.Mask, inst.Base, inst.Syntax[0], inst.Bits, seeRE.FindAllString(inst.Code, -1))
}
//checkOverlap(used, insts)
return
}
for i := 31; i >= 0; i-- {
if m&(1<<uint(i)) != 0 {
m = 1 << uint(i)
break
}
}
var bit [2][]Inst
for _, inst := range insts {
b := (inst.Base / m) & 1
bit[b] = append(bit[b], inst)
}
for b, list := range bit {
if len(list) > 0 {
suffix := ""
if len(bit[1-b]) == 0 {
suffix = " (only)"
}
fmt.Printf("%*sbit %#08x = %d%s\n", depth*2, "", m, b, suffix)
split(list, used|m, depth+1)
}
}
}
var seeRE = regexp.MustCompile(`SEE ([^;\n]+)`)
func updateMask(inst *Inst) bool {
defer func() {
if err := recover(); err != nil {
fmt.Println("PANIC:", err)
return
}
}()
print(".")
println(inst.Name, inst.ID, inst.Bits)
println(inst.Code)
wiggle := ^inst.Mask &^ 0xF0000000
n := countbits(wiggle)
m1 := ^uint32(0)
m2 := ^uint32(0)
for i := uint32(0); i < 1<<uint(n); i++ {
w := inst.Base | expand(i, wiggle)
if !isValid(inst, w) {
continue
}
m1 &= w
m2 &= ^w
}
m := m1 | m2
m &^= 0xF0000000
m |= 0xF0000000 & inst.Mask
if m&^inst.Mask != 0 {
fmt.Printf("%s %s: mask=%#x but decided %#x\n", inst.Name, inst.ID, inst.Mask, m)
inst.Mask = m
inst.Base = m1
return true
}
if inst.Mask&^m != 0 {
fmt.Printf("%s %s: mask=%#x but got %#x\n", inst.Name, inst.ID, inst.Mask, m)
panic("bad updateMask")
}
return false
}
func countbits(x uint32) int {
n := 0
for ; x != 0; x >>= 1 {
n += int(x & 1)
}
return n
}
func expand(x, m uint32) uint32 {
var out uint32
for i := uint(0); i < 32; i++ {
out >>= 1
if m&1 != 0 {
out |= (x & 1) << 31
x >>= 1
}
m >>= 1
}
return out
}