6371 lines
166 KiB
Plaintext
6371 lines
166 KiB
Plaintext
# Specification for the ARM Version 4, 4T, 5, 5T, 5E
|
|
# The following boolean defines control specific support: T_VARIANT, VERSION_5, VERSION_5E
|
|
|
|
#
|
|
# WARNING NOTE: Be very careful taking a subpiece or truncating a register with :# or (#)
|
|
# The LEBE hybrid language causes endian issues if you do not assign the register to a temp
|
|
# variable and then take a subpiece or truncate.
|
|
#
|
|
|
|
@if defined(SIMD) || defined(VFPv2) || defined(VFPv3)
|
|
@define INCLUDE_NEON "" # Neon instructions included with SIMD, VFPv2 or VFPv3
|
|
@endif
|
|
|
|
@if defined(T_VARIANT)
|
|
@define AMODE "TMode=0" # T_VARIANT must restrict ARM instruction decoding and require TMode=0
|
|
@else
|
|
@define AMODE "epsilon" # THUMB instructions not supported - ARM only
|
|
@endif
|
|
|
|
@if defined(T_VARIANT)
|
|
@define VERSION_5_or_T ""
|
|
@endif
|
|
@if defined(VERSION_5)
|
|
@define VERSION_5_or_T ""
|
|
@endif
|
|
|
|
define token prefix (32)
|
|
pref=(0,31)
|
|
;
|
|
|
|
define token instrArm (32)
|
|
cond=(28,31)
|
|
I25=(25,25)
|
|
P24=(24,24)
|
|
H24=(24,24)
|
|
L24=(24,24)
|
|
U23=(23,23)
|
|
B22=(22,22)
|
|
N22=(22,22)
|
|
S22=(22,22)
|
|
op=(21,24)
|
|
W21=(21,21)
|
|
S20=(20,20)
|
|
L20=(20,20)
|
|
Rn=(16,19)
|
|
RnLo=(0,3)
|
|
msb=(16,20)
|
|
satimm5=(16,20)
|
|
satimm4=(16,19)
|
|
mask=(16,19)
|
|
Rd=(12,15)
|
|
Rd2=(12,15)
|
|
CRd=(12,15)
|
|
CRn=(16,19)
|
|
CRm=(0,3)
|
|
RdHi=(16,19)
|
|
RdLo=(12,15)
|
|
smRd=(16,19)
|
|
smRa=(12,15)
|
|
smRm=(8,11)
|
|
smRn=(0,3)
|
|
immed12=(8,19)
|
|
Rs=(8,11)
|
|
rotate=(8,11)
|
|
immedH=(8,11)
|
|
cpn=(8,11)
|
|
opc1=(21,23)
|
|
opcode1=(20,23)
|
|
opc2=(5,7)
|
|
opcode2=(5,7)
|
|
opcode3=(4,7)
|
|
lsb=(7,11)
|
|
sftimm=(7,11)
|
|
sh=(6,6)
|
|
shft=(5,6)
|
|
immed24=(0,23)
|
|
addr24=(0,23) signed
|
|
offset_12=(0,11)
|
|
immed=(0,7)
|
|
srsMode=(0,4)
|
|
immedL=(0,3)
|
|
immed4=(0,3)
|
|
dbOption=(0,3)
|
|
ibOption=(0,3)
|
|
Rm=(0,3)
|
|
RmHi=(8,11)
|
|
Rm2=(0,3)
|
|
x=(5,5)
|
|
r=(5,5)
|
|
y=(6,6)
|
|
|
|
# Advanced SIMD and VFP instruction fields
|
|
D22=(22,22)
|
|
N7=(7,7)
|
|
L7=(7,7)
|
|
Q6=(6,6)
|
|
M5=(5,5)
|
|
Qn0=(16,19)
|
|
Qd0=(12,15)
|
|
Qm0=(0,3)
|
|
Qn1=(16,19)
|
|
Qd1=(12,15)
|
|
Qm1=(0,3)
|
|
Dn0=(16,19)
|
|
Dd0=(12,15)
|
|
Dm0=(0,3)
|
|
Dn1=(16,19)
|
|
Dd1=(12,15)
|
|
Dm1=(0,3)
|
|
Dm_3=(0,2)
|
|
Dm_4=(0,3)
|
|
Sn0=(16,19)
|
|
Sd0=(12,15)
|
|
Sm0=(0,3)
|
|
Sm0next=(0,3)
|
|
Sn1=(16,19)
|
|
Sd1=(12,15)
|
|
Sm1=(0,3)
|
|
Sm1next=(0,3)
|
|
cmode=(8,11)
|
|
|
|
|
|
|
|
# Arbitrary bit fields
|
|
bit31=(31,31)
|
|
bit30=(30,30)
|
|
bit29=(29,29)
|
|
bit28=(28,28)
|
|
c2831=(28,31)
|
|
c2627=(26,27)
|
|
c2531=(25,31)
|
|
c2527=(25,27)
|
|
c2525=(25,25)
|
|
c2427=(24,27)
|
|
c2424=(24,24)
|
|
c2331=(23,31)
|
|
c2327=(23,27)
|
|
c2324=(23,24)
|
|
c2323=(23,23)
|
|
c2222=(22,22)
|
|
c2131=(21,31)
|
|
c2127=(21,27)
|
|
c2124=(21,24)
|
|
c2123=(21,23)
|
|
c2122=(21,22)
|
|
c2121=(21,21)
|
|
c2027=(20,27)
|
|
c2024=(20,24)
|
|
c2022=(20,22)
|
|
c2021=(20,21)
|
|
c2020=(20,20)
|
|
c1921=(19,21)
|
|
c1919=(19,19)
|
|
c1821=(18,21)
|
|
c1819=(18,19)
|
|
c1818=(18,18)
|
|
c1721=(17,21)
|
|
c1719=(17,19)
|
|
c1718=(17,18)
|
|
c1717=(17,17)
|
|
c1631=(16,31)
|
|
c1627=(16,27)
|
|
c1621=(16,21)
|
|
c1620=(16,20)
|
|
c1619=(16,19)
|
|
c1618=(16,18)
|
|
c1617=(16,17)
|
|
c1616=(16,16)
|
|
c1515=(15,15)
|
|
c1415=(14,15)
|
|
c1414=(14,14)
|
|
c1315=(13,15)
|
|
c1313=(13,13)
|
|
c1215=(12,15)
|
|
c1212=(12,12)
|
|
c1115=(11,15)
|
|
c1111=(11,11)
|
|
c1015=(10,15)
|
|
c1011=(10,11)
|
|
c1010=(10,10)
|
|
c0916=(9,16)
|
|
c0915=(9,15)
|
|
c0911=(9,11)
|
|
c0909=(9,9)
|
|
c0815=(8,15)
|
|
c0811=(8,11)
|
|
c0809=(8,9)
|
|
c0808=(8,8)
|
|
c0715=(7,15)
|
|
c0711=(7,11)
|
|
c0709=(7,9)
|
|
c0708=(7,8)
|
|
c0707=(7,7)
|
|
c0615=(6,15)
|
|
c0611=(6,11)
|
|
c0607=(6,7)
|
|
c0606=(6,6)
|
|
c0515=(5,15)
|
|
c0508=(5,8)
|
|
c0507=(5,7)
|
|
c0506=(5,6)
|
|
c0505=(5,5)
|
|
c0431=(4,31)
|
|
c0427=(4,27)
|
|
c0415=(4,15)
|
|
c0411=(4,11)
|
|
c0409=(4,9)
|
|
c0408=(4,8)
|
|
c0407=(4,7)
|
|
c0406=(4,6)
|
|
c0405=(4,5)
|
|
c0404=(4,4)
|
|
c0315=(3,15)
|
|
c0303=(3,3)
|
|
c0215=(2,15)
|
|
c0202=(2,2)
|
|
c0115=(1,15)
|
|
c0101=(1,1)
|
|
c0031=(0,31)
|
|
c0027=(0,27)
|
|
c0014=(0,14)
|
|
c0013=(0,13)
|
|
c0012=(0,12)
|
|
c0011=(0,11)
|
|
c0010=(0,10)
|
|
c0009=(0,9)
|
|
c0008=(0,8)
|
|
c0007=(0,7)
|
|
c0006=(0,6)
|
|
c0005=(0,5)
|
|
c0004=(0,4)
|
|
c0003=(0,3)
|
|
c0002=(0,2)
|
|
c0001=(0,1)
|
|
c0000=(0,0)
|
|
|
|
#
|
|
# 32-bit Thumb fields which correspond closely with ARM fields for
|
|
# certain coprocessor instructions
|
|
#
|
|
|
|
@if ENDIAN == "little"
|
|
|
|
# Advanced SIMD and VFP instruction fields for 32-bit Little Endian Thumb
|
|
thv_D22=(6,6)
|
|
thv_N7=(23,23)
|
|
thv_L7=(23,23)
|
|
thv_Q6=(22,22)
|
|
thv_M5=(21,21)
|
|
thv_Qn0=(0,3)
|
|
thv_Qd0=(28,31)
|
|
thv_Qm0=(16,19)
|
|
thv_Qn1=(0,3)
|
|
thv_Qd1=(28,31)
|
|
thv_Qm1=(16,19)
|
|
thv_Dn0=(0,3)
|
|
thv_Dd0=(28,31)
|
|
thv_Dd_1=(28,31)
|
|
thv_Dd_2=(28,31)
|
|
thv_Dd_3=(28,31)
|
|
thv_Dd_4=(28,31)
|
|
thv_Dd_5=(28,31)
|
|
thv_Dd_6=(28,31)
|
|
thv_Dd_7=(28,31)
|
|
thv_Dd_8=(28,31)
|
|
thv_Dd_9=(28,31)
|
|
thv_Dd_10=(28,31)
|
|
thv_Dd_11=(28,31)
|
|
thv_Dd_12=(28,31)
|
|
thv_Dd_13=(28,31)
|
|
thv_Dd_14=(28,31)
|
|
thv_Dd_15=(28,31)
|
|
thv_Dd_16=(28,31)
|
|
thv_Dm0=(16,19)
|
|
thv_Dn1=(0,3)
|
|
thv_Dd1=(28,31)
|
|
thv_Dm1=(16,19)
|
|
thv_Dm_3=(16,18)
|
|
thv_Dm_4=(16,19)
|
|
thv_Sn0=(0,3)
|
|
thv_Sd0=(28,31)
|
|
thv_Sm0=(16,19)
|
|
thv_Sm0next=(16,19)
|
|
thv_Sn1=(0,3)
|
|
thv_Sd1=(28,31)
|
|
thv_Sm1=(16,19)
|
|
thv_Sm1next=(16,19)
|
|
thv_cmode=(24,27)
|
|
|
|
thv_Rd=(28,31)
|
|
thv_Rt=(28,31)
|
|
thv_Rn=(0,3)
|
|
thv_Rm=(16,19)
|
|
thv_Rt2=(24,27)
|
|
thv_immed=(16,23)
|
|
|
|
# Arbitrary bit fields for 32-bit Little Endian Thumb
|
|
|
|
thv_bit31=(15,15)
|
|
thv_bit30=(14,14)
|
|
thv_bit29=(13,13)
|
|
thv_bit28=(12,12)
|
|
thv_bit23=(7,7)
|
|
thv_bit21=(5,5)
|
|
thv_bit20=(4,4)
|
|
thv_bit07=(23,23)
|
|
thv_bit06=(22,22)
|
|
thv_bit00=(16,16)
|
|
thv_c2931=(13,15)
|
|
thv_c2831=(12,15)
|
|
thv_c2828=(12,12)
|
|
thv_c2627=(10,11)
|
|
thv_c2531=(9,15)
|
|
thv_c2527=(9,11)
|
|
thv_c2525=(9,9)
|
|
thv_c2427=(8,11)
|
|
thv_c2424=(8,8)
|
|
thv_c2331=(7,15)
|
|
thv_c2327=(7,11)
|
|
thv_c2324=(7,8)
|
|
thv_c2323=(7,7)
|
|
thv_c2222=(6,6)
|
|
thv_c2131=(5,15)
|
|
thv_c2127=(5,11)
|
|
thv_c2124=(5,8)
|
|
thv_c2123=(5,7)
|
|
thv_c2122=(5,6)
|
|
thv_c2121=(5,5)
|
|
thv_c2031=(4,15)
|
|
thv_c2027=(4,11)
|
|
thv_c2024=(4,8)
|
|
thv_c2022=(4,6)
|
|
thv_c2021=(4,5)
|
|
thv_c2020=(4,4)
|
|
thv_c1921=(3,5)
|
|
thv_c1919=(3,3)
|
|
thv_c1821=(2,5)
|
|
thv_c1819=(2,3)
|
|
thv_c1818=(2,2)
|
|
thv_c1721=(1,5)
|
|
thv_c1719=(1,3)
|
|
thv_c1718=(1,2)
|
|
thv_c1717=(1,1)
|
|
thv_c1631=(0,15)
|
|
thv_c1627=(0,11)
|
|
thv_c1621=(0,5)
|
|
thv_c1620=(0,4)
|
|
thv_c1619=(0,3)
|
|
thv_c1618=(0,2)
|
|
thv_c1617=(0,1)
|
|
thv_c1616=(0,0)
|
|
thv_c1515=(31,31)
|
|
thv_c1415=(30,31)
|
|
thv_c1414=(30,30)
|
|
thv_c1313=(29,29)
|
|
thv_c1215=(28,31)
|
|
thv_c1212=(28,28)
|
|
thv_c1111=(27,27)
|
|
thv_c1011=(26,27)
|
|
thv_c1010=(26,26)
|
|
thv_c0911=(25,27)
|
|
thv_c0909=(25,25)
|
|
thv_c0811=(24,27)
|
|
thv_c0809=(24,25)
|
|
thv_c0808=(24,24)
|
|
thv_c0711=(23,27)
|
|
thv_c0709=(23,25)
|
|
thv_c0708=(23,24)
|
|
thv_c0707=(23,23)
|
|
thv_c0611=(22,27)
|
|
thv_c0607=(22,23)
|
|
thv_c0606=(22,22)
|
|
thv_c0508=(21,24)
|
|
thv_c0507=(21,23)
|
|
thv_c0506=(21,22)
|
|
thv_c0505=(21,21)
|
|
thv_c0431=(4,31)
|
|
thv_c0427=(4,27)
|
|
thv_c0411=(20,27)
|
|
thv_c0409=(20,25)
|
|
thv_c0407=(20,23)
|
|
thv_c0406=(20,22)
|
|
thv_c0405=(20,21)
|
|
thv_c0404=(20,20)
|
|
thv_c0303=(19,19)
|
|
thv_c0215=(18,31)
|
|
thv_c0202=(18,18)
|
|
thv_c0101=(17,17)
|
|
thv_c0104=(17,20)
|
|
thv_c0031=(0,31)
|
|
thv_c0027=(0,27)
|
|
thv_c0015=(16,31)
|
|
thv_c0011=(16,27)
|
|
thv_c0010=(16,26)
|
|
thv_c0008=(16,24)
|
|
thv_c0007=(16,23)
|
|
thv_c0006=(16,22)
|
|
thv_c0004=(16,20)
|
|
thv_c0003=(16,19)
|
|
thv_c0001=(16,17)
|
|
thv_c0000=(16,16)
|
|
thv_option=(16,19)
|
|
|
|
@else # ENDIAN == "big"
|
|
|
|
# Advanced SIMD and VFP instruction fields for 32-bit Big Endian Thumb
|
|
thv_D22=(22,22)
|
|
thv_N7=(7,7)
|
|
thv_L7=(7,7)
|
|
thv_Q6=(6,6)
|
|
thv_M5=(5,5)
|
|
thv_Qn0=(16,19)
|
|
thv_Qd0=(12,15)
|
|
thv_Qm0=(0,3)
|
|
thv_Qn1=(16,19)
|
|
thv_Qd1=(12,15)
|
|
thv_Qm1=(0,3)
|
|
thv_Dn0=(16,19)
|
|
thv_Dd0=(12,15)
|
|
thv_Dd_1=(12,15)
|
|
thv_Dd_2=(12,15)
|
|
thv_Dd_3=(12,15)
|
|
thv_Dd_4=(12,15)
|
|
thv_Dd_5=(12,15)
|
|
thv_Dd_6=(12,15)
|
|
thv_Dd_7=(12,15)
|
|
thv_Dd_8=(12,15)
|
|
thv_Dd_9=(12,15)
|
|
thv_Dd_10=(12,15)
|
|
thv_Dd_11=(12,15)
|
|
thv_Dd_12=(12,15)
|
|
thv_Dd_13=(12,15)
|
|
thv_Dd_14=(12,15)
|
|
thv_Dd_15=(12,15)
|
|
thv_Dd_16=(12,15)
|
|
thv_Dm0=(0,3)
|
|
thv_Dn1=(16,19)
|
|
thv_Dd1=(12,15)
|
|
thv_Dm1=(0,3)
|
|
thv_Dm_3=(0,2)
|
|
thv_Dm_4=(0,3)
|
|
thv_Sn0=(16,19)
|
|
thv_Sd0=(12,15)
|
|
thv_Sm0=(0,3)
|
|
thv_Sm0next=(0,3)
|
|
thv_Sn1=(16,19)
|
|
thv_Sd1=(12,15)
|
|
thv_Sm1=(0,3)
|
|
thv_Sm1next=(0,3)
|
|
thv_cmode=(8,11)
|
|
|
|
thv_Rd=(12,15)
|
|
thv_Rt=(12,15)
|
|
thv_Rn=(16,19)
|
|
thv_Rm=(0,3)
|
|
thv_Rt2=(8,11)
|
|
thv_immed=(0,7)
|
|
|
|
# Arbitrary bit fields for 32-bit Big Endian Thumb
|
|
thv_bit31=(31,31)
|
|
thv_bit30=(30,30)
|
|
thv_bit29=(29,29)
|
|
thv_bit28=(28,28)
|
|
thv_bit23=(23,23)
|
|
thv_bit21=(21,21)
|
|
thv_bit20=(20,20)
|
|
thv_bit07=(7,7)
|
|
thv_bit06=(6,6)
|
|
thv_bit00=(0,0)
|
|
thv_c2931=(29,31)
|
|
thv_c2831=(28,31)
|
|
thv_c2828=(28,28)
|
|
thv_c2627=(26,27)
|
|
thv_c2531=(25,31)
|
|
thv_c2527=(25,27)
|
|
thv_c2525=(25,25)
|
|
thv_c2427=(24,27)
|
|
thv_c2424=(24,24)
|
|
thv_c2331=(23,31)
|
|
thv_c2327=(23,27)
|
|
thv_c2324=(23,24)
|
|
thv_c2323=(23,23)
|
|
thv_c2222=(22,22)
|
|
thv_c2131=(21,31)
|
|
thv_c2127=(21,27)
|
|
thv_c2124=(21,24)
|
|
thv_c2123=(21,23)
|
|
thv_c2122=(21,22)
|
|
thv_c2121=(21,21)
|
|
thv_c2031=(20,31)
|
|
thv_c2027=(20,27)
|
|
thv_c2024=(20,24)
|
|
thv_c2022=(20,22)
|
|
thv_c2021=(20,21)
|
|
thv_c2020=(20,20)
|
|
thv_c1921=(19,21)
|
|
thv_c1919=(19,19)
|
|
thv_c1821=(18,21)
|
|
thv_c1819=(18,19)
|
|
thv_c1818=(18,18)
|
|
thv_c1721=(17,21)
|
|
thv_c1719=(17,19)
|
|
thv_c1718=(17,18)
|
|
thv_c1717=(17,17)
|
|
thv_c1631=(16,31)
|
|
thv_c1627=(16,27)
|
|
thv_c1621=(16,21)
|
|
thv_c1620=(16,20)
|
|
thv_c1619=(16,19)
|
|
thv_c1618=(16,18)
|
|
thv_c1617=(16,17)
|
|
thv_c1616=(16,16)
|
|
thv_c1515=(15,15)
|
|
thv_c1415=(14,15)
|
|
thv_c1414=(14,14)
|
|
thv_c1313=(13,13)
|
|
thv_c1215=(12,15)
|
|
thv_c1212=(12,12)
|
|
thv_c1111=(11,11)
|
|
thv_c1011=(10,11)
|
|
thv_c1010=(10,10)
|
|
thv_c0911=(9,11)
|
|
thv_c0909=(9,9)
|
|
thv_c0811=(8,11)
|
|
thv_c0809=(8,9)
|
|
thv_c0808=(8,8)
|
|
thv_c0711=(7,11)
|
|
thv_c0709=(7,9)
|
|
thv_c0708=(7,8)
|
|
thv_c0707=(7,7)
|
|
thv_c0611=(6,11)
|
|
thv_c0607=(6,7)
|
|
thv_c0606=(6,6)
|
|
thv_c0508=(5,8)
|
|
thv_c0507=(5,7)
|
|
thv_c0506=(5,6)
|
|
thv_c0505=(5,5)
|
|
thv_c0431=(4,31)
|
|
thv_c0427=(4,27)
|
|
thv_c0411=(4,11)
|
|
thv_c0409=(4,9)
|
|
thv_c0407=(4,7)
|
|
thv_c0406=(4,6)
|
|
thv_c0405=(4,5)
|
|
thv_c0404=(4,4)
|
|
thv_c0303=(3,3)
|
|
thv_c0215=(2,15)
|
|
thv_c0202=(2,2)
|
|
thv_c0101=(1,1)
|
|
thv_c0104=(1,4)
|
|
thv_c0031=(0,31)
|
|
thv_c0027=(0,27)
|
|
thv_c0015=(0,15)
|
|
thv_c0011=(0,11)
|
|
thv_c0010=(0,10)
|
|
thv_c0008=(0,8)
|
|
thv_c0007=(0,7)
|
|
thv_c0006=(0,6)
|
|
thv_c0004=(0,4)
|
|
thv_c0003=(0,3)
|
|
thv_c0001=(0,1)
|
|
thv_c0000=(0,0)
|
|
thv_option=(0,3)
|
|
|
|
@endif # ENDIAN = "big"
|
|
|
|
;
|
|
|
|
attach variables [ Rn Rd Rs Rm RdHi RdLo smRd smRn smRm smRa RmHi RnLo ] [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ];
|
|
attach variables [ Rd2 Rm2 ] [ r1 _ r3 _ r5 _ r7 _ r9 _ r11 _ sp _ _ _ ]; # see LDREXD
|
|
attach variables [ CRd CRn CRm ] [ cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7 cr8 cr9 cr10 cr11 cr12 cr13 cr14 cr15 ];
|
|
attach variables [ thv_Rd thv_Rn thv_Rt thv_Rt2 ] [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ];
|
|
|
|
attach names [ cpn ] [ p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 ];
|
|
attach names [ ibOption ] [ opt0 opt1 opt2 opt3 opt4 opt5 opt6 opt7 opt8 opt9 opt10 opt11 opt12 opt13 opt14 SY ];
|
|
attach names [ dbOption ] [ opt0 opt1 OSHST OSH opt4 opt5 NSHST NSH opt8 opt9 ISHST ISH opt12 opt13 ST SY ];
|
|
|
|
macro addflags(op1,op2) {
|
|
tmpCY = carry(op1,op2);
|
|
tmpOV = scarry(op1,op2);
|
|
}
|
|
|
|
# NOTE: unlike x86, carry flag is SET if there is NO borrow
|
|
macro subflags(op1,op2) {
|
|
tmpCY = op2 <= op1;
|
|
tmpOV = sborrow(op1,op2);
|
|
}
|
|
|
|
macro logicflags() {
|
|
tmpCY = shift_carry;
|
|
tmpOV = OV;
|
|
}
|
|
|
|
macro CVunaffected() {
|
|
tmpCY = CY;
|
|
tmpOV = OV;
|
|
}
|
|
|
|
macro resultflags(result) {
|
|
tmpNG = result s< 0;
|
|
tmpZR = result == 0;
|
|
}
|
|
|
|
rn: pc is pc & c1619=15 { tmp:4 = inst_start+8; export tmp; }
|
|
rn: Rn is Rn { export Rn; }
|
|
|
|
rm: pc is pc & Rm=15 { tmp:4 = inst_start+8; export tmp; }
|
|
rm: Rm is Rm { export Rm; }
|
|
|
|
rs: pc is pc & Rs=15 { tmp:4 = inst_start+8; export tmp; }
|
|
rs: Rs is Rs { export Rs; }
|
|
|
|
cc: "eq" is cond=0 { export ZR; }
|
|
cc: "ne" is cond=1 { tmp:1 = !ZR; export tmp; }
|
|
cc: "cs" is cond=2 { export CY; }
|
|
cc: "cc" is cond=3 { tmp:1 = !CY; export tmp; }
|
|
cc: "mi" is cond=4 { export NG; }
|
|
cc: "pl" is cond=5 { tmp:1 = !NG; export tmp; }
|
|
cc: "vs" is cond=6 { export OV; }
|
|
cc: "vc" is cond=7 { tmp:1 = !OV; export tmp; }
|
|
cc: "hi" is cond=8 { tmp:1 = CY && (!ZR); export tmp; }
|
|
cc: "ls" is cond=9 { tmp:1 = (!CY) || ZR; export tmp; }
|
|
cc: "ge" is cond=10 { tmp:1 = (NG==OV); export tmp; }
|
|
cc: "lt" is cond=11 { tmp:1 = (NG!=OV); export tmp; }
|
|
cc: "gt" is cond=12 { tmp:1 = (!ZR) && (NG==OV); export tmp; }
|
|
cc: "le" is cond=13 { tmp:1 = ZR || (NG!=OV); export tmp; }
|
|
|
|
COND: cc is $(AMODE) & cc { if (!cc) goto inst_next; } # Execute conditionally
|
|
COND: is $(AMODE) & cond=14 { } # Always execute
|
|
COND: is $(AMODE) & cond=15 { } # Always execute - some A32 instructions that can only be executed unconditionally
|
|
@if defined(INCLUDE_NEON) # Unconditional Neon Thumb instructions share many Conditional Neon ARM constructors
|
|
COND: ItCond is TMode=1 & thv_c2831=14 & cond & ItCond { } # ItCond execute
|
|
COND: ItCond is TMode=1 & thv_c2831=15 & cond & ItCond { } # ItCond execute
|
|
@endif
|
|
|
|
SBIT_CZNO: is S20=0 { } # Do nothing to the flag bits
|
|
SBIT_CZNO: "s" is S20=1 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV; }
|
|
SBIT_ZN: is S20=0 { } # Do nothing to the flag bits
|
|
SBIT_ZN: "s" is S20=1 { ZR = tmpZR; NG = tmpNG; }
|
|
|
|
Addr24: reloc is addr24 [ reloc = (inst_next+4) + (4*addr24); ] { export *[ram]:4 reloc; }
|
|
|
|
# see blx(1) instruction
|
|
@if defined(T_VARIANT) && defined(VERSION_5)
|
|
|
|
HAddr24: reloc is addr24 & H24
|
|
[ reloc = ((inst_next+4) + (4*addr24) + (2*H24)) & 0xFFFFFFFF; TMode=1; globalset(reloc,TMode); ]
|
|
{ export *[ram]:4 reloc; }
|
|
@endif # T_VARIANT && VERSION_5
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
XBIT: "b" is x=0 & smRn { local tmpRn = smRn; tmp:2 = tmpRn:2; export tmp; }
|
|
XBIT: "t" is x=1 & smRn { local tmpRn = smRn; tmp:2 = tmpRn(2); export tmp; }
|
|
|
|
YBIT: "b" is y=0 & smRm { local tmpRm = smRm; tmp:2 = tmpRm:2; export tmp; }
|
|
YBIT: "t" is y=1 & smRm { local tmpRm = smRm; tmp:2 = tmpRm(2); export tmp; }
|
|
|
|
@endif # VERSION_5E
|
|
|
|
|
|
|
|
#####################
|
|
###### shift1 ######
|
|
#####################
|
|
|
|
shift1: "#"^value is I25=1 & immed & rotate
|
|
[ value=((immed<<(32-rotate*2))|(immed>>(rotate*2))) $and 0xffffffff; ]
|
|
{
|
|
local tmp:4 = (value >> 31); shift_carry = ((rotate == 0:1) && CY) || ((rotate != 0:1) && tmp(0)); export *[const]:4 value;
|
|
}
|
|
|
|
####################
|
|
define pcodeop coproc_moveto_Main_ID;
|
|
define pcodeop coproc_moveto_Cache_Type;
|
|
define pcodeop coproc_moveto_TCM_Status;
|
|
define pcodeop coproc_moveto_TLB_Type;
|
|
define pcodeop coproc_moveto_Control;
|
|
define pcodeop coproc_moveto_Auxilary_Control;
|
|
define pcodeop coproc_moveto_Coprocessor_Access_Control;
|
|
define pcodeop coproc_moveto_Translation_table_base_0;
|
|
define pcodeop coproc_moveto_Translation_table_base_1;
|
|
define pcodeop coproc_moveto_Translation_table_control;
|
|
define pcodeop coproc_moveto_Domain_Access_Control;
|
|
define pcodeop coproc_moveto_Data_Fault_Status;
|
|
define pcodeop coproc_moveto_Instruction_Fault_Status;
|
|
define pcodeop coproc_moveto_Instruction_Fault_Address;
|
|
define pcodeop coproc_moveto_Fault_Address;
|
|
define pcodeop coproc_moveto_Instruction_Fault;
|
|
define pcodeop coproc_moveto_Wait_for_interrupt;
|
|
define pcodeop coproc_moveto_Invalidate_Entire_Instruction;
|
|
define pcodeop coproc_moveto_Invalidate_Instruction_Cache_by_MVA;
|
|
define pcodeop coproc_moveto_Flush_Prefetch_Buffer;
|
|
define pcodeop coproc_moveto_Invalidate_Entire_Data_cache;
|
|
define pcodeop coproc_moveto_Invalidate_Entire_Data_by_MVA;
|
|
define pcodeop coproc_moveto_Invalidate_Entire_Data_by_Index;
|
|
define pcodeop coproc_moveto_Clean_Entire_Data_Cache;
|
|
define pcodeop coproc_moveto_Clean_Data_Cache_by_MVA;
|
|
define pcodeop coproc_moveto_Clean_Data_Cache_by_Index;
|
|
define pcodeop coproc_moveto_Data_Synchronization;
|
|
define pcodeop coproc_moveto_Data_Memory_Barrier;
|
|
define pcodeop coproc_moveto_Invalidate_Entire_Data_Cache;
|
|
define pcodeop coproc_moveto_Invalidate_Data_Cache_by_MVA;
|
|
define pcodeop coproc_moveto_Invalidate_unified_TLB_unlocked;
|
|
define pcodeop coproc_moveto_Invalidate_unified_TLB_by_MVA;
|
|
define pcodeop coproc_moveto_Invalidate_unified_TLB_by_ASID_match;
|
|
define pcodeop coproc_moveto_FCSE_PID;
|
|
define pcodeop coproc_moveto_Context_ID;
|
|
define pcodeop coproc_moveto_User_RW_Thread_and_Process_ID;
|
|
define pcodeop coproc_moveto_User_R_Thread_and_Process_ID;
|
|
define pcodeop coproc_moveto_Privileged_only_Thread_and_Process_ID;
|
|
define pcodeop coproc_moveto_Peripherial_Port_Memory_Remap;
|
|
define pcodeop coproc_moveto_Feature_Identification;
|
|
define pcodeop coproc_moveto_ISA_Feature_Identification;
|
|
define pcodeop coproc_moveto_Peripheral_Port_Memory_Remap;
|
|
define pcodeop coproc_moveto_Control_registers;
|
|
define pcodeop coproc_moveto_Security_world_control;
|
|
define pcodeop coproc_moveto_Translation_table;
|
|
define pcodeop coproc_moveto_Instruction_cache;
|
|
define pcodeop coproc_moveto_Data_cache_operations;
|
|
define pcodeop coproc_moveto_Identification_registers;
|
|
define pcodeop coproc_moveto_Peripheral_System;
|
|
|
|
define pcodeop coproc_movefrom_Main_ID;
|
|
define pcodeop coproc_movefrom_Cache_Type;
|
|
define pcodeop coproc_movefrom_TCM_Status;
|
|
define pcodeop coproc_movefrom_TLB_Type;
|
|
define pcodeop coproc_movefrom_Control;
|
|
define pcodeop coproc_movefrom_Auxilary_Control;
|
|
define pcodeop coproc_movefrom_Coprocessor_Access_Control;
|
|
define pcodeop coproc_movefrom_Translation_table_base_0;
|
|
define pcodeop coproc_movefrom_Translation_table_base_1;
|
|
define pcodeop coproc_movefrom_Translation_table_control;
|
|
define pcodeop coproc_movefrom_Domain_Access_Control;
|
|
define pcodeop coproc_movefrom_Data_Fault_Status;
|
|
define pcodeop coproc_movefrom_Instruction_Fault;
|
|
define pcodeop coproc_movefrom_Fault_Address;
|
|
define pcodeop coproc_movefrom_Instruction_Fault_Status;
|
|
define pcodeop coproc_movefrom_Instruction_Fault_Address;
|
|
define pcodeop coproc_movefrom_Wait_for_interrupt;
|
|
define pcodeop coproc_movefrom_Invalidate_Entire_Instruction;
|
|
define pcodeop coproc_movefrom_Invalidate_Instruction_Cache_by_MVA;
|
|
define pcodeop coproc_movefrom_Flush_Prefetch_Buffer;
|
|
define pcodeop coproc_movefrom_Invalidate_Entire_Data_cache;
|
|
define pcodeop coproc_movefrom_Invalidate_Entire_Data_by_MVA;
|
|
define pcodeop coproc_movefrom_Invalidate_Entire_Data_by_Index;
|
|
define pcodeop coproc_movefrom_Clean_Entire_Data_Cache;
|
|
define pcodeop coproc_movefrom_Clean_Data_Cache_by_MVA;
|
|
define pcodeop coproc_movefrom_Clean_Data_Cache_by_Index;
|
|
define pcodeop coproc_movefrom_Data_Synchronization;
|
|
define pcodeop coproc_movefrom_Data_Memory_Barrier;
|
|
define pcodeop coproc_movefrom_Invalidate_Entire_Data_Cache;
|
|
define pcodeop coproc_movefrom_Invalidate_Data_Cache_by_MVA;
|
|
define pcodeop coproc_movefrom_Invalidate_unified_TLB_unlocked;
|
|
define pcodeop coproc_movefrom_Invalidate_unified_TLB_by_MVA;
|
|
define pcodeop coproc_movefrom_Invalidate_unified_TLB_by_ASID_match;
|
|
define pcodeop coproc_movefrom_FCSE_PID;
|
|
define pcodeop coproc_movefrom_Context_ID;
|
|
define pcodeop coproc_movefrom_User_RW_Thread_and_Process_ID;
|
|
define pcodeop coproc_movefrom_User_R_Thread_and_Process_ID;
|
|
define pcodeop coproc_movefrom_Privileged_only_Thread_and_Process_ID;
|
|
define pcodeop coproc_movefrom_Peripherial_Port_Memory_Remap;
|
|
define pcodeop coproc_movefrom_Feature_Identification;
|
|
define pcodeop coproc_movefrom_ISA_Feature_Identification;
|
|
define pcodeop coproc_movefrom_Peripheral_Port_Memory_Remap;
|
|
define pcodeop coproc_movefrom_Control_registers;
|
|
define pcodeop coproc_movefrom_Security_world_control;
|
|
define pcodeop coproc_movefrom_Translation_table;
|
|
define pcodeop coproc_movefrom_Instruction_cache;
|
|
define pcodeop coproc_movefrom_Data_cache_operations;
|
|
define pcodeop coproc_movefrom_Identification_registers;
|
|
define pcodeop coproc_movefrom_Peripheral_System;
|
|
|
|
mcrOperands: cpn,opc1,Rd,CRn,CRm,opc2 is CRm & opc2 & cpn & CRn & opc1 & Rd { }
|
|
|
|
#####################
|
|
###### shift2 ######
|
|
#####################
|
|
|
|
shift2: rm is I25=0 & sftimm=0 & c0406=0 & rm
|
|
{
|
|
shift_carry = CY; export rm;
|
|
}
|
|
|
|
shift2: rm, "lsl #"^sftimm is I25=0 & sftimm & c0406=0 & rm
|
|
{
|
|
local tmp1=(rm>>(32-sftimm))&1; shift_carry=tmp1(0); local tmp2=rm<<sftimm; export tmp2;
|
|
}
|
|
|
|
shift2: rm, "lsr #32" is I25=0 & sftimm=0 & c0406=2 & rm
|
|
{
|
|
local tmp1=(rm>>31); shift_carry=tmp1(0); tmp2:4=0; export tmp2;
|
|
}
|
|
|
|
shift2: rm, "lsr #"^sftimm is I25=0 & sftimm & c0406=2 & rm
|
|
{
|
|
local tmp1=(rm>>(sftimm-1))&1; shift_carry=tmp1(0); local tmp2=rm>>sftimm; export tmp2;
|
|
}
|
|
|
|
shift2: rm, "asr #32" is I25=0 & sftimm=0 & c0406=4 & rm
|
|
{
|
|
local tmp1=(rm>>31); shift_carry=tmp1(0); local tmp2 = rm s>> 32; export tmp2;
|
|
}
|
|
|
|
shift2: rm, "asr #"^sftimm is I25=0 & sftimm & c0406=4 & rm
|
|
{
|
|
local tmp1=(rm>>(sftimm-1))&1; shift_carry=tmp1(0); local tmp2=rm s>> sftimm; export tmp2;
|
|
}
|
|
|
|
shift2: rm, "rrx" is I25=0 & c0411=6 & rm
|
|
{
|
|
local tmp1=rm&1; shift_carry=tmp1(0); local tmp2 = (zext(CY)<<31)|(rm>>1); export tmp2;
|
|
}
|
|
|
|
shift2: rm, "ror #"^sftimm is I25=0 & sftimm & c0406=6 & rm
|
|
{
|
|
local tmp1=(rm>>sftimm)|(rm<<(32-sftimm)); local tmp2=(tmp1>>31)&1; shift_carry=tmp2(0); export tmp1;
|
|
}
|
|
|
|
#####################
|
|
###### shift3 ######
|
|
#####################
|
|
|
|
shift3: rm, "lsl "^rs is I25=0 & rs & c0407=1 & rm
|
|
{
|
|
local sa=rs&0xff; local tmp1=(rm>>(32-sa))&1; shift_carry=((sa==0:4)&&CY) || ((sa!=0:4)&&tmp1(0)); local tmp2=rm<<sa; export tmp2;
|
|
}
|
|
|
|
shift3: rm, "lsr "^rs is I25=0 & rs & c0407=3 & rm
|
|
{
|
|
local sa=rs&0xff; local tmp1=(rm>>(sa-1))&1; shift_carry=((sa==0:4)&&CY) || ((sa!=0:4)&&tmp1(0)); local tmp2=rm>>sa; export tmp2;
|
|
}
|
|
|
|
shift3: rm, "asr "^rs is I25=0 & rs & c0407=5 & rm
|
|
{
|
|
local sa=rs&0xff; local tmp1=(rm s>>(sa-1))&1; shift_carry=((sa==0:4)&&CY) || ((sa!=0:4)&&tmp1(0)); local tmp2=rm s>> sa; export tmp2;
|
|
}
|
|
|
|
shift3: rm, "ror "^rs is I25=0 & rs & c0407=7 & rm
|
|
{
|
|
local sa=rs&0x1f; local tmp1=(rm>>sa)|(rm<<(32-sa)); local tmp2=tmp1>>31; shift_carry=(((rs&0xff)==0:4)&&CY) || (((rs&0xff)!=0:4)&&tmp2(0)); export tmp1;
|
|
}
|
|
|
|
|
|
#####################
|
|
###### shift4 ######
|
|
#####################
|
|
@if defined(VERSION_6)
|
|
|
|
shift4: rm is sftimm=0 & sh=0 & rm
|
|
{
|
|
shift_carry = CY; export rm;
|
|
}
|
|
|
|
shift4: rm, "lsl #"^sftimm is sftimm & sh=0 & rm
|
|
{
|
|
local tmp1=(rm>>(32-sftimm))&1; shift_carry=tmp1(0); local tmp2=rm<<sftimm; export tmp2;
|
|
}
|
|
|
|
shift4: rm, "asr #32" is sftimm=0 & sh=1 & rm
|
|
{
|
|
local tmp1=(rm>>31); shift_carry=tmp1(0); local tmp2 = rm s>> 32; export tmp2;
|
|
}
|
|
|
|
shift4: rm, "asr #"^sftimm is sftimm & sh=1 & rm
|
|
{
|
|
local tmp1=(rm>>(sftimm-1))&1; shift_carry=tmp1(0); local tmp2=rm s>> sftimm; export tmp2;
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
#####################
|
|
###### ror1 ######
|
|
#####################
|
|
@if defined(VERSION_6)
|
|
|
|
ror1: rm is c1011=0 & rm
|
|
{
|
|
local tmp = rm;
|
|
export tmp;
|
|
}
|
|
|
|
ror1: rm, "ror #8" is c1011=1 & rm
|
|
{
|
|
local tmp = (rm <<24)| (rm >> 8);
|
|
export tmp;
|
|
}
|
|
|
|
ror1: rm, "ror #16" is c1011=2 & rm
|
|
{
|
|
local tmp = (rm << 16) | (rm >> 16);
|
|
export tmp;
|
|
}
|
|
|
|
ror1: rm, "ror #24" is c1011=3 & rm
|
|
{
|
|
local tmp = (rm << 8) | (rm >> 24);
|
|
export tmp;
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
#####################
|
|
# addrmode2 is the resulting address for Addressing Mode 2
|
|
# it takes care of bits 27-0, except for the B and L flags and the Rd register
|
|
# the Rn register is taken care of including any possible write-back
|
|
# it returns a varnode containing the address
|
|
#####################
|
|
|
|
# addr2shift is the register rm shifting portion of Addressing Mode 2
|
|
addr2shift: rm is c0411=0 & rm { export rm; }
|
|
addr2shift: rm,"lsl #"^sftimm is sftimm & shft=0 & c0404=0 & rm { local tmp = rm << sftimm; export tmp; }
|
|
addr2shift: rm,"lsr #"^sftimm is sftimm & shft=1 & c0404=0 & rm { local tmp = rm >> sftimm; export tmp; }
|
|
addr2shift: rm,"lsr #32" is sftimm=0 & shft=1 & c0404=0 & rm { tmp:4 = 0; export tmp; }
|
|
addr2shift: rm,"asr #"^sftimm is sftimm & shft=2 & c0404=0 & rm { local tmp = rm s>> sftimm; export tmp; }
|
|
addr2shift: rm,"asr #32" is sftimm=0 & shft=2 & c0404=0 & rm { local tmp = rm s>> 32; export tmp; }
|
|
addr2shift: rm,"ror #"^sftimm is sftimm & shft=3 & c0404=0 & rm { local tmp = (rm>>sftimm) | (rm<<(32-sftimm)); export tmp; }
|
|
addr2shift: rm,"rrx" is sftimm=0 & shft=3 & c0404=0 & rm { tmp:4 = zext(CY); tmp = (tmp<<31) | (rm>>1); export tmp; }
|
|
|
|
# no writeback
|
|
|
|
addrmode2: [reloff] is I25=0 & P24=1 & U23=1 & W21=0 & c1619=15 & offset_12
|
|
[ reloff = inst_start + 8 + offset_12; ]
|
|
{
|
|
export *[const]:4 reloff;
|
|
}
|
|
|
|
addrmode2: [reloff] is I25=0 & P24=1 & U23=0 & W21=0 & c1619=15 & offset_12
|
|
[ reloff = inst_start + 8 - offset_12; ]
|
|
{
|
|
export *[const]:4 reloff;
|
|
}
|
|
|
|
addrmode2: [rn,"#"^offset_12] is I25=0 & P24=1 & U23=1 & W21=0 & rn & offset_12 { local tmp = rn + offset_12; export tmp; }
|
|
addrmode2: [rn,"#"^noff] is I25=0 & P24=1 & U23=0 & W21=0 & rn & offset_12 [ noff = -offset_12; ] { local tmp = rn + noff; export tmp; }
|
|
addrmode2: [rn,addr2shift] is I25=1 & P24=1 & U23=1 & W21=0 & rn & addr2shift { local tmp = rn + addr2shift; export tmp; }
|
|
addrmode2: [rn,-addr2shift] is I25=1 & P24=1 & U23=0 & W21=0 & rn & addr2shift { local tmp = rn - addr2shift; export tmp; }
|
|
# pre-indexed writeback
|
|
addrmode2: [rn,"#"^offset_12]! is I25=0 & P24=1 & U23=1 & W21=1 & rn & offset_12 { rn = rn + offset_12; export rn; }
|
|
addrmode2: [rn,"#"^noff]! is I25=0 & P24=1 & U23=0 & W21=1 & rn & offset_12 [ noff = -offset_12; ] { rn = rn + noff; export rn; }
|
|
addrmode2: [rn,addr2shift]! is I25=1 & P24=1 & U23=1 & W21=1 & rn & addr2shift { rn = rn + addr2shift; export rn; }
|
|
addrmode2: [rn,-addr2shift]! is I25=1 & P24=1 & U23=0 & W21=1 & rn & addr2shift { rn = rn - addr2shift; export rn; }
|
|
# post-indexed writeback
|
|
addrmode2: [rn],"#"^offset_12 is I25=0 & P24=0 & U23=1 & W21=0 & rn & offset_12 { local tmp = rn; rn = rn + offset_12; export tmp; }
|
|
addrmode2: [rn],"#"^noff is I25=0 & P24=0 & U23=0 & W21=0 & rn & offset_12 [ noff = -offset_12; ] { local tmp = rn; rn = rn + noff; export tmp; }
|
|
addrmode2: [rn],addr2shift is I25=1 & P24=0 & U23=1 & W21=0 & rn & addr2shift { local tmp = rn; rn = rn + addr2shift; export tmp; }
|
|
addrmode2: [rn],-addr2shift is I25=1 & P24=0 & U23=0 & W21=0 & rn & addr2shift { local tmp = rn; rn = rn - addr2shift; export tmp; }
|
|
# special-form post-indexed writeback for ldrbt, ldrt, strbt, etc.
|
|
addrmode2: [rn],"#"^offset_12 is I25=0 & P24=0 & U23=1 & W21=1 & rn & offset_12 { local tmp = rn; rn = rn + offset_12; export tmp; }
|
|
addrmode2: [rn],"#"^noff is I25=0 & P24=0 & U23=0 & W21=1 & rn & offset_12 [ noff = -offset_12; ] { local tmp = rn; rn = rn + noff; export tmp; }
|
|
addrmode2: [rn],addr2shift is I25=1 & P24=0 & U23=1 & W21=1 & rn & addr2shift { local tmp = rn; rn = rn + addr2shift; export tmp; }
|
|
addrmode2: [rn],-addr2shift is I25=1 & P24=0 & U23=0 & W21=1 & rn & addr2shift { local tmp = rn; rn = rn - addr2shift; export tmp; }
|
|
|
|
###########################
|
|
# addrmode3 is the resulting address for Addressing Mode 3
|
|
# it takes care of bits 27-0, except for the L, S, and H flags and the Rd register
|
|
# the Rn register is taken care of including any possible write-back
|
|
# it returns a varnode containing the address
|
|
###########################
|
|
|
|
addrmode3: [reloff] is P24=1 & U23=1 & c2122=2 & c1619=15 & immedH & c0707=1 & c0404=1 & immedL
|
|
[ reloff=inst_start+8+((immedH<<4) | immedL);]
|
|
{
|
|
export *:4 reloff;
|
|
}
|
|
|
|
addrmode3: [reloff] is P24=1 & U23=0 & c2122=2 & c1619=15 & immedH & c0707=1 & c0404=1 & immedL
|
|
[ reloff=inst_start+8-((immedH<<4) | immedL);]
|
|
{
|
|
export *:4 reloff;
|
|
}
|
|
|
|
addrmode3: [rn,"#"^off8] is P24=1 & U23=1 & c2122=2 & rn & immedH & c0707=1 & c0404=1 & immedL
|
|
[ off8=(immedH<<4)|immedL;]
|
|
{
|
|
local tmp = rn + off8; export tmp;
|
|
}
|
|
|
|
addrmode3: [rn,"#"^noff8] is P24=1 & U23=0 & c2122=2 & rn & immedH & c0707=1 & c0404=1 & immedL
|
|
[ noff8=-((immedH<<4)|immedL);]
|
|
{
|
|
local tmp = rn + noff8; export tmp;
|
|
}
|
|
|
|
addrmode3: [rn,rm] is P24=1 & U23=1 & c2122=0 & rn & c0811=0 & c0707=1 & c0404=1 & rm
|
|
{
|
|
local tmp = rn + rm; export tmp;
|
|
}
|
|
|
|
addrmode3: [rn,-rm] is P24=1 & U23=0 & c2122=0 & rn & c0811=0 & c0707=1 & c0404=1 & rm
|
|
{
|
|
local tmp = rn - rm; export tmp;
|
|
}
|
|
|
|
addrmode3: [rn,"#"^off8]! is P24=1 & U23=1 & c2122=3 & rn & immedH & c0707=1 & c0404=1 & immedL
|
|
[ off8=(immedH<<4)|immedL;]
|
|
{
|
|
rn=rn + off8; export rn;
|
|
}
|
|
|
|
addrmode3: [rn,"#"^noff8]! is P24=1 & U23=0 & c2122=3 & rn & immedH & c0707=1 & c0404=1 & immedL
|
|
[ noff8=-((immedH<<4)|immedL);]
|
|
{
|
|
rn=rn + noff8; export rn;
|
|
}
|
|
|
|
addrmode3: [rn,rm]! is P24=1 & U23=1 & c2122=1 & rn & c0811=0 & c0707=1 & c0404=1 & rm
|
|
{
|
|
rn = rn+rm; export rn;
|
|
}
|
|
|
|
addrmode3: [rn,-rm]! is P24=1 & U23=0 & c2122=1 & rn & c0811=0 & c0707=1 & c0404=1 & rm
|
|
{
|
|
rn = rn - rm; export rn;
|
|
}
|
|
|
|
addrmode3: [rn],"#"^off8 is P24=0 & U23=1 & c2122=2 & rn & immedH & c0707=1 & c0404=1 & immedL
|
|
[ off8=(immedH<<4)|immedL;]
|
|
{
|
|
local tmp=rn; rn=rn + off8; export tmp;
|
|
}
|
|
|
|
addrmode3: [rn],"#"^noff8 is P24=0 & U23=0 & c2122=2 & rn & immedH & c0707=1 & c0404=1 & immedL
|
|
[ noff8=-((immedH<<4)|immedL);]
|
|
{
|
|
local tmp=rn; rn=rn + noff8; export tmp;
|
|
}
|
|
|
|
addrmode3: [rn],rm is P24=0 & U23=1 & c2122=0 & rn & c0811=0 & c0707=1 & c0404=1 & rm
|
|
{
|
|
local tmp=rn; rn=rn+rm; export tmp;
|
|
}
|
|
|
|
addrmode3: [rn],-rm is P24=0 & U23=0 & c2122=0 & rn & c0811=0 & c0707=1 & c0404=1 & rm
|
|
{
|
|
local tmp=rn; rn=rn-rm; export tmp;
|
|
}
|
|
|
|
############################
|
|
# Addressing Mode 4. These 4 types take care of the register_list argument in Addressing Mode 4.
|
|
############################
|
|
|
|
|
|
# ldlist_inc is the list of registers to be loaded using IA or IB in Addressing Mode 4
|
|
linc15: r0 is c0000=1 & r0 { r0 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc15: is c0000=0 { }
|
|
linc14: linc15 r1 is c0101=1 & linc15 & r1 { r1 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc14: r1 is c0101=1 & c0000=0 & r1 { r1 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc14: linc15 is c0101=0 & linc15 { }
|
|
linc13: linc14 r2 is c0202=1 & linc14 & r2 { r2 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc13: r2 is c0202=1 & c0001=0 & r2 { r2 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc13: linc14 is c0202=0 & linc14 { }
|
|
linc12: linc13 r3 is c0303=1 & linc13 & r3 { r3 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc12: r3 is c0303=1 & c0002=0 & r3 { r3 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc12: linc13 is c0303=0 & linc13 { }
|
|
linc11: linc12 r4 is c0404=1 & linc12 & r4 { r4 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc11: r4 is c0404=1 & c0003=0 & r4 { r4 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc11: linc12 is c0404=0 & linc12 { }
|
|
linc10: linc11 r5 is c0505=1 & linc11 & r5 { r5 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc10: r5 is c0505=1 & c0004=0 & r5 { r5 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc10: linc11 is c0505=0 & linc11 { }
|
|
linc9: linc10 r6 is c0606=1 & linc10 & r6 { r6 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc9: r6 is c0606=1 & c0005=0 & r6 { r6 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc9: linc10 is c0606=0 & linc10 { }
|
|
linc8: linc9 r7 is c0707=1 & linc9 & r7 { r7 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc8: r7 is c0707=1 & c0006=0 & r7 { r7 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc8: linc9 is c0707=0 & linc9 { }
|
|
linc7: linc8 r8 is c0808=1 & linc8 & r8 { r8 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc7: r8 is c0808=1 & c0007=0 & r8 { r8 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc7: linc8 is c0808=0 & linc8 { }
|
|
linc6: linc7 r9 is c0909=1 & linc7 & r9 { r9 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc6: r9 is c0909=1 & c0008=0 & r9 { r9 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc6: linc7 is c0909=0 & linc7 { }
|
|
linc5: linc6 r10 is c1010=1 & linc6 & r10 { r10 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc5: r10 is c1010=1 & c0009=0 & r10 { r10 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc5: linc6 is c1010=0 & linc6 { }
|
|
linc4: linc5 r11 is c1111=1 & linc5 & r11 { r11 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc4: r11 is c1111=1 & c0010=0 & r11 { r11 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc4: linc5 is c1111=0 & linc5 { }
|
|
linc3: linc4 r12 is c1212=1 & linc4 & r12 { r12 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc3: r12 is c1212=1 & c0011=0 & r12 { r12 = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc3: linc4 is c1212=0 & linc4 { }
|
|
linc2: linc3 sp is c1313=1 & linc3 & sp { sp = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc2: sp is c1313=1 & c0012=0 & sp { sp = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc2: linc3 is c1313=0 & linc3 { }
|
|
linc1: linc2 lr is c1414=1 & linc2 & lr { lr = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc1: lr is c1414=1 & c0013=0 & lr { lr = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc1: linc2 is c1414=0 & linc2 { }
|
|
linc0: linc1 pc is c1515=1 & linc1 & pc { pc = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc0: pc is c1515=1 & c0014=0 & pc { pc = * mult_addr; mult_addr = mult_addr + 4; }
|
|
linc0: linc1 is c1515=0 & linc1 { }
|
|
ldlist_inc: {linc0} is linc0 { }
|
|
|
|
# stlist_inc is the list of registers to be stored using IA or IB in Addressing Mode 4
|
|
sinc15: r0 is c0000=1 & r0 { * mult_addr = r0; mult_addr = mult_addr + 4; }
|
|
sinc15: is c0000=0 { }
|
|
sinc14: sinc15 r1 is c0101=1 & sinc15 & r1 { * mult_addr = r1; mult_addr = mult_addr + 4; }
|
|
sinc14: r1 is c0101=1 & c0000=0 & r1 { * mult_addr = r1; mult_addr = mult_addr + 4; }
|
|
sinc14: sinc15 is c0101=0 & sinc15 { }
|
|
sinc13: sinc14 r2 is c0202=1 & sinc14 & r2 { * mult_addr = r2; mult_addr = mult_addr + 4; }
|
|
sinc13: r2 is c0202=1 & c0001=0 & r2 { * mult_addr = r2; mult_addr = mult_addr + 4; }
|
|
sinc13: sinc14 is c0202=0 & sinc14 { }
|
|
sinc12: sinc13 r3 is c0303=1 & sinc13 & r3 { * mult_addr = r3; mult_addr = mult_addr + 4; }
|
|
sinc12: r3 is c0303=1 & c0002=0 & r3 { * mult_addr = r3; mult_addr = mult_addr + 4; }
|
|
sinc12: sinc13 is c0303=0 & sinc13 { }
|
|
sinc11: sinc12 r4 is c0404=1 & sinc12 & r4 { * mult_addr = r4; mult_addr = mult_addr + 4; }
|
|
sinc11: r4 is c0404=1 & c0003=0 & r4 { * mult_addr = r4; mult_addr = mult_addr + 4; }
|
|
sinc11: sinc12 is c0404=0 & sinc12 { }
|
|
sinc10: sinc11 r5 is c0505=1 & sinc11 & r5 { * mult_addr = r5; mult_addr = mult_addr + 4; }
|
|
sinc10: r5 is c0505=1 & c0004=0 & r5 { * mult_addr = r5; mult_addr = mult_addr + 4; }
|
|
sinc10: sinc11 is c0505=0 & sinc11 { }
|
|
sinc9: sinc10 r6 is c0606=1 & sinc10 & r6 { * mult_addr = r6; mult_addr = mult_addr + 4; }
|
|
sinc9: r6 is c0606=1 & c0005=0 & r6 { * mult_addr = r6; mult_addr = mult_addr + 4; }
|
|
sinc9: sinc10 is c0606=0 & sinc10 { }
|
|
sinc8: sinc9 r7 is c0707=1 & sinc9 & r7 { * mult_addr = r7; mult_addr = mult_addr + 4; }
|
|
sinc8: r7 is c0707=1 & c0006=0 & r7 { * mult_addr = r7; mult_addr = mult_addr + 4; }
|
|
sinc8: sinc9 is c0707=0 & sinc9 { }
|
|
sinc7: sinc8 r8 is c0808=1 & sinc8 & r8 { * mult_addr = r8; mult_addr = mult_addr + 4; }
|
|
sinc7: r8 is c0808=1 & c0007=0 & r8 { * mult_addr = r8; mult_addr = mult_addr + 4; }
|
|
sinc7: sinc8 is c0808=0 & sinc8 { }
|
|
sinc6: sinc7 r9 is c0909=1 & sinc7 & r9 { * mult_addr = r9; mult_addr = mult_addr + 4; }
|
|
sinc6: r9 is c0909=1 & c0008=0 & r9 { * mult_addr = r9; mult_addr = mult_addr + 4; }
|
|
sinc6: sinc7 is c0909=0 & sinc7 { }
|
|
sinc5: sinc6 r10 is c1010=1 & sinc6 & r10 { * mult_addr = r10; mult_addr = mult_addr + 4; }
|
|
sinc5: r10 is c1010=1 & c0009=0 & r10 { * mult_addr = r10; mult_addr = mult_addr + 4; }
|
|
sinc5: sinc6 is c1010=0 & sinc6 { }
|
|
sinc4: sinc5 r11 is c1111=1 & sinc5 & r11 { * mult_addr = r11; mult_addr = mult_addr + 4; }
|
|
sinc4: r11 is c1111=1 & c0010=0 & r11 { * mult_addr = r11; mult_addr = mult_addr + 4; }
|
|
sinc4: sinc5 is c1111=0 & sinc5 { }
|
|
sinc3: sinc4 r12 is c1212=1 & sinc4 & r12 { * mult_addr = r12; mult_addr = mult_addr + 4; }
|
|
sinc3: r12 is c1212=1 & c0011=0 & r12 { * mult_addr = r12; mult_addr = mult_addr + 4; }
|
|
sinc3: sinc4 is c1212=0 & sinc4 { }
|
|
sinc2: sinc3 sp is c1313=1 & sinc3 & sp { * mult_addr = sp; mult_addr = mult_addr + 4; }
|
|
sinc2: sp is c1313=1 & c0012=0 & sp { * mult_addr = sp; mult_addr = mult_addr + 4; }
|
|
sinc2: sinc3 is c1313=0 & sinc3 { }
|
|
sinc1: sinc2 lr is c1414=1 & sinc2 & lr { * mult_addr = lr; mult_addr = mult_addr + 4; }
|
|
sinc1: lr is c1414=1 & c0013=0 & lr { * mult_addr = lr; mult_addr = mult_addr + 4; }
|
|
sinc1: sinc2 is c1414=0 & sinc2 { }
|
|
sinc0: sinc1 pc is c1515=1 & sinc1 & pc { *:4 mult_addr = (inst_start + 8); mult_addr = mult_addr + 4; }
|
|
sinc0: pc is c1515=1 & c0014=0 & pc { *:4 mult_addr = (inst_start + 8); mult_addr = mult_addr + 4; }
|
|
sinc0: sinc1 is c1515=0 & sinc1 { }
|
|
stlist_inc: { sinc0 } is sinc0 { }
|
|
|
|
|
|
# ldlist_dec is the list of registers to be loaded using DA or DB in Addressing Mode 4
|
|
ldec15: pc is c1515=1 & pc { pc = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec15: is c1515=0 { }
|
|
ldec14: lr ldec15 is c1414=1 & ldec15 & lr { lr = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec14: lr is c1414=1 & c1515=0 & lr { lr = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec14: ldec15 is c1414=0 & ldec15 { }
|
|
ldec13: sp ldec14 is c1313=1 & ldec14 & sp { sp = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec13: sp is c1313=1 & c1415=0 & sp { sp = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec13: ldec14 is c1313=0 & ldec14 { }
|
|
ldec12: r12 ldec13 is c1212=1 & ldec13 & r12 { r12 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec12: r12 is c1212=1 & c1315=0 & r12 { r12 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec12: ldec13 is c1212=0 & ldec13 { }
|
|
ldec11: r11 ldec12 is c1111=1 & ldec12 & r11 { r11 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec11: r11 is c1111=1 & c1215=0 & r11 { r11 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec11: ldec12 is c1111=0 & ldec12 { }
|
|
ldec10: r10 ldec11 is c1010=1 & ldec11 & r10 { r10 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec10: r10 is c1010=1 & c1115=0 & r10 { r10 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec10: ldec11 is c1010=0 & ldec11 { }
|
|
ldec9: r9 ldec10 is c0909=1 & ldec10 & r9 { r9 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec9: r9 is c0909=1 & c1015=0 & r9 { r9 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec9: ldec10 is c0909=0 & ldec10 { }
|
|
ldec8: r8 ldec9 is c0808=1 & ldec9 & r8 { r8 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec8: r8 is c0808=1 & c0915=0 & r8 { r8 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec8: ldec9 is c0808=0 & ldec9 { }
|
|
ldec7: r7 ldec8 is c0707=1 & ldec8 & r7 { r7 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec7: r7 is c0707=1 & c0815=0 & r7 { r7 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec7: ldec8 is c0707=0 & ldec8 { }
|
|
ldec6: r6 ldec7 is c0606=1 & ldec7 & r6 { r6 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec6: r6 is c0606=1 & c0715=0 & r6 { r6 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec6: ldec7 is c0606=0 & ldec7 { }
|
|
ldec5: r5 ldec6 is c0505=1 & ldec6 & r5 { r5 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec5: r5 is c0505=1 & c0615=0 & r5 { r5 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec5: ldec6 is c0505=0 & ldec6 { }
|
|
ldec4: r4 ldec5 is c0404=1 & ldec5 & r4 { r4 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec4: r4 is c0404=1 & c0515=0 & r4 { r4 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec4: ldec5 is c0404=0 & ldec5 { }
|
|
ldec3: r3 ldec4 is c0303=1 & ldec4 & r3 { r3 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec3: r3 is c0303=1 & c0415=0 & r3 { r3 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec3: ldec4 is c0303=0 & ldec4 { }
|
|
ldec2: r2 ldec3 is c0202=1 & ldec3 & r2 { r2 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec2: r2 is c0202=1 & c0315=0 & r2 { r2 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec2: ldec3 is c0202=0 & ldec3 { }
|
|
ldec1: r1 ldec2 is c0101=1 & ldec2 & r1 { r1 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec1: r1 is c0101=1 & c0215=0 & r1 { r1 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec1: ldec2 is c0101=0 & ldec2 { }
|
|
ldec0: r0 ldec1 is c0000=1 & ldec1 & r0 { r0 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec0: r0 is c0000=1 & c0115=0 & r0 { r0 = * mult_addr; mult_addr = mult_addr - 4; }
|
|
ldec0: ldec1 is c0000=0 & ldec1 { }
|
|
ldlist_dec: { ldec0 } is ldec0 { }
|
|
|
|
# stlist_dec is the list of registers to be stored using DA or DB in Addressing Mode 4
|
|
sdec15: pc is c1515=1 & pc { *:4 mult_addr = (inst_start + 8); mult_addr = mult_addr - 4; }
|
|
sdec15: is c1515=0 { }
|
|
sdec14: lr sdec15 is c1414=1 & sdec15 & lr { * mult_addr=lr; mult_addr = mult_addr - 4; }
|
|
sdec14: lr is c1414=1 & c1515=0 & lr { * mult_addr=lr; mult_addr = mult_addr - 4; }
|
|
sdec14: sdec15 is c1414=0 & sdec15 { }
|
|
sdec13: sp sdec14 is c1313=1 & sdec14 & sp { * mult_addr=sp; mult_addr = mult_addr - 4; }
|
|
sdec13: sp is c1313=1 & c1415=0 & sp { * mult_addr=sp; mult_addr = mult_addr - 4; }
|
|
sdec13: sdec14 is c1313=0 & sdec14 { }
|
|
sdec12: r12 sdec13 is c1212=1 & sdec13 & r12 { * mult_addr=r12; mult_addr = mult_addr - 4; }
|
|
sdec12: r12 is c1212=1 & c1315=0 & r12 { * mult_addr=r12; mult_addr = mult_addr - 4; }
|
|
sdec12: sdec13 is c1212=0 & sdec13 { }
|
|
sdec11: r11 sdec12 is c1111=1 & sdec12 & r11 { * mult_addr=r11; mult_addr = mult_addr - 4; }
|
|
sdec11: r11 is c1111=1 & c1215=0 & r11 { * mult_addr=r11; mult_addr = mult_addr - 4; }
|
|
sdec11: sdec12 is c1111=0 & sdec12 { }
|
|
sdec10: r10 sdec11 is c1010=1 & sdec11 & r10 { * mult_addr=r10; mult_addr = mult_addr - 4; }
|
|
sdec10: r10 is c1010=1 & c1115=0 & r10 { * mult_addr=r10; mult_addr = mult_addr - 4; }
|
|
sdec10: sdec11 is c1010=0 & sdec11 { }
|
|
sdec9: r9 sdec10 is c0909=1 & sdec10 & r9 { * mult_addr=r9; mult_addr = mult_addr - 4; }
|
|
sdec9: r9 is c0909=1 & c1015=0 & r9 { * mult_addr=r9; mult_addr = mult_addr - 4; }
|
|
sdec9: sdec10 is c0909=0 & sdec10 { }
|
|
sdec8: r8 sdec9 is c0808=1 & sdec9 & r8 { * mult_addr=r8; mult_addr = mult_addr - 4; }
|
|
sdec8: r8 is c0808=1 & c0915=0 & r8 { * mult_addr=r8; mult_addr = mult_addr - 4; }
|
|
sdec8: sdec9 is c0808=0 & sdec9 { }
|
|
sdec7: r7 sdec8 is c0707=1 & sdec8 & r7 { * mult_addr=r7; mult_addr = mult_addr - 4; }
|
|
sdec7: r7 is c0707=1 & c0815=0 & r7 { * mult_addr=r7; mult_addr = mult_addr - 4; }
|
|
sdec7: sdec8 is c0707=0 & sdec8 { }
|
|
sdec6: r6 sdec7 is c0606=1 & sdec7 & r6 { * mult_addr=r6; mult_addr = mult_addr - 4; }
|
|
sdec6: r6 is c0606=1 & c0715=0 & r6 { * mult_addr=r6; mult_addr = mult_addr - 4; }
|
|
sdec6: sdec7 is c0606=0 & sdec7 { }
|
|
sdec5: r5 sdec6 is c0505=1 & sdec6 & r5 { * mult_addr=r5; mult_addr = mult_addr - 4; }
|
|
sdec5: r5 is c0505=1 & c0615=0 & r5 { * mult_addr=r5; mult_addr = mult_addr - 4; }
|
|
sdec5: sdec6 is c0505=0 & sdec6 { }
|
|
sdec4: r4 sdec5 is c0404=1 & sdec5 & r4 { * mult_addr=r4; mult_addr = mult_addr - 4; }
|
|
sdec4: r4 is c0404=1 & c0515=0 & r4 { * mult_addr=r4; mult_addr = mult_addr - 4; }
|
|
sdec4: sdec5 is c0404=0 & sdec5 { }
|
|
sdec3: r3 sdec4 is c0303=1 & sdec4 & r3 { * mult_addr=r3; mult_addr = mult_addr - 4; }
|
|
sdec3: r3 is c0303=1 & c0415=0 & r3 { * mult_addr=r3; mult_addr = mult_addr - 4; }
|
|
sdec3: sdec4 is c0303=0 & sdec4 { }
|
|
sdec2: r2 sdec3 is c0202=1 & sdec3 & r2 { * mult_addr=r2; mult_addr = mult_addr - 4; }
|
|
sdec2: r2 is c0202=1 & c0315=0 & r2 { * mult_addr=r2; mult_addr = mult_addr - 4; }
|
|
sdec2: sdec3 is c0202=0 & sdec3 { }
|
|
sdec1: r1 sdec2 is c0101=1 & sdec2 & r1 { * mult_addr=r1; mult_addr = mult_addr - 4; }
|
|
sdec1: r1 is c0101=1 & c0215=0 & r1 { * mult_addr=r1; mult_addr = mult_addr - 4; }
|
|
sdec1: sdec2 is c0101=0 & sdec2 { }
|
|
|
|
sdec0: r0 sdec1 is c0000=1 & sdec1 & r0 { * mult_addr=r0; mult_addr = mult_addr - 4; }
|
|
sdec0: r0 is c0000=1 & c0115=0 & r0 { * mult_addr=r0; mult_addr = mult_addr - 4; }
|
|
sdec0: sdec1 is c0000=0 & sdec1 { }
|
|
|
|
stlist_dec: {sdec0} is sdec0 { }
|
|
|
|
# reglist deals with Addressing Mode 4
|
|
# it takes care of bits 0-27
|
|
# we assume that alignment checking is turned on
|
|
reglist: rn,ldlist_inc is P24=0 & U23=1 & S22=0 & W21=0 & L20=1 & rn & ldlist_inc
|
|
{
|
|
mult_addr=rn; build ldlist_inc;
|
|
}
|
|
|
|
reglist: rn,ldlist_inc"^" is P24=0 & U23=1 & S22=1 & W21=0 & L20=1 & rn & ldlist_inc
|
|
{
|
|
mult_addr=rn; build ldlist_inc;
|
|
}
|
|
|
|
reglist: rn!,ldlist_inc is P24=0 & U23=1 & S22=0 & W21=1 & L20=1 & rn & ldlist_inc
|
|
{
|
|
mult_addr=rn; build ldlist_inc; rn=mult_addr;
|
|
}
|
|
|
|
reglist: rn!,ldlist_inc"^" is P24=0 & U23=1 & S22=1 & W21=1 & L20=1 & rn & ldlist_inc
|
|
{
|
|
mult_addr=rn; build ldlist_inc; rn=mult_addr;
|
|
}
|
|
|
|
reglist: rn,ldlist_inc is P24=1 & U23=1 & S22=0 & W21=0 & L20=1 & rn & ldlist_inc
|
|
{
|
|
mult_addr=(rn+4); build ldlist_inc;
|
|
}
|
|
|
|
reglist: rn,ldlist_inc"^" is P24=1 & U23=1 & S22=1 & W21=0 & L20=1 & rn & ldlist_inc
|
|
{
|
|
mult_addr=(rn+4); build ldlist_inc;
|
|
}
|
|
|
|
reglist: rn!,ldlist_inc is P24=1 & U23=1 & S22=0 & W21=1 & L20=1 & rn & ldlist_inc
|
|
{
|
|
mult_addr=(rn+4); build ldlist_inc; rn=mult_addr-4;
|
|
}
|
|
|
|
reglist: rn!,ldlist_inc"^" is P24=1 & U23=1 & S22=1 & W21=1 & L20=1 & rn & ldlist_inc
|
|
{
|
|
mult_addr=(rn+4); build ldlist_inc; rn=mult_addr-4;
|
|
}
|
|
|
|
reglist: rn,ldlist_dec is P24=0 & U23=0 & S22=0 & W21=0 & L20=1 & rn & ldlist_dec
|
|
{
|
|
mult_addr=rn; build ldlist_dec;
|
|
}
|
|
|
|
reglist: rn,ldlist_dec"^" is P24=0 & U23=0 & S22=1 & W21=0 & L20=1 & rn & ldlist_dec
|
|
{
|
|
mult_addr=rn; build ldlist_dec;
|
|
}
|
|
|
|
reglist: rn!,ldlist_dec is P24=0 & U23=0 & S22=0 & W21=1 & L20=1 & rn & ldlist_dec
|
|
{
|
|
mult_addr=rn; build ldlist_dec; rn=mult_addr;
|
|
}
|
|
|
|
reglist: rn!,ldlist_dec"^" is P24=0 & U23=0 & S22=1 & W21=1 & L20=1 & rn & ldlist_dec
|
|
{
|
|
mult_addr=rn; build ldlist_dec; rn=mult_addr;
|
|
}
|
|
|
|
reglist: rn,ldlist_dec is P24=1 & U23=0 & S22=0 & W21=0 & L20=1 & rn & ldlist_dec
|
|
{
|
|
mult_addr=(rn-4); build ldlist_dec;
|
|
}
|
|
|
|
reglist: rn,ldlist_dec"^" is P24=1 & U23=0 & S22=1 & W21=0 & L20=1 & rn & ldlist_dec
|
|
{
|
|
mult_addr=(rn-4); build ldlist_dec;
|
|
}
|
|
|
|
reglist: rn!,ldlist_dec is P24=1 & U23=0 & S22=0 & W21=1 & L20=1 & rn & ldlist_dec
|
|
{
|
|
mult_addr=(rn-4); build ldlist_dec; rn=mult_addr+4;
|
|
}
|
|
|
|
reglist: rn!,ldlist_dec"^" is P24=1 & U23=0 & S22=1 & W21=1 & L20=1 & rn & ldlist_dec
|
|
{
|
|
mult_addr=(rn-4); build ldlist_dec; rn=mult_addr+4;
|
|
}
|
|
|
|
reglist: rn,stlist_inc is P24=0 & U23=1 & S22=0 & W21=0 & L20=0 & rn & stlist_inc
|
|
{
|
|
mult_addr=rn; build stlist_inc;
|
|
}
|
|
|
|
reglist: rn,stlist_inc"^" is P24=0 & U23=1 & S22=1 & W21=0 & L20=0 & rn & stlist_inc
|
|
{
|
|
mult_addr=rn; build stlist_inc;
|
|
}
|
|
|
|
## This is here to allow old versions of this instruction to decode.
|
|
## The W-Bit21 is specified as (0) in the manual meaning should be 0 but is unpredictable if 1
|
|
## Some older processors did not specify that Writeback was not available if the P24=0 and S22=0,
|
|
## which is a system interrupt instruction.
|
|
## I AM ASSUMING, that the W-bit is honored on these processors and does update the register!!!!
|
|
## This is probably an arbitrary decision, but keeps with what old processor did.
|
|
reglist: rn,stlist_inc"^" is P24=0 & U23=1 & S22=1 & W21=1 & L20=0 & rn & stlist_inc
|
|
{
|
|
mult_addr=rn; build stlist_inc; rn=mult_addr;
|
|
}
|
|
|
|
|
|
reglist: rn!,stlist_inc is P24=0 & U23=1 & S22=0 & W21=1 & L20=0 & rn & stlist_inc
|
|
{
|
|
mult_addr=rn; build stlist_inc; rn=mult_addr;
|
|
}
|
|
|
|
reglist: rn,stlist_inc is P24=1 & U23=1 & S22=0 & W21=0 & L20=0 & rn & stlist_inc
|
|
{
|
|
mult_addr=(rn+4); build stlist_inc;
|
|
}
|
|
|
|
reglist: rn,stlist_inc"^" is P24=1 & U23=1 & S22=1 & W21=0 & L20=0 & rn & stlist_inc
|
|
{
|
|
mult_addr=(rn+4); build stlist_inc;
|
|
}
|
|
|
|
reglist: rn!,stlist_inc is P24=1 & U23=1 & S22=0 & W21=1 & L20=0 & rn & stlist_inc
|
|
{
|
|
mult_addr=(rn+4); build stlist_inc; rn=mult_addr-4;
|
|
}
|
|
|
|
reglist: rn,stlist_dec is P24=0 & U23=0 & S22=0 & W21=0 & L20=0 & rn & stlist_dec
|
|
{
|
|
mult_addr=rn; build stlist_dec;
|
|
}
|
|
|
|
reglist: rn,stlist_dec"^" is P24=0 & U23=0 & S22=1 & W21=0 & L20=0 & rn & stlist_dec
|
|
{
|
|
mult_addr=rn; build stlist_dec;
|
|
}
|
|
|
|
reglist: rn!,stlist_dec is P24=0 & U23=0 & S22=0 & W21=1 & L20=0 & rn & stlist_dec
|
|
{
|
|
mult_addr=rn; build stlist_dec; rn=mult_addr;
|
|
}
|
|
|
|
reglist: rn,stlist_dec is P24=1 & U23=0 & S22=0 & W21=0 & L20=0 & rn & stlist_dec
|
|
{
|
|
mult_addr=(rn-4); build stlist_dec;
|
|
}
|
|
|
|
reglist: rn,stlist_dec"^" is P24=1 & U23=0 & S22=1 & W21=0 & L20=0 & rn & stlist_dec
|
|
{
|
|
mult_addr=(rn-4); build stlist_dec;
|
|
}
|
|
|
|
reglist: rn!,stlist_dec is P24=1 & U23=0 & S22=0 & W21=1 & L20=0 & rn & stlist_dec
|
|
{
|
|
mult_addr=(rn-4); build stlist_dec; rn=mult_addr+4;
|
|
}
|
|
|
|
# mdir is for attaching the load/store multiple addressing mode mnemonic to the mnemonic
|
|
mdir: "ia" is P24=0 & U23=1 { }
|
|
mdir: "ib" is P24=1 & U23=1 { }
|
|
mdir: "da" is P24=0 & U23=0 { }
|
|
mdir: "db" is P24=1 & U23=0 { }
|
|
|
|
# addrmode5 is the <addressing_mode> parameter in Addressing Mode5
|
|
# it takes care of bits 27-0 except for the N and L flags and CRd and cp#
|
|
# it takes care of possible writebacks to Rn
|
|
addrmode5: [rn,"#"^off8] is P24=1 & U23=1 & W21=0 & rn & immed [ off8=immed*4; ] { local tmp = rn + off8; export tmp; }
|
|
addrmode5: [rn,"#"^noff8] is P24=1 & U23=0 & W21=0 & rn & immed [ noff8=-(immed*4); ] { local tmp = rn + noff8; export tmp; }
|
|
addrmode5: [rn,"#"^off8]! is P24=1 & U23=1 & W21=1 & rn & immed [ off8=immed*4; ] { rn = rn + off8; export rn; }
|
|
addrmode5: [rn,"#"^noff8]! is P24=1 & U23=0 & W21=1 & rn & immed [ noff8=-(immed*4); ] { rn = rn + noff8; export rn; }
|
|
addrmode5: [rn],"#"^off8 is P24=0 & U23=1 & W21=1 & rn & immed [ off8=immed*4; ] { local tmp = rn; rn = rn+off8; export tmp; }
|
|
addrmode5: [rn],"#"^noff8 is P24=0 & U23=0 & W21=1 & rn & immed [ noff8=-(immed*4); ] { local tmp = rn; rn = rn + noff8; export tmp; }
|
|
addrmode5: [rn],{immed} is P24=0 & U23=1 & W21=0 & rn & immed { export rn; }
|
|
|
|
# cpsrmask is the resulting cpsr mask for the msr instruction
|
|
|
|
cpsrmask: is mask=0 { export 0:4; }
|
|
cpsrmask: "cpsr_c" is mask=1 { export 0xff:4; }
|
|
cpsrmask: "cpsr_x" is mask=2 { export 0xff00:4; }
|
|
cpsrmask: "cpsr_cx" is mask=3 { export 0xffff:4; }
|
|
cpsrmask: "cpsr_s" is mask=4 { export 0xff0000:4; }
|
|
cpsrmask: "cpsr_cs" is mask=5 { export 0xff00ff:4; }
|
|
cpsrmask: "cpsr_xs" is mask=6 { export 0xffff00:4; }
|
|
cpsrmask: "cpsr_cxs" is mask=7 { export 0xffffff:4; }
|
|
cpsrmask: "cpsr_f" is mask=8 { export 0xff000000:4; }
|
|
cpsrmask: "cpsr_cf" is mask=9 { export 0xff0000ff:4; }
|
|
cpsrmask: "cpsr_xf" is mask=10 { export 0xff00ff00:4; }
|
|
cpsrmask: "cpsr_cxf" is mask=11 { export 0xff00ffff:4; }
|
|
cpsrmask: "cpsr_sf" is mask=12 { export 0xffff0000:4; }
|
|
cpsrmask: "cpsr_csf" is mask=13 { export 0xffff00ff:4; }
|
|
cpsrmask: "cpsr_xsf" is mask=14 { export 0xffffff00:4; }
|
|
cpsrmask: "cpsr_cxsf" is mask=15 { export 0xffffffff:4; }
|
|
|
|
# spsrmask is the mask for spsr in the msr instruction
|
|
|
|
spsrmask: is mask=0 { export 0:4; }
|
|
spsrmask: "spsr_c" is mask=1 { export 0xff:4; }
|
|
spsrmask: "spsr_x" is mask=2 { export 0xff00:4; }
|
|
spsrmask: "spsr_cx" is mask=3 { export 0xffff:4; }
|
|
spsrmask: "spsr_s" is mask=4 { export 0xff0000:4; }
|
|
spsrmask: "spsr_cs" is mask=5 { export 0xff00ff:4; }
|
|
spsrmask: "spsr_xs" is mask=6 { export 0xffff00:4; }
|
|
spsrmask: "spsr_cxs" is mask=7 { export 0xffffff:4; }
|
|
spsrmask: "spsr_f" is mask=8 { export 0xff000000:4; }
|
|
spsrmask: "spsr_cf" is mask=9 { export 0xff0000ff:4; }
|
|
spsrmask: "spsr_xf" is mask=10 { export 0xff00ff00:4; }
|
|
spsrmask: "spsr_cxf" is mask=11 { export 0xff00ffff:4; }
|
|
spsrmask: "spsr_sf" is mask=12 { export 0xffff0000:4; }
|
|
spsrmask: "spsr_csf" is mask=13 { export 0xffff00ff:4; }
|
|
spsrmask: "spsr_xsf" is mask=14 { export 0xffffff00:4; }
|
|
spsrmask: "spsr_cxsf" is mask=15 { export 0xffffffff:4; }
|
|
|
|
#####################
|
|
###### immediate bit-number data for unsigned/signed saturated instructions
|
|
#####################
|
|
@if defined(VERSION_6)
|
|
|
|
sSatImm5: "#"^satimm is satimm5 [ satimm = satimm5 + 1; ] { export *[const]:2 satimm; }
|
|
sSatImm4: "#"^satimm is satimm4 [ satimm = satimm4 + 1; ] { export *[const]:2 satimm; }
|
|
uSatImm5: "#"^satimm5 is satimm5 { export *[const]:2 satimm5; }
|
|
uSatImm4: "#"^satimm4 is satimm4 { export *[const]:2 satimm4; }
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_6K) || defined(VERSION_6T2)
|
|
optionImm: "#"^immed4 is immed4 { export *[const]:4 immed4; }
|
|
@endif
|
|
|
|
@if defined(VERSION_6T2) || defined(VERSION_7)
|
|
|
|
lsbImm: "#"^lsb is lsb { export *[const]:4 lsb; }
|
|
msbImm: "#"^msb is msb { export *[const]:4 msb; }
|
|
widthMinus1: "#"^width is msb [ width = msb + 1; ] { export *[const]:4 msb; }
|
|
bitWidth: "#"^w is lsb & msb [ w = msb - lsb + 1; ] { export *[const]:4 w; }
|
|
|
|
@endif # VERSION_6T2 || VERSION_7
|
|
|
|
#
|
|
# Modes for SRS instructions
|
|
#
|
|
@if defined(VERSION_6)
|
|
SRSMode: "usr" is srsMode=8 & c0004 { export *[const]:1 c0004; }
|
|
SRSMode: "fiq" is srsMode=9 & c0004 { export *[const]:1 c0004; }
|
|
SRSMode: "irq" is srsMode=10 & c0004 { export *[const]:1 c0004; }
|
|
SRSMode: "svc" is srsMode=11 & c0004 { export *[const]:1 c0004; }
|
|
SRSMode: "mon" is srsMode=14 & c0004 { export *[const]:1 c0004; }
|
|
SRSMode: "abt" is srsMode=15 & c0004 { export *[const]:1 c0004; }
|
|
SRSMode: "und" is srsMode=19 & c0004 { export *[const]:1 c0004; }
|
|
SRSMode: "sys" is srsMode=23 & c0004 { export *[const]:1 c0004; }
|
|
SRSMode: "#"^srsMode is srsMode { export *[const]:1 srsMode; }
|
|
@endif # VERSION_6
|
|
|
|
# Add a hat instruction to set the ARMcond context variable which
|
|
# tells whether this is a legal conditional instruction (for v7 and
|
|
# later).
|
|
|
|
@if defined(VERSION_6T2) || defined(VERSION_7)
|
|
:^instruction is ARMcondCk=0 & itmode=0 & TMode=0 & (bit31=0|bit30=0|bit29=0|bit28=0) & instruction [ ARMcondCk=1; ARMcond=1; ] {}
|
|
:^instruction is ARMcondCk=0 & instruction [ ARMcondCk=1; ARMcond=0; ] {}
|
|
|
|
# Ensure one of the recursive rules above is applied for assembly
|
|
with : ARMcondCk=1 {
|
|
|
|
@endif
|
|
|
|
#################################################
|
|
#
|
|
# Include the SIMD/VFP instructions before the
|
|
# other ARM instructions to avoid incorrect
|
|
# constructor matching for those that use the
|
|
# COND subconstructor. This also ensures
|
|
# that the various VFP instructions supersede the
|
|
# CDP/MCR/MRC general coprocessor instructions
|
|
#
|
|
#################################################
|
|
@if defined(INCLUDE_NEON)
|
|
@include "ARMneon.sinc"
|
|
@endif
|
|
|
|
#################################################
|
|
#
|
|
# Do the same now for ARMv8, which also has neon
|
|
#
|
|
#################################################
|
|
@if defined(VERSION_8)
|
|
@include "ARMv8.sinc"
|
|
@endif # VERSION_8
|
|
|
|
################################################
|
|
#
|
|
# These instructions must come first because the cond pattern match
|
|
# is more specific than the subconstructor COND. If a base intruction
|
|
# matches and then COND fails (cond=14 or cond=15) then the disassembly
|
|
# will fail
|
|
#
|
|
################################################
|
|
|
|
@if defined(VERSION_5)
|
|
|
|
# Exception Generation and UDF
|
|
|
|
# immed12_4 used in Exception Generation and Media instructions class
|
|
|
|
immed12_4: "#"^tmp is $(AMODE) & immed12 & immed4 [tmp = (immed12 << 4) | immed4; ] { export *[const]:4 tmp; }
|
|
|
|
:hlt immed12_4 is $(AMODE) & cond=0xe & c2027=0x10 & c0407=0x7 & immed12_4
|
|
{
|
|
software_hlt(immed12_4);
|
|
}
|
|
|
|
:bkpt immed12_4 is $(AMODE) & cond=0xe & c2027=0x12 & c0407=0x7 & immed12_4
|
|
{
|
|
software_bkpt(immed12_4);
|
|
}
|
|
|
|
:hvc immed12_4 is $(AMODE) & cond=0xe & c2027=0x14 & c0407=0x7 & immed12_4
|
|
{
|
|
software_hvc(immed12_4);
|
|
}
|
|
|
|
@if defined(VERSION_6T2) || defined(VERSION_7)
|
|
|
|
define pcodeop SG;
|
|
|
|
:sg is TMode=1 & thv_c0031=0xe97fe97f
|
|
{
|
|
SG();
|
|
}
|
|
@endif
|
|
|
|
# Requires Security Extensions
|
|
:smc^COND immed4 is $(AMODE) & COND & c2027=0x16 & c0407=0x7 & immed4
|
|
{
|
|
build COND;
|
|
software_smc(immed4:4);
|
|
}
|
|
|
|
@if defined(VERSION_6T2) || defined(VERSION_7)
|
|
define pcodeop TT;
|
|
|
|
:tt^ItCond thv_Rt2, thv_Rn is TMode=1 & ItCond & thv_c2031=0b111010000100 & thv_c1215=0b1111 & thv_bit07=0 & thv_bit06=0 & thv_Rt2 & thv_Rn
|
|
{
|
|
thv_Rt2 = TT(thv_Rn);
|
|
}
|
|
|
|
define pcodeop TTA;
|
|
|
|
:tta^ItCond thv_Rt2, thv_Rn is TMode=1 & ItCond & thv_c2031=0b111010000100 & thv_c1215=0b1111 & thv_bit07=1 & thv_bit06=0 & thv_Rt2 & thv_Rn
|
|
{
|
|
thv_Rt2 = TTA(thv_Rn);
|
|
}
|
|
|
|
define pcodeop TTAT;
|
|
|
|
:ttat^ItCond thv_Rt2, thv_Rn is TMode=1 & ItCond & thv_c2031=0b111010000100 & thv_c1215=0b1111 & thv_bit07=1 & thv_bit06=1 & thv_Rt2 & thv_Rn
|
|
{
|
|
thv_Rt2 = TTAT(thv_Rn);
|
|
}
|
|
|
|
define pcodeop TTT;
|
|
|
|
:ttt^ItCond thv_Rt2, thv_Rn is TMode=1 & ItCond & thv_c2031=0b111010000100 & thv_c1215=0b1111 & thv_bit07=0 & thv_bit06=1 & thv_Rt2 & thv_Rn
|
|
{
|
|
thv_Rt2 = TTT(thv_Rn);
|
|
}
|
|
|
|
@endif
|
|
|
|
:udf immed12_4 is $(AMODE) & cond=0xe & c2027=0x7f & c0407=0xf & immed12_4
|
|
{
|
|
local excaddr:4 = inst_start;
|
|
local target:4 = software_udf(immed12_4:4, excaddr);
|
|
goto [target];
|
|
}
|
|
|
|
@endif # VERSION_5
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
AFLAG: "a" is c0808=1 & c1819=2 { enableDataAbortInterrupts(); }
|
|
AFLAG: "a" is c0808=1 { disableDataAbortInterrupts(); }
|
|
AFLAG: is c0808=0 { }
|
|
IFLAG: "i" is c0707=1 & c1819=2 { enableIRQinterrupts(); }
|
|
IFLAG: "i" is c0707=1 { disableIRQinterrupts(); }
|
|
IFLAG: is c0707=0 { }
|
|
FFLAG: "f" is c0606=1 & c1819=2 { enableFIQinterrupts(); }
|
|
FFLAG: "f" is c0606=1 { disableFIQinterrupts(); }
|
|
FFLAG: is c0606=0 { }
|
|
IFLAGS: AFLAG^IFLAG^FFLAG is AFLAG & IFLAG & FFLAG { }
|
|
|
|
SetMode: "#"^16 is c0004=0x10 { setUserMode(); }
|
|
SetMode: "#"^17 is c0004=0x11 { setFIQMode(); }
|
|
SetMode: "#"^18 is c0004=0x12 { setIRQMode(); }
|
|
SetMode: "#"^19 is c0004=0x13 { setSupervisorMode(); }
|
|
SetMode: "#"^22 is c0004=0x16 { setMonitorMode(); }
|
|
SetMode: "#"^23 is c0004=0x17 { setAbortMode(); }
|
|
SetMode: "#"^27 is c0004=0x1b { setUndefinedMode(); }
|
|
SetMode: "#"^31 is c0004=0x1f { setSystemMode(); }
|
|
|
|
:cps SetMode is $(AMODE) & cond=15 & c2027=16 & c1819=0 & c1717=1 & c0916=0 & c0508=0 & SetMode { }
|
|
:cpsie IFLAGS is $(AMODE) & cond=15 & c2027=16 & c1819=2 & c1717=0 & c0916=0 & c0505=0 & c0004=0 & IFLAGS { }
|
|
:cpsid IFLAGS is $(AMODE) & cond=15 & c2027=16 & c1819=3 & c1717=0 & c0916=0 & c0505=0 & c0004=0 & IFLAGS { }
|
|
:cpsie IFLAGS, SetMode is $(AMODE) & cond=15 & c2027=16 & c1819=2 & c1717=1 & c0916=0 & c0505=0 & IFLAGS & SetMode { }
|
|
:cpsid IFLAGS, SetMode is $(AMODE) & cond=15 & c2027=16 & c1819=3 & c1717=1 & c0916=0 & c0505=0 & IFLAGS & SetMode { }
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:pld addrmode2 is $(AMODE) & cond=0xf & c2627=1 & c2424=1 & c2022=5 & c1215=0xf & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
HintPreloadData(addrmode2);
|
|
}
|
|
|
|
# prevent literal form getting matched by pldw
|
|
:pld addrmode2 is $(AMODE) & cond=0xf & c2627=1 & c2424=1 & c2022=5 & c1619=0xf & c1215=0xf & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
HintPreloadData(addrmode2);
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
@if defined(VERSION_7)
|
|
|
|
:pldw addrmode2 is $(AMODE) & cond=0xf & c2627=1 & c2424=1 & c2022=1 & c1215=0xf & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
HintPreloadDataForWrite(addrmode2);
|
|
}
|
|
|
|
:pli addrmode2 is $(AMODE) & cond=0xf & c2627=1 & c2424=0 & c2022=5 & c1215=0xf & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
HintPreloadInstruction(addrmode2);
|
|
}
|
|
|
|
@endif # VERSION_7
|
|
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:rfeia rn is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=1 & S22=0 & W21=0 & L20=1 & rn & c1215=0 & c0811=10 & c0007=0
|
|
{
|
|
# register list is always: pc, cpsr
|
|
ptr:4 = rn;
|
|
cpsr = *ptr;
|
|
ptr = ptr + 4;
|
|
pc = *ptr;
|
|
return [pc];
|
|
}
|
|
|
|
:rfeib rn is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=1 & S22=0 & W21=0 & L20=1 & rn & c1215=0 & c0811=10 & c0007=0
|
|
{
|
|
# register list is always: pc, cpsr
|
|
ptr:4 = rn + 4;
|
|
cpsr = *ptr;
|
|
ptr = ptr + 4;
|
|
pc = *ptr;
|
|
return [pc];
|
|
}
|
|
|
|
:rfeda rn is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=0 & S22=0 & W21=0 & L20=1 & rn & c1215=0 & c0811=10 & c0007=0
|
|
{
|
|
# register list is always: pc, cpsr
|
|
ptr:4 = rn;
|
|
cpsr = *ptr;
|
|
ptr = ptr - 4;
|
|
pc = *ptr;
|
|
return [pc];
|
|
}
|
|
|
|
:rfedb rn is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=0 & S22=0 & W21=0 & L20=1 & rn & c1215=0 & c0811=10 & c0007=0
|
|
{
|
|
# register list is always: pc, cpsr
|
|
ptr:4 = rn - 4;
|
|
cpsr = *ptr;
|
|
ptr = ptr - 4;
|
|
pc = *ptr;
|
|
return [pc];
|
|
}
|
|
|
|
:rfeia Rn! is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=1 & S22=0 & W21=1 & L20=1 & Rn & c1215=0 & c0811=10 & c0007=0
|
|
{
|
|
# register list is always: pc, cpsr
|
|
ptr:4 = Rn;
|
|
cpsr = *ptr;
|
|
ptr = ptr + 4;
|
|
pc = *ptr;
|
|
Rn = ptr + 4;
|
|
return [pc];
|
|
}
|
|
|
|
:rfeib Rn! is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=1 & S22=0 & W21=1 & L20=1 & Rn & c1215=0 & c0811=10 & c0007=0
|
|
{
|
|
# register list is always: pc, cpsr
|
|
ptr:4 = Rn + 4;
|
|
cpsr = *ptr;
|
|
ptr = ptr + 4;
|
|
pc = *ptr;
|
|
Rn = ptr;
|
|
return [pc];
|
|
}
|
|
|
|
:rfeda Rn! is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=0 & S22=0 & W21=1 & L20=1 & Rn & c1215=0 & c0811=10 & c0007=0
|
|
{
|
|
# register list is always: pc, cpsr
|
|
ptr:4 = Rn;
|
|
cpsr = *ptr;
|
|
ptr = ptr - 4;
|
|
pc = *ptr;
|
|
Rn = ptr - 4;
|
|
return [pc];
|
|
}
|
|
|
|
:rfedb Rn! is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=0 & S22=0 & W21=1 & L20=1 & Rn & c1215=0 & c0811=10 & c0007=0
|
|
{
|
|
# register list is always: pc, cpsr
|
|
ptr:4 = Rn - 4;
|
|
cpsr = *ptr;
|
|
ptr = ptr - 4;
|
|
pc = *ptr;
|
|
Rn = ptr;
|
|
return [pc];
|
|
}
|
|
|
|
:srsia SRSMode is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=1 & S22=1 & W21=0 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode
|
|
{
|
|
# register list is always: r14, spsr
|
|
ptr:4 = sp;
|
|
*ptr = lr;
|
|
ptr = ptr + 4;
|
|
*ptr = spsr;
|
|
ptr = ptr + 4;
|
|
}
|
|
|
|
:srsib SRSMode is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=1 & W21=0 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode
|
|
{
|
|
# register list is always: r14, spsr
|
|
ptr:4 = sp + 4;
|
|
*ptr = lr;
|
|
ptr = ptr + 4;
|
|
*ptr = spsr;
|
|
}
|
|
|
|
:srsda SRSMode is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=0 & W21=0 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode
|
|
{
|
|
# register list is always: r14, spsr
|
|
ptr:4 = sp;
|
|
*ptr = lr;
|
|
ptr = ptr - 4;
|
|
*ptr = spsr;
|
|
ptr = ptr - 4;
|
|
}
|
|
|
|
:srsdb SRSMode is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=0 & W21=0 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode
|
|
{
|
|
# register list is always: r14, spsr
|
|
ptr:4 = sp - 4;
|
|
*ptr = lr;
|
|
ptr = ptr - 4;
|
|
*ptr = spsr;
|
|
}
|
|
|
|
:srsia SRSMode! is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=1 & S22=1 & W21=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode
|
|
{
|
|
# register list is always: r14, spsr
|
|
ptr:4 = sp;
|
|
*ptr = lr;
|
|
ptr = ptr + 4;
|
|
*ptr = spsr;
|
|
ptr = ptr + 4;
|
|
sp = ptr;
|
|
}
|
|
|
|
:srsib SRSMode! is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=1 & W21=1 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode
|
|
{
|
|
# register list is always: r14, spsr
|
|
ptr:4 = sp + 4;
|
|
*ptr = lr;
|
|
ptr = ptr + 4;
|
|
*ptr = spsr;
|
|
sp = ptr;
|
|
}
|
|
|
|
:srsda SRSMode! is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=0 & W21=1 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode
|
|
{
|
|
# register list is always: r14, spsr
|
|
ptr:4 = sp;
|
|
*ptr = lr;
|
|
ptr = ptr - 4;
|
|
*ptr = spsr;
|
|
ptr = ptr - 4;
|
|
sp = ptr;
|
|
}
|
|
|
|
:srsdb SRSMode! is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=0 & W21=1 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode
|
|
{
|
|
# register list is always: r14, spsr
|
|
ptr:4 = sp;
|
|
ptr = ptr - 4;
|
|
*ptr = lr;
|
|
ptr = ptr - 4;
|
|
*ptr = spsr;
|
|
sp = ptr;
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_5)
|
|
|
|
:stc2 cpn,CRd,addrmode5 is $(AMODE) & cond=15 & c2527=6 & addrmode5 & cpn & CRd & N22=0 & L20=0
|
|
{
|
|
t_cpn:4 = cpn;
|
|
coprocessor_store2(t_cpn,CRd,addrmode5);
|
|
}
|
|
|
|
:stc2l cpn,CRd,addrmode5 is $(AMODE) & cond=15 & c2527=6 & addrmode5 & cpn & CRd & N22=1 & L20=0
|
|
{
|
|
t_cpn:4 = cpn;
|
|
coprocessor_storelong2(t_cpn,CRd,addrmode5);
|
|
}
|
|
|
|
@endif # VERSION_5
|
|
|
|
#################################################
|
|
#
|
|
# Here are the rest of instructions in alphabetical order
|
|
#
|
|
#################################################
|
|
|
|
#See Section 2-13, "Overflow Detection", of Hacker's Delight (2nd ed)
|
|
macro add_with_carry_flags(op1,op2){
|
|
tmpCY = ((CY == 0) && carry(op1,op2)) || ((CY == 1) && (op1 >= op1 + op2 + 1:4));
|
|
local total= op1 + op2 + zext(CY);
|
|
local sign_total = (total >> 31) != 0;
|
|
local sign_op1 = (op1 >> 31) != 0;
|
|
local sign_op2 = (op2 >> 31) != 0;
|
|
tmpOV = (sign_op1 == sign_op2) && (sign_total != sign_op1);
|
|
}
|
|
|
|
:adc^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=5 & SBIT_CZNO & rn & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
add_with_carry_flags(rn,shift1);
|
|
Rd = rn+shift1+zext(CY);
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:adc^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=5 & SBIT_CZNO & rn & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
add_with_carry_flags(rn,shift2);
|
|
Rd = rn+shift2+zext(CY);
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:adc^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=5 & SBIT_CZNO & rn & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
add_with_carry_flags(rn,shift3);
|
|
Rd = rn+shift3+zext(CY);
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:adc^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=5 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
add_with_carry_flags(rn,shift1);
|
|
dest:4 = rn + shift1 + zext(CY);
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:adc^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=5 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
add_with_carry_flags(rn,shift2);
|
|
dest:4 = rn + shift2 + zext(CY);
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:adc^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=5 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
add_with_carry_flags(rn,shift3);
|
|
dest:4 = rn + shift3 + zext(CY);
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
ArmPCRelImmed12: reloff is U23=1 & immed & rotate
|
|
[ reloff = inst_start + 8 + ( ((immed<<(32-rotate*2))|(immed>>(rotate*2))) $and 0xffffffff); ]
|
|
{
|
|
export *[const]:4 reloff;
|
|
}
|
|
|
|
ArmPCRelImmed12: reloff is U23=0 & immed & rotate
|
|
[ reloff = inst_start + 8 - ( ((immed<<(32-rotate*2))|(immed>>(rotate*2))) $and 0xffffffff); ]
|
|
{
|
|
export *[const]:4 reloff;
|
|
}
|
|
|
|
#
|
|
# ADR constructors must appear before ADD constructors to give ADR parsing precedence
|
|
#
|
|
|
|
:adr^COND Rd,ArmPCRelImmed12 is $(AMODE) & COND & c2527=1 & (c2024=8 | c2024=4) & Rn=15 & Rd & ArmPCRelImmed12
|
|
{
|
|
build COND;
|
|
Rd = ArmPCRelImmed12;
|
|
}
|
|
|
|
:adr^COND pc,ArmPCRelImmed12 is $(AMODE) & COND & c2527=1 & (c2024=8 | c2024=4) & Rn=15 & Rd=15 & pc & ArmPCRelImmed12
|
|
{
|
|
build COND;
|
|
dest:4 = ArmPCRelImmed12;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
|
|
:add^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=4 & SBIT_CZNO & rn & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
addflags(rn,shift1);
|
|
Rd = rn + shift1;
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:add^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=4 & SBIT_CZNO & rn & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
addflags(rn,shift2);
|
|
Rd = rn + shift2;
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:add^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=4 & SBIT_CZNO & rn & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
addflags(rn,shift3);
|
|
Rd = rn + shift3;
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:add^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=4 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
addflags(rn,shift1);
|
|
dest:4 = rn + shift1;
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:add^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=4 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
addflags(rn,shift2);
|
|
dest:4 = rn + shift2;
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:add^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=4 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
addflags(rn,shift3);
|
|
dest:4 = rn + shift3;
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:and^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=0 & SBIT_CZNO & rn & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
Rd = rn & shift1;
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:and^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=0 & SBIT_CZNO & rn & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
Rd = rn & shift2;
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:and^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=0 & SBIT_CZNO & rn & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
Rd = rn & shift3;
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:and^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=0 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
dest:4 = rn & shift1;
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:and^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=0 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
dest:4 = rn & shift2;
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:and^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=0 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
dest:4 = rn & shift3;
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
# must match first! before conditional goto
|
|
|
|
:b Addr24 is $(AMODE) & cond=14 & c2527=5 & L24=0 & Addr24
|
|
{
|
|
goto Addr24;
|
|
}
|
|
|
|
:b^cc Addr24 is $(AMODE) & cc & c2527=5 & L24=0 & Addr24
|
|
{
|
|
if (cc) goto Addr24;
|
|
}
|
|
|
|
|
|
|
|
@if defined(VERSION_6T2)
|
|
|
|
:bfc^COND Rd,lsbImm,bitWidth is $(AMODE) & COND & c2127=0x3e & msbImm & Rd & lsbImm & bitWidth & c0006=0x1f {
|
|
build COND;
|
|
build lsbImm;
|
|
build msbImm;
|
|
build bitWidth;
|
|
clearMask:4 = (-1 << (msbImm + 1)) | (-1 >> (32 - lsbImm));
|
|
Rd = Rd & clearMask;
|
|
}
|
|
|
|
:bfi^COND Rd,Rm,lsbImm,bitWidth is $(AMODE) & COND & c2127=0x3e & msbImm & Rd & Rm & lsbImm & bitWidth & c0406=1 {
|
|
build COND;
|
|
build lsbImm;
|
|
build msbImm;
|
|
build bitWidth;
|
|
clearMask:4 = (-1 << (msbImm + 1)) | (-1 >> (32 - lsbImm));
|
|
bits:4 = (Rm << lsbImm) & ~clearMask;
|
|
Rd = (Rd & clearMask) | bits;
|
|
}
|
|
|
|
@endif # VERSION_6T2
|
|
|
|
:bic^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=14 & SBIT_CZNO & rn & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
Rd = rn&(~shift1);
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:bic^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=14 & SBIT_CZNO & rn & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
Rd = rn&(~shift2);
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:bic^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=14 & SBIT_CZNO & rn & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
Rd = rn&(~shift3);
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:bic^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=14 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
dest:4 = rn&(~shift1);
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:bic^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=14 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
dest:4 = rn&(~shift2);
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:bic^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=14 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
dest:4 = rn&(~shift3);
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
# bl used as a PIC instruction to get at current PC in lr
|
|
:bl Addr24 is $(AMODE) & cond=14 & c2527=5 & L24=1 & immed24=0xffffff & Addr24
|
|
{
|
|
lr = inst_next;
|
|
goto Addr24;
|
|
}
|
|
|
|
:bl Addr24 is $(AMODE) & cond=14 & c2527=5 & L24=1 & Addr24
|
|
{
|
|
lr = inst_next;
|
|
call Addr24;
|
|
}
|
|
|
|
:bl^COND Addr24 is $(AMODE) & CALLoverride=0 & COND & c2527=5 & L24=1 & Addr24
|
|
{
|
|
build COND;
|
|
build Addr24;
|
|
lr = inst_next;
|
|
call Addr24;
|
|
}
|
|
|
|
:bl^COND Addr24 is $(AMODE) & CALLoverride=1 & COND & c2527=5 & L24=1 & Addr24
|
|
{
|
|
build COND;
|
|
build Addr24;
|
|
lr = inst_next;
|
|
goto Addr24;
|
|
}
|
|
|
|
# blx(1) instruction
|
|
@if defined(T_VARIANT) && defined(VERSION_5)
|
|
|
|
# Two forms of blx needed to distinguish from b
|
|
:blx HAddr24 is $(AMODE) & CALLoverride=0 & cond=15 & c2527=5 & H24=0 & HAddr24
|
|
{
|
|
lr = inst_next;
|
|
SetThumbMode(1);
|
|
call HAddr24;
|
|
# don't do causes decompiler trouble TB = 0;
|
|
} # Always changes to THUMB mode
|
|
|
|
:blx HAddr24 is $(AMODE) & CALLoverride=1 & cond=15 & c2527=5 & H24=0 & HAddr24
|
|
{
|
|
lr = inst_next;
|
|
SetThumbMode(1);
|
|
goto HAddr24;
|
|
} # Always changes to THUMB mode
|
|
|
|
|
|
:blx HAddr24 is $(AMODE) & CALLoverride=0 & cond=15 & c2527=5 & H24=1 & HAddr24
|
|
{
|
|
lr = inst_next;
|
|
SetThumbMode(1);
|
|
call HAddr24;
|
|
# don't do causes decompiler trouble TB = 0;
|
|
} # Always changes to THUMB mode
|
|
|
|
:blx HAddr24 is $(AMODE) & CALLoverride=1 & cond=15 & c2527=5 & H24=1 & HAddr24
|
|
{
|
|
lr = inst_next;
|
|
SetThumbMode(1);
|
|
goto HAddr24;
|
|
} # Always changes to THUMB mode
|
|
|
|
@endif # T_VARIANT && VERSION_5
|
|
|
|
@if defined(VERSION_5)
|
|
|
|
:blx^COND rm is $(AMODE) & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=3 & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
BXWritePC(rm);
|
|
lr=inst_next;
|
|
call [pc];
|
|
# don't do causes decompiler trouble TB = 0;
|
|
} # Optional THUMB
|
|
|
|
:blx^COND rm is $(AMODE) & CALLoverride=1 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=3 & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
BXWritePC(rm);
|
|
lr=inst_next;
|
|
goto [pc];
|
|
} # Optional THUMB
|
|
|
|
@endif # VERSION_5
|
|
|
|
@if defined(VERSION_5_or_T)
|
|
|
|
# if branching using lr, assume return
|
|
:bx^COND rm is $(AMODE) & REToverride=0 & LRset=0 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & rm & Rm=14
|
|
{
|
|
build COND;
|
|
build rm;
|
|
BXWritePC(rm);
|
|
return [pc];
|
|
} # Optional change to THUMB
|
|
|
|
:bx^COND rm is $(AMODE) & REToverride=0 & LRset=0 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & rm & Rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
BXWritePC(rm);
|
|
goto [pc];
|
|
} # Optional change to THUMB
|
|
|
|
# if lr has just been set, assume call
|
|
:bx^COND rm is $(AMODE) & REToverride=0 & LRset=1 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & rm & Rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
BXWritePC(rm);
|
|
call [pc];
|
|
} # Optional change to THUMB
|
|
|
|
:bx^COND rm is $(AMODE) & REToverride=1 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
BXWritePC(rm);
|
|
goto [pc];
|
|
} # Optional change to THUMB
|
|
|
|
#:bx^COND lr is $(AMODE) & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & Rm=14 & lr
|
|
#{
|
|
# build COND;
|
|
# TB=(lr&0x00000001)!=0;
|
|
# tmp = lr & 0xfffffffe;
|
|
# return [tmp];
|
|
#} # Optional change to THUMB
|
|
|
|
@endif # VERSION_5_or_T
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
# bxj behaves like bx except that Jazelle state is enabled if available (added with Version-5 J-variant)
|
|
|
|
:bxj^COND rm is $(AMODE) & REToverride=0 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=2 & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
success:1 = jazelle_branch();
|
|
if (success) goto <skipBx>;
|
|
BXWritePC(rm);
|
|
return [pc];
|
|
<skipBx>
|
|
} # Optional change to THUMB
|
|
|
|
# if branching using "ip" then is a goto
|
|
:bxj^COND rm is $(AMODE) & REToverride=0 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=2 & rm & Rm=12
|
|
{
|
|
build COND;
|
|
build rm;
|
|
success:1 = jazelle_branch();
|
|
if (success) goto <skipBx>;
|
|
BXWritePC(rm);
|
|
goto [pc];
|
|
<skipBx>
|
|
} # Optional change to THUMB
|
|
|
|
:bxj^COND rm is $(AMODE) & REToverride=1 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=2 & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
success:1 = jazelle_branch();
|
|
if (success) goto <skipBx>;
|
|
BXWritePC(rm);
|
|
goto [pc];
|
|
<skipBx>
|
|
} # Optional change to THUMB
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_5)
|
|
|
|
:cdp2 cpn,opcode1,CRd,CRn,CRm,opcode2 is $(AMODE) & cond=15 & c2427=14 & opcode1 & CRn & CRd & cpn & opcode2 & c0404=0 & CRm
|
|
{
|
|
t_cpn:4 = cpn;
|
|
t_op1:4 = opcode1;
|
|
t_op2:4 = opcode2;
|
|
coprocessor_function2(t_cpn,t_op1,t_op2,CRd,CRn,CRm);
|
|
}
|
|
|
|
@endif # VERSION_5
|
|
|
|
:cdp^COND cpn,opcode1,CRd,CRn,CRm,opcode2 is $(AMODE) & COND & c2427=14 & opcode1 & CRn & CRd & cpn & opcode2 & c0404=0 & CRm
|
|
{
|
|
build COND;
|
|
t_cpn:4 = cpn;
|
|
t_op1:4 = opcode1;
|
|
t_op2:4 = opcode2;
|
|
coprocessor_function(t_cpn,t_op1,t_op2,CRd,CRn,CRm);
|
|
}
|
|
|
|
@if defined(VERSION_6K) || defined(VERSION_7)
|
|
|
|
:clrex is $(AMODE) & c0031=0xf57ff01f {
|
|
ClearExclusiveLocal();
|
|
}
|
|
|
|
@endif # VERSION_6K
|
|
|
|
@if defined(VERSION_5)
|
|
|
|
:clz^COND Rd,rm is $(AMODE) & COND & c2027=22 & c1619=15 & Rd & c0811=15 & c0407=1 & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
Rd = count_leading_zeroes(rm);
|
|
}
|
|
|
|
@endif # VERSION_5
|
|
|
|
:cmn^COND rn,shift1 is $(AMODE) & COND & c2024=23 & rn & c1215=0 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
addflags(rn,shift1);
|
|
local tmp = rn + shift1;
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:cmn^COND rn,shift2 is $(AMODE) & COND & c2024=23 & rn & c1215=0 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
addflags(rn,shift2);
|
|
local tmp = rn + shift2;
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:cmn^COND rn,shift3 is $(AMODE) & COND & c2024=23 & rn & c1215=0 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
addflags(rn,shift3);
|
|
local tmp = rn + shift3;
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:cmp^COND rn,shift1 is $(AMODE) & COND & c2024=21 & rn & c1215=0 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
subflags(rn,shift1);
|
|
local tmp = rn - shift1;
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:cmp^COND rn,shift2 is $(AMODE) & COND & c2024=21 & rn & c1215=0 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
subflags(rn,shift2);
|
|
local tmp = rn - shift2;
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:cmp^COND rn,shift3 is $(AMODE) & COND & c2024=21 & rn & c1215=0 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
subflags(rn,shift3);
|
|
local tmp = rn - shift3;
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
# cpy is a pre-UAL synonym for mov
|
|
:cpy^COND pc,rm is $(AMODE) & COND & pc & c2027=0x1a & c1619=0 & c0411=0 & Rd=15 & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
BXWritePC(rm);
|
|
goto [pc];
|
|
}
|
|
|
|
:cpy^COND lr,rm is $(AMODE) & COND & c2027=0x1a & c1619=0 & c0411=0 & Rd=14 & lr & rm & Rm2=15
|
|
[ LRset=1; globalset(inst_next,LRset); ]
|
|
{
|
|
build COND;
|
|
lr = rm;
|
|
}
|
|
|
|
:cpy^COND Rd,rm is $(AMODE) & COND & c2027=0x1a & c1619=0 & c0411=0 & Rd & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
Rd = rm;
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_6K) || defined(VERSION_6T2)
|
|
|
|
:dbg^COND optionImm is $(AMODE) & COND & c0427=0x320f0f & optionImm {
|
|
@if defined(VERSION_7)
|
|
build COND;
|
|
build optionImm;
|
|
HintDebug(optionImm);
|
|
@endif # VERSION_7
|
|
}
|
|
|
|
@endif # VERSION_6K || VERSION_6T2
|
|
|
|
@if defined(VERSION_7)
|
|
|
|
|
|
|
|
:dmb dbOption is $(AMODE) & c0431=0xf57ff05 & dbOption {
|
|
DataMemoryBarrier(dbOption:1);
|
|
}
|
|
|
|
:dsb dbOption is $(AMODE) & c0431=0xf57ff04 & dbOption {
|
|
DataSynchronizationBarrier(dbOption:1);
|
|
}
|
|
|
|
@endif # VERSION_7
|
|
|
|
:eor^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=1 & SBIT_CZNO & rn & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
Rd = rn^shift1;
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:eor^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=1 & SBIT_CZNO & rn & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
Rd = rn^shift2;
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:eor^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=1 & SBIT_CZNO & rn & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
Rd = rn^shift3;
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:eor^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=1 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
dest:4 = rn^shift1;
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:eor^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=1 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
dest:4 = rn^shift2;
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:eor^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=1 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
dest:4 = rn^shift3;
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
@if defined(VERSION_7)
|
|
|
|
|
|
:isb ibOption is $(AMODE) & c0431=0xf57ff06 & ibOption {
|
|
InstructionSynchronizationBarrier(ibOption:1);
|
|
}
|
|
|
|
@endif # VERSION_7
|
|
|
|
### These must come first, because of cond=15 match
|
|
@if defined(VERSION_5)
|
|
|
|
:ldc2 cpn,CRd,addrmode5 is $(AMODE) & cond=15 & c2527=6 & addrmode5 & cpn & CRd & N22=0 & L20=1
|
|
{
|
|
t_cpn:4 = cpn;
|
|
coprocessor_load2(t_cpn,CRd,addrmode5);
|
|
}
|
|
|
|
:ldc2l cpn,CRd,addrmode5 is $(AMODE) & cond=15 & c2527=6 & addrmode5 & cpn & CRd & N22=1 & L20=1
|
|
{
|
|
t_cpn:4 = cpn;
|
|
coprocessor_loadlong2(t_cpn,CRd,addrmode5);
|
|
}
|
|
|
|
@endif # VERSION_5
|
|
######## cond=15 match
|
|
|
|
:ldc^COND cpn,CRd,addrmode5 is $(AMODE) & COND & c2527=6 & addrmode5 & cpn & CRd & N22=0 & L20=1
|
|
{
|
|
build COND;
|
|
build addrmode5;
|
|
t_cpn:4 = cpn;
|
|
coprocessor_load(t_cpn,CRd,addrmode5);
|
|
}
|
|
|
|
:ldcl^COND cpn,CRd,addrmode5 is $(AMODE) & COND & c2527=6 & addrmode5 & cpn & CRd & N22=1 & L20=1
|
|
{
|
|
build COND;
|
|
build addrmode5;
|
|
t_cpn:4 = cpn;
|
|
coprocessor_loadlong(t_cpn,CRd,addrmode5);
|
|
}
|
|
|
|
:ldm^mdir^COND reglist is $(AMODE) & COND & c2527=4 & mdir & L20=1 & c1515=0 & reglist
|
|
{
|
|
build COND;
|
|
build reglist;
|
|
}
|
|
|
|
:ldm^mdir^COND reglist is $(AMODE) & COND & c2527=4 & mdir & L20=1 & c1515=1 & reglist
|
|
{
|
|
build COND;
|
|
build reglist;
|
|
LoadWritePC(pc);
|
|
return [pc];
|
|
}
|
|
|
|
#:ldr^COND Rd,addrmode2 is $(AMODE) & COND & B22=0 & L20=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
#{
|
|
# build COND;
|
|
# build addrmode2;
|
|
# tmp:4=addrmode2&0xfffffffc;
|
|
# tmp2:4=(addrmode2&3)<<3;
|
|
# Rd=*tmp;
|
|
# Rd = (Rd >> tmp2) | (Rd << (32-tmp2));
|
|
#}
|
|
|
|
# The following form of ldr assumes alignment checking is on
|
|
:ldr^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
Rd = *addrmode2;
|
|
}
|
|
|
|
# Two forms of ldr with destination=pc needed to distinguish from ldrt
|
|
:ldr^COND pc,addrmode2 is $(AMODE) & pc & COND & LRset=1 & c2627=1 & B22=0 & L20=1 & Rd=15 & P24=1 & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
[ LRset=0; globalset(inst_next,LRset); ]
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
dest:4=*addrmode2;
|
|
SetThumbMode((dest&0x00000001)!=0);
|
|
pc=dest&0xfffffffe;
|
|
call [pc];
|
|
SetThumbMode(0);
|
|
} # No unaligned address
|
|
|
|
:ldr^COND pc,addrmode2 is $(AMODE) & pc & COND & LRset=1 & c2627=1 & B22=0 & L20=1 & Rd=15 & P24=0 & W21=0 & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
[ LRset=0; globalset(inst_next,LRset); ]
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
dest:4=*addrmode2;
|
|
SetThumbMode((dest&0x00000001)!=0);
|
|
pc=dest&0xfffffffe;
|
|
call [pc];
|
|
SetThumbMode(0);
|
|
} # No unaligned address
|
|
|
|
# Two forms of ldr with destination=pc needed to distinguish from ldrt
|
|
:ldr^COND pc,addrmode2 is $(AMODE) & pc & COND & c2627=1 & B22=0 & L20=1 & Rd=15 & P24=1 & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
dest:4=*addrmode2;
|
|
BXWritePC(dest);
|
|
goto [pc];
|
|
} # No unaligned address
|
|
|
|
:ldr^COND pc,addrmode2 is $(AMODE) & pc & COND & c2627=1 & B22=0 & L20=1 & Rd=15 & P24=0 & W21=0 & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
dest:4=*addrmode2;
|
|
BXWritePC(dest);
|
|
goto [pc];
|
|
} # No unaligned address
|
|
|
|
:ldrb^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=1 & L20=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
Rd = zext( *:1 addrmode2);
|
|
}
|
|
|
|
:ldrbt^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=1 & L20=1 & P24=0 & W21=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
Rd = zext( *:1 addrmode2);
|
|
}
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:ldrd^COND Rd,Rd2,addrmode3 is $(AMODE) & COND & c2527=0 & c0407=13 & c1212=0 & L20=0 & Rd & Rd2 & addrmode3
|
|
{
|
|
build COND;
|
|
build addrmode3;
|
|
Rd = *(addrmode3);
|
|
Rd2 = *(addrmode3+4);
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:ldrex^COND Rd,[Rn] is $(AMODE) & COND & c2027=0x19 & Rn & Rd & c0011=0xf9f
|
|
{
|
|
build COND;
|
|
Rd = *Rn;
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_6K)
|
|
|
|
:ldrexb^COND Rd,[Rn] is $(AMODE) & COND & c2027=0x1d & Rn & Rd & c0011=0xf9f
|
|
{
|
|
build COND;
|
|
Rd = zext(*:1 Rn);
|
|
}
|
|
|
|
:ldrexd^COND Rd,Rd2,[Rn] is $(AMODE) & COND & c2027=0x1b & Rn & Rd & Rd2 & c0011=0xf9f
|
|
{
|
|
build COND;
|
|
Rd = *(Rn);
|
|
Rd2 = *(Rn + 4);
|
|
}
|
|
|
|
:ldrexh^COND Rd,[Rn] is $(AMODE) & COND & c2027=0x1f & Rn & Rd & c0011=0xf9f
|
|
{
|
|
build COND;
|
|
Rd = zext(*:2 Rn);
|
|
}
|
|
|
|
@endif # VERSION_6K
|
|
|
|
:ldrh^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & L20=1 & c0407=11 & Rd & addrmode3
|
|
{
|
|
build COND;
|
|
build addrmode3;
|
|
Rd = zext( *:2 addrmode3);
|
|
}
|
|
|
|
@if defined(VERSION_6T2)
|
|
|
|
:ldrht^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & P24=0 & W21=1 & L20=1 & c0407=11 & Rd & addrmode3 {
|
|
build COND;
|
|
build addrmode3;
|
|
Rd = zext( *:2 addrmode3);
|
|
}
|
|
|
|
@endif # VERSION_6T2
|
|
|
|
:ldrsb^COND^"sb" Rd,addrmode3 is $(AMODE) & COND & c2527=0 & L20=1 & c0407=13 & Rd & addrmode3
|
|
{
|
|
build COND;
|
|
build addrmode3;
|
|
Rd = sext( *:1 addrmode3);
|
|
}
|
|
|
|
@if defined(VERSION_6T2)
|
|
|
|
:ldrsbt^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & P24=0 & W21=1 & L20=1 & c0407=13 & Rd & addrmode3 {
|
|
build COND;
|
|
build addrmode3;
|
|
Rd = sext( *:1 addrmode3);
|
|
}
|
|
|
|
@endif # VERSION_6T2
|
|
|
|
:ldrsh^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & L20=1 & c0407=15 & Rd & addrmode3
|
|
{
|
|
build COND;
|
|
build addrmode3;
|
|
Rd = sext( *:2 addrmode3);
|
|
}
|
|
|
|
@if defined(VERSION_6T2)
|
|
|
|
:ldrsht^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & P24=0 & W21=1 & L20=1 & c0407=15 & Rd & addrmode3 {
|
|
build COND;
|
|
build addrmode3;
|
|
Rd = sext( *:2 addrmode3);
|
|
}
|
|
|
|
@endif # VERSION_6T2
|
|
|
|
# The following form of ldr assumes alignment checking is on
|
|
:ldrt^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=1 & P24=0 & W21=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
Rd = *addrmode2;
|
|
}
|
|
|
|
|
|
###### must come first cond=15
|
|
@if defined(VERSION_5)
|
|
:mcr2 cpn,opc1,Rd,CRn,CRm,opc2 is $(AMODE) & cond=15 & c2427=14 & opc1 & c2020=0 & CRn & Rd & cpn & opc2 & c0404=1 & CRm
|
|
{
|
|
t_cpn:4 = cpn;
|
|
t_op1:4 = opc1;
|
|
t_op2:4 = opc2;
|
|
coprocessor_moveto(t_cpn,t_op1,t_op2,Rd,CRn,CRm);
|
|
}
|
|
@endif # VERSION_5
|
|
###### must come first cond=15
|
|
|
|
|
|
# ===== START mcr
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Main_ID(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Cache_Type(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_TCM_Status(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=3 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_TLB_Type(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Control(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=1 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Auxilary_Control(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=2 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Coprocessor_Access_Control(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=2 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Translation_table_base_0(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=2 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Translation_table_base_1(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=2 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Translation_table_control(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=3 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Domain_Access_Control(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=5 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Data_Fault_Status(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=5 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Instruction_Fault(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=6 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Fault_Address(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=6 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Instruction_Fault(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Wait_for_interrupt(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=5 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Invalidate_Entire_Instruction(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=5 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Invalidate_Instruction_Cache_by_MVA(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=5 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Flush_Prefetch_Buffer(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=6 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Invalidate_Entire_Data_cache(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=6 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Invalidate_Entire_Data_by_MVA(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=6 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Invalidate_Entire_Data_by_Index(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Clean_Entire_Data_Cache(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Clean_Data_Cache_by_MVA(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Clean_Data_Cache_by_Index(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Data_Synchronization(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2=5 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Data_Memory_Barrier(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=14 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Invalidate_Entire_Data_Cache(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=14 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Invalidate_Data_Cache_by_MVA(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=7 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=8 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Invalidate_unified_TLB_unlocked(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=7 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=8 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Invalidate_unified_TLB_by_MVA(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=7 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=8 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Invalidate_unified_TLB_by_ASID_match(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=13 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_FCSE_PID(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=13 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Context_ID(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=13 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_User_RW_Thread_and_Process_ID(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=3 & cpn=15 & Rd & CRn=13 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_User_R_Thread_and_Process_ID(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=13 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Privileged_only_Thread_and_Process_ID(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=2 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=15 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
coproc_moveto_Peripherial_Port_Memory_Remap(Rd);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=1 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opt2:4=opc2;
|
|
coproc_moveto_Feature_Identification(Rd,t_opt2);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=2 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opt2:4=opc2;
|
|
coproc_moveto_ISA_Feature_Identification(Rd,t_opt2);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=4 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=2 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
coproc_moveto_Peripheral_Port_Memory_Remap(Rd,t_opc2);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
coproc_moveto_Control_registers(Rd, t_opc2);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=1 & c0404=1 & opc2 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
coproc_moveto_Security_world_control(Rd, t_opc2);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2 & cpn=15 & Rd & CRn=2 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
coproc_moveto_Translation_table(Rd,t_opc2);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=5 & c0404=1 & opc2 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
coproc_moveto_Instruction_cache(Rd,t_opc2);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
coproc_moveto_Data_cache_operations(Rd,t_opc2);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2; t_crm:4 = CRm;
|
|
coproc_moveto_Identification_registers(Rd,t_opc2,t_crm);
|
|
}
|
|
|
|
|
|
:mcr^COND mcrOperands is
|
|
$(AMODE) & CRm & c0404=1 & opc2 & cpn=15 & Rd & CRn=15 & c2020=0 & opc1 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2; t_crm:4 = CRm; t_op1:4 = opc1;
|
|
coproc_moveto_Peripheral_System(Rd,t_opc2,t_crm,t_op1);
|
|
}
|
|
|
|
|
|
# ===== END mcr
|
|
|
|
:mcr^COND cpn,opc1,Rd,CRn,CRm,opc2 is $(AMODE) & COND & c2427=14 & opc1 & c2020=0 & CRn & Rd & cpn & opc2 & c0404=1 & CRm
|
|
{
|
|
build COND;
|
|
t_cpn:4 = cpn;
|
|
t_op1:4 = opc1;
|
|
t_op2:4 = opc2;
|
|
coprocessor_moveto(t_cpn,t_op1,t_op2,Rd,CRn,CRm);
|
|
}
|
|
|
|
##### must come first cond=15
|
|
@if defined(VERSION_6)
|
|
:mcrr2 cpn,opcode3,Rd,Rn,CRm is $(AMODE) & cond=15 & c2027=0xc4 & cpn & opcode3 & Rd & Rn & CRm
|
|
{
|
|
t_cpn:4 = cpn;
|
|
t_op:4 = opcode3;
|
|
coprocessor_moveto2(t_cpn,t_op,Rd,Rn,CRm);
|
|
}
|
|
|
|
:mrrc2 cpn,opcode3,Rd,Rn,CRm is $(AMODE) & cond=15 & c2027=0xc5 & cpn & opcode3 & Rd & Rn & CRm
|
|
{
|
|
t_cpn:4 = cpn;
|
|
t_op:4 = opcode3;
|
|
Rd = coprocessor_movefromRt(t_cpn,t_op,CRm);
|
|
Rn = coprocessor_movefromRt2(t_cpn,t_op,CRm);
|
|
}
|
|
@endif # VERSION_6
|
|
##### must come first cond=15
|
|
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:mcrr^COND cpn,opcode3,Rd,Rn,CRm is $(AMODE) & c2027=0xc4 & COND & cpn & opcode3 & Rd & Rn & CRm
|
|
{
|
|
build COND;
|
|
t_cpn:4 = cpn;
|
|
t_op:4 = opcode3;
|
|
coprocessor_moveto2(t_cpn,t_op,Rd,Rn,CRm);
|
|
}
|
|
|
|
:mrrc^COND cpn,opcode3,Rd,Rn,CRm is $(AMODE) & c2027=0xc5 & COND & cpn & opcode3 & Rd & Rn & CRm
|
|
{
|
|
build COND;
|
|
t_cpn:4 = cpn;
|
|
t_op:4 = opcode3;
|
|
Rd = coprocessor_movefromRt(t_cpn,t_op,CRm);
|
|
Rn = coprocessor_movefromRt2(t_cpn,t_op,CRm);
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
:mla^COND^SBIT_ZN Rn,Rm,Rs,Rd is $(AMODE) & COND & c2527=0 & c2124=1 & SBIT_ZN & Rn & Rd & Rs & c0407=9 & Rm
|
|
{
|
|
build COND;
|
|
Rn = Rm*Rs + Rd;
|
|
resultflags(Rn);
|
|
build SBIT_ZN;
|
|
}
|
|
|
|
@if defined(VERSION_6T2)
|
|
|
|
:mls^COND Rn,Rm,Rs,Rd is $(AMODE) & COND & c2027=0x06 & Rn & Rd & Rs & c0407=9 & Rm {
|
|
build COND;
|
|
Rn = Rd - Rm*Rs;
|
|
}
|
|
|
|
@endif # VERSION_6T2
|
|
|
|
:mov^COND^SBIT_CZNO Rd,shift1 is $(AMODE) & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build shift1;
|
|
Rd = shift1;
|
|
resultflags(Rd);
|
|
logicflags();
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:mov^COND^SBIT_CZNO Rd,shift2 is $(AMODE) & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build shift2;
|
|
Rd = shift2;
|
|
resultflags(Rd);
|
|
logicflags();
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:mov lr,pc is $(AMODE) & c0031=0xe1a0e00f & lr & pc
|
|
[ LRset=1; globalset(inst_next,LRset); ]
|
|
{
|
|
lr = inst_next + 4;
|
|
resultflags(lr);
|
|
logicflags();
|
|
}
|
|
|
|
:mov^COND^SBIT_CZNO Rd,shift3 is $(AMODE) & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build shift3;
|
|
Rd = shift3;
|
|
resultflags(Rd);
|
|
logicflags();
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:mov^COND^SBIT_CZNO pc,shift1 is $(AMODE) & pc & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build shift1;
|
|
SetThumbMode((shift1&0x00000001)!=0);
|
|
local tmp=shift1&0xfffffffe;
|
|
resultflags(tmp);
|
|
logicflags();
|
|
build SBIT_CZNO;
|
|
ALUWritePC(tmp);
|
|
goto [pc];
|
|
}
|
|
|
|
:mov^COND^SBIT_CZNO pc,shift2 is $(AMODE) & pc & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build shift2;
|
|
SetThumbMode((shift2&0x00000001)!=0);
|
|
local tmp=shift2&0xfffffffe;
|
|
resultflags(tmp);
|
|
logicflags();
|
|
build SBIT_CZNO;
|
|
ALUWritePC(tmp);
|
|
goto [pc];
|
|
}
|
|
:mov^COND^SBIT_CZNO pc,shift2 is $(AMODE) & LRset=1 & pc & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build shift2;
|
|
SetThumbMode((shift2&0x00000001)!=0);
|
|
local tmp=shift2&0xfffffffe;
|
|
resultflags(tmp);
|
|
logicflags();
|
|
build SBIT_CZNO;
|
|
ALUWritePC(tmp);
|
|
call [pc];
|
|
}
|
|
|
|
:mov^COND^SBIT_CZNO pc,shift3 is $(AMODE) & pc & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build shift3;
|
|
SetThumbMode((shift3&0x00000001)!=0);
|
|
local tmp=shift3&0xfffffffe;
|
|
resultflags(tmp);
|
|
logicflags();
|
|
build SBIT_CZNO;
|
|
ALUWritePC(tmp);
|
|
goto [pc];
|
|
}
|
|
|
|
:mov lr,rm is $(AMODE) & cond=15 & c2527=0 & S20=0 & c2124=13 & c1619=0 & rm & Rm2=15 & sftimm=0 & c0406=0 & Rd=14 & lr
|
|
[ LRset=1; globalset(inst_next,LRset); ]
|
|
{
|
|
lr = rm;
|
|
}
|
|
|
|
:mov^COND pc,lr is $(AMODE) & pc & COND & c2527=0 & S20=0 & c2124=13 & c1619=0 & Rd=15 & sftimm=0 & c0406=0 & Rm=14 & lr
|
|
{
|
|
build COND;
|
|
dest:4 = lr;
|
|
ALUWritePC(dest);
|
|
return [pc];
|
|
}
|
|
|
|
@if defined(VERSION_6T2)
|
|
|
|
:movw^COND Rd,"#"^val is $(AMODE) & COND & c2027=0x30 & c1619 & Rd & c0011 [ val = (c1619 << 12) | c0011; ] {
|
|
build COND;
|
|
Rd = val;
|
|
}
|
|
|
|
:movt^COND Rd,"#"^val is $(AMODE) & COND & c2027=0x34 & c1619 & Rd & c0011 [ val = (c1619 << 12) | c0011; ] {
|
|
build COND;
|
|
Rd = (val << 16) | (Rd & 0xffff);
|
|
}
|
|
|
|
@endif # VERSION_6T2
|
|
|
|
###### must come before next instruction because cond=15
|
|
@if defined(VERSION_5)
|
|
|
|
|
|
:mrc2 cpn,opc1,Rd,CRn,CRm,opc2 is $(AMODE) & cond=15 & c2427=14 & opc1 & c2020=1 & CRn & Rd & cpn & opc2 & c0404=1 & CRm
|
|
{
|
|
t_cpn:4 = cpn;
|
|
t_op1:4 = opc1;
|
|
t_op2:4 = opc2;
|
|
Rd = coprocessor_movefromRt(t_cpn,t_op1,t_op2,CRn,CRm);
|
|
}
|
|
@endif # VERSION_5
|
|
|
|
# ===== Start mrc
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Main_ID();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Cache_Type();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_TCM_Status();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=3 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_TLB_Type();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Control();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=1 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Auxilary_Control();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=2 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Coprocessor_Access_Control();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=2 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Translation_table_base_0();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=2 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Translation_table_base_1();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=2 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Translation_table_control();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=3 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Domain_Access_Control();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=5 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Instruction_Fault_Status();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=5 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Data_Fault_Status();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=6 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Fault_Address();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=6 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Instruction_Fault_Address();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Wait_for_interrupt();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=5 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Invalidate_Entire_Instruction();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=5 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Invalidate_Instruction_Cache_by_MVA();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=5 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Flush_Prefetch_Buffer();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=6 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Invalidate_Entire_Data_cache();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=6 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Invalidate_Entire_Data_by_MVA();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=6 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Invalidate_Entire_Data_by_Index();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Clean_Entire_Data_Cache();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Clean_Data_Cache_by_MVA();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Clean_Data_Cache_by_Index();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Data_Synchronization();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2=5 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Data_Memory_Barrier();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=14 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Invalidate_Entire_Data_Cache();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=14 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Invalidate_Data_Cache_by_MVA();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=7 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=8 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Invalidate_unified_TLB_unlocked();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=7 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=8 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Invalidate_unified_TLB_by_MVA();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=7 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=8 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Invalidate_unified_TLB_by_ASID_match();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=13 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_FCSE_PID();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=13 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Context_ID();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=13 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_User_RW_Thread_and_Process_ID();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=3 & cpn=15 & Rd & CRn=13 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_User_R_Thread_and_Process_ID();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=13 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Privileged_only_Thread_and_Process_ID();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=2 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=15 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
Rd = coproc_movefrom_Peripherial_Port_Memory_Remap();
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=1 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opt2:4=opc2;
|
|
Rd = coproc_movefrom_Feature_Identification(t_opt2);
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=2 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
Rd = coproc_movefrom_ISA_Feature_Identification(t_opc2);
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=4 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=2 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
Rd = coproc_movefrom_Peripheral_Port_Memory_Remap(t_opc2);
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
Rd = coproc_movefrom_Control_registers(t_opc2);
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=1 & c0404=1 & opc2 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
Rd = coproc_movefrom_Security_world_control(t_opc2);
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=0 & c0404=1 & opc2 & cpn=15 & Rd & CRn=2 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
Rd = coproc_movefrom_Translation_table(t_opc2);
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=5 & c0404=1 & opc2 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
Rd = coproc_movefrom_Instruction_cache(t_opc2);
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm=10 & c0404=1 & opc2 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2;
|
|
Rd = coproc_movefrom_Data_cache_operations(t_opc2);
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2; t_crm:4 = CRm;
|
|
Rd = coproc_movefrom_Identification_registers(t_opc2,t_crm);
|
|
}
|
|
|
|
|
|
|
|
:mrc^COND mcrOperands is
|
|
$(AMODE) & CRm & c0404=1 & opc2 & cpn=15 & Rd & CRn=15 & c2020=1 & opc1 & c2427=14 & COND &
|
|
mcrOperands
|
|
{
|
|
build COND;
|
|
t_opc2:4 = opc2; t_crm:4 = CRm; t_op1:4 = opc1;
|
|
Rd = coproc_movefrom_Peripheral_System(t_opc2,t_crm,t_op1);
|
|
}
|
|
|
|
|
|
|
|
# ===== End mrc
|
|
|
|
:mrc^COND cpn,opc1,Rd,CRn,CRm,opc2 is $(AMODE) & COND & c2427=14 & opc1 & c2020=1 & CRn & Rd & cpn & opc2 & c0404=1 & CRm
|
|
{
|
|
build COND;
|
|
t_cpn:4 = cpn;
|
|
t_op1:4 = opc1;
|
|
t_opc2:4 = opc2;
|
|
Rd = coprocessor_movefromRt(t_cpn,t_op1,t_opc2,CRn,CRm);
|
|
}
|
|
|
|
|
|
:mrs^COND Rd,cpsr is $(AMODE) & COND & c2027=16 & c1619=15 & Rd & offset_12=0 & cpsr
|
|
{
|
|
# TODO: GE bits have not been included
|
|
build COND;
|
|
Rd = zext( (NG<<4) | (ZR<<3) | (CY<<2) | (OV<<1) | (Q) ) << 27;
|
|
}
|
|
|
|
:mrs^COND Rd,spsr is $(AMODE) & COND & c2027=20 & c1619=15 & Rd & offset_12=0 & spsr
|
|
{
|
|
build COND;
|
|
Rd = spsr;
|
|
}
|
|
|
|
:msr^COND cpsrmask,shift1 is $(AMODE) & COND & c2027=50 & cpsrmask & c1215=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build cpsrmask;
|
|
build shift1;
|
|
cpsr = (cpsr& ~cpsrmask) | (shift1 & cpsrmask);
|
|
}
|
|
|
|
:msr^COND cpsrmask,rm is $(AMODE) & COND & c2027=18 & cpsrmask & c1215=15 & c0811=0 & c0407=0 & rm
|
|
{
|
|
# TODO: GE bits have not been included
|
|
build COND;
|
|
build cpsrmask;
|
|
cpsr = (cpsr& ~cpsrmask) | (rm & cpsrmask);
|
|
local tmp = cpsr >> 27 & 0x1f;
|
|
Q = ((tmp ) & 0x1) != 0;
|
|
OV = ((tmp >> 1) & 0x1) != 0;
|
|
CY = ((tmp >> 2) & 0x1) != 0;
|
|
ZR = ((tmp >> 3) & 0x1) != 0;
|
|
NG = ((tmp >> 4) & 0x1) != 0;
|
|
}
|
|
|
|
:msr^COND spsrmask,shift1 is $(AMODE) & COND & c2027=54 & spsrmask & c1215=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build spsrmask;
|
|
build shift1;
|
|
spsr = (spsr& ~spsrmask) | (shift1 & spsrmask);
|
|
}
|
|
|
|
:msr^COND spsrmask,rm is $(AMODE) & COND & c2027=22 & spsrmask & c1215=15 & c0811=0 & c0407=0 & rm
|
|
{
|
|
build COND;
|
|
build spsrmask;
|
|
spsr = (spsr& ~spsrmask) | (rm & spsrmask);
|
|
}
|
|
|
|
:mul^COND^SBIT_ZN rn,rm,rs is $(AMODE) & COND & c2527=0 & c2124=0 & SBIT_ZN & rn & c1215=0 & rs & c0407=9 & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
build rs;
|
|
rn = rm*rs;
|
|
resultflags(rn);
|
|
build SBIT_ZN;
|
|
}
|
|
|
|
:mvn^COND^SBIT_CZNO Rd,shift1 is $(AMODE) & COND & c2124=15 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build shift1;
|
|
Rd=~shift1;
|
|
resultflags(Rd);
|
|
logicflags();
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:mvn^COND^SBIT_CZNO Rd,shift2 is $(AMODE) & COND & c2124=15 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build shift2;
|
|
Rd=~shift2;
|
|
resultflags(Rd);
|
|
logicflags();
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:mvn^COND^SBIT_CZNO Rd,shift3 is $(AMODE) & COND & c2124=15 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build shift3;
|
|
Rd=~shift3;
|
|
resultflags(Rd);
|
|
logicflags();
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:mvn^COND^SBIT_ZN pc,shift1 is $(AMODE) & pc & COND & c2124=15 & SBIT_ZN & c1619=0 & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build shift1;
|
|
dest:4 = ~shift1;
|
|
resultflags(dest);
|
|
build SBIT_ZN;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:mvn^COND^SBIT_ZN pc,shift2 is $(AMODE) & pc & COND & c2124=15 & SBIT_ZN & c1619=0 & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build shift2;
|
|
dest:4 = ~shift2;
|
|
resultflags(dest);
|
|
build SBIT_ZN;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:mvn^COND^SBIT_ZN pc,shift3 is $(AMODE) & pc & COND & c2124=15 & SBIT_ZN & c1619=0 & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build shift3;
|
|
dest:4 = ~shift3;
|
|
resultflags(dest);
|
|
build SBIT_ZN;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
@if defined(VERSION_6K) || defined(VERSION_6T2) || defined(VERSION_7)
|
|
|
|
:nop^COND is $(AMODE) & COND & c0027=0x320f000 {
|
|
}
|
|
|
|
@endif # VERSION_6K
|
|
|
|
:orr^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=12 & SBIT_CZNO & rn & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
Rd = rn|shift1;
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:orr^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=12 & SBIT_CZNO & rn & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
Rd = rn|shift2;
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:orr^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=12 & SBIT_CZNO & rn & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
Rd = rn|shift3;
|
|
logicflags();
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:orr^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=12 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
dest:4 = rn|shift1;
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:orr^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=12 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
dest:4 = rn|shift2;
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:orr^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=12 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
dest:4 = rn|shift3;
|
|
logicflags();
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:pkhbt^COND Rd,rn,shift4 is $(AMODE) & COND & c2027=0x68 & c0406=1 & Rd & rn & shift4
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift4;
|
|
Rd = (rn & 0xffff) + (shift4 & 0xffff0000);
|
|
}
|
|
|
|
:pkhtb^COND Rd,rn,shift4 is $(AMODE) & COND & c2027=0x68 & c0406=5 & Rd & rn & shift4
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift4;
|
|
Rd = (shift4 & 0xffff) + (rn & 0xffff0000);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:qadd^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=0x10 & Rn & Rd & c0811=0 & c0407=5 & Rm
|
|
{
|
|
build COND;
|
|
local sum1 = Rm + Rn;
|
|
sum1 = SignedSaturate(sum1,32:2);
|
|
Q = SignedDoesSaturate(sum1,32:2);
|
|
Rd = sum1;
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:qadd16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=1 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local lRn = Rn & 0xffff;
|
|
local lRm = Rm & 0xffff;
|
|
local uRn = (Rn >> 16) & 0xffff;
|
|
local uRm = (Rm >> 16) & 0xffff;
|
|
sum1:2 = lRn:2 + lRm:2;
|
|
sum1 = SignedSaturate(sum1,16:2);
|
|
sum2:2 = uRn:2 + uRm:2;
|
|
sum2 = SignedSaturate(sum2,16:2);
|
|
Rd = (zext(sum2) << 16) | zext(sum1);
|
|
}
|
|
|
|
:qadd8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=9 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local rn1 = Rn & 0xff;
|
|
local rm1 = Rm & 0xff;
|
|
local rn2 = (Rn >> 8) & 0xff;
|
|
local rm2 = (Rm >> 8) & 0xff;
|
|
local rn3 = (Rn >> 16) & 0xff;
|
|
local rm3 = (Rm >> 16) & 0xff;
|
|
local rn4 = (Rn >> 24) & 0xff;
|
|
local rm4 = (Rm >> 24) & 0xff;
|
|
sum1:1 = rn1:1 + rm1:1;
|
|
sum1 = SignedSaturate(sum1,8:2);
|
|
sum2:1 = rn2:1 + rm2:1;
|
|
sum2 = SignedSaturate(sum2,8:2);
|
|
sum3:1 = rn3:1 + rm3:1;
|
|
sum3 = SignedSaturate(sum3,8:2);
|
|
sum4:1 = rn4:1 + rm4:1;
|
|
sum4 = SignedSaturate(sum4,8:2);
|
|
Rd = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1);
|
|
}
|
|
|
|
# qaddsubx
|
|
:qasx^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=3 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local lRn = Rn & 0xffff;
|
|
local lRm = Rm & 0xffff;
|
|
local uRn = (Rn >> 16) & 0xffff;
|
|
local uRm = (Rm >> 16) & 0xffff;
|
|
sum1:2 = lRn:2 - lRm:2;
|
|
sum1 = SignedSaturate(sum1,16:2);
|
|
sum2:2 = uRn:2 + uRm:2;
|
|
sum2 = SignedSaturate(sum2,16:2);
|
|
Rd = (zext(sum2) << 16) | zext(sum1);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:qdadd^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=0x14 & Rn & Rd & c0811=0 & c0407=5 & Rm
|
|
{
|
|
build COND;
|
|
tmp:4 = Rn * 2;
|
|
tmp = SignedSaturate(tmp,32:2);
|
|
Q = SignedDoesSaturate(tmp,32:2);
|
|
tmp = tmp + Rm;
|
|
tmp = SignedSaturate(tmp,32:2);
|
|
Q = Q | SignedDoesSaturate(tmp,32:2);
|
|
Rd = tmp;
|
|
}
|
|
|
|
:qdsub^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=0x16 & Rn & Rd & c0811=0 & c0407=5 & Rm
|
|
{
|
|
build COND;
|
|
tmp:4 = Rn * 2;
|
|
tmp = SignedSaturate(tmp);
|
|
Q = SignedDoesSaturate(tmp,32:2);
|
|
tmp = Rm - tmp;
|
|
tmp = SignedSaturate(tmp,32:2);
|
|
Q = Q | SignedDoesSaturate(tmp,32:2);
|
|
Rd = tmp;
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
# qsubaddx
|
|
:qsax^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=5 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local lRn = Rn & 0xffff;
|
|
local lRm = Rm & 0xffff;
|
|
local uRn = (Rn >> 16) & 0xffff;
|
|
local uRm = (Rm >> 16) & 0xffff;
|
|
sum1:2 = lRn:2 + lRm:2;
|
|
sum1 = SignedSaturate(sum1,16:2);
|
|
sum2:2 = uRn:2 - uRm:2;
|
|
sum2 = SignedSaturate(sum2,16:2);
|
|
Rd = (zext(sum2) << 16) | zext(sum1);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:qsub^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=0x12 & Rn & Rd & c0811=0 & c0407=5 & Rm
|
|
{
|
|
build COND;
|
|
tmp:4 = Rm - Rn;
|
|
tmp = SignedSaturate(tmp,32:2);
|
|
Q = SignedDoesSaturate(tmp,32:2);
|
|
Rd = tmp;
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:qsub16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=7 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local lRn = Rn & 0xffff;
|
|
local lRm = Rm & 0xffff;
|
|
local uRn = (Rn >> 16) & 0xffff;
|
|
local uRm = (Rm >> 16) & 0xffff;
|
|
sum1:2 = lRn:2 - lRm:2;
|
|
sum1 = SignedSaturate(sum1,16:2);
|
|
sum2:2 = uRn:2 - uRm:2;
|
|
sum2 = SignedSaturate(sum2,16:2);
|
|
Rd = (zext(sum2) << 16) | zext(sum1);
|
|
}
|
|
|
|
:qsub8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=15 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local rn1 = Rn & 0xff;
|
|
local rm1 = Rm & 0xff;
|
|
local rn2 = (Rn >> 8) & 0xff;
|
|
local rm2 = (Rm >> 8) & 0xff;
|
|
local rn3 = (Rn >> 16) & 0xff;
|
|
local rm3 = (Rm >> 16) & 0xff;
|
|
local rn4 = (Rn >> 24) & 0xff;
|
|
local rm4 = (Rm >> 24) & 0xff;
|
|
sum1:1 = rn1:1 - rm1:1;
|
|
sum1 = SignedSaturate(sum1,8:2);
|
|
sum2:1 = rn2:1 - rm2:1;
|
|
sum2 = SignedSaturate(sum2,8:2);
|
|
sum3:1 = rn3:1 - rm3:1;
|
|
sum3 = SignedSaturate(sum3,8:2);
|
|
sum4:1 = rn4:1 - rm4:1;
|
|
sum4 = SignedSaturate(sum4,8:2);
|
|
Rd = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_6T2)
|
|
|
|
macro BitReverse_arm(val) {
|
|
tval:1 = val;
|
|
result:1 = 0;
|
|
result = (result << 1) | (tval & 1);
|
|
tval = tval >> 1;
|
|
result = (result << 1) | (tval & 1);
|
|
tval = tval >> 1;
|
|
result = (result << 1) | (tval & 1);
|
|
tval = tval >> 1;
|
|
result = (result << 1) | (tval & 1);
|
|
tval = tval >> 1;
|
|
result = (result << 1) | (tval & 1);
|
|
tval = tval >> 1;
|
|
result = (result << 1) | (tval & 1);
|
|
tval = tval >> 1;
|
|
result = (result << 1) | (tval & 1);
|
|
tval = tval >> 1;
|
|
result = (result << 1) | (tval & 1);
|
|
tval = tval >> 1;
|
|
val = result;
|
|
}
|
|
|
|
|
|
:rbit^COND Rd, rm is $(AMODE) & COND & c2327=13 & c2022=7 & c0407=3 & c1619=15 & c0811=15 & Rd & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
local t:4 = rm & 0xff;
|
|
local b1:1 = t:1;
|
|
t = (rm >> 8) & 0xff;
|
|
local b2:1 = t:1;
|
|
t = (rm >> 16) & 0xff;
|
|
local b3:1 = t:1;
|
|
t = (rm >> 24) & 0xff;
|
|
local b4:1 = t:1;
|
|
BitReverse_arm(b1);
|
|
BitReverse_arm(b2);
|
|
BitReverse_arm(b3);
|
|
BitReverse_arm(b4);
|
|
Rd = (zext(b1) << 24) | (zext(b2) << 16) | (zext(b3) << 8) | zext(b4);
|
|
}
|
|
|
|
@endif # VERSION_6T2
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:rev^COND Rd, rm is $(AMODE) & COND & c2327=13 & c2022=3 & c0407=3 & c1619=15 & c0811=15 & Rd & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
local tmp1 = rm & 0xff;
|
|
local tmp2 = (rm >> 8) & 0xff;
|
|
local tmp3 = (rm >> 16) & 0xff;
|
|
local tmp4 = (rm >> 24) & 0xff;
|
|
Rd = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | tmp4;
|
|
}
|
|
|
|
:rev16^COND Rd, rm is $(AMODE) & COND & c2327=13 & c2022=3 & c0407=11 & Rd & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
local tmp1 = rm & 0xff;
|
|
local tmp2 = (rm >> 8) & 0xff;
|
|
local tmp3 = (rm >> 16) & 0xff;
|
|
local tmp4 = (rm >> 24) & 0xff;
|
|
Rd = (tmp3 << 24) | (tmp4 << 16) | (tmp1 << 8) | tmp2;
|
|
}
|
|
|
|
:revsh^COND Rd, rm is $(AMODE) & COND & c2327=13 & c2022=7 & c0407=11 & Rd & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
local tmp1 = rm & 0xff;
|
|
local tmp2 = (rm >> 8) & 0xff;
|
|
tmp3:2 = zext(tmp1:1) << 8 | zext(tmp2:1);
|
|
Rd = sext(tmp3);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
:rsb^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=3 & SBIT_CZNO & rn & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
subflags(shift1,rn);
|
|
Rd = shift1-rn;
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:rsb^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=3 & SBIT_CZNO & rn & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
subflags(shift2,rn);
|
|
Rd = shift2-rn;
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:rsb^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=3 & SBIT_CZNO & rn & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
subflags(shift3,rn);
|
|
Rd = shift3-rn;
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:rsb^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=3 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
subflags(shift1,rn);
|
|
dest:4 = shift1-rn;
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:rsb^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=3 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
subflags(shift2,rn);
|
|
dest:4 = shift2-rn;
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:rsb^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=3 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
subflags(shift3,rn);
|
|
dest:4 = shift3-rn;
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:rsc^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=7 & SBIT_CZNO & rn & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
add_with_carry_flags(~rn,shift1);
|
|
Rd=shift1-(rn+zext(!CY));
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:rsc^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=7 & SBIT_CZNO & rn & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
add_with_carry_flags(~rn,shift2);
|
|
Rd=shift2-(rn+zext(!CY));
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:rsc^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=7 & SBIT_CZNO & rn & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
add_with_carry_flags(~rn,shift3);
|
|
Rd=shift3-(rn+zext(!CY));
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:rsc^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=7 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
add_with_carry_flags(~rn,shift1);
|
|
local dest:4=shift1-(rn+zext(!CY));
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:rsc^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=7 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
add_with_carry_flags(~rn,shift2);
|
|
local dest:4=shift2-(rn + zext(!CY));
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:rsc^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=7 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
add_with_carry_flags(~rn,shift3);
|
|
local dest:4=shift3-(rn + zext(!CY));
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:sadd16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=1 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn & 0xffff;
|
|
local tmpRm = Rm & 0xffff;
|
|
local sum1 = sext(tmpRn:2) + sext(tmpRm:2);
|
|
GE1 = sum1 s>= 0;
|
|
GE2 = sum1 s>= 0;
|
|
tmpRn = (Rn >> 16) & 0xffff;
|
|
tmpRm = (Rm >> 16) & 0xffff;
|
|
local sum2 = sext(tmpRn:2) + sext(tmpRm:2);
|
|
GE3 = sum2 s>= 0;
|
|
GE4 = sum2 s>= 0;
|
|
Rd = ((sum2 & 0xffff) << 16) | (sum1 & 0xffff);
|
|
}
|
|
|
|
:sadd8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=9 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn & 0xff;
|
|
local tmpRm = Rm & 0xff;
|
|
local sum1 = sext(tmpRn:1) + sext(tmpRm:1);
|
|
GE1 = sum1 s>= 0;
|
|
tmpRn = (Rn >> 8) & 0xff;
|
|
tmpRm = (Rm >> 8) & 0xff;
|
|
local sum2 = sext(tmpRn:1) + sext(tmpRm:1);
|
|
GE2 = sum2 s>= 0;
|
|
tmpRn = (Rn >> 16) & 0xff;
|
|
tmpRm = (Rm >> 16) & 0xff;
|
|
local sum3 = sext(tmpRn:1) + sext(tmpRm:1);
|
|
GE3 = sum3 s>= 0;
|
|
tmpRn = (Rn >> 24) & 0xff;
|
|
tmpRm = (Rm >> 24) & 0xff;
|
|
local sum4 = sext(tmpRn:1) + sext(tmpRm:1);
|
|
GE4 = sum4 s>= 0;
|
|
Rd = ((sum4 & 0xff) << 24) | ((sum3 & 0xff) << 16) | ((sum2 & 0xff) << 8) | (sum1 & 0xff);
|
|
}
|
|
|
|
# saddsubx
|
|
:sasx^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=3 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local lRn = Rn & 0xffff;
|
|
local lRm = Rm & 0xffff;
|
|
local uRn = (Rn >> 16) & 0xffff;
|
|
local uRm = (Rm >> 16) & 0xffff;
|
|
local sum1 = sext(uRn:2) + sext(lRm:2);
|
|
GE3 = sum1 s>= 0;
|
|
GE4 = sum1 s>= 0;
|
|
local diff = sext(lRn:2) - sext(uRm:2);
|
|
GE1 = diff s>= 0;
|
|
GE2 = diff s>= 0;
|
|
|
|
Rd = ((sum1 & 0xffff) << 16) | (diff & 0xffff);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
:sbc^SBIT_CZNO^COND Rd,rn,shift1 is $(AMODE) & COND & c2124=6 & SBIT_CZNO & rn & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
add_with_carry_flags(rn,~shift1);
|
|
Rd = rn-(shift1+zext(!CY));
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:sbc^SBIT_CZNO^COND Rd,rn,shift2 is $(AMODE) & COND & c2124=6 & SBIT_CZNO & rn & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
add_with_carry_flags(rn,~shift2);
|
|
Rd = rn-(shift2 + zext(!CY));
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:sbc^SBIT_CZNO^COND Rd,rn,shift3 is $(AMODE) & COND & c2124=6 & SBIT_CZNO & rn & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
add_with_carry_flags(rn,~shift3);
|
|
Rd = rn-(shift3+zext(!CY));
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:sbc^SBIT_CZNO^COND pc,rn,shift1 is $(AMODE) & pc & COND & c2124=6 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
add_with_carry_flags(rn,~shift1);
|
|
local dest:4 = rn-(shift1 + zext(!CY));
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:sbc^SBIT_CZNO^COND pc,rn,shift2 is $(AMODE) & pc & COND & c2124=6 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
add_with_carry_flags(rn,~shift2);
|
|
local dest:4 = rn-(shift2+zext(!CY));
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
:sbc^SBIT_CZNO^COND pc,rn,shift3 is $(AMODE) & pc & COND & c2124=6 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
add_with_carry_flags(rn,~shift3);
|
|
local dest:4 = rn-(shift3 + zext(!CY));
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
ALUWritePC(dest);
|
|
goto [pc];
|
|
}
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
@if defined(VERSION_6T2)
|
|
|
|
:sbfx^COND Rd,Rm,lsbImm,widthMinus1 is $(AMODE) & COND & c2127=0x3d & widthMinus1 & Rd & lsbImm & c0406=5 & Rm
|
|
{
|
|
build COND;
|
|
build lsbImm;
|
|
build widthMinus1;
|
|
shift:4 = 31 - (lsbImm + widthMinus1);
|
|
Rd = Rm << shift;
|
|
shift = 31 - widthMinus1;
|
|
Rd = Rd s>> shift;
|
|
}
|
|
|
|
@endif # VERSION_6T2
|
|
|
|
@if defined(VERSION_7)
|
|
|
|
# Warning: note the non-standard use of Rd, Rm, Rn
|
|
:sdiv^COND RdHi,RnLo,RmHi is $(AMODE) & COND & c2027=0x71 & RdHi & c1215=0xf & RmHi & c0407=0x1 & RnLo
|
|
{
|
|
build COND;
|
|
local result = RnLo / RmHi;
|
|
RdHi = result;
|
|
}
|
|
|
|
@endif # VERSION_7
|
|
|
|
:sel^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x68 & Rn & Rd & c0811=15 & c0407=11 & Rm
|
|
{
|
|
build COND;
|
|
local rD1 = ((zext(GE1) * Rn) + (zext(!GE1) * Rm)) & 0x0ff;
|
|
local rD2 = ((zext(GE2) * Rn) + (zext(!GE2) * Rm)) & 0x0ff00;
|
|
local rD3 = ((zext(GE3) * Rn) + (zext(!GE3) * Rm)) & 0x0ff0000;
|
|
local rD4 = ((zext(GE4) * Rn) + (zext(!GE4) * Rm)) & 0x0ff000000;
|
|
Rd = rD1 | rD2 | rD3 | rD4;
|
|
}
|
|
|
|
@if defined(VERSION_6K)
|
|
|
|
:sev^COND is $(AMODE) & COND & c0027=0x320f004
|
|
{
|
|
build COND;
|
|
SendEvent();
|
|
}
|
|
|
|
@endif # VERSION_6K
|
|
|
|
# Hopefully we never encounter this instruction since we can not change the effective endianess of the language
|
|
armEndianNess: "LE" is c0031=0xf1010000 { export 0:1; }
|
|
armEndianNess: "BE" is c0031=0xf1010200 { export 1:1; }
|
|
|
|
:setend armEndianNess is $(AMODE) & (c0031=0xf1010000 | c0031=0xf1010200) & armEndianNess { setEndianState(armEndianNess); }
|
|
|
|
|
|
:shadd16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=1 & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
sum1:4 = (sext(tmpRn:2) + sext(tmpRm:2)) >> 1;
|
|
sum2:4 = ((tmpRn s>> 16) + (tmpRm s>> 16)) >> 1;
|
|
Rd = (sum2 << 16) + (sum1 & 0xffff);
|
|
}
|
|
|
|
:shadd8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=9 & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
sum1:4 = (sext(tmpRn:1) + sext(tmpRm:1)) >> 1;
|
|
local tmpn = tmpRn >> 8;
|
|
local tmpm = tmpRm >> 8;
|
|
sum2:4 = (sext(tmpn:1) + sext(tmpm:1)) >> 1;
|
|
tmpn = tmpRn >> 16;
|
|
tmpm = tmpRm >> 16;
|
|
sum3:4 = (sext(tmpn:1) + sext(tmpm:1)) >> 1;
|
|
tmpn = tmpRn >> 24;
|
|
tmpm = tmpRm >> 24;
|
|
sum4:4 = (sext(tmpn:1) + sext(tmpm:1)) >> 1;
|
|
Rd = (sum4 << 24) + ((sum3 & 0xff) << 16) + ((sum2 & 0xff) << 8) + (sum1 & 0xff);
|
|
}
|
|
|
|
# shaddsubx
|
|
:shasx^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=3 & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
local diff:4 = sext(tmpRn[ 0,16]) - sext(tmpRm[16,16]);
|
|
local sum:4 = sext(tmpRn[16,16]) + sext(tmpRm[ 0,16]);
|
|
Rd[0,16] = diff[1,16];
|
|
Rd[16,16] = sum[1,16];
|
|
}
|
|
|
|
# shsubbaddx
|
|
:shsax^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=5 & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
local sum:4 = sext(tmpRn[ 0,16]) + sext(tmpRm[16,16]);
|
|
local diff:4 = sext(tmpRn[16,16]) - sext(tmpRm[ 0,16]);
|
|
Rd[ 0,16] = sum[1,16];
|
|
Rd[16,16] = diff[1,16];
|
|
}
|
|
|
|
:shsub16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=7 & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
sum1:4 = (sext(tmpRn:2) - sext(tmpRm:2)) >> 1;
|
|
sum2:4 = ((tmpRn s>> 16) - (tmpRm s>> 16)) >> 1;
|
|
Rd = (sum2 << 16) + (sum1 & 0xffff);
|
|
}
|
|
|
|
:shsub8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=15 & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
sum1:4 = (sext(tmpRn:1) - sext(tmpRm:1)) >> 1;
|
|
local tmpn = tmpRn >> 8;
|
|
local tmpm = tmpRm >> 8;
|
|
sum2:4 = (sext(tmpn:1) - sext(tmpm:1)) >> 1;
|
|
tmpn = tmpRn >> 16;
|
|
tmpm = tmpRm >> 16;
|
|
sum3:4 = (sext(tmpn:1) - sext(tmpm:1)) >> 1;
|
|
tmpn = tmpRn >> 24;
|
|
tmpm = tmpRm >> 24;
|
|
sum4:4 = (sext(tmpn:1) - sext(tmpm:1)) >> 1;
|
|
Rd = (sum4 << 24) + ((sum3 & 0xff) << 16) + ((sum2 & 0xff) << 8) + (sum1 & 0xff);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:smla^XBIT^YBIT^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x10 & smRd & smRn & smRm & c0707=1 & XBIT & YBIT & c0404=0 & smRa
|
|
{
|
|
build COND;
|
|
local tmp:4 = sext(XBIT) * sext(YBIT);
|
|
Q = scarry(tmp,smRa) || Q; #Q flag is sticky
|
|
smRd = tmp+smRa;
|
|
}
|
|
|
|
@endif
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:smlad^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x70 & c0407=1 & smRd & smRa & smRm & smRn
|
|
{
|
|
build COND;
|
|
local tmpRn = smRn;
|
|
local tmpRm = smRm;
|
|
local tmpLRn = tmpRn:2;
|
|
local tmpURn = tmpRn >> 16;
|
|
local tmpLRm = tmpRm:2;
|
|
local tmpURm = tmpRm >> 16;
|
|
local product1 = sext(tmpLRn) * sext(tmpLRm);
|
|
local product2 = sext(tmpURn:2) * sext(tmpURm:2);
|
|
local tmpprod = product1 + product2;
|
|
Q = scarry(smRa, tmpprod) || Q; #Q is sticky
|
|
smRd = smRa + tmpprod;
|
|
}
|
|
|
|
:smladx^COND smRd, smRn, smRm, smRa is $(AMODE) & COND & c2027=0x70 & c0407=3 & smRd & smRn & smRm & smRa
|
|
{
|
|
build COND;
|
|
local tmpRn = smRn;
|
|
local tmpRm = smRm;
|
|
local tmpLRn = tmpRn:2;
|
|
local tmpURn = tmpRn >> 16;
|
|
local tmpLRm = tmpRm:2;
|
|
local tmpURm = tmpRm >> 16;
|
|
local product1 = sext(tmpLRn) * sext(tmpURm:2);
|
|
local product2 = sext(tmpURn:2) * sext(tmpLRm);
|
|
local tmpprod = product1 + product2;
|
|
Q = scarry(smRa, tmpprod) || Q; #Q is sticky
|
|
smRd = smRa + tmpprod;
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
:smlal^COND^SBIT_ZN RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2527=0 & c2124=7 & SBIT_ZN & RdLo & RdHi & smRn & c0407=9 & smRm
|
|
{
|
|
build COND;
|
|
tmp:8 = (zext(RdHi) << 32) | zext(RdLo);
|
|
rs64:8 = sext(smRm);
|
|
rm64:8 = sext(smRn);
|
|
tmp = rs64 * rm64 + tmp;
|
|
resultflags(tmp);
|
|
RdLo = tmp(0);
|
|
RdHi = tmp(4);
|
|
build SBIT_ZN;
|
|
}
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:smlal^XBIT^YBIT^COND RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2027=0x14 & RdLo & RdHi & smRm & c0707=1 & XBIT & YBIT & c0404=0 & smRn
|
|
{
|
|
build COND;
|
|
local prod:8 = sext(XBIT) * sext(YBIT);
|
|
local result:8 = (zext(RdHi) << 32) | zext(RdLo);
|
|
result = result + prod;
|
|
RdLo = result(0);
|
|
RdHi = result(4);
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:smlald^COND RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2027=0x74 & RdLo & RdHi & c0607=0 & c0405=1 & smRn & smRm
|
|
{
|
|
build COND;
|
|
local tmpRn = smRn;
|
|
local tmpRm = smRm;
|
|
prod1:8 = sext(tmpRn:2) * sext(tmpRm:2);
|
|
rmHi:2 = tmpRm(2);
|
|
rnHi:2 = tmpRn(2);
|
|
prod2:8 = sext(rmHi) * sext(rnHi);
|
|
result:8 = zext(RdLo) + (zext(RdHi) << 32) + prod1 + prod2;
|
|
RdLo = result:4;
|
|
RdHi = result(4);
|
|
}
|
|
|
|
:smlaldx^COND RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2027=0x74 & RdLo & RdHi & c0607=0 & c0405=3 & smRn & smRm
|
|
{
|
|
build COND;
|
|
local tmpRn = smRn;
|
|
local tmpRm = smRm;
|
|
rmHi:2 = tmpRm(2);
|
|
rnHi:2 = tmpRn(2);
|
|
prod1:8 = sext(tmpRn:2) * sext(rmHi);
|
|
prod2:8 = sext(rnHi) * sext(tmpRm:2);
|
|
result:8 = zext(RdLo) + (zext(RdHi) << 32) + prod1 + prod2;
|
|
RdLo = result:4;
|
|
RdHi = result(4);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:smlaw^YBIT^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x12 & smRd & smRn & smRm & c0707=1 & YBIT & x=0 & c0404=0 & smRa
|
|
{
|
|
build COND;
|
|
local tmp64:6 = sext(smRn) * sext(YBIT);
|
|
local tmp32:4 = tmp64(2);
|
|
Q = scarry(tmp32, smRa) || Q; #Q flag is sticky
|
|
smRd = tmp32 + smRa;
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:smlsd^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x70 & smRd & smRn & c0607=1 & x=0 & c0404=1 & smRm & smRa
|
|
{
|
|
build COND;
|
|
local tmpRn = smRn;
|
|
local tmpRm = smRm;
|
|
prod1:4 = sext(tmpRn:2) * sext(tmpRm:2);
|
|
rnHi:2 = tmpRn(2);
|
|
rmHi:2 = tmpRm(2);
|
|
prod2:4 = sext(rnHi) * sext(rmHi);
|
|
diff:4 = prod1 - prod2;
|
|
Q = scarry(diff, smRa) || Q; #Q is sticky
|
|
smRd = smRa + diff;
|
|
}
|
|
|
|
:smlsdx^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x70 & smRd & smRn & c0607=1 & x=1 & c0404=1 & smRm & smRa
|
|
{
|
|
build COND;
|
|
local tmpRn = smRn;
|
|
local tmpRm = smRm;
|
|
rnHi:2 = tmpRn(2);
|
|
rmHi:2 = tmpRm(2);
|
|
prod1:4 = sext(tmpRn:2) * sext(rmHi);
|
|
prod2:4 = sext(rnHi) * sext(tmpRm:2);
|
|
diff:4 = prod1 - prod2;
|
|
Q = scarry(diff, smRa) || Q; #Q is sticky
|
|
smRd = smRa + diff;
|
|
}
|
|
|
|
:smlsld^COND RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2027=0x74 & RdHi & RdLo & smRm & c0607=1 & x=0 & c0404=1 & smRn
|
|
{
|
|
build COND;
|
|
local tmpRn = smRn;
|
|
local tmpRm = smRm;
|
|
prod1:8 = sext(tmpRn:2) * sext(tmpRm:2);
|
|
rnHi:2 = tmpRn(2);
|
|
rmHi:2 = tmpRm(2);
|
|
prod2:8 = sext(rnHi) * sext(rmHi);
|
|
result:8 = zext(RdLo) + (zext(RdHi) << 32) + (prod1 - prod2);
|
|
RdLo = result:4;
|
|
RdHi = result(4);
|
|
}
|
|
|
|
:smlsldx^COND RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2027=0x74 & RdHi & RdLo & smRm & c0607=1 & x=1 & c0404=1 & smRn
|
|
{
|
|
build COND;
|
|
local tmpRn = smRn;
|
|
local tmpRm = smRm;
|
|
rnHi:2 = tmpRn(2);
|
|
rmHi:2 = tmpRm(2);
|
|
prod1:8 = sext(tmpRn:2) * sext(rmHi);
|
|
prod2:8 = sext(rnHi) * sext(tmpRm:2);
|
|
result:8 = zext(RdLo) + (zext(RdHi) << 32) + (prod1 - prod2);
|
|
RdLo = result:4;
|
|
RdHi = result(4);
|
|
}
|
|
|
|
:smmla^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x75 & smRd & smRn & smRm & c0607=0 & r=0 & c0404=1 & smRa
|
|
{
|
|
build COND;
|
|
val:8 = sext(smRn) * sext(smRm);
|
|
val = (zext(smRa) << 32) + val;
|
|
smRd = val(4);
|
|
}
|
|
|
|
:smmlar^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x75 & smRd & smRn & smRm & c0607=0 & r=1 & c0404=1 & smRa
|
|
{
|
|
build COND;
|
|
val:8 = sext(smRn) * sext(smRm);
|
|
val = (zext(smRa) << 32) + val + 0x80000000;
|
|
smRd = val(4);
|
|
}
|
|
|
|
:smmls^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x75 & smRd & smRn & smRm & c0607=3 & r=0 & c0404=1 & smRa
|
|
{
|
|
build COND;
|
|
val:8 = sext(smRn) * sext(smRm);
|
|
val = (zext(smRa) << 32) - val;
|
|
smRd = val(4);
|
|
}
|
|
|
|
:smmlsr^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x75 & smRd & smRn & smRm & c0607=3 & r=1 & c0404=1 & smRa
|
|
{
|
|
build COND;
|
|
val:8 = sext(smRn) * sext(smRm);
|
|
val = (zext(smRa) << 32) - val + 0x80000000;
|
|
smRd = val(4);
|
|
}
|
|
|
|
:smmul^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x75 & smRd & c1215=15 & smRn & c0607=0 & r=0 & c0404=1 & smRm
|
|
{
|
|
build COND;
|
|
val:8 = sext(smRn) * sext(smRm);
|
|
smRd = val(4);
|
|
}
|
|
|
|
:smmulr^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x75 & smRd & c1215=15 & smRn & c0607=0 & r=1 & c0404=1 & smRm
|
|
{
|
|
build COND;
|
|
val:8 = (sext(smRn) * sext(smRm)) + 0x080000000;
|
|
smRd = val(4);
|
|
}
|
|
|
|
:smuad^COND smRd, smRn, smRm is $(AMODE) & COND & c2027=0x70 & c0407=1 & smRd & c1619=15 & smRn & smRm
|
|
{
|
|
build COND;
|
|
local tmpRm = smRm;
|
|
local tmpRn = smRn;
|
|
local tmpLRm = tmpRm:2;
|
|
local tmpURm = tmpRm >> 16;
|
|
local tmpLRn = tmpRn:2;
|
|
local tmpURn = tmpRn >> 16;
|
|
local product1 = sext(tmpLRm) * sext(tmpLRn);
|
|
local product2 = sext(tmpURm:2) * sext(tmpURn:2);
|
|
local tmpprod = product1 + product2;
|
|
Q = scarry(product1, product2);
|
|
smRd = tmpprod;
|
|
}
|
|
|
|
:smuadx^COND smRd, smRn, smRm is $(AMODE) & COND & c2027=0x70 & c0407=3 & smRd & c1619=15 & smRn & smRm
|
|
{
|
|
build COND;
|
|
local tmpRm = smRm;
|
|
local tmpRn = smRn;
|
|
local tmpLRm = tmpRm:2;
|
|
local tmpURm = tmpRm >> 16;
|
|
local tmpLRn = tmpRn:2;
|
|
local tmpURn = tmpRn >> 16;
|
|
local product1 = sext(tmpLRm) * sext(tmpURn:2);
|
|
local product2 = sext(tmpURm:2) * sext(tmpLRn);
|
|
local tmpprod = product1 + product2;
|
|
Q = scarry(product1, product2);
|
|
smRd = tmpprod;
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:smul^XBIT^YBIT^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x16 & smRd & c1215=0 & smRm & c0707=1 & XBIT & YBIT & c0404=0 & smRn
|
|
{
|
|
build COND;
|
|
tmp:8 = sext(XBIT) * sext(YBIT);
|
|
smRd = tmp:4;
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
:smull^COND^SBIT_ZN RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2527=0 & c2124=6 & SBIT_ZN & RdHi & RdLo & smRn & c0407=9 & smRm
|
|
{
|
|
build COND;
|
|
rn64:8 = sext(smRn);
|
|
rm64:8 = sext(smRm);
|
|
local tmp = rn64 * rm64;
|
|
resultflags(tmp);
|
|
RdLo = tmp(0);
|
|
RdHi = tmp(4);
|
|
build SBIT_ZN;
|
|
}
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:smulw^YBIT^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x12 & smRd & c1215=0 & smRn & c0707=1 & YBIT & x=1 & c0404=0 & smRm
|
|
{
|
|
build COND;
|
|
tmp:6 = sext(smRn) * sext(YBIT);
|
|
tmp = tmp >> 16;
|
|
smRd = tmp:4;
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:smusd^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x70 & smRd & c1215=15 & smRm & c0607=1 & x=0 & c0404=1 & smRn
|
|
{
|
|
build COND;
|
|
local tmpRn = smRn;
|
|
local tmpRm = smRm;
|
|
rmHi:2 = tmpRm(2);
|
|
prod1:4 = sext(tmpRn:2) * sext(tmpRm:2);
|
|
rnHi:2 = tmpRn(2);
|
|
prod2:4 = sext(rnHi) * sext(rmHi);
|
|
smRd = prod1 - prod2;
|
|
}
|
|
|
|
:smusdx^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x70 & smRd & c1215=15 & smRm & c0607=1 & x=1 & c0404=1 & smRn
|
|
{
|
|
build COND;
|
|
local tmpRn = smRn;
|
|
local tmpRm = smRm;
|
|
rmHi:2 = tmpRm(2);
|
|
rnHi:2 = tmpRn(2);
|
|
prod1:4 = sext(tmpRn:2) * sext(rmHi);
|
|
prod2:4 = sext(rnHi) * sext(tmpRm:2);
|
|
smRd = prod1 - prod2;
|
|
}
|
|
|
|
|
|
:ssat^COND Rd, sSatImm5, shift4 is $(AMODE) & COND & c2127=0x35 & c0405=1 & sSatImm5 & Rd & shift4
|
|
{
|
|
build COND;
|
|
build shift4;
|
|
tmp:4 = SignedSaturate(shift4, sSatImm5);
|
|
Q = SignedDoesSaturate(shift4, sSatImm5);
|
|
Rd = tmp;
|
|
}
|
|
|
|
:ssat16^COND Rd, sSatImm4, Rm is $(AMODE) & COND & c2027=0x6a & c0811=15 & c0407=0x3 & sSatImm4 & Rd & Rm
|
|
{
|
|
build COND;
|
|
build sSatImm4;
|
|
local tmpl = Rm & 0xffff;
|
|
tmpl = SignedSaturate(tmpl, sSatImm4);
|
|
local tmpu = Rm >> 16;
|
|
tmpu = SignedSaturate(tmpu, sSatImm4);
|
|
Q = SignedDoesSaturate(tmpl,sSatImm4) | SignedDoesSaturate(tmpu,sSatImm4);
|
|
Rd = ((tmpu & 0xffff) << 16) | (tmpl & 0xffff);
|
|
}
|
|
|
|
# ssubaddx
|
|
:ssax^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=5 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local lRn = Rn & 0xffff;
|
|
local lRm = Rm & 0xffff;
|
|
local uRn = (Rn >> 16) & 0xffff;
|
|
local uRm = (Rm >> 16) & 0xffff;
|
|
local diff = sext(uRn:2) - sext(lRm:2);
|
|
GE3 = diff s>= 0;
|
|
GE4 = diff s>= 0;
|
|
local sum = sext(lRn:2) + sext(uRm:2);
|
|
GE1 = sum s>= 0;
|
|
GE2 = sum s>= 0;
|
|
Rd = ((diff & 0xffff) << 16) | (sum & 0xffff);
|
|
}
|
|
|
|
:ssub16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=7 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local lRn = Rn & 0xffff;
|
|
local lRm = Rm & 0xffff;
|
|
local uRn = (Rn >> 16) & 0xffff;
|
|
local uRm = (Rm >> 16) & 0xffff;
|
|
local diffl = sext(lRn:2) - sext(lRm:2);
|
|
GE1 = diffl s>= 0;
|
|
GE2 = diffl s>= 0;
|
|
local diffu = sext(uRn:2) - sext(uRm:2);
|
|
GE3 = diffu s>= 0;
|
|
GE4 = diffu s>= 0;
|
|
Rd = ((diffu & 0xffff) << 16) | (diffl & 0xffff);
|
|
}
|
|
|
|
:ssub8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=15 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn & 0xff;
|
|
local tmpRm = Rm & 0xff;
|
|
local diff1 = sext(tmpRn:1) - sext(tmpRm:1);
|
|
GE1 = diff1 s>= 0;
|
|
tmpRn = (Rn >> 8) & 0xff;
|
|
tmpRm = (Rm >> 8) & 0xff;
|
|
local diff2 = sext(tmpRn:1) - sext(tmpRm:1);
|
|
GE2 = diff2 s>= 0;
|
|
tmpRn = (Rn >> 16) & 0xff;
|
|
tmpRm = (Rm >> 16) & 0xff;
|
|
local diff3 = sext(tmpRn:1) - sext(tmpRm:1);
|
|
GE3 = diff3 s>= 0;
|
|
tmpRn = (Rn >> 24) & 0xff;
|
|
tmpRm = (Rm >> 24) & 0xff;
|
|
local diff4 = sext(tmpRn:1) - sext(tmpRm:1);
|
|
GE4 = diff4 s>= 0;
|
|
Rd = ((diff4 & 0xff) << 24) | ((diff3 & 0xff) << 16) | ((diff2 & 0xff) << 8) | (diff1 & 0xff);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
:stc^COND cpn,CRd,addrmode5 is $(AMODE) & COND & c2527=6 & addrmode5 & cpn & CRd & N22=0 & L20=0
|
|
{
|
|
build COND;
|
|
build addrmode5;
|
|
t_cpn:4 = cpn;
|
|
coprocessor_store(t_cpn,CRd,addrmode5);
|
|
}
|
|
|
|
:stcl^COND cpn,CRd,addrmode5 is $(AMODE) & COND & c2527=6 & addrmode5 & cpn & CRd & N22=1 & L20=0
|
|
{
|
|
build COND;
|
|
build addrmode5;
|
|
t_cpn:4 = cpn;
|
|
coprocessor_storelong(t_cpn,CRd,addrmode5);
|
|
}
|
|
|
|
:stm^mdir^COND reglist is $(AMODE) & COND & c2527=4 & mdir & L20=0 & reglist
|
|
{
|
|
build COND;
|
|
build reglist;
|
|
}
|
|
|
|
#:str^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=0 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
#{
|
|
# build COND;
|
|
# build addrmode2;
|
|
# tmp=addrmode2&0xfffffffc;
|
|
# *tmp = Rd;
|
|
#}
|
|
|
|
# The following form of str assumes alignment checking is on
|
|
:str^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=0 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
*addrmode2 = Rd;
|
|
}
|
|
|
|
:strb^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=1 & L20=0 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
local tmpRd = Rd;
|
|
*addrmode2 = tmpRd:1;
|
|
}
|
|
|
|
:strbt^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 &P24=0 & B22=1 & W21=1 & L20=0 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
local tmpRd = Rd;
|
|
*addrmode2 = tmpRd:1;
|
|
}
|
|
|
|
:strh^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & L20=0 & c0407=11 & Rd & addrmode3
|
|
{
|
|
build COND;
|
|
build addrmode3;
|
|
local tmpRd = Rd;
|
|
*addrmode3 = tmpRd:2;
|
|
}
|
|
|
|
@if defined(VERSION_5E)
|
|
|
|
:strd^COND Rd,Rd2,addrmode3 is $(AMODE) & COND & c2527=0 & c0407=0xf & L20=0 & Rd & Rd2 & addrmode3
|
|
{
|
|
build COND;
|
|
build addrmode3;
|
|
local addr = addrmode3;
|
|
*(addr) = Rd;
|
|
addr = addr + 4;
|
|
*(addr) = Rd2;
|
|
}
|
|
|
|
@endif # VERSION_5E
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:strex^COND Rd,Rm,[Rn] is $(AMODE) & COND & c2027=0x18 & c0411=0xf9 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmp = Rn;
|
|
access:1 = hasExclusiveAccess(tmp);
|
|
Rd = 1;
|
|
if (!access) goto inst_next;
|
|
Rd = 0;
|
|
*tmp = Rm;
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_6K)
|
|
|
|
:strexb^COND Rd,Rm,[Rn] is $(AMODE) & COND & c2027=0x1c & c0411=0xf9 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmp = Rn;
|
|
access:1 = hasExclusiveAccess(tmp);
|
|
Rd = 1;
|
|
if (!access) goto inst_next;
|
|
Rd = 0;
|
|
local tmpRm = Rm;
|
|
*tmp = tmpRm:1;
|
|
}
|
|
|
|
:strexd^COND Rd,Rm,Rm2,[Rn] is $(AMODE) & COND & c2027=0x1a & Rn & Rd & c0411=0xf9 & c0003 & Rm & Rm2
|
|
{
|
|
build COND;
|
|
local addr = Rn;
|
|
access:1 = hasExclusiveAccess(addr);
|
|
Rd = 1;
|
|
if (!access) goto inst_next;
|
|
Rd = 0;
|
|
*(addr) = Rm;
|
|
addr = addr + 4;
|
|
*(addr) = Rm2;
|
|
}
|
|
|
|
:strexh^COND Rd,Rm,[Rn] is $(AMODE) & COND & c2027=0x1e & c0411=0xf9 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmp = Rn;
|
|
access:1 = hasExclusiveAccess(tmp);
|
|
Rd = 1;
|
|
if (!access) goto inst_next;
|
|
Rd = 0;
|
|
local tmpRm = Rm;
|
|
*tmp = tmpRm:2;
|
|
}
|
|
|
|
:strht^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & P24=0 & W21=1 & L20=0 & c0407=11 & Rd & addrmode3 {
|
|
build COND;
|
|
*:2 addrmode3 = Rd;
|
|
}
|
|
|
|
@endif # VERSION_6K
|
|
|
|
#:strt^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=0 & P24=0 & W21=1 & Rd & addrmode2
|
|
#{
|
|
# build COND;
|
|
# build addrmode2;
|
|
# tmp=addrmode2&0xfffffffc;
|
|
# *tmp = Rd;
|
|
#}
|
|
|
|
# The following form of str assumes alignment checking is on
|
|
:strt^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=0 & P24=0 & W21=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2
|
|
{
|
|
build COND;
|
|
build addrmode2;
|
|
*addrmode2 = Rd;
|
|
}
|
|
|
|
:sub^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=2 & SBIT_CZNO & rn & Rd & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
subflags(rn,shift1);
|
|
Rd = rn-shift1;
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:sub^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=2 & SBIT_CZNO & rn & Rd & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
subflags(rn,shift2);
|
|
Rd = rn-shift2;
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:sub^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=2 & SBIT_CZNO & rn & Rd & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
subflags(rn,shift3);
|
|
Rd = rn-shift3;
|
|
resultflags(Rd);
|
|
build SBIT_CZNO;
|
|
}
|
|
|
|
:sub^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=2 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
subflags(rn,shift1);
|
|
dest:4 = rn-shift1;
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
cpsr = spsr;
|
|
SetThumbMode( ((cpsr >> 5) & 1) != 0 );
|
|
pc = dest;
|
|
goto [pc];
|
|
}
|
|
|
|
:sub^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=2 & SBIT_CZNO & rn & Rd=15 & Rn=14 & I25=1 & immed=0 & rotate=0 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
subflags(rn,shift1);
|
|
dest:4 = rn-shift1;
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
cpsr = spsr;
|
|
ALUWritePC(dest);
|
|
return [pc];
|
|
}
|
|
|
|
:sub^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=2 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
subflags(rn,shift2);
|
|
dest:4 = rn-shift2;
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
cpsr = spsr;
|
|
SetThumbMode( ((cpsr >> 5) & 1) != 0 );
|
|
pc = dest;
|
|
goto [pc];
|
|
}
|
|
|
|
:sub^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=2 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
subflags(rn,shift3);
|
|
dest:4 = rn-shift3;
|
|
resultflags(dest);
|
|
build SBIT_CZNO;
|
|
cpsr = spsr;
|
|
SetThumbMode( ((cpsr >> 5) & 1) != 0 );
|
|
pc = dest;
|
|
goto [pc];
|
|
}
|
|
|
|
:swi^COND immed24 is $(AMODE) & COND & c2427=15 & immed24
|
|
{
|
|
build COND;
|
|
tmp:4 = immed24;
|
|
software_interrupt(tmp);
|
|
}
|
|
|
|
#:swp^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=16 & Rn & Rd & c0811=0 & c0407=9 & Rm
|
|
#{
|
|
# build COND;
|
|
# tmp = Rn & 0xfffffffc;
|
|
# tmp2 = (Rn&3)<<3;
|
|
# val:4 = *tmp;
|
|
# val=(val>>tmp2) | (val << (32-tmp2));
|
|
# *tmp = Rm;
|
|
# Rd = val;
|
|
#}
|
|
|
|
# Assuming alignment checking is enabled
|
|
:swp^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=16 & Rn & Rd & c0811=0 & c0407=9 & Rm
|
|
{
|
|
build COND;
|
|
val:4 = *Rn;
|
|
*Rn = Rm;
|
|
Rd = val;
|
|
}
|
|
|
|
:swpb^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=20 & Rn & Rd & c0811=0 & c0407=9 & Rm
|
|
{
|
|
build COND;
|
|
local tmp = *:1 Rn;
|
|
local tmpRm = Rm;
|
|
*Rn = tmpRm:1;
|
|
Rd = zext(tmp);
|
|
}
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:sxtab^COND Rd,Rn,ror1 is $(AMODE) & COND & c2327=13 & c2022=2 & c0407=7 & Rd & Rn & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
Rd = Rn + sext(ror1:1);
|
|
}
|
|
|
|
:sxtab16^COND Rd,Rn,ror1 is $(AMODE) & COND & c2027=0x68 & c0407=7 & Rn & Rd & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
b:1 = ror1:1;
|
|
lo:2 = Rn:2 + sext(b);
|
|
b = ror1(2);
|
|
hi:2 = Rn(2) + sext(b);
|
|
Rd = (zext(hi) << 16) + zext(lo);
|
|
}
|
|
|
|
:sxtah^COND Rd,Rn,ror1 is $(AMODE) & COND & c2327=13 & c2022=3 & c0407=7 & Rd & Rn & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
Rd = Rn + sext(ror1:2);
|
|
}
|
|
|
|
:sxtb^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=2 & c0407=7 & Rd & c1619=15 & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
Rd = sext(ror1:1);
|
|
}
|
|
|
|
:sxtb16^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=0 & c0407=7 & Rd & c1619=15 & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
local tmp1:1 = ror1:1;
|
|
local low:2 = sext(tmp1);
|
|
local tmp2:1 = ror1(2);
|
|
local high:2 = sext(tmp2);
|
|
Rd = (zext(high) << 16) | zext(low);
|
|
}
|
|
|
|
:sxth^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=3 & c0407=7 & Rd & c1619=15 & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
Rd = sext(ror1:2);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
:teq^COND rn,shift1 is $(AMODE) & COND & c2024=19 & rn & c1215=0 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
local tmp = rn^shift1;
|
|
logicflags();
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:teq^COND rn,shift2 is $(AMODE) & COND & c2024=19 & rn & c1215=0 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
local tmp = rn^shift2;
|
|
logicflags();
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:teq^COND rn,shift3 is $(AMODE) & COND & c2024=19 & rn & c1215=0 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
local tmp = rn^shift3;
|
|
logicflags();
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:teq^COND^"p" rn,shift1 is $(AMODE) & COND & c2024=19 & rn & c1215=15 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
local tmp = rn^shift1;
|
|
logicflags();
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:teq^COND^"p" rn,shift2 is $(AMODE) & COND & c2024=19 & rn & c1215=15 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
local tmp = rn^shift2;
|
|
logicflags();
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:teq^COND^"p" rn,shift3 is $(AMODE) & COND & c2024=19 & rn & c1215=15 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
local tmp = rn^shift3;
|
|
logicflags();
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
|
|
:tst^COND rn,shift1 is $(AMODE) & COND & c2024=17 & rn & c1215=0 & c2627=0 & shift1
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift1;
|
|
local tmp = rn & shift1;
|
|
logicflags();
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:tst^COND rn,shift2 is $(AMODE) & COND & c2024=17 & rn & c1215=0 & c2627=0 & shift2
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift2;
|
|
local tmp = rn & shift2;
|
|
logicflags();
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
:tst^COND rn,shift3 is $(AMODE) & COND & c2024=17 & rn & c1215=0 & c2627=0 & shift3
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build shift3;
|
|
local tmp = rn & shift3;
|
|
logicflags();
|
|
resultflags(tmp);
|
|
affectflags();
|
|
}
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:uadd16^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=1 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:2 = tmpRn:2;
|
|
tmp2:2 = tmpRm:2;
|
|
local tcarry = carry(tmp1,tmp2);
|
|
GE1 = tcarry;
|
|
GE2 = tcarry;
|
|
local tmpLow = tmp1 + tmp2;
|
|
tmp1 = rn(2);
|
|
tmp2 = rm(2);
|
|
tcarry = carry(tmp1,tmp2);
|
|
GE3 = tcarry;
|
|
GE4 = tcarry;
|
|
local tmpHigh = tmp1 + tmp2;
|
|
Rd = zext(tmpHigh) << 16 | zext(tmpLow);
|
|
}
|
|
|
|
:uadd8^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=9 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:1 = tmpRn:1;
|
|
tmp2:1 = tmpRm:1;
|
|
GE1 = carry(tmp1,tmp2);
|
|
b1:1 = tmp1 + tmp2;
|
|
tmp1 = rn(1);
|
|
tmp2 = rm(1);
|
|
GE2 = carry(tmp1,tmp2);
|
|
b2:1 = tmp1 + tmp2;
|
|
tmp1 = rn(2);
|
|
tmp2 = rm(2);
|
|
GE3 = carry(tmp1,tmp2);
|
|
b3:1 = tmp1 + tmp2;
|
|
tmp1 = rn(3);
|
|
tmp2 = rm(3);
|
|
GE4 = carry(tmp1,tmp2);
|
|
b4:1 = tmp1 + tmp2;
|
|
Rd = (zext(b4) << 24) | (zext(b3) << 16) | (zext(b2) << 8) | zext(b1);
|
|
}
|
|
|
|
# uaddsubx
|
|
:uasx^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=3 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:2 = tmpRn:2;
|
|
tmp2:2 = tmpRm(2);
|
|
local tmpLow:4 = zext(tmp1) - zext(tmp2);
|
|
GE1 = tmpLow s>= 0;
|
|
GE2 = tmpLow s>= 0;
|
|
tmp1 = tmpRn(2);
|
|
tmp2 = tmpRm:2;
|
|
tcarry:1 = carry(tmp1,tmp2);
|
|
GE3 = tcarry;
|
|
GE4 = tcarry;
|
|
local tmpHigh = tmp1 + tmp2;
|
|
Rd[0,16] = tmpLow[0,16];
|
|
Rd[16,16] = tmpHigh;
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
@if defined(VERSION_6T2)
|
|
|
|
:ubfx^COND Rd,Rm,lsbImm,widthMinus1 is $(AMODE) & COND & c2127=0x3f & widthMinus1 & Rd & lsbImm & c0406=5 & Rm
|
|
{
|
|
build COND;
|
|
build lsbImm;
|
|
build widthMinus1;
|
|
shift:4 = 31 - (lsbImm + widthMinus1);
|
|
Rd = Rm << shift;
|
|
shift = 31 - widthMinus1;
|
|
Rd = Rd >> shift;
|
|
}
|
|
|
|
@endif # VERSION_6T2
|
|
|
|
@if defined(VERSION_7)
|
|
|
|
:udiv^COND RdHi,RnLo,RmHi is $(AMODE) & COND & c2027=0x73 & RdHi & c1215=0xf & RmHi & c0407=0x1 & RnLo
|
|
{
|
|
build COND;
|
|
result:8 = zext(RnLo) / zext(RmHi);
|
|
RdHi = result(0);
|
|
}
|
|
|
|
@endif # VERSION_7
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:uhadd16^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=1 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:4 = tmpRn & 0xffff;
|
|
tmp2:4 = tmpRm & 0xffff;
|
|
local tmpLow = tmp1 + tmp2;
|
|
local tmpHigh = (tmpRn >> 16) + (tmpRm >> 16);
|
|
Rd[0,16] = tmpLow[1,16];
|
|
Rd[16,16] = tmpHigh[1,16];
|
|
}
|
|
|
|
:uhadd8^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=9 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:1 = tmpRn:1;
|
|
tmp2:1 = tmpRm:1;
|
|
b1:2 = (zext(tmp1) + zext(tmp2)) >> 1;
|
|
tmp1 = tmpRn(1);
|
|
tmp2 = tmpRm(1);
|
|
b2:2 = (zext(tmp1) + zext(tmp2)) >> 1;
|
|
tmp1 = tmpRn(2);
|
|
tmp2 = tmpRm(2);
|
|
b3:2 = (zext(tmp1) + zext(tmp2)) >> 1;
|
|
tmp1 = tmpRn(3);
|
|
tmp2 = tmpRm(3);
|
|
b4:2 = (zext(tmp1) + zext(tmp2)) >> 1;
|
|
Rd = (zext(b4) << 24) | (zext(b3) << 16) | (zext(b2) << 8) | zext(b1);
|
|
}
|
|
|
|
# uhaddsubx
|
|
:uhasx^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=3 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:2 = tmpRn:2;
|
|
tmp2:2 = tmpRm(2);
|
|
tmpLow:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ffff;
|
|
tmp1 = tmpRn(2);
|
|
tmp2 = tmpRm:2;
|
|
tmpHigh:4 = (zext(tmp1) + zext(tmp2)) >> 1;
|
|
Rd = (tmpHigh << 16) | tmpLow;
|
|
}
|
|
|
|
# uhsubaddx
|
|
:uhsax^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=5 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:2 = tmpRn:2;
|
|
tmp2:2 = tmpRm(2);
|
|
tmpLow:4 = (zext(tmp1) + zext(tmp2)) >> 1;
|
|
tmp1 = tmpRn(2);
|
|
tmp2 = tmpRm:2;
|
|
tmpHigh:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ffff;
|
|
Rd = (tmpHigh << 16) | tmpLow;
|
|
}
|
|
|
|
:uhsub16^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=7 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:2 = tmpRn:2;
|
|
tmp2:2 = tmpRm:2;
|
|
tmpLow:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ffff;
|
|
tmp1 = rn(2);
|
|
tmp2 = rm(2);
|
|
tmpHigh:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ffff;
|
|
Rd = (tmpHigh << 16) | tmpLow;
|
|
}
|
|
|
|
:uhsub8^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=15 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:1 = tmpRn:1;
|
|
tmp2:1 = tmpRm:1;
|
|
b1:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ff;
|
|
tmp1 = tmpRn(1);
|
|
tmp2 = tmpRm(1);
|
|
b2:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ff;
|
|
tmp1 = tmpRn(2);
|
|
tmp2 = tmpRm(2);
|
|
b3:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ff;
|
|
tmp1 = tmpRn(3);
|
|
tmp2 = tmpRm(3);
|
|
b4:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ff;
|
|
Rd = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
|
|
}
|
|
|
|
:umaal^COND RdLo,RdHi,Rm,Rs is $(AMODE) & COND & c2027=0x04 & RdHi & RdLo & Rs & c0407=9 & Rm
|
|
{
|
|
build COND;
|
|
result:8 = (zext(Rm) * zext(Rs)) + zext(RdLo) + zext(RdHi);
|
|
RdLo = result:4;
|
|
RdHi = result(4);
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
:umlal^COND^SBIT_ZN Rd,Rn,rm,rs is $(AMODE) & COND & c2527=0 & c2124=5 & SBIT_ZN & Rn & Rd & rs & c0407=9 & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
build rs;
|
|
tmp:8 = (zext(Rn) << 32) | zext(Rd);
|
|
rs64:8 = zext(rs);
|
|
rm64:8 = zext(rm);
|
|
tmp = rs64 * rm64 + tmp;
|
|
resultflags(tmp);
|
|
Rd = tmp(0);
|
|
Rn = tmp(4);
|
|
build SBIT_ZN;
|
|
}
|
|
|
|
:umull^COND^SBIT_ZN Rd,Rn,rm,rs is $(AMODE) & COND & c2527=0 & c2124=4 & SBIT_ZN & Rn & Rd & rs & c0407=9 & rm
|
|
{
|
|
build COND;
|
|
build rm;
|
|
build rs;
|
|
rs64:8 = zext(rs);
|
|
rm64:8 = zext(rm);
|
|
local tmp = rs64 * rm64;
|
|
resultflags(tmp);
|
|
Rd = tmp(0);
|
|
Rn = tmp(4);
|
|
build SBIT_ZN;
|
|
}
|
|
|
|
@if defined(VERSION_6)
|
|
|
|
:uqadd16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=1 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
tmp2Rn:2 = tmpRn:2;
|
|
tmp2Rm:2 = tmpRm:2;
|
|
sum1:2 = UnsignedSaturate(tmp2Rn + tmp2Rm, 16:2);
|
|
tmp2Rn = tmpRn(2);
|
|
tmp2Rm = tmpRm(2);
|
|
sum2:2 = UnsignedSaturate(tmp2Rn + tmp2Rm, 16:2);
|
|
Rd = (zext(sum2) << 16) | zext(sum1);
|
|
}
|
|
|
|
:uqadd8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=9 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
tmp1Rn:1 = tmpRn:1;
|
|
tmp1Rm:1 = tmpRm:1;
|
|
sum1:1 = UnsignedSaturate(tmp1Rn + tmp1Rm, 16:2);
|
|
tmp1Rn = tmpRn(1);
|
|
tmp1Rm = tmpRm(1);
|
|
sum2:2 = UnsignedSaturate(tmp1Rn + tmp1Rm, 16:2);
|
|
tmp1Rn = tmpRn(2);
|
|
tmp1Rm = tmpRm(2);
|
|
sum3:2 = UnsignedSaturate(tmp1Rn + tmp1Rm, 16:2);
|
|
tmp1Rn = tmpRn(3);
|
|
tmp1Rm = tmpRm(3);
|
|
sum4:2 = UnsignedSaturate(tmp1Rn + tmp1Rm, 16:2);
|
|
Rd = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1);
|
|
}
|
|
|
|
# uqaddsubx
|
|
:uqasx^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=3 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
tmp2Rn:2 = tmpRn:2;
|
|
tmp2Rm:2 = tmpRm(2);
|
|
sum1:2 = UnsignedSaturate(tmp2Rn - tmp2Rm, 16:2);
|
|
tmp2Rn = tmpRn(2);
|
|
tmp2Rm = tmpRm:2;
|
|
sum2:2 = UnsignedSaturate(tmp2Rn + tmp2Rm, 16:2);
|
|
Rd = (zext(sum2) << 16) | zext(sum1);
|
|
}
|
|
|
|
# uqsubaddx
|
|
:uqsax^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=5 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
tmp2Rn:2 = tmpRn:2;
|
|
tmp2Rm:2 = tmpRm(2);
|
|
sum1:2 = UnsignedSaturate(tmp2Rn + tmp2Rm, 16:2);
|
|
tmp2Rn = tmpRn(2);
|
|
tmp2Rm = tmpRm:2;
|
|
sum2:2 = UnsignedSaturate(tmp2Rn - tmp2Rm, 16:2);
|
|
Rd = (zext(sum2) << 16) | zext(sum1);
|
|
}
|
|
|
|
:uqsub16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=7 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
tmp2Rn:2 = tmpRn:2;
|
|
tmp2Rm:2 = tmpRm:2;
|
|
sum1:2 = UnsignedSaturate(tmp2Rn - tmp2Rm, 16:2);
|
|
tmp2Rn = tmpRn(2);
|
|
tmp2Rm = tmpRm(2);
|
|
sum2:2 = UnsignedSaturate(tmp2Rn - tmp2Rm, 16:2);
|
|
Rd = (zext(sum2) << 16) | zext(sum1);
|
|
}
|
|
|
|
:uqsub8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=15 & Rn & Rd & Rm
|
|
{
|
|
build COND;
|
|
local tmpRn = Rn;
|
|
local tmpRm = Rm;
|
|
tmp1Rn:1 = tmpRn:1;
|
|
tmp1Rm:1 = tmpRm:1;
|
|
sum1:1 = UnsignedSaturate(tmp1Rn - tmp1Rm, 16:2);
|
|
tmp1Rn = tmpRn(1);
|
|
tmp1Rm = tmpRm(1);
|
|
sum2:2 = UnsignedSaturate(tmp1Rn - tmp1Rm, 16:2);
|
|
tmp1Rn = tmpRn(2);
|
|
tmp1Rm = tmpRm(2);
|
|
sum3:2 = UnsignedSaturate(tmp1Rn - tmp1Rm, 16:2);
|
|
tmp1Rn = tmpRn(3);
|
|
tmp1Rm = tmpRm(3);
|
|
sum4:2 = UnsignedSaturate(tmp1Rn - tmp1Rm, 16:2);
|
|
Rd = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1);
|
|
}
|
|
|
|
:usad8^COND Rd, Rm, Rs is $(AMODE) & COND & c2027=0x78 & c1215=15 & c0407=1 & Rd & Rm & Rs
|
|
{
|
|
build COND;
|
|
local tmpRs = Rs;
|
|
local tmpRm = Rm;
|
|
tmp1Rs:1 = tmpRs:1;
|
|
tmp1Rm:1 = tmpRm:1;
|
|
sum1:1 = Absolute(tmp1Rs - tmp1Rm);
|
|
tmp1Rs = tmpRs(1);
|
|
tmp1Rm = tmpRm(1);
|
|
sum2:1 = Absolute(tmp1Rs - tmp1Rm);
|
|
tmp1Rs = tmpRs(2);
|
|
tmp1Rm = tmpRm(2);
|
|
sum3:1 = Absolute(tmp1Rs - tmp1Rm);
|
|
tmp1Rs = tmpRs(3);
|
|
tmp1Rm = tmpRm(3);
|
|
sum4:1 = Absolute(tmp1Rs - tmp1Rm);
|
|
Rd = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1);
|
|
}
|
|
|
|
:usada8^COND Rd, Rm, Rs, Rn is $(AMODE) & COND & c2027=0x78 & c0407=1 & Rd & Rn& Rm & Rs
|
|
{
|
|
build COND;
|
|
local tmpRs = Rs;
|
|
local tmpRm = Rm;
|
|
tmp1Rs:1 = tmpRs:1;
|
|
tmp1Rm:1 = tmpRm:1;
|
|
sum1:1 = Absolute(tmp1Rs - tmp1Rm);
|
|
tmp1Rs = tmpRs(1);
|
|
tmp1Rm = tmpRm(1);
|
|
sum2:1 = Absolute(tmp1Rs - tmp1Rm);
|
|
tmp1Rs = tmpRs(2);
|
|
tmp1Rm = tmpRm(2);
|
|
sum3:1 = Absolute(tmp1Rs - tmp1Rm);
|
|
tmp1Rs = tmpRs(3);
|
|
tmp1Rm = tmpRm(3);
|
|
sum4:1 = Absolute(tmp1Rs - tmp1Rm);
|
|
Rd = Rn + ((zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1));
|
|
}
|
|
|
|
:usat^COND Rd, uSatImm5, shift4 is $(AMODE) & COND & c2127=0x37 & c0405=0x1 & uSatImm5 & Rd & shift4
|
|
{
|
|
build COND;
|
|
build uSatImm5;
|
|
build shift4;
|
|
tmp:4 = UnsignedSaturate(shift4, uSatImm5);
|
|
Q = UnsignedDoesSaturate(shift4, uSatImm5);
|
|
Rd = tmp;
|
|
}
|
|
|
|
:usat16^COND Rd, uSatImm4, Rm is $(AMODE) & COND & c2027=0x6e & c0811=15 & c0407=0x3 & uSatImm4 & Rd & Rm
|
|
{
|
|
build COND;
|
|
build uSatImm4;
|
|
local tmpl = Rm & 0xffff;
|
|
tmpl = UnsignedSaturate(tmpl, uSatImm4);
|
|
local tmpu = Rm >> 16;
|
|
tmpu = UnsignedSaturate(tmpu, uSatImm4);
|
|
Q = UnsignedDoesSaturate(tmpl,uSatImm4) | UnsignedDoesSaturate(tmpu,uSatImm4);
|
|
Rd = ((tmpu & 0xffff) << 16) | (tmpl & 0xffff);
|
|
}
|
|
|
|
# usubaddx
|
|
:usax^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=5 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:2 = tmpRn:2;
|
|
tmp2:2 = tmpRm(2);
|
|
local tcarry = carry(tmp2,tmp1);
|
|
GE1 = tcarry;
|
|
GE2 = tcarry;
|
|
local tmpLow = tmp1 + tmp2;
|
|
tmp1 = tmpRn(2);
|
|
tmp2 = tmpRm:2;
|
|
tcarry = tmp2 <= tmp1;
|
|
GE3 = tcarry;
|
|
GE4 = tcarry;
|
|
local tmpHigh = tmp1 - tmp2;
|
|
Rd = zext(tmpHigh) << 16 | zext(tmpLow);
|
|
}
|
|
|
|
:usub16^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=7 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:2 = tmpRn:2;
|
|
tmp2:2 = tmpRm:2;
|
|
local tcarry = tmp2 <= tmp1;
|
|
GE1 = tcarry;
|
|
GE2 = tcarry;
|
|
local tmpLow = tmp1 - tmp2;
|
|
tmp1 = tmpRn(2);
|
|
tmp2 = tmpRm(2);
|
|
tcarry = tmp2 <= tmp1;
|
|
GE3 = tcarry;
|
|
GE4 = tcarry;
|
|
local tmpHigh = tmp1 - tmp2;
|
|
Rd = zext(tmpHigh) << 16 | zext(tmpLow);
|
|
}
|
|
|
|
:usub8^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=15 & Rd & rn & rm
|
|
{
|
|
build COND;
|
|
build rn;
|
|
build rm;
|
|
local tmpRn = rn;
|
|
local tmpRm = rm;
|
|
tmp1:1 = tmpRn:1;
|
|
tmp2:1 = tmpRm:1;
|
|
GE1 = tmp2 <= tmp1;
|
|
b1:1 = tmp1 - tmp2;
|
|
tmp1 = tmpRn(1);
|
|
tmp2 = tmpRm(1);
|
|
GE2 = tmp2 <= tmp1;
|
|
b2:1 = tmp1 - tmp2;
|
|
tmp1 = tmpRn(2);
|
|
tmp2 = tmpRm(2);
|
|
GE3 = tmp2 <= tmp1;
|
|
b3:1 = tmp1 - tmp2;
|
|
tmp1 = tmpRn(3);
|
|
tmp2 = tmpRm(3);
|
|
GE4 = tmp2 <= tmp1;
|
|
b4:1 = tmp1 - tmp2;
|
|
Rd = (zext(b4) << 24) | (zext(b3) << 16) | (zext(b2) << 8) | zext(b1);
|
|
}
|
|
|
|
:uxtab^COND Rd,Rn,ror1 is $(AMODE) & COND & c2327=13 & c2022=6 & c0407=7 & Rd & Rn & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
Rd = Rn + zext(ror1:1);
|
|
}
|
|
|
|
:uxtab16^COND Rd,Rn,ror1 is $(AMODE) & COND & c2327=13 & c2022=4 & c0407=7 & Rd & Rn & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
local tmp1 = ror1 & 0xff;
|
|
local tmp2 = (ror1 >> 16) & 0xff;
|
|
local tmp1n = (Rn + tmp1) & 0xffff;
|
|
local tmp2n = (Rn >> 16) + tmp2;
|
|
Rd = (tmp2n << 16) | tmp1n;
|
|
}
|
|
|
|
:uxtah^COND Rd,Rn,ror1 is $(AMODE) & COND & c2327=13 & c2022=7 & c0407=7 & Rd & Rn & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
Rd = Rn + zext(ror1:2);
|
|
}
|
|
|
|
:uxtb^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=6 & c0407=7 & Rd & c1619=15 & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
Rd = ror1 & 0x0ff;
|
|
}
|
|
|
|
:uxtb16^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=4 & c0407=7 & Rd & c1619=15 & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
Rd = ror1 & 0x0ff00ff;
|
|
}
|
|
|
|
:uxth^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=7 & c0407=7 & Rd & c1619=15 & ror1
|
|
{
|
|
build COND;
|
|
build ror1;
|
|
Rd = ror1 & 0x0ffff;
|
|
}
|
|
|
|
@endif # VERSION_6
|
|
|
|
# :v* Advanced SIMD and VFP instructions - see ARMneon.sinc
|
|
|
|
@if defined(VERSION_6K)
|
|
|
|
:wfe^COND is $(AMODE) & COND & c0027=0x320f002
|
|
{
|
|
build COND;
|
|
WaitForEvent();
|
|
}
|
|
|
|
:wfi^COND is $(AMODE) & COND & c0027=0x320f003
|
|
{
|
|
build COND;
|
|
WaitForInterrupt();
|
|
}
|
|
|
|
:yield^COND is $(AMODE) & COND & c0027=0x320f001
|
|
{
|
|
build COND;
|
|
HintYield();
|
|
}
|
|
|
|
@endif # VERSION_6K
|
|
|
|
## Some special pseudo ops for better distinguishing
|
|
## indirect calls, and returns
|
|
|
|
#:callx rm is $(AMODE) & pref=0xe1a0e00f; cond=14 & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & rm
|
|
#{
|
|
# lr = inst_next + 8;
|
|
# TB=(rm&0x00000001)!=0;
|
|
# tmp=rm&0xfffffffe;
|
|
# call [tmp];
|
|
# TB=0;
|
|
#} # Optional change to THUMB
|
|
|
|
#:call^COND^SBIT_CZNO shift1 is $(AMODE) & pref=0xe1a0e00f; COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift1
|
|
#{
|
|
# lr = inst_next + 8;
|
|
# build COND;
|
|
# build shift1;
|
|
# pc = shift1;
|
|
# resultflags(pc);
|
|
# logicflags();
|
|
# build SBIT_CZNO;
|
|
# call [pc];
|
|
#}
|
|
|
|
#:call^COND^SBIT_CZNO shift2 is $(AMODE) & pref=0xe1a0e00f; COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift2
|
|
#{
|
|
# lr = inst_next + 8;
|
|
# build COND;
|
|
# build shift2;
|
|
# pc = shift2;
|
|
# resultflags(pc);
|
|
# logicflags();
|
|
# build SBIT_CZNO;
|
|
# call [pc];
|
|
#}
|
|
|
|
#:call^COND^SBIT_CZNO shift3 is $(AMODE) & pref=0xe1a0e00f; COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift3
|
|
#{
|
|
# lr = inst_next + 8;
|
|
# build COND;
|
|
# build shift3;
|
|
# pc = shift3;
|
|
# resultflags(pc);
|
|
# logicflags();
|
|
# build SBIT_CZNO;
|
|
# call [pc];
|
|
#}
|
|
|
|
|
|
@if defined(VERSION_6T2) || defined(VERSION_7)
|
|
} # End with : ARMcondCk=1
|
|
@endif
|