# Advanced SIMD support / NEON

# 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.
#

@define FPSCR_RMODE "fpscr[22,2]"

@define TMODE_E "TMode=1 & thv_c2831=14"   # check for neon instructions in thumb mode
@define TMODE_F "TMode=1 & thv_c2831=15"
@define TMODE_EorF "TMode=1 & thv_c2931=7"

# The RM field is bits 22 and 23 of FPSCR
@define FPSCR_RMODE "fpscr[21,2]"

zero: "#0"			is c0000 				{ export 0:8; }

@if defined(SIMD)
  
attach variables [ thv_Rm ] [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ];

attach variables [ Qn0 Qd0 Qm0 thv_Qn0 thv_Qd0 thv_Qm0 ] [ q0 _ q1 _ q2 _ q3 _ q4 _ q5 _ q6 _ q7 _ ];
attach variables [ Qn1 Qd1 Qm1 thv_Qn1 thv_Qd1 thv_Qm1 ] [ q8 _ q9 _ q10 _ q11 _ q12 _ q13 _ q14 _ q15 _ ];

Qd: Qd0		is TMode=0 & Qd0 & D22=0	{ export Qd0; }
Qd: Qd1		is TMode=0 & Qd1 & D22=1	{ export Qd1; }
Qd: thv_Qd0	is TMode=1 & thv_Qd0 & thv_D22=0	{ export thv_Qd0; }
Qd: thv_Qd1	is TMode=1 & thv_Qd1 & thv_D22=1	{ export thv_Qd1; }

Qn: Qn0		is TMode=0 & Qn0 & N7=0	{ export Qn0; }
Qn: Qn1		is TMode=0 & Qn1 & N7=1	{ export Qn1; }
Qn: thv_Qn0		is TMode=1 & thv_Qn0 & thv_N7=0	{ export thv_Qn0; }
Qn: thv_Qn1		is TMode=1 & thv_Qn1 & thv_N7=1	{ export thv_Qn1; }

Qm: Qm0		is TMode=0 & Qm0 & M5=0	{ export Qm0; }
Qm: Qm1		is TMode=0 & Qm1 & M5=1	{ export Qm1; }
Qm: thv_Qm0		is TMode=1 & thv_Qm0 & thv_M5=0	{ export thv_Qm0; }
Qm: thv_Qm1		is TMode=1 & thv_Qm1 & thv_M5=1	{ export thv_Qm1; }

@endif # SIMD

@if defined(SIMD) || defined(VFPv3) || defined(VFPv2)
  
attach variables [ Dm_3 thv_Dm_3 ] [ d0 d1 d2 d3 d4 d5 d6 d7 ];

attach variables [ Dn0 Dd0 Dm0 Dm_4 thv_Dn0 thv_Dd0 thv_Dm0 thv_Dm_4 ] [ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 ];
attach variables [ thv_Dd_1 Dd_1 ] [ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 ];
attach variables [ thv_Dd_2 Dd_2 ] [ d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ ];
attach variables [ thv_Dd_3 Dd_3 ] [ d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ ];
attach variables [ thv_Dd_4 Dd_4 ] [ d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ ];
attach variables [ thv_Dd_5 Dd_5 ] [ d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ ];
attach variables [ thv_Dd_6 Dd_6 ] [ d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ ];
attach variables [ thv_Dd_7 Dd_7 ] [ d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ ];
attach variables [ thv_Dd_8 Dd_8 ] [ d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_9 Dd_9 ] [ d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_10 Dd_10 ] [ d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_11 Dd_11 ] [ d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_12 Dd_12 ] [ d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_13 Dd_13 ] [ d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_14 Dd_14 ] [ d13 d14 d15 _ _ _ _ _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_15 Dd_15 ] [ d14 d15 _ _ _ _ _ _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_16 Dd_16 ] [ d15 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ];
  
Dd: Dd0		is TMode=0 & Dd0 & D22=0	{ export Dd0; }
Dn: Dn0		is TMode=0 & Dn0 & N7=0	{ export Dn0; }
Dm: Dm0		is TMode=0 & Dm0 & M5=0	{ export Dm0; }
Dd: thv_Dd0	is TMode=1 & thv_Dd0 & thv_D22=0	{ export thv_Dd0; }
Dn: thv_Dn0	is TMode=1 & thv_Dn0 & thv_N7=0	{ export thv_Dn0; }
Dm: thv_Dm0	is TMode=1 & thv_Dm0 & thv_M5=0	{ export thv_Dm0; }

Dd2: Dd		is Dd			{ export Dd; }

@endif # SIMD || VFPv3 || VFPv2

@if defined(SIMD) || defined(VFPv3)

attach variables [ Dn1 Dd1 Dm1 thv_Dn1 thv_Dd1 thv_Dm1 ] [ d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 ];
  
Dd: Dd1		is TMode=0 & Dd1 & D22=1 { export Dd1; }
Dn: Dn1		is TMode=0 & Dn1 & N7=1	{ export Dn1; }
Dm: Dm1		is TMode=0 & Dm1 & M5=1	{ export Dm1; }
Dd: thv_Dd1	is TMode=1 & thv_Dd1 & thv_D22=1 { export thv_Dd1; }
Dn: thv_Dn1	is TMode=1 & thv_Dn1 & thv_N7=1	{ export thv_Dn1; }
Dm: thv_Dm1	is TMode=1 & thv_Dm1 & thv_M5=1	{ export thv_Dm1; }

attach variables [ Sm0_3 thv_Sm0_3 ][s0 s2 s4 s6 s8 s10 s12 s14];
attach variables [ Sm1_3 thv_Sm1_3][s1 s3 s5 s7 s9 s11 s13 s15];

Sm_3: Sm0_3 is TMode=0 & Sm0_3 & M5=0 { export Sm0_3; }
Sm_3: Sm1_3 is TMode=0 & Sm1_3 & M5=1 { export Sm1_3; }
Sm_3: thv_Sm0_3 is TMode=1 & thv_Sm0_3 & M5=0 { export thv_Sm0_3; }
Sm_3: thv_Sm1_3 is TMode=1 & thv_Sm1_3 & M5=1 { export thv_Sm1_3; }

@endif # SIMD || VFPv3

@if defined(VFPv2) || defined(VFPv3)

attach variables [ Sn0 Sd0 Sm0 thv_Sn0 thv_Sd0 thv_Sm0 ] [ s0 s2 s4 s6 s8 s10 s12 s14 s16 s18 s20 s22 s24 s26 s28 s30 ];
attach variables [ Sn1 Sd1 Sm1 thv_Sn1 thv_Sd1 thv_Sm1 ] [ s1 s3 s5 s7 s9 s11 s13 s15 s17 s19 s21 s23 s25 s27 s29 s31 ];

attach variables [ Sm0next thv_Sm0next ] [ s1 s3 s5 s7 s9 s11 s13 s15 s17 s19 s21 s23 s25 s27 s29 s31 ];
attach variables [ Sm1next thv_Sm1next ] [ s2 s4 s6 s8 s10 s12 s14 s16 s18 s20 s22 s24 s26 s28 s30 _ ];

# We need to create separate constructors for each register rather than attaching
# directly to a context variable
@if defined (VFPv2) || defined(SIMD)
Sreg: s0 is s0 & regNum=0 { export s0; }
Sreg: s1 is s1 & regNum=1 { export s1; }
Sreg: s2 is s2 & regNum=2 { export s2; }
Sreg: s3 is s3 & regNum=3 { export s3; }
Sreg: s4 is s4 & regNum=4 { export s4; }
Sreg: s5 is s5 & regNum=5 { export s5; }
Sreg: s6 is s6 & regNum=6 { export s6; }
Sreg: s7 is s7 & regNum=7 { export s7; }
Sreg: s8 is s8 & regNum=8 { export s8; }
Sreg: s9 is s9 & regNum=9 { export s9; }
Sreg: s10 is s10 & regNum=10 { export s10; }
Sreg: s11 is s11 & regNum=11 { export s11; }
Sreg: s12 is s12 & regNum=12 { export s12; }
Sreg: s13 is s13 & regNum=13 { export s13; }
Sreg: s14 is s14 & regNum=14 { export s14; }
Sreg: s15 is s15 & regNum=15 { export s15; }
Sreg: s16 is s16 & regNum=16 { export s16; }
Sreg: s17 is s17 & regNum=17 { export s17; }
Sreg: s18 is s18 & regNum=18 { export s18; }
Sreg: s19 is s19 & regNum=19 { export s19; }
Sreg: s20 is s20 & regNum=20 { export s20; }
Sreg: s21 is s21 & regNum=21 { export s21; }
Sreg: s22 is s22 & regNum=22 { export s22; }
Sreg: s23 is s23 & regNum=23 { export s23; }
Sreg: s24 is s24 & regNum=24 { export s24; }
Sreg: s25 is s25 & regNum=25 { export s25; }
Sreg: s26 is s26 & regNum=26 { export s26; }
Sreg: s27 is s27 & regNum=27 { export s27; }
Sreg: s28 is s28 & regNum=28 { export s28; }
Sreg: s29 is s29 & regNum=29 { export s29; }
Sreg: s30 is s30 & regNum=30 { export s30; }
Sreg: s31 is s31 & regNum=31 { export s31; }

Sreg2: s0 is s0 & reg2Num=0 { export s0; }
Sreg2: s1 is s1 & reg2Num=1 { export s1; }
Sreg2: s2 is s2 & reg2Num=2 { export s2; }
Sreg2: s3 is s3 & reg2Num=3 { export s3; }
Sreg2: s4 is s4 & reg2Num=4 { export s4; }
Sreg2: s5 is s5 & reg2Num=5 { export s5; }
Sreg2: s6 is s6 & reg2Num=6 { export s6; }
Sreg2: s7 is s7 & reg2Num=7 { export s7; }
Sreg2: s8 is s8 & reg2Num=8 { export s8; }
Sreg2: s9 is s9 & reg2Num=9 { export s9; }
Sreg2: s10 is s10 & reg2Num=10 { export s10; }
Sreg2: s11 is s11 & reg2Num=11 { export s11; }
Sreg2: s12 is s12 & reg2Num=12 { export s12; }
Sreg2: s13 is s13 & reg2Num=13 { export s13; }
Sreg2: s14 is s14 & reg2Num=14 { export s14; }
Sreg2: s15 is s15 & reg2Num=15 { export s15; }
Sreg2: s16 is s16 & reg2Num=16 { export s16; }
Sreg2: s17 is s17 & reg2Num=17 { export s17; }
Sreg2: s18 is s18 & reg2Num=18 { export s18; }
Sreg2: s19 is s19 & reg2Num=19 { export s19; }
Sreg2: s20 is s20 & reg2Num=20 { export s20; }
Sreg2: s21 is s21 & reg2Num=21 { export s21; }
Sreg2: s22 is s22 & reg2Num=22 { export s22; }
Sreg2: s23 is s23 & reg2Num=23 { export s23; }
Sreg2: s24 is s24 & reg2Num=24 { export s24; }
Sreg2: s25 is s25 & reg2Num=25 { export s25; }
Sreg2: s26 is s26 & reg2Num=26 { export s26; }
Sreg2: s27 is s27 & reg2Num=27 { export s27; }
Sreg2: s28 is s28 & reg2Num=28 { export s28; }
Sreg2: s29 is s29 & reg2Num=29 { export s29; }
Sreg2: s30 is s30 & reg2Num=30 { export s30; }
Sreg2: s31 is s31 & reg2Num=31 { export s31; }

Dreg: d0 is d0 & regNum=0 { export d0; }
Dreg: d1 is d1 & regNum=1 { export d1; }
Dreg: d2 is d2 & regNum=2 { export d2; }
Dreg: d3 is d3 & regNum=3 { export d3; }
Dreg: d4 is d4 & regNum=4 { export d4; }
Dreg: d5 is d5 & regNum=5 { export d5; }
Dreg: d6 is d6 & regNum=6 { export d6; }
Dreg: d7 is d7 & regNum=7 { export d7; }
Dreg: d8 is d8 & regNum=8 { export d8; }
Dreg: d9 is d9 & regNum=9 { export d9; }
Dreg: d10 is d10 & regNum=10 { export d10; }
Dreg: d11 is d11 & regNum=11 { export d11; }
Dreg: d12 is d12 & regNum=12 { export d12; }
Dreg: d13 is d13 & regNum=13 { export d13; }
Dreg: d14 is d14 & regNum=14 { export d14; }
Dreg: d15 is d15 & regNum=15 { export d15; }
Dreg2: d0 is d0 & reg2Num=0 { export d0; }
Dreg2: d1 is d1 & reg2Num=1 { export d1; }
Dreg2: d2 is d2 & reg2Num=2 { export d2; }
Dreg2: d3 is d3 & reg2Num=3 { export d3; }
Dreg2: d4 is d4 & reg2Num=4 { export d4; }
Dreg2: d5 is d5 & reg2Num=5 { export d5; }
Dreg2: d6 is d6 & reg2Num=6 { export d6; }
Dreg2: d7 is d7 & reg2Num=7 { export d7; }
Dreg2: d8 is d8 & reg2Num=8 { export d8; }
Dreg2: d9 is d9 & reg2Num=9 { export d9; }
Dreg2: d10 is d10 & reg2Num=10 { export d10; }
Dreg2: d11 is d11 & reg2Num=11 { export d11; }
Dreg2: d12 is d12 & reg2Num=12 { export d12; }
Dreg2: d13 is d13 & reg2Num=13 { export d13; }
Dreg2: d14 is d14 & reg2Num=14 { export d14; }
Dreg2: d15 is d15 & reg2Num=15 { export d15; }
@if defined(SIMD) || defined(VFPv3)
Dreg: d16 is d16 & regNum=16 { export d16; }
Dreg: d17 is d17 & regNum=17 { export d17; }
Dreg: d18 is d18 & regNum=18 { export d18; }
Dreg: d19 is d19 & regNum=19 { export d19; }
Dreg: d20 is d20 & regNum=20 { export d20; }
Dreg: d21 is d21 & regNum=21 { export d21; }
Dreg: d22 is d22 & regNum=22 { export d22; }
Dreg: d23 is d23 & regNum=23 { export d23; }
Dreg: d24 is d24 & regNum=24 { export d24; }
Dreg: d25 is d25 & regNum=25 { export d25; }
Dreg: d26 is d26 & regNum=26 { export d26; }
Dreg: d27 is d27 & regNum=27 { export d27; }
Dreg: d28 is d28 & regNum=28 { export d28; }
Dreg: d29 is d29 & regNum=29 { export d29; }
Dreg: d30 is d30 & regNum=30 { export d30; }
Dreg: d31 is d31 & regNum=31 { export d31; }
Dreg2: d16 is d16 & reg2Num=16 { export d16; }
Dreg2: d17 is d17 & reg2Num=17 { export d17; }
Dreg2: d18 is d18 & reg2Num=18 { export d18; }
Dreg2: d19 is d19 & reg2Num=19 { export d19; }
Dreg2: d20 is d20 & reg2Num=20 { export d20; }
Dreg2: d21 is d21 & reg2Num=21 { export d21; }
Dreg2: d22 is d22 & reg2Num=22 { export d22; }
Dreg2: d23 is d23 & reg2Num=23 { export d23; }
Dreg2: d24 is d24 & reg2Num=24 { export d24; }
Dreg2: d25 is d25 & reg2Num=25 { export d25; }
Dreg2: d26 is d26 & reg2Num=26 { export d26; }
Dreg2: d27 is d27 & reg2Num=27 { export d27; }
Dreg2: d28 is d28 & reg2Num=28 { export d28; }
Dreg2: d29 is d29 & reg2Num=29 { export d29; }
Dreg2: d30 is d30 & reg2Num=30 { export d30; }
Dreg2: d31 is d31 & reg2Num=31 { export d31; }
@else
# this is just a placeholder so the parse patterns will match correctly.
# regNum is 31 when the base pattern matches, and incremented when
# this constructor actually matches
Dreg: d0 is d0 & regNum=31 { export d0; }
Dreg2: d0 is d0 & reg2Num=31 { export d0; }
@endif
@endif

VRm: Rm     is TMode=0 & Rm     { export Rm; }
VRm: thv_Rm is TMode=1 & thv_Rm { export thv_Rm; }

VRn: Rn     is TMode=0 & Rn     { export Rn; }
VRn: thv_Rn is TMode=1 & thv_Rn { export thv_Rn; }

VRd: Rd       is TMode=0 & Rd  { export Rd; }
VRd: thv_Rd   is TMode=1 & thv_Rd { export thv_Rd; }

Sd: Sd0		is TMode=0 & Sd0 & D22=0	{ export Sd0; }
Sd: Sd1		is TMode=0 & Sd1 & D22=1	{ export Sd1; }
Sd: thv_Sd0	is TMode=1 & thv_Sd0 & thv_D22=0	{ export thv_Sd0; }
Sd: thv_Sd1	is TMode=1 & thv_Sd1 & thv_D22=1	{ export thv_Sd1; }

Sn: Sn0		is TMode=0 & Sn0 & N7=0	{ export Sn0; }
Sn: Sn1		is TMode=0 & Sn1 & N7=1	{ export Sn1; }
Sn: thv_Sn0	is TMode=1 & thv_Sn0 & thv_N7=0	{ export thv_Sn0; }
Sn: thv_Sn1	is TMode=1 & thv_Sn1 & thv_N7=1	{ export thv_Sn1; }

Sm: Sm0		is TMode=0 & Sm0 & M5=0	{ export Sm0; }
Sm: Sm1		is TMode=0 & Sm1 & M5=1	{ export Sm1; }
Sm: thv_Sm0	is TMode=1 & thv_Sm0 & thv_M5=0	{ export thv_Sm0; }
Sm: thv_Sm1	is TMode=1 & thv_Sm1 & thv_M5=1	{ export thv_Sm1; }

SmNext: Sm0next		is TMode=0 & Sm0next & M5=0	{ export Sm0next; }
SmNext: Sm1next		is TMode=0 & Sm1next & M5=1	{ export Sm1next; }
SmNext: thv_Sm0next	is TMode=1 & thv_Sm0next & thv_M5=0	{ export thv_Sm0next; }
SmNext: thv_Sm1next	is TMode=1 & thv_Sm1next & thv_M5=1	{ export thv_Sm1next; }

Sd2: Sd		is Sd			{ export Sd; }

@endif # VFPv2 || VFPv3

udt: "s"	is TMode=0 & c2424=0			{ export 0:1; }
udt: "u"	is TMode=0 & c2424=1			{ export 1:1; }
udt: "s"	is TMode=1 & thv_c2828=0		{ export 0:1; }
udt: "u"	is TMode=1 & thv_c2828=1		{ export 1:1; }

udt7: "s"	is TMode=0 & c0707=0			{ export 0:1; }
udt7: "u"	is TMode=0 & c0707=1			{ export 1:1; }
udt7: "s"	is TMode=1 & thv_c0707=0		{ export 0:1; }
udt7: "u"	is TMode=1 & thv_c0707=1		{ export 1:1; }

fdt: "u"	is TMode=0 & c0808=0			{ export 0:1; }
fdt: "f"	is TMode=0 & c0808=1			{ export 1:1; }
fdt: "u"	is TMode=1 & thv_c0808=0		{ export 0:1; }
fdt: "f"	is TMode=1 & thv_c0808=1		{ export 1:1; }

esize2021: "8" 		is TMode=0 & c2021=0		{ export 1:4; }
esize2021: "16" 	is TMode=0 & c2021=1		{ export 2:4; }
esize2021: "32" 	is TMode=0 & c2021=2		{ export 4:4; }
esize2021: "64" 	is TMode=0 & c2021=3		{ export 8:4; }
esize2021: "8" 		is TMode=1 & thv_c2021=0	{ export 1:4; }
esize2021: "16" 	is TMode=1 & thv_c2021=1	{ export 2:4; }
esize2021: "32" 	is TMode=1 & thv_c2021=2	{ export 4:4; }
esize2021: "64" 	is TMode=1 & thv_c2021=3	{ export 8:4; }

esize2021x2: "16" 	is TMode=0 & c2021=0		{ export 2:4; }
esize2021x2: "32" 	is TMode=0 & c2021=1		{ export 4:4; }
esize2021x2: "64" 	is TMode=0 & c2021=2		{ export 8:4; }
esize2021x2: "16" 	is TMode=1 & thv_c2021=0	{ export 2:4; }
esize2021x2: "32" 	is TMode=1 & thv_c2021=1	{ export 4:4; }
esize2021x2: "64" 	is TMode=1 & thv_c2021=2	{ export 8:4; }

esize1819: "8" 		is TMode=0 & c1819=0		{ export 1:4; }
esize1819: "16" 	is TMode=0 & c1819=1		{ export 2:4; }
esize1819: "32" 	is TMode=0 & c1819=2		{ export 4:4; }
esize1819: "64" 	is TMode=0 & c1819=3		{ export 8:4; }
esize1819: "8" 		is TMode=1 & thv_c1819=0	{ export 1:4; }
esize1819: "16" 	is TMode=1 & thv_c1819=1	{ export 2:4; }
esize1819: "32" 	is TMode=1 & thv_c1819=2	{ export 4:4; }
esize1819: "64" 	is TMode=1 & thv_c1819=3	{ export 8:4; }

esize1819x2: "16" 	is TMode=0 & c1819=0		{ export 2:4; }
esize1819x2: "32" 	is TMode=0 & c1819=1		{ export 4:4; }
esize1819x2: "64" 	is TMode=0 & c1819=2		{ export 8:4; }
esize1819x2: "16" 	is TMode=1 & thv_c1819=0	{ export 2:4; }
esize1819x2: "32" 	is TMode=1 & thv_c1819=1	{ export 4:4; }
esize1819x2: "64" 	is TMode=1 & thv_c1819=2	{ export 8:4; }

esize1819x3: "8" 	is TMode=0 & c1819=0		{ export 1:4; }
esize1819x3: "16" 	is TMode=0 & c1819=1		{ export 2:4; }
esize1819x3: "32" 	is TMode=0 & c1819=2		{ export 4:4; }
esize1819x3: "8" 	is TMode=1 & thv_c1819=0	{ export 1:4; }
esize1819x3: "16" 	is TMode=1 & thv_c1819=1	{ export 2:4; }
esize1819x3: "32" 	is TMode=1 & thv_c1819=2	{ export 4:4; }

esize1011: "8" 		is TMode=0 & c1011=0	    { export 1:4; }
esize1011: "16" 	is TMode=0 & c1011=1		{ export 2:4; }
esize1011: "32" 	is TMode=0 & c1011=2		{ export 4:4; }
esize1011: "64" 	is TMode=0 & c1011=3		{ export 8:4; }
esize1011: "8" 		is TMode=1 & thv_c1011=0	{ export 1:4; }
esize1011: "16" 	is TMode=1 & thv_c1011=1	{ export 2:4; }
esize1011: "32" 	is TMode=1 & thv_c1011=2	{ export 4:4; }
esize1011: "64" 	is TMode=1 & thv_c1011=3	{ export 8:4; }

esize0607: "8" 		is TMode=0 & c0607=0	{ export 1:4; }
esize0607: "16" 	is TMode=0 & c0607=1	{ export 2:4; }
esize0607: "32" 	is TMode=0 & c0607=2	{ export 4:4; }
esize0607: "64" 	is TMode=0 & c0607=3	{ export 8:4; } # see VLD4 (single 4-element structure to all lanes)
esize0607: "8" 		is TMode=1 & thv_c0607=0	{ export 1:4; }
esize0607: "16" 	is TMode=1 & thv_c0607=1	{ export 2:4; }
esize0607: "32" 	is TMode=1 & thv_c0607=2	{ export 4:4; }
esize0607: "64" 	is TMode=1 & thv_c0607=3	{ export 8:4; } # see VLD4 (single 4-element structure to all lanes)


fesize2323: "16" 	is TMode=0 & c2323=1		{ export 4:4; }
fesize2323: "32" 	is TMode=0 & c2323=0		{ export 2:4; }
fesize2323: "16" 	is TMode=1 & thv_c2323=1	{ export 4:4; }
fesize2323: "32" 	is TMode=1 & thv_c2323=0	{ export 2:4; }

fesize2020: "16" 	is TMode=0 & c2020=1		{ export 4:4; }
fesize2020: "32" 	is TMode=0 & c2020=0		{ export 2:4; }
fesize2020: "16" 	is TMode=1 & thv_c2020=1	{ export 4:4; }
fesize2020: "32" 	is TMode=1 & thv_c2020=0	{ export 2:4; }

fesize1819: "16" 	is TMode=0 & c1819=1		{ export 4:4; }
fesize1819: "32" 	is TMode=0 & c1819=2		{ export 2:4; }
fesize1819: "16" 	is TMode=1 & thv_c1819=1	{ export 4:4; }
fesize1819: "32" 	is TMode=1 & thv_c1819=2	{ export 2:4; }

roundType: "a" is TMode=0 & c0809=0 { export 0:1; }
roundType: "a" is TMode=1 & thv_c0809=0 { export 0:1; }
roundType: "n" is TMode=0 & c0809=1 { export 1:1; }
roundType: "n" is TMode=1 & thv_c0809=1 { export 1:1; }
roundType: "p" is TMode=0 & c0809=2 { export 2:1; }
roundType: "p" is TMode=1 & thv_c0809=2 { export 2:1; }
roundType: "m" is TMode=0 & c0809=3 { export 3:1; }
roundType: "m" is TMode=1 & thv_c0809=3 { export 3:1; }

define pcodeop VFPExpandImmediate;



# float
vfpExpImm_4: imm		is TMode=0 & c1919 & c1818 & c1617 & c0003 [ imm = (c1919 << 31) | ((c1818 $xor 1) << 30) | ((c1818 * 0x1f) << 25) | (c1617 << 23) | (c0003 << 19); ] 	{
	export *[const]:4 imm; 
}

# float
vfpExpImm_4: imm		is TMode=1 & thv_c1919 & thv_c1818 & thv_c1617 & thv_c0003 [ imm = (thv_c1919 << 31) | ((thv_c1818 $xor 1) << 30) | ((thv_c1818 * 0x1f) << 25) | (thv_c1617 << 23) | (thv_c0003 << 19); ] 	{
	export *[const]:4 imm; 
}


# double 
vfpExpImm_8: imm		is TMode=0 & c1919 & c1818 & c1617 & c0003 [ imm = (c1919 << 63) | ((c1818 $xor 1) << 62) | ((c1818 * 0xff) << 54) | (c1617 << 52) | (c0003 << 48); ] 	{
	export *[const]:8 imm;
}

# double 
vfpExpImm_8: imm		is TMode=1 & thv_c1919 & thv_c1818 & thv_c1617 & thv_c0003 [ imm = (thv_c1919 << 63) | ((thv_c1818 $xor 1) << 62) | ((thv_c1818 * 0xff) << 54) | (thv_c1617 << 52) | (thv_c0003 << 48); ] 	{
	export *[const]:8 imm;
}

define pcodeop SIMDExpandImmediate;

simdExpImm_8: "#0" 	is TMode=0 & c2424=0 & c1618=0 & c0003=0	{
	export 0:8;
}
simdExpImm_8: "simdExpand("^c0505^","^cmode^","^val^")" 	is TMode=0 & c2424 & c1618 & c0505 & c0003 & cmode [ val = (c2424 << 7) | (c1618 << 4) | c0003; ]	{
	imm64:8 = SIMDExpandImmediate(c0505:1, cmode:1, val:1);
	export imm64;
}
simdExpImm_8: "#0" 	is TMode=1 & thv_c2828=0 & thv_c1618=0 & thv_c0003=0	{
	export 0:8;
}
simdExpImm_8: "simdExpand("^thv_c0505^","^thv_cmode^","^val^")" 	is TMode=1 & thv_c2828 & thv_c1618 & thv_c0505 & thv_c0003 & thv_cmode [ val = (thv_c2828 << 7) | (thv_c1618 << 4) | thv_c0003; ]	{
	imm64:8 = SIMDExpandImmediate(thv_c0505:1, thv_cmode:1, val:1);
	export imm64;
}

simdExpImm_16: "#0" 	is TMode=0 & c2424=0 & c1618=0 & c0003=0	{
	tmp:8 = 0; 
	tmp1:16 = zext(tmp); 
	export tmp1;
}
simdExpImm_16: "simdExpand("^c0505^","^cmode^","^val^")" 	is TMode=0 & c2424 & c1618 & c0505 & c0003 & cmode [ val = (c2424 << 7) | (c1618 << 4) | c0003; ]	{
	imm128:16 = SIMDExpandImmediate(c0505:1, cmode:1, val:1);
	export imm128;
}
simdExpImm_16: "#0" 	is TMode=1 & thv_c2828=0 & thv_c1618=0 & thv_c0003=0	{
	tmp:8 = 0; 
	tmp1:16 = zext(tmp); 
	export tmp1;
}
simdExpImm_16: "simdExpand("^thv_c0505^","^thv_cmode^","^val^")" 	is TMode=1 & thv_c2828 & thv_c1618 & thv_c0505 & thv_c0003 & thv_cmode [ val = (thv_c2828 << 7) | (thv_c1618 << 4) | thv_c0003; ]	{
	imm128:16 = SIMDExpandImmediate(thv_c0505:1, thv_cmode:1, val:1);
	export imm128;
}

simdExpImmDT: "i32"	is TMode=0 & c0911=0 { }
simdExpImmDT: "i32"	is TMode=0 & c0911=1 { }
simdExpImmDT: "i32"	is TMode=0 & c0911=2 { }
simdExpImmDT: "i32"	is TMode=0 & c0911=3 { }
simdExpImmDT: "i16"	is TMode=0 & c0911=4 { }
simdExpImmDT: "i16"	is TMode=0 & c0911=5 { }
simdExpImmDT: "i32"	is TMode=0 & c0811=12 { }
simdExpImmDT: "i32"	is TMode=0 & c0811=13 { }
simdExpImmDT: "i8"	is TMode=0 & c0811=14 & c0505=0 { }
simdExpImmDT: "i64"	is TMode=0 & c0811=14 & c0505=1 { }
simdExpImmDT: "f32"	is TMode=0 & c0811=15 & c0505=0 { }

simdExpImmDT: "i32"	is TMode=1 & thv_c0911=0 { }
simdExpImmDT: "i32"	is TMode=1 & thv_c0911=1 { }
simdExpImmDT: "i32"	is TMode=1 & thv_c0911=2 { }
simdExpImmDT: "i32"	is TMode=1 & thv_c0911=3 { }
simdExpImmDT: "i16"	is TMode=1 & thv_c0911=4 { }
simdExpImmDT: "i16"	is TMode=1 & thv_c0911=5 { }
simdExpImmDT: "i32"	is TMode=1 & thv_c0811=12 { }
simdExpImmDT: "i32"	is TMode=1 & thv_c0811=13 { }
simdExpImmDT: "i8"	is TMode=1 & thv_c0811=14 & thv_c0505=0 { }
simdExpImmDT: "i64"	is TMode=1 & thv_c0811=14 & thv_c0505=1 { }
simdExpImmDT: "f32"	is TMode=1 & thv_c0811=15 & thv_c0505=0 { }

macro replicate1to8(bytes, dest) {
	local val:8 = zext(bytes);
	val = val | (val << 8);
	val = val | (val << 16);
	dest = val | (val << 32);
}

macro replicate2to8(bytes, dest) {
	local val:8 = zext(bytes);
	val = val | (val << 16);
	dest = val | (val << 32);
}

macro replicate4to8(bytes, dest) {
	local val:8 = zext(bytes);
	dest = val | (val << 32);
}

define pcodeop VectorAbsoluteDifferenceAndAccumulate;
define pcodeop VectorAbsoluteDifference;
define pcodeop FloatVectorAbsoluteDifference;
define pcodeop VectorAbsolute;
define pcodeop FloatVectorAbsolute;

@if defined(SIMD)
# CryptOp(val)
#	Various crypto algorithms, too numerous for explication at
#	this time

define pcodeop CryptOp;
#######
# AESD single round decryption

define pcodeop AESInvShiftRows;
define pcodeop AESInvSubBytes;
# F6.1.1 p3235 A1/T1
:aesd.8		Qd,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00111 &     c2021=0b11 &     c1819=0b00 &     c1617=0b00 &     c0611=0b001101 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b00 & thv_c1617=0b00 & thv_c0611=0b001101 & thv_c0404=0))
	& Qd & Qm
{
	local shiftRows:16 = AESInvShiftRows(Qd ^ Qm);
	Qd = AESInvSubBytes(shiftRows);
}

#######
# AESE single round encryption

define pcodeop AESShiftRows;
define pcodeop AESSubBytes;
# F6.1.2 p3237 A1/T1
:aese.8		Qd,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00111 &     c2021=0b11 &     c1819=0b00 &     c1617=0b00 &     c0611=0b001100 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b00 & thv_c1617=0b00 & thv_c0611=0b001100 & thv_c0404=0))
	& Qd & Qm
{
	local shiftRows:16 = AESInvShiftRows(Qd ^ Qm);
	Qd = AESSubBytes(shiftRows);
}

#######
# AESIMC inverse mix columns

define pcodeop AESInvMixColumns;
# F6.1.3 p3239 A1/T1
:aesimc.8	Qd,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00111 &     c2021=0b11 &     c1819=0b00 &     c1617=0b00 &     c0611=0b001111 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b00 & thv_c1617=0b00 & thv_c0611=0b001111 & thv_c0404=0))
	& Qd & Qm
{
	Qd = AESInvMixColumns(Qm);
}

#######
# AESMC mix columns

define pcodeop AESMixColumns;
# F6.1.4 p3240 A1/T1
:aesmc.8	Qd,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00111 &     c2021=0b11 &     c1819=0b00 &     c1617=0b00 &     c0611=0b001110 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b00 & thv_c1617=0b00 & thv_c0611=0b001110 & thv_c0404=0))
	& Qd & Qm
{
	Qd = AESMixColumns(Qm);
}

#######
# SHA1C SHA1 hash update (choose)

define pcodeop SHA1HashUpdateChoose;
# F6.1.7 p3248 A1/T1
:sha1c.32	Qd,Qn,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00100 &     c2021=0b00 &     c0811=0b1100 &     c0606=1 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11110 & thv_c2021=0b00 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0))
	& Qn & Qd & Qm
{
	local X = Qd;
	local Y = Qn:4;
	local W = Qm;
	Qd = SHA1HashUpdateChoose(X, Y, W);
}

#######
# SHA1H SHA1 fixed rotate

# F6.1.8 p3250 A1/T1
:sha1h.32	Qd,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00111 &     c2021=0b11 &     c1819=0b10 &     c1617=0b01 &     c0611=0b001011 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b01 & thv_c0611=0b001011 & thv_c0404=0))
	& Qd & Qm
{
	local W:4 = Qm(0);
	Qd = zext(W << 30 | W >> 2);
}

#######
# SHA1M SHA1 hash update (majority)

define pcodeop SHA1HashUpdateMajority;
# F6.1.9 p3251 A1/T1
:sha1m.32	Qd,Qn,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00100 &     c2021=0b10 &     c0811=0b1100 &     c0606=1 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11110 & thv_c2021=0b10 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0))
	& Qn & Qd & Qm
{
	local X = Qd;
	local Y = Qn:4;
	local W = Qm;
	Qd = SHA1HashUpdateMajority(X, Y, W);
}

#######
# SHA1P SHA1 hash update (parity)

define pcodeop SHA1HashUpdateParity;
# F6.1.10 p3253 A1/T1
:sha1p.32	Qd,Qn,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00100 &     c2021=0b01 &     c0811=0b1100 &     c0606=1 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11110 & thv_c2021=0b01 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0))
	& Qn & Qd & Qm
{
	local X = Qd;
	local Y = Qn:4;
	local W = Qm;
	Qd = SHA1HashUpdateParity(X, Y, W);
}

#######
# SHA1SU0 SHA1 schedule update 0

# F6.1.11 p3255 A1/T1
:sha1su0.32	Qd,Qn,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00100 &     c2021=0b11 &     c0811=0b1100 &     c0606=1 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11110 & thv_c2021=0b11 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0))
	& Qn & Qd & Qm
{
	local op1 = Qd;
	local op2 = Qn;
	local op3 = Qm;
	local op2lo:8 = op2(0);
	local op1hi:8 = op1(8);
	op2 = zext(op2lo << 64) | zext(op1hi);
	Qd = op1 ^ op2 ^ op3;
}

#######
# SHA1SU1 SHA1 schedule update 1

# F6.1.12 p3257 A1/T1
:sha1su1.32	Qd,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00111 &     c2021=0b11 &     c1819=0b10 &     c1617=0b10 &     c0611=0b001110 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b10 & thv_c0611=0b001110 & thv_c0404=0))
	& Qd & Qm
{
	local X = Qd;
	local Y = Qm;
	local Tm = X ^ (Y >> 32);
	local t0:4 = Tm(0);
	local t1:4 = Tm(4);
	local t2:4 = Tm(8);
	local t3:4 = Tm(12);
	local W0:4 = (t0 << 1 | t0 >> 31);
	local W1:4 = (t1 << 1 | t1 >> 31);
	local W2:4 = (t2 << 1 | t2 >> 31);
	local W3:4 = (t3 << 1 | t3 >> 31) ^ (t0 << 2 | t0 >> 30);
	Qd = zext(W3 << 96) | zext(W2 << 64) | zext(W1 << 32) | zext(W0);
}

#######
# SHA256H SHA256 hash update part 1

define pcodeop SHA256hash;
# F6.1.13 p3259 A1/T1
:sha256h.32	Qd,Qn,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00110 &     c2021=0b00 &     c0811=0b1100 &     c0606=1 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b00 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0))
	& Qn & Qd & Qm
{
	local part1:1 = 1;
	Qd = SHA256hash(Qd,Qn,Qm, part1);
}

#######
# SHA256H2 SHA256 hash update part 2

# F6.1.14 p3260 A1/T1
:sha256h2.32	Qd,Qn,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00110 &     c2021=0b01 &     c0811=0b1100 &     c0606=1 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b01 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0))
	& Qn & Qd & Qm
{
	local part1:1 = 0;
	Qd = SHA256hash(Qd,Qn,Qm, part1);
}

#######
# SHA256SU0 SHA256 schedule update 0

define pcodeop SHA256ScheduleUpdate0;
# F6.1.15 p3261 A1/T1
:sha256su0.32	Qd,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00111 &     c2021=0b11 &     c1819=0b10 &     c1617=0b10 &     c0611=0b001111 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b10 & thv_c0611=0b001111 & thv_c0404=0))
	& Qd & Qm
{
	Qd = SHA256ScheduleUpdate0(Qd,Qm);
}

#######
# SHA256SU1 SHA256 schedule update 1

define pcodeop SHA256ScheduleUpdate1;
# F6.1.16 p3263 A1/T1
:sha256su1.32	Qd,Qn,Qm
	is ((TMode=0 & ARMcond=0 &     c2831=0b1111 &     c2327=0b00110 &     c2021=0b10 &     c0811=0b1100 &     c0606=1 &     c0404=0)
	|   (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b10 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0))
	& Qn & Qd & Qm
{
	Qd = SHA256ScheduleUpdate1(Qd,Qn,Qm);
}

# TODO: watch out for c2021=3

:vaba.^udt^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=7 & Q6=0 & c0404=1) | 
                                     ($(TMODE_EorF) &     thv_c2327=0x1e &    thv_c2021<3 & thv_c0811=7 & thv_c0606=0 & thv_c0404=1 ) ) & Dm & Dn & Dd & udt & esize2021
{
	Dd = VectorAbsoluteDifferenceAndAccumulate(Dn,Dm,esize2021,udt);
}

:vaba.^udt^esize2021 Qd,Qn,Qm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=7 & Q6=1 & c0404=1) | 
                                     ($(TMODE_EorF) &     thv_c2327=0x1e &    thv_c2021<3 & thv_c0811=7 & thv_c0606=1 & thv_c0404=1 ) ) & Qd & Qn & Qm & udt & esize2021
{
	Qd = VectorAbsoluteDifferenceAndAccumulate(Qn,Qm,esize2021,udt);
}

:vabal.^udt^esize2021 Qd,Dn,Dm    is (($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c2021<3 & c0811=5 & Q6=0 & c0404=0) |
                                      ($(TMODE_EorF) &     thv_c2327=0x1f &    thv_c2021<3 & thv_c0811=5 & thv_c0606=0 & thv_c0404=0 ) ) & Qd & Dm & Dn & udt & esize2021
{
	Qd = VectorAbsoluteDifferenceAndAccumulate(Dn,Dm,esize2021,udt);
}

:vabd.^udt^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=7 & Q6=0 & c0404=0) |
                                      ($(TMODE_EorF) &     thv_c2327=0x1e &    thv_c2021<3 & thv_c0811=7 & thv_c0606=0 & thv_c0404=0 ) ) & Dm & Dn & Dd & udt & esize2021
{
	Dd = VectorAbsoluteDifference(Dn,Dm,esize2021,udt);
}

:vabd.^udt^esize2021 Qd,Qn,Qm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=7 & Q6=1 & c0404=0) |
                                     ($(TMODE_EorF) &     thv_c2327=0x1e &    thv_c2021<3 & thv_c0811=7 & thv_Q6=1 & thv_c0404=0 ) ) & Qd & Qn & Qm & udt & esize2021
{
	Qd = VectorAbsoluteDifference(Qn,Qm,esize2021,udt);
}

:vabdl.^udt^esize2021 Qd,Dn,Dm    is ( ($(AMODE) & ARMcond=0 & cond=15 &    c2527=1 & c2323=1 & c2021<3 &     c0811=7 &        Q6=0 &     c0404=0 ) | 
                                       ($(TMODE_EorF) &     thv_c2327=0x1f &    thv_c2021<3 & thv_c0811=7 & thv_c0606=0 & thv_c0404=0 ) ) & Dm & Dn & Qd & udt & esize2021
{
	Qd = VectorAbsoluteDifference(Dn,Dm,esize2021,udt);
}

:vabd.f^fesize2020 Dd,Dn,Dm    is ( ( $(AMODE) & ARMcond=0 & cond=15 &       c2327=6 &     c0811=13 &        Q6=0 &     c0404=0 ) |
                                   ($(TMODE_F)  &       thv_c2327=0x1e & thv_c0811=13 & thv_c0606=0 & thv_c0404=0 ) ) & fesize2020 & Dd & Dm & Dn
{
	Dd = FloatVectorAbsoluteDifference(Dn,Dm,fesize2020);
}

:vabd.f^fesize2020 Qd,Qn,Qm    is ( ( $(AMODE) & ARMcond=0 & cond=15 &   c2327=6 &     c0811=13 &        Q6=1 &     c0404=0 ) | 
                                  ($(TMODE_F)  &    thv_c2327=0x1e & thv_c0811=13 & thv_c0606=1 & thv_c0404=0 ) ) & fesize2020 & Qd & Qm & Qn
{
	Qd = FloatVectorAbsoluteDifference(Qn,Qm,fesize2020);
}

:vabs.s^esize1819 Dd,Dm    is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &        c2021=3 &     c1819<3 &     c1617=1 &     c0711=6 &        Q6=0 &     c0404=0 ) |
                                 ($(TMODE_F)  &       thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=6 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm & esize1819
{
	Dd = VectorAbsolute(Dm,esize1819);
}

:vabs.s^esize1819 Qd,Qm    is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &        c2021=3 &     c1819<3 &     c1617=1 &     c0711=6 &        Q6=1 &     c0404=0 ) |
                                 ($(TMODE_F)  &       thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=6 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm & esize1819
{
	Qd = VectorAbsolute(Qm,esize1819);
}

:vabs.f^esize1819 Dd,Dm    is ( ( $(AMODE) & ARMcond=0 & cond=15 &   c2327=7 &     c2021=3 &     (c1819=1 | c1819=2) &     c1617=1 &     c0711=0xe &        Q6=0 &     c0404=0 ) |
                             ($(TMODE_F)  &      thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2) & thv_c1617=1 & thv_c0711=0xe & thv_c0606=0 & thv_c0404=0 ) ) & esize1819 & Dm & Dd
{
	Dd = FloatVectorAbsolute(Dm,esize1819);
}

:vabs.f^esize1819 Qd,Qm    is ( ( $(AMODE) & ARMcond=0 & cond=15 &   c2327=7 &     c2021=3 &     (c1819=1 | c1819=2) &     c1617=1 &     c0711=0xe &        Q6=1 & c0404=0 ) |
                             ($(TMODE_F)  &                   thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2) & thv_c1617=1 & thv_c0711=0xe & thv_c0606=1 & thv_c0404=0 ) ) & esize1819 & Qd & Qm
{
	Qd = FloatVectorAbsolute(Qm,esize1819);
}

@endif # SIMD

@if defined(VFPv2) || defined(VFPv3)

:vabs^COND^".f32" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x30 &     c0611=0x2b &     c0404=0 ) |
                            ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x30 & thv_c0611=0x2b & thv_c0404=0 ) ) & COND & Sm & Sd
{
	build COND;
	build Sd;
	build Sm;
	Sd = abs(Sm);
}

:vabs^COND^".f64" Dd,Dm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x30 &     c0611=0x2f &     c0404=0 ) |
                            ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x30 & thv_c0611=0x2f & thv_c0404=0 ) ) & COND & Dd & Dm
{
	build COND;
	build Dd;
	build Dm;
	Dd = abs(Dm);
}

@endif # VFPv2 || VFPv3

define pcodeop FloatCompareGE;
define pcodeop FloatCompareGT;
define pcodeop VectorAbs;
define pcodeop VectorAdd;
define pcodeop VectorSub;
define pcodeop FloatVectorAdd;
define pcodeop VectorPairwiseAdd;
define pcodeop VectorPairwiseMin;
define pcodeop VectorPairwiseMax;
define pcodeop FloatVectorPairwiseAdd;
define pcodeop FloatVectorPairwiseMin;
define pcodeop FloatVectorPairwiseMax;
define pcodeop VectorPairwiseAddLong;
define pcodeop VectorPairwiseAddAccumulateLong;
define pcodeop VectorGetElement;

@if defined(SIMD)

:vacge.f^fesize2020 Dd,Dn,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &   c2327=6 &     c2121=0 &     c0811=14 &        Q6=0 &     c0404=1  ) |
                                 ($(TMODE_F)  &      thv_c2327=0x1e & thv_c2121=0 & thv_c0811=14 & thv_c0606=0 & thv_c0404=1 ) ) & fesize2020 & Dn & Dd & Dm
{
	Dd = FloatCompareGE(Dn,Dm,fesize2020);
}

:vacge.f^fesize2020 Qd,Qn,Qm is ( ( $(AMODE) & ARMcond=0 & cond=15 &   c2327=6 &     c2121=0 &     c0811=14 &        Q6=1 &     c0404=1  ) |
                                ($(TMODE_F)  &      thv_c2327=0x1e & thv_c2121=0 & thv_c0811=14 & thv_c0606=1 & thv_c0404=1 ) ) & fesize2020 & Qn & Qd & Qm
{
	Qd = FloatCompareGE(Qn,Qm,fesize2020);
}

:vacgt.f^fesize2020 Dd,Dn,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &   c2327=6 &     c2121=1 &     c0811=14 &        Q6=0 &     c0404=1  ) |
                                 ($(TMODE_F)  &      thv_c2327=0x1e & thv_c2121=1 & thv_c0811=14 & thv_c0606=0 & thv_c0404=1 ) ) & fesize2020 & Dn & Dd & Dm
{
	Dd = FloatCompareGT(Dn,Dm,fesize2020);
}

:vacgt.f^fesize2020 Qd,Qn,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &   c2327=6 &     c2121=1 &     c0811=14 &        Q6=1 &     c0404=1  ) |
                                 ($(TMODE_F)  &      thv_c2327=0x1e & thv_c2121=1 & thv_c0811=14 & thv_c0606=1 & thv_c0404=1 ) ) & fesize2020 & Qn & Qd & Qm
{
	Qd = FloatCompareGT(Qn,Qm,fesize2020);
}

:vadd.i^esize2021 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c0811=8 &     Q6=0 &     c0404=0) |
                               ($(TMODE_E) &    thv_c2327=0x1e & thv_c0811=8 & thv_Q6=0 & thv_c0404=0)) & esize2021 & Dn & Dd & Dm
{
	Dd = VectorAdd(Dn,Dm,esize2021);
}

:vadd.i^esize2021 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c0811=8 &     Q6=1 &     c0404=0) |
                               ($(TMODE_E) &    thv_c2327=0x1e & thv_c0811=8 & thv_Q6=1 & thv_c0404=0)) & esize2021 & Qm & Qn & Qd
{
	Qd = VectorAdd(Qn,Qm,esize2021);
}

:vadd.f^fesize2020 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2121=0 &     c0811=13 &     Q6=0 &     c0404=0) |
                              ($(TMODE_E) &    thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_Q6=0 & thv_c0404=0) ) & fesize2020 & Dm & Dn & Dd 
{
	Dd = FloatVectorAdd(Dn,Dm,fesize2020);
}

:vadd.f^fesize2020 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2121=0 &     c0811=13 &     Q6=1 &     c0404=0) |
                              ($(TMODE_E) &    thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_Q6=1 & thv_c0404=0) ) & fesize2020 & Qn & Qd & Qm
{
	Qd = FloatVectorAdd(Qn,Qm,fesize2020);
}

:vpadd.i^esize2021 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c0811=11 &     Q6=0 &     c0404=1) |
                                ($(TMODE_E) &    thv_c2327=0x1e & thv_c0811=11 & thv_Q6=0 & thv_c0404=1)) & esize2021 & Dn & Dd & Dm
{
	Dd = VectorPairwiseAdd(Dn,Dm,esize2021);
}

:vpadd.i^esize2021 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2021<3 &     c0811=11 &     Q6=1 &     c0404=1) |
                                ($(TMODE_E) &    thv_c2327=0x1e & thv_c2021<3 & thv_c0811=11 & thv_Q6=1 & thv_c0404=1) ) & esize2021 & Qm & Qn & Qd
{
	Qd = VectorPairwiseAdd(Qn,Qm,esize2021);
}

:vpadd.f^fesize2020 Dd,Dn,Dm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2121=0 &     c0811=13 &     Q6=0 &      c0404=0) |
                              ($(TMODE_F)  &   thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_Q6=0 & thv_c0404=0) ) & fesize2020 & Dm& Dn & Dd 
{
	Dd = FloatVectorPairwiseAdd(Dn,Dm,fesize2020:1);
}


:vpmax.^udt^esize2021 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3  &     c0811=10 &     Q6=0 &     c0404=0) |
                                   ($(TMODE_EorF) & thv_c2327=0x1e &       thv_c2021<3  & thv_c0811=10 & thv_Q6=0 & thv_c0404=0)) & udt & esize2021 & Dn & Dd & Dm
{
	Dd = VectorPairwiseMax(Dn,Dm,esize2021,udt);
}


:vpmax.f^fesize2020 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2121=0 &     c0811=15 &     Q6=0 &     c0404=0) |
                                 ($(TMODE_F) &    thv_c2327=0x1e & thv_c2121=0 & thv_c0811=15 & thv_Q6=0 & thv_c0404=0) ) & fesize2020 & Dm & Dn & Dd 
{
	Dd = FloatVectorPairwiseMax(Dn,Dm,fesize2020:1);
}

:vpmin.^udt^esize2021 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3  &     c0811=10 &     Q6=0 &     c0404=1) |
                                   ($(TMODE_EorF) &   thv_c2327=0x1e &       thv_c2021<3  & thv_c0811=10 & thv_Q6=0 & thv_c0404=1)) & udt & esize2021 & Dn & Dd & Dm
{
	Dd = VectorPairwiseMin(Dn,Dm,esize2021,udt);
}

:vpmin.f^fesize2020 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2121=1 &     c0811=15 &     Q6=0 &     c0404=0) |
                                 ($(TMODE_F) &    thv_c2327=0x1e & thv_c2121=1 & thv_c0811=15 & thv_Q6=0 & thv_c0404=0) ) & fesize2020 & Dm & Dn & Dd 
{
	Dd = FloatVectorPairwiseMin(Dn,Dm,fesize2020);
}

:vpadal.^udt7^esize1819 Dd,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &          c2021=3 &     c1617=0 &     c0811=6 &     Q6=0 &     c0404=0) |
                                  ($(TMODE_F)  &   thv_c2327=0x1f &      thv_c2021=3 & thv_c1617=0 & thv_c0811=6 & thv_Q6=0 & thv_c0404=0)) & udt7 & esize1819 & Dd & Dm
{
	Dd = VectorPairwiseAddAccumulateLong(Dm,esize1819);
}

:vpadal.^udt7^esize1819 Qd,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 &   c2327=7 &     c2021=3 &     c1617=0 &     c0811=6 &     Q6=1 &     c0404=0) |
                                  ($(TMODE_F) &      thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0811=6 & thv_Q6=1 & thv_c0404=0)) & udt7 & esize1819 & Qd & Qm
{
	Qd = VectorPairwiseAddAccumulateLong(Qm,esize1819);
}

:vpaddl.^udt7^esize1819 Dd,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1617=0 &     c0811=2 &     Q6=0 &     c0404=0) |
                                  ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0811=2 & thv_Q6=0 & thv_c0404=0)) & udt7 & esize1819 & Dd & Dm
{
	Dd = VectorPairwiseAddLong(Dm,esize1819);
}

:vpaddl.^udt7^esize1819 Qd,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 &   c2327=7 &     c2021=3 &     c1617=0 &     c0811=2 &     Q6=1 &     c0404=0) |
                                  ($(TMODE_F) &      thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0811=2 & thv_Q6=1 & thv_c0404=0)) & udt7 & esize1819 & Qd & Qm
{
	Qd = VectorPairwiseAddLong(Qm,esize1819);
}

@endif # SIMD

@if defined(VFPv2) || defined(VFPv3)

:vadd^COND^".f16" Sd,Sn,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=3 &     c0811=9 &     c0606=0 &     c0404=0) |
                               ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=3 & thv_c0811=9 & thv_c0606=0 & thv_c0404=0) ) & COND & Sm & Sd & Sn
{
	build COND;
	build Sd;
	build Sm;
	build Sn;
	local result:2 = Sn(0) f+ Sm(0);
	Sd = zext(result);
}

:vadd^COND^".f32" Sd,Sn,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=3 &     c0811=10 &     c0606=0 &     c0404=0) |
                               ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=3 & thv_c0811=10 & thv_c0606=0 & thv_c0404=0) ) & COND & Sm & Sd & Sn
{
	build COND;
	build Sd;
	build Sm;
	build Sn;
	Sd = Sn f+ Sm;
}

:vadd^COND^".f64" Dd,Dn,Dm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=3 &     c0811=11 &     c0606=0 &     c0404=0) |
                               ($(TMODE_E) &          thv_c2327=0x1c & thv_c2021=3 & thv_c0811=11 & thv_c0606=0 & thv_c0404=0) )  & COND & Dm & Dd & Dn
{
	build COND;
	build Dd;
	build Dm;
	build Dn;
	Dd = Dn f+ Dm;
}

@endif # VFPv2 || VFPv3

define pcodeop VectorAddReturnHigh;
define pcodeop VectorBitwiseInsertIfFalse;
define pcodeop VectorBitwiseInsertIfTrue;
define pcodeop VectorBitwiseSelect;
define pcodeop VectorCompareEqual;
define pcodeop FloatVectorCompareEqual;
define pcodeop VectorCompareGreaterThanOrEqual;
define pcodeop FloatVectorCompareGreaterThanOrEqual;
define pcodeop VectorCompareGreaterThan;
define pcodeop FloatVectorCompareGreaterThan;
define pcodeop VectorCountLeadingSignBits;
define pcodeop VectorCountLeadingZeros;
define pcodeop VectorComplexAdd;
define pcodeop VectorComplexMultiplyAccumulate;
define pcodeop VectorComplexMultiplyAccumulateByElement;

@if defined(SIMD)

:vaddhn.i^esize2021x2 Dd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=5 &     c2021<3 &     c0811=4 &     c0606=0 &     c0404=0) |
                                   ($(TMODE_E) &    thv_c2327=0x1f & thv_c2021<3 & thv_c0811=4 & thv_c0606=0 & thv_c0404=0) ) & esize2021x2 & Qn & Dd & Qm
{
	Dd = VectorAddReturnHigh(Qn,Qm,esize2021x2);
}

:vaddl.^udt^esize2021 Qd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 &     c2021<3  &    c0811=0 &      c0606=0 &     c0404=0) |
                                   ($(TMODE_EorF) &           thv_c2327=0x1f & thv_c2021<3 & thv_c0811=0  & thv_c0606=0 & thv_c0404=0) ) & esize2021 & udt & Dn & Qd & Dm
{
	Qd = VectorAdd(Dn,Dm,esize2021,udt);
}

:vaddw.^udt^esize2021 Qd,Qn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 &       c2021<3  &    c0811=1 &      c0606=0 &     c0404=0) |
                                     ($(TMODE_EorF) &         thv_c2327=0x1f &    thv_c2021<3 & thv_c0811=1  & thv_c0606=0 & thv_c0404=0) ) & esize2021 & udt & Qn & Qd & Dm
{
	Qd = VectorAdd(Qn,Dm,esize2021,udt);
}


:vand Dd,Dn,Dm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 & c2021=0 &         c0811=1 &     Q6=0 &     c0404=1)  |
                       ($(TMODE_E) &  thv_c2327=0x1e & thv_c2021=0 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm
{
	Dd = Dn & Dm;
}

:vand Qd,Qn,Qm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &    c2021=0 &     c0811=1 &     Q6=1 &     c0404=1)  |
                       ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qn & Qd & Qm
{
	Qd = Qn & Qm;
}

:vbic.i32 Dd,simdExpImm_8  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1111=0 &     c0808=1 &     c0407=3 ) |
                              ($(TMODE_EorF) &  thv_c2327=0x1f &      thv_c1921=0 & thv_c1111=0 & thv_c0808=1 & thv_c0407=3) ) & Dd & simdExpImm_8
{
	Dd = Dd & ~simdExpImm_8;
}

:vbic.i32 Qd,simdExpImm_16  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1111=0 &     c0808=1 &     c0407=7 ) |
                               ($(TMODE_EorF) & thv_c2327=0x1f &       thv_c1921=0 & thv_c1111=0 & thv_c0808=1 & thv_c0407=7) ) & Qd & simdExpImm_16
{
	Qd = Qd & ~simdExpImm_16;
}

:vbic.i16 Dd,simdExpImm_8	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1011=2 &     c0808=1 &     c0407=3 ) |
                                 ($(TMODE_EorF) &  thv_c2327=0x1f &    thv_c1921=0 & thv_c1011=2 & thv_c0808=1 & thv_c0407=3) ) & Dd & simdExpImm_8
{
	Dd = Dd & ~simdExpImm_8;
}

:vbic.i16 Qd,simdExpImm_16	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1011=2 &     c0808=1 &     c0407=7 ) |
                                 ($(TMODE_EorF) &  thv_c2327=0x1f &    thv_c1921=0 & thv_c1011=2 & thv_c0808=1 & thv_c0407=7) ) & Qd & simdExpImm_16
{
	Qd = Qd & ~simdExpImm_16;
}

:vbic Dd,Dn,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &        c2021=1 &     c0811=1 &     Q6=0 &     c0404=1 ) |
                     ($(TMODE_E) &     thv_c2327=0x1e & thv_c2021=1 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1) ) & Dm & Dn & Dd
{
	Dd = Dn & ~Dm;
}

:vbic Qd,Qn,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &        c2021=1 &     c0811=1 &     Q6=1 &     c0404=1 ) |
                     ($(TMODE_E) &     thv_c2327=0x1e & thv_c2021=1 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1) ) & Qm & Qn & Qd
{
	Qd = Qn & ~Qm;
}

:vbif Dd,Dn,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &        c2021=3 &     c0811=1 &     Q6=0 &     c0404=1 ) |
                     ($(TMODE_F)  &    thv_c2327=0x1e & thv_c2021=3 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1) ) & Dm & Dn & Dd
{
	Dd = VectorBitwiseInsertIfFalse(Dd,Dn,Dm);
}

:vbif Qd,Qn,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &        c2021=3 &     c0811=1 &     Q6=1 &     c0404=1 ) |
                      ($(TMODE_F)  &     thv_c2327=0x1e & thv_c2021=3 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qm & Qn & Qd
{
	Qd = VectorBitwiseInsertIfFalse(Qd,Qn,Qm);
}

:vbit Dd,Dn,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &        c2021=2 &     c0811=1 &     Q6=0 &     c0404=1 ) |
                     ($(TMODE_F)  &    thv_c2327=0x1e & thv_c2021=2 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dm & Dn & Dd
{
	Dd = VectorBitwiseInsertIfTrue(Dd,Dn,Dm);
}

:vbit Qd,Qn,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &        c2021=2 &     c0811=1 &     Q6=1 &     c0404=1 ) |
                     ($(TMODE_F)  &    thv_c2327=0x1e & thv_c2021=2 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qm & Qn & Qd
{
	Qd = VectorBitwiseInsertIfTrue(Qd,Qn,Qm);
}

:vbsl Dd,Dn,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &        c2021=1 &     c0811=1 &     Q6=0 &     c0404=1 ) |
                     ($(TMODE_F)  &    thv_c2327=0x1e & thv_c2021=1 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dm & Dn & Dd
{
	Dd = VectorBitwiseSelect(Dd,Dn,Dm);
}

:vbsl Qd,Qn,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &        c2021=1 &     c0811=1 &     Q6=1 &     c0404=1 ) |
                     ($(TMODE_F)  &    thv_c2327=0x1e & thv_c2021=1 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qm & Qn & Qd
{
	Qd = VectorBitwiseSelect(Qd,Qn,Qm);
}

crot2424: "#"^90  is ($(AMODE) & c2424=0 ) | (TMode=1 & thv_c2424=0) { local tmp:4 = 90;  export tmp; }
crot2424: "#"^270 is ($(AMODE) & c2424=1 ) | (TMode=1 & thv_c2424=1) { local tmp:4 = 270; export tmp; }


:vcadd.f^fesize2020 Dd,Dn,Dm,crot2424  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=6 &     c2323=1 &     c2121=0 &     c0811=8 &     Q6=0 &     c0404=1 ) |
                                        ($(TMODE_F) &       thv_c2527=6 & thv_c2323=1 & thv_c2121=0 & thv_c0811=8 & thv_Q6=0 & thv_c0404=1)) & crot2424 & fesize2020 & Dm & Dn & Dd
{
	Dd = VectorComplexAdd(Dd,Dn,Dm,crot2424,fesize2020);
}

:vcadd.f^fesize2020 Qd,Qn,Qm,crot2424  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=6 &     c2323=1 &     c2121=0 &     c0811=8 &     Q6=1 &     c0404=1 )|
                                        ($(TMODE_F) &       thv_c2527=6 & thv_c2323=1 & thv_c2021=0 & thv_c0811=8 & thv_Q6=1 & thv_c0404=1)) & crot2424 & fesize2020 & Qm & Qn & Qd
{
	Qd = VectorComplexAdd(Qd,Qn,Qm,crot2424,fesize2020);
}


:vceq.i^esize2021 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2021<3 &     c0811=8 &     Q6=0 &     c0404=1) |
                               ($(TMODE_F) &    thv_c2327=0x1e & thv_c2021<3 & thv_c0811=8 & thv_Q6=0 & thv_c0404=1) ) & esize2021 & Dm & Dn & Dd
{
	Dd = VectorCompareEqual(Dn,Dm,esize2021);
}

:vceq.i^esize2021 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2021<3 &     c0811=8 &     Q6=1 &     c0404=1) |
                               ($(TMODE_F) &    thv_c2327=0x1e & thv_c2021<3 & thv_c0811=8 & thv_Q6=1 & thv_c0404=1) ) & esize2021 & Qm & Qn & Qd
{
	Qd = VectorCompareEqual(Qn,Qm,esize2021);
}

:vceq.f^fesize2020 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &      c0811=14 &     Q6=0 &     c0404=0) |
                              ($(TMODE_E) &    thv_c2327=0x1e &  thv_c0811=14 & thv_Q6=0 & thv_c0404=0) ) & fesize2020 & Dm & Dn & Dd
{
	Dd = FloatVectorCompareEqual(Dn,Dm,fesize2020);
}

:vceq.f^fesize2020 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &      c0811=14 &     Q6=1 &     c0404=0) |
                              ($(TMODE_E) &    thv_c2327=0x1e &  thv_c0811=14 & thv_Q6=1 & thv_c0404=0) ) & fesize2020 & Qm & Qn & Qd
{
	Qd = FloatVectorCompareEqual(Qn,Qm,fesize2020);
}

:vceq.i^esize1819 Dd,Dm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=2 &     Q6=0 &     c0404=0) |
                                 ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=2 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero
{
	Dd = VectorCompareEqual(Dm,zero,esize1819);
}

:vceq.i^esize1819 Qd,Qm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=2 &     Q6=1 &     c0404=0) |
                                 ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=2 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd & zero
{
	Qd = VectorCompareEqual(Qm,zero,esize1819);
}

:vceq.f^fesize1819 Dd,Dm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &         (c1819=1 | c1819=2) &     c1617=1 &     c0711=10 &     Q6=0 &     c0404=0) |
                                ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2) & thv_c1617=1 & thv_c0711=10 & thv_Q6=0 & thv_c0404=0) ) & fesize1819 & Dm & Dd & zero
{
	Dd = FloatVectorCompareEqual(Dm,zero,fesize1819);
}

:vceq.f^fesize1819 Qd,Qm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3  &     c1617=1 &     c0711=10 &     Q6=1 &     c0404=0) |
                                ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3  & thv_c1617=1 & thv_c0711=10 & thv_Q6=1 & thv_c0404=0) ) & fesize1819 & Qm & Qd & zero
{
	Qd = FloatVectorCompareEqual(Qm,zero,fesize1819);
}

:vcge.^udt^esize2021 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 &     c2021<3 &     c0811=3 &     Q6=0 &     c0404=1) |
                                  ($(TMODE_EorF) &           thv_c2327=0x1e & thv_c2021<3 & thv_c0811=3 & thv_Q6=0 & thv_c0404=1) ) & udt & esize2021 & Dm & Dn & Dd
{
	Dd = VectorCompareGreaterThanOrEqual(Dn,Dm,esize2021,udt);
}

:vcge.^udt^esize2021 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 &     c2021<3 &     c0811=3 &     Q6=1 &     c0404=1) |
                                  ($(TMODE_EorF) &           thv_c2327=0x1e & thv_c2021<3 & thv_c0811=3 & thv_Q6=1 & thv_c0404=1) ) & udt & esize2021 & Qm & Qn & Qd
{
	Qd = VectorCompareGreaterThanOrEqual(Qn,Qm,esize2021,udt);
}

:vcge.f^fesize2020 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2121=0 &     c0811=14 &     Q6=0 &     c0404=0) |
                              ($(TMODE_F) &    thv_c2327=0x1e & thv_c2021=0 & thv_c0811=14 & thv_Q6=0 & thv_c0404=0) ) & fesize2020 & Dm & Dn & Dd
{
	Dd = FloatVectorCompareGreaterThanOrEqual(Dn,Dm,2:1,32:1);
}

:vcge.f^fesize2020 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2121=0 &     c0811=14 &     Q6=1 &     c0404=0) |
                              ($(TMODE_F) &    thv_c2327=0x1e & thv_c2021=0 & thv_c0811=14 & thv_Q6=1 & thv_c0404=0) ) & fesize2020 & Qm & Qn & Qd
{
	Qd = FloatVectorCompareGreaterThanOrEqual(Qn,Qm,2:1,32:1);
}

:vcge.s^esize1819 Dd,Dm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=1 &     Q6=0 &     c0404=0) |
                                 ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=1 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero
{
	Dd = VectorCompareGreaterThanOrEqual(Dm,zero,esize1819);
}

:vcge.s^esize1819 Qd,Qm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=1 &     Q6=1 &     c0404=0) |
                                 ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=1 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd & zero
{
	Qd = VectorCompareGreaterThanOrEqual(Qm,zero,esize1819);
}

:vcge.f^fesize1819 Dd,Dm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &         (c1819=1 | c1819=2) &     c1617=1 &     c0711=9 &     Q6=0 &     c0404=0) |
                                ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2) & thv_c1617=1 & thv_c0711=9 & thv_Q6=0 & thv_c0404=0) ) & fesize1819 & Dm & Dd & zero
{
	Dd = FloatVectorCompareGreaterThanOrEqual(Dm,zero,fesize1819);
}

:vcge.f^fesize1819 Qd,Qm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &         (c1819=1 | c1819=2) &     c1617=1 &     c0711=9 &     Q6=1 &     c0404=0) |
                                ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2) & thv_c1617=1 & thv_c0711=9 & thv_Q6=1 & thv_c0404=0) ) & fesize1819 & Qm & Qd & zero
{
	Qd = FloatVectorCompareGreaterThanOrEqual(Qm,zero,fesize1819);
}

:vcgt.^udt^esize2021 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 &     c2021<3 &     c0811=3 &     Q6=0 &     c0404=0) |
                                  ($(TMODE_EorF) &           thv_c2327=0x1e & thv_c2021<3 & thv_c0811=3 & thv_Q6=0 & thv_c0404=0) ) & udt & esize2021 & Dm & Dn & Dd
{
	Dd = VectorCompareGreaterThan(Dn,Dm,esize2021);
}

:vcgt.^udt^esize2021 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 &     c2021<3 &     c0811=3 &     Q6=1 &     c0404=0) |
                                  ($(TMODE_EorF) &           thv_c2327=0x1e & thv_c2021<3 & thv_c0811=3 & thv_Q6=1 & thv_c0404=0) ) & udt & esize2021 & Qm & Qn & Qd
{
	Qd = VectorCompareGreaterThan(Qn,Qm,esize2021);
}

:vcgt.f^fesize2020 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2121=1 &     c0811=14 &     Q6=0 &     c0404=0) |
                              ($(TMODE_F) &    thv_c2327=0x1e & thv_c2121=1 & thv_c0811=14 & thv_Q6=0 & thv_c0404=0) ) & fesize2020 & Dm & Dn & Dd
{
	Dd = FloatVectorCompareGreaterThan(Dn,Dm,fesize2020);
}

:vcgt.f^fesize2020 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2121=1 &     c0811=14 &     Q6=1 &     c0404=0) |
                              ($(TMODE_F) &    thv_c2327=0x1e & thv_c2121=1 & thv_c0811=14 & thv_Q6=1 & thv_c0404=0) ) & fesize2020 & Qm & Qn & Qd
{
	Qd = FloatVectorCompareGreaterThan(Qn,Qm,fesize2020);
}

:vcgt.i^esize1819 Dd,Dm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=0 &     Q6=0 &     c0404=0) |
                                 ($(TMODE_F)  &       thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=0 & thv_Q6=0 & thv_c0404=0 ) ) & esize1819 & Dd & Dm & zero
{
	Dd = VectorCompareGreaterThan(Dm,zero,esize1819);
}

:vcgt.i^esize1819 Qd,Qm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=0 &     Q6=1 &     c0404=0) |
                                 ($(TMODE_F)  &       thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=0 & thv_Q6=1 & thv_c0404=0 ) ) & esize1819 & Qd & Qm & zero
{
	Qd = VectorCompareGreaterThan(Qm,zero,esize1819);
}

:vcgt.f^fesize1819 Dd,Dm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 &      c2327=7 &     c2021=3 &         (c1819=1 | c1819=2) &     c1617=1 &     c0711=8 &     Q6=0 &     c0404=0) |
                                ($(TMODE_F)  &        thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2)  & thv_c1617=1 & thv_c0711=8 & thv_Q6=0 & thv_c0404=0 ) ) & fesize1819 & Dd & Dm & zero
{
	Dd = FloatVectorCompareGreaterThan(Dm,zero,fesize1819);
}

:vcgt.f^fesize1819 Qd,Qm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 &      c2327=7 &     c2021=3 &         (c1819=1 | c1819=2) &     c1617=1 &     c0711=8 &     Q6=1 &     c0404=0) |
                                ($(TMODE_F)  &        thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2) & thv_c1617=1 & thv_c0711=8 & thv_Q6=1 & thv_c0404=0 ) ) & fesize1819 & Qd & Qm & zero
{
	Qd = FloatVectorCompareGreaterThan(Qm,zero,fesize1819);
}

:vcle.s^esize1819 Dd,Dm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=3 &     Q6=0 &     c0404=0) |
                                 ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=3 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dd & Dm & zero
{
	Dd = VectorCompareGreaterThanOrEqual(zero,Dm,esize1819);
}

:vcle.s^esize1819 Qd,Qm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=3 &     Q6=1 &     c0404=0) |
                                 ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=3 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qd & Qm & zero
{
	Qd = VectorCompareGreaterThanOrEqual(zero,Qm,esize1819);
}

:vcle.f^fesize1819 Dd,Dm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &         (c1819=1 | c1819=2) &     c1617=1 &     c0711=0xb &     Q6=0 &     c0404=0) |
                                ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2) & thv_c1617=1 & thv_c0711=0xb & thv_Q6=0 & thv_c0404=0) ) & fesize1819 & Dd & Dm & zero
{
	Dd = FloatVectorCompareGreaterThanOrEqual(zero,Dm,fesize1819);
}

:vcle.f^fesize1819 Qd,Qm,zero  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &         (c1819=1 | c1819=2) &     c1617=1 &     c0711=0xb &     Q6=1 &     c0404=0) |
                                ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2) & thv_c1617=1 & thv_c0711=0xb & thv_Q6=1 & thv_c0404=0) ) & fesize1819 & Qd & Qm & zero
{
	Qd = FloatVectorCompareGreaterThanOrEqual(zero,Qm,fesize1819);
}

:vcls.s^esize1819 Dd,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=0 &     c0711=8 &     Q6=0 &     c0404=0) |
                            ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=0 & thv_c0711=8 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dd & Dm
{
	Dd = VectorCountLeadingSignBits(Dm,esize1819);
}

:vcls.s^esize1819 Qd,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=0 &     c0711=8 &     Q6=1 &     c0404=0) |
                            ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=0 & thv_c0711=8 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qd & Qm
{
	Qd = VectorCountLeadingSignBits(Qm,esize1819);
}

:vclt.s^esize1819 Dd,Dm,zero  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=4 &     Q6=0 &     c0404=0) |
                                 ( $(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=4 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero
{
	Dd = VectorCompareGreaterThan(zero,Dm,esize1819);
}

:vclt.s^esize1819 Qd,Qm,zero  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=4 &     Q6=1 &     c0404=0) |
                                 ( $(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=4 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd & zero
{
	Qd = VectorCompareGreaterThan(zero,Qm,esize1819);
}

:vclt.f^fesize1819 Dd,Dm,zero  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &         (c1819=1 | c1819=2) &     c1617=1 &     c0711=12 &     Q6=0 &     c0404=0) |
                                ( $(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2) & thv_c1617=1 & thv_c0711=12 & thv_Q6=0 & thv_c0404=0) ) & fesize1819 & Dm & Dd & zero
{
	Dd = FloatVectorCompareGreaterThan(zero,Dm,fesize1819);
}

:vclt.f^fesize1819 Qd,Qm,zero  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &         (c1819=1 | c1819=2) &     c1617=1 &     c0711=12 &     Q6=1 &     c0404=0) |
                                ( $(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & (thv_c1819=1 | thv_c1819=2) & thv_c1617=1 & thv_c0711=12 & thv_Q6=1 & thv_c0404=0) ) & fesize1819 & Qm & Qd & zero
{
	Qd = FloatVectorCompareGreaterThan(zero,Qm,fesize1819);
}

:vclz.i^esize1819 Dd,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=0 &     c0711=9 &     Q6=0 & c0404=0) | 
                            ( $(TMODE_F) &   thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=0 & thv_c0711=9 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dd & Dm
{
	Dd = VectorCountLeadingZeros(Dm,esize1819);
}

:vclz.i^esize1819 Qd,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=0 &     c0711=9 &     Q6=1 &     c0404=0) | 
                              ( $(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=0 & thv_c0711=9 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qd & Qm
{
	Qd = VectorCountLeadingZeros(Qm,esize1819);
}

crot2324: "#"^0  is ($(AMODE) & c2324=0 ) | (TMode=1 & thv_c2324=0) { local tmp:4 = 0;  export tmp; }
crot2324: "#"^90 is ($(AMODE) & c2324=1 ) | (TMode=1 & thv_c2324=1) { local tmp:4 = 90; export tmp; }
crot2324: "#"^180 is ($(AMODE) & c2324=2 ) | (TMode=1 & thv_c2324=2) { local tmp:4 = 180; export tmp; }
crot2324: "#"^270 is ($(AMODE) & c2324=3 ) | (TMode=1 & thv_c2324=3) { local tmp:4 = 270; export tmp; }
crot2021: "#"^0  is ($(AMODE) & c2021=0 ) | (TMode=1 & thv_c2021=0) { local tmp:4 = 0;  export tmp; }
crot2021: "#"^90 is ($(AMODE) & c2021=1 ) | (TMode=1 & thv_c2021=1) { local tmp:4 = 90; export tmp; }
crot2021: "#"^180 is ($(AMODE) & c2021=2 ) | (TMode=1 & thv_c2021=2) { local tmp:4 = 180; export tmp; }
crot2021: "#"^270 is ($(AMODE) & c2021=3 ) | (TMode=1 & thv_c2021=3) { local tmp:4 = 270; export tmp; }

:vcmla.f^fesize2020 Dd,Dn,Dm,crot2324  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=6 &     c2121=1 &     c0811=8 &     Q6=0 &     c0404=0 ) |
                                        ($(TMODE_F) &       thv_c2527=6 &               thv_c2121=1 & thv_c0811=8 & thv_Q6=0 & thv_c0404=0)) & crot2324 & fesize2020 & Dm & Dn & Dd
{
	Dd = VectorComplexMultiplyAccumulate(Dd,Dn,Dm,crot2324,fesize2020);
}

:vcmla.f^fesize2020 Qd,Qn,Qm,crot2324  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=6 &     c2121=1 &     c0811=8 &     Q6=1 &     c0404=0 )|
                                        ($(TMODE_F) &       thv_c2527=6 &               thv_c2021=1 & thv_c0811=8 & thv_Q6=1 & thv_c0404=0)) & crot2324 & fesize2020 & Qm & Qn & Qd
{
	Qd = VectorComplexMultiplyAccumulate(Qd,Qn,Qm,crot2324,fesize2020);
}

:vcmla.f^fesize2323 Dd,Dn,Dm,crot2021  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=7 &     c2424=0 &     c0811=8 &     Q6=0 &     c0404=0 ) |
                                        ($(TMODE_F) &                     thv_c2527=7 & thv_c2424=0 & thv_c0811=8 & thv_Q6=0 & thv_c0404=0)) & crot2021 & fesize2323 & Dm & Dn & Dd
{
	Dd = VectorComplexMultiplyAccumulateByElement(Dd,Dn,Dm,crot2021,fesize2323);
}

:vcmla.f^fesize2323 Qd,Qn,Qm,crot2021  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=7 &     c2424=0 &     c0811=8 &     Q6=1 &     c0404=0 )|
                                        ($(TMODE_F) &                     thv_c2527=7 & thv_c2424=0 & thv_c0811=8 & thv_Q6=1 & thv_c0404=0)) & crot2021 & fesize2323 & Qm & Qn & Qd
{
	Qd = VectorComplexMultiplyAccumulateByElement(Qd,Qn,Qm,crot2021,fesize2323);
}

@endif # SIMD

# set float register flags correctly for comparison
macro FloatVectorCompare(op1,op2,nanx) {
	local tNG = op1 f< op2;
	local tZR = op1 f== op2;	
	local tCY = op2 f<= op1;
	tOV:1 = nan(op1) | nan(op2);  # this is really a comparison with NAN and may also raise an exception when NAN
	
	fpscr = (fpscr & 0x0fffffff) | (zext(tNG) << 31) | (zext(tZR) << 30) | (zext(tCY) << 29) | (zext(tOV) << 28);
}

@if defined(VFPv2) || defined(VFPv3)

nanx: "e"	is c0707=1	{ export 1:1; }
nanx: 		is c0707=0	{ export 0:1; }

:vcmp^nanx^COND^".f16" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d & c2021=3 & c1619=4 & c0811=0b1001 & c0606=1 & c0404=0) |
	                             ( $(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c1619=4 & thv_c0811=0b1001 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & nanx & Sm
{
	build COND;
	build Sd;
	build Sm;
	local sm16:2 = Sm(0);
	local sd16:2 = Sd(0);
	
	FloatVectorCompare(sd16,sm16,nanx);
}

:vcmp^nanx^COND^".f32" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=3 &     c1619=4 &     c0811=0b1010 &     c0606=1 &     c0404=0) |
	                             ( $(TMODE_E) &                thv_c2327=0x1d & thv_c2021=3 & thv_c1619=4 & thv_c0811=0b1010 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & nanx & Sm
{
	build COND;
	build Sd;
	build Sm;

	FloatVectorCompare(Sd,Sm,nanx);
}

:vcmp^nanx^COND^".f64" Dd,Dm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=3 &     c1619=4 &     c0811=0b1011 &     c0606=1 &     c0404=0) |
	                             ( $(TMODE_E) &                thv_c2327=0x1d & thv_c2021=3 & thv_c1619=4 & thv_c0811=0b1011 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & nanx & Dm
{
	build COND;
	build Dd;
	build Dm;
	FloatVectorCompare(Dd,Dm,nanx);
}

:vcmp^nanx^COND^".f16" Sd,zero  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=3 &     c1619=5 &     c0811=0b1001 &     c0006=0b1000000 ) |
		                           ( $(TMODE_E) &                thv_c2327=0x1d & thv_c2021=3 & thv_c1619=5 & thv_c0811=0b1001 & thv_c0006=0b1000000 ) ) & COND & Sd & nanx & zero
{
	build COND;
	build Sd;
	local Zero:2 = 0;
	local sd16:2 = Sd(0);
	
	FloatVectorCompare(sd16,Zero,nanx);
}

:vcmp^nanx^COND^".f32" Sd,zero  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=3 &     c1619=5 &     c0811=0b1010 &     c0006=0b1000000 ) |
		                           ( $(TMODE_E) &                thv_c2327=0x1d & thv_c2021=3 & thv_c1619=5 & thv_c0811=0b1010 & thv_c0006=0b1000000 ) ) & COND & Sd & nanx & zero
{
	build COND;
	build Sd;
	local Zero:4 = 0;
	FloatVectorCompare(Sd,Zero,nanx);
}

:vcmp^nanx^COND^".f64" Dd,zero  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=3 &     c1619=5 &     c0811=0b1011 &     c0006=0b1000000 ) |
		                           ( $(TMODE_E) &                thv_c2327=0x1d & thv_c2021=3 & thv_c1619=5 & thv_c0811=0b1011 & thv_c0006=0b1000000 ) ) & COND & Dd & nanx & zero
{
	build COND;
	build Dd;
	local Zero:8 = 0;
	FloatVectorCompare(Dd,Zero,nanx);
}

@endif # VFPv2 || VFPv3

define pcodeop VectorCountOneBits;


@ifndef VERSION_8
#second arg to conversion function indicates rounding mode (see RMODE bits of FPSCR)
define pcodeop VectorFloatToSigned;
define pcodeop VectorFloatToUnsigned;
define pcodeop VectorSignedToFloat;
define pcodeop VectorUnsignedToFloat;
@endif # VERSION_8

@if defined(SIMD)
#######
# VCVT (between floating-point and integer, Advanced SIMD)
#

:vcnt.8 Dd,Dm   is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 & c2021=3 & c1619=0 & c0711=10 & Q6=0 & c0404=0) |
					 ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0 & thv_c0711=10 & thv_c0606=0 & thv_c0404=0) ) & Dd & Dm
{
	Dd = VectorCountOneBits(Dm,8:1,8:1);
}

:vcnt.8 Qd,Qm   is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 & c2021=3 & c1819=0 & c1617=0 & c0711=10 & Q6=1 & c0404=0) |
					 ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0 & thv_c0711=10 & thv_c0606=1 & thv_c0404=0) ) & Qd & Qm
{
	Qd = VectorCountOneBits(Qm,8:1,8:1);
}

@ifndef VERSION_8
:vcvt.s16.f16 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x37 &     c0911=3 &     c0708=2 &        Q6=0 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x37 & thv_c0911=3 & thv_c0708=2 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm

{
	Dd = VectorFloatToSigned(Dm,3:1);
}

:vcvt.u16.f16 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x37 &     c0911=3 &     c0708=3 &        Q6=0 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x37 & thv_c0911=3 & thv_c0708=3 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm

{
	Dd = VectorFloatToUnsigned(Dm,0:1);
}

:vcvt.f16.s16 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x37 &     c0911=3 &     c0708=0 &        Q6=0 &     c0404=0) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x37 & thv_c0911=3 & thv_c0708=0 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm
{
	Dd = VectorSignedToFloat(Dm,0:1);
}

:vcvt.f16.u16 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x37 &     c0911=3 &     c0708=1 &        Q6=0 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x37 & thv_c0911=3 & thv_c0708=1 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm

{
	Dd = VectorUnsignedToFloat(Dm,0:1);
}

:vcvt.s32.f32 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x3b &     c0911=3 &     c0708=2 &        Q6=0 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=2 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm

{
	Dd = VectorFloatToSigned(Dm,3:1);
}

:vcvt.u32.f32 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x3b &     c0911=3 &     c0708=3 &        Q6=0 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=3 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm

{
	Dd = VectorFloatToUnsigned(Dm,3:1);
}

:vcvt.f32.s32 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x3b &     c0911=3 &     c0708=0 &        Q6=0 &     c0404=0) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=0 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm
{
	Dd = VectorSignedToFloat(Dm,0:1);
}

:vcvt.f32.u32 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &   c1621=0x3b &     c0911=3 &     c0708=1 &        Q6=0 &     c0404=0 ) |
                        ( $(TMODE_F) &  thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=1 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm

{
	Dd = VectorUnsignedToFloat(Dm,0:1);
}





:vcvt.s16.f16 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x37 &     c0911=3 &     c0708=2 &        Q6=1 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x37 & thv_c0911=3 & thv_c0708=2 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm

{
	Qd = VectorFloatToSigned(Qm,6:1);
}

:vcvt.u16.f16 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x37 &     c0911=3 &     c0708=3 &        Q6=1 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x37 & thv_c0911=3 & thv_c0708=3 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm

{
	Qd = VectorFloatToUnsigned(Qm,7:1);
}

:vcvt.f16.s16 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x37 &     c0911=3 &     c0708=0 &        Q6=1 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x37 & thv_c0911=3 & thv_c0708=0 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm

{
	Qd = VectorSignedToFloat(Qm,4:1);
}

:vcvt.f16.u16 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x37 &     c0911=3 &     c0708=1 &        Q6=1 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x37 & thv_c0911=3 & thv_c0708=1 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm

{
	Qd = VectorUnsignedToFloat(Qm,5:1);
}

:vcvt.s32.f32 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x3b &     c0911=3 &     c0708=2 &        Q6=1 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=2 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm

{
	Qd = VectorFloatToSigned(Qm,10:1);
}

:vcvt.u32.f32 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x3b &     c0911=3 &     c0708=3 &        Q6=1 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=3 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm

{
	Qd = VectorFloatToUnsigned(Qm,11:1);
}

:vcvt.f32.s32 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x3b &     c0911=3 &     c0708=0 &        Q6=1 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=0 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm

{
	Qd = VectorSignedToFloat(Qm,8:1);
}

:vcvt.f32.u32 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x3b &     c0911=3 &     c0708=1 &        Q6=1 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=1 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm

{
	Qd = VectorUnsignedToFloat(Qm,9:1);
}

@endif # ! VERSION_8
@endif # SIMD

@if defined(VFPv2) || defined(VFPv3)

@ifndef VERSION_8
#######
# VCVT (between floating-point and integer, VFP)
#

roundMode: "r"	is TMode=0 & c0707=0		{ tmp:1 = $(FPSCR_RMODE); export tmp; }
roundMode: 		is TMode=0 & c0707=1		{ export 3:1; } # Round towards zero
roundMode: "r"	is TMode=1 & thv_c0707=0	{ tmp:1 = $(FPSCR_RMODE); export tmp; }
roundMode: 		is TMode=1 & thv_c0707=1	{ export 3:1; } # Round towards zero

:vcvt^roundMode^COND^".s32.f16" Sd,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=5 &     c0911=4 &     c0808=1 &     c0606=1 &     c0404=0) | 
                                          ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=5 & thv_c0911=4 & thv_c0808=1 & thv_c0606=1 & thv_c0404=0) ) & COND &  Sd & Sm & roundMode
{
	build COND;
	build Sd;
	build Sm;
	build roundMode;
    local Sm16:2 = Sm(0);
	Sd = trunc(Sm16);#VectorFloatToSigned(Sm16,roundMode);
}

:vcvt^roundMode^COND^".s32.f32" Sd,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=5 &     c0911=5 &     c0808=0 &    c0606=1 &     c0404=0) | 
                                          ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=5 & thv_c0911=5 & thv_c0808=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sm & roundMode
{
	build COND;
	build Sd;
	build Sm;
	build roundMode;
	Sd = trunc(Sm);#VectorFloatToSigned(Sm16,roundMode);
}

:vcvt^roundMode^COND^".s32.f64" Sd,Dm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=5 &     c0911=5 &     c0808=1 &     c0606=1 &     c0404=0) | 
                                          ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=5 & thv_c0911=5 & thv_c0808=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & roundMode & Dm
{
	build COND;
	build Sd;
	build Dm;
	build roundMode;
	Sd = VectorFloatToSigned(Dm,roundMode);
}

:vcvt^roundMode^COND^".u32.f16" Sd,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=4 &     c0911=4 &     c0808=1 &     c0606=1 &     c0404=0) | 
                                          ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=4 & thv_c0911=4 & thv_c0808=1 & thv_c0606=1 & thv_c0404=0) ) & COND & roundMode & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	build roundMode;
    local Sm16:2 = Sm(0);
	Sd = VectorFloatToUnsigned(Sm16,roundMode);
}

:vcvt^roundMode^COND^".u32.f32" Sd,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=4 &     c0911=5 &     c0808=0 &     c0606=1 &     c0404=0) | 
                                          ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=4 & thv_c0911=5 & thv_c0808=0 & thv_c0606=1 & thv_c0404=0) ) & COND & roundMode & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	build roundMode;
	Sd = VectorFloatToUnsigned(Sm,roundMode);
}

:vcvt^roundMode^COND^".u32.f64" Sd,Dm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=4 &     c0911=5 &     c0808=1 &     c0606=1 &     c0404=0) | 
                                          ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=4 & thv_c0911=5 & thv_c0808=1 & thv_c0606=1 & thv_c0404=0)) & COND & roundMode & Sd & Dm
{
	build COND;
	build Sd;
	build Dm;
	build roundMode;
	Sd = VectorFloatToUnsigned(Dm,roundMode);
}

:vcvt^COND^".f16.s32" Sd,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=0 &     c0911=4 &     c0808=1 &     c0707=1 &     c0606=1 &     c0404=0) |
                                ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=0 & thv_c0911=4 & thv_c0808=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	local mode:1 = $(FPSCR_RMODE);
	local Sm16:2 = Sm(0);
	Sd = VectorSignedToFloat(Sm16,mode);
}

:vcvt^COND^".f16.u32" Sd,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=0 &     c0911=4 &     c0808=1 &     c0707=0 &     c0606=1 &     c0404=0) |
                                ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=0 & thv_c0911=4 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	local mode:1 = $(FPSCR_RMODE);
	local Sm16:2 = Sm(0);
	Sd = VectorUnsignedToFloat(Sm16,mode);
}

:vcvt^COND^".f64.s32" Dd,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=0 &     c0911=5 &     c0808=1 &     c0707=1 &     c0606=1 &     c0404=0) |
                                ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=0 & thv_c0911=5 & thv_c0808=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & Sm
{
	build COND;
	build Dd;
	build Sm;
	mode:1 = $(FPSCR_RMODE);
	Dd = VectorSignedToFloat(Sm,mode);
}

:vcvt^COND^".f32.s32" Sd,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=0 &     c0911=5 &     c0808=0 &     c0707=1 &     c0606=1 &     c0404=0) |
                                ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=0 & thv_c0911=5 & thv_c0808=0 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	mode:1 = $(FPSCR_RMODE);
	Sd = VectorSignedToFloat(Sm,mode);
}

:vcvt^COND^".f32.u32" Sd,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=0 &     c0911=5 &     c0808=0 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=0 & thv_c0911=5 & thv_c0808=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	mode:1 = $(FPSCR_RMODE);
	Sd = VectorUnsignedToFloat(Sm,mode);
}

:vcvt^COND^".f64.u32" Dd,Sm  is  ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1618=0 &     c0911=5 &     c0808=1 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                 ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1618=0 & thv_c0911=5 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & Sm
{
	build COND;
	build Dd;
	build Sm;
	mode:1 = $(FPSCR_RMODE);
	Dd = VectorUnsignedToFloat(Sm,mode);
}

@endif # ! VERSION_8
@endif # VFPv2 || VFPv3

@if defined(SIMD)
@ifndef VERSION_8
define pcodeop VectorFloatToSignedFixed;
define pcodeop VectorFloatToUnsignedFixed;
define pcodeop VectorSignedFixedToFloat;
define pcodeop VectorUnsignedFixedToFloat;

#######
# VCVT (between floating-point and fixed-point, Advanced SIMD)
#

fbits: "#"val	is TMode=0 & c1621     [ val = 64 - c1621; ]     { tmp:1 = val; export tmp; }
fbits: "#"val	is TMode=1 & thv_c1621 [ val = 64 - thv_c1621; ] { tmp:1 = val; export tmp; }

:vcvt.s16.f16 Dd,Dm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 &     c2121=1 &     c0911=6 &     c0808=1 &     c0707=0 &        Q6=0 &     c0404=1) |
                               ($(TMODE_E) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=6 & thv_c0808=1 & thv_c0707=0 & thv_c0606=0 & thv_c0404=1) ) & fbits & Dd & Dm
{
	Dd = VectorFloatToSignedFixed(Dm,fbits);
}

:vcvt.u16.f16 Dd,Dm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 &     c2121=1 &     c0911=6 &     c0808=1 &     c0707=0 &        Q6=0 &     c0404=1) |
                               ($(TMODE_F) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=6 & thv_c0808=1 & thv_c0707=0 & thv_c0606=0 & thv_c0404=1) ) & fbits & Dd & Dm

{
	Dd = VectorFloatToUnsignedFixed(Dm,fbits);
}

:vcvt.f16.s16 Dd,Dm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 &     c2121=1 &     c0911=6 &     c0808=0 &     c0707=0 &        Q6=0 &     c0404=1) |
                               ($(TMODE_E) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=6 & thv_c0808=0 & thv_c0707=0 & thv_c0606=0 & thv_c0404=1) ) & fbits & Dd & Dm
{
	Dd = VectorSignedFixedToFloat(Dm,fbits);
}

:vcvt.f16.u16 Dd,Dm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 &     c2121=1 &     c0911=6 &     c0808=0 &     c0707=0 &        Q6=0 &     c0404=1) |
                               ($(TMODE_F) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=6 & thv_c0808=0 & thv_c0707=0 & thv_c0606=0 & thv_c0404=1) ) & fbits & Dd & Dm
{
	Dd = VectorUnsignedFixedToFloat(Dm,fbits);
}

:vcvt.s16.f16 Qd,Qm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 &     c2121=1 &     c0911=6 &     c0808=1 &     c0707=0 &        Q6=1 &     c0404=1) |
                               ($(TMODE_E) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=6 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=1) ) & fbits & Qd & Qm
{
	Qd = VectorFloatToSignedFixed(Qm,fbits);
}

:vcvt.u16.f16 Qd,Qm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 &     c2121=1 &     c0911=6 &     c0808=1 &     c0707=0 &        Q6=1 &     c0404=1) |
                               ($(TMODE_F) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=6 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=1) ) & fbits & Qd & Qm
{
	Qd = VectorFloatToUnsignedFixed(Qm,fbits);
}

:vcvt.f16.s16 Qd,Qm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 &     c2121=1 &     c0911=0 &     c0808=0 &     c0707=0 &        Q6=1 &     c0404=1) |
                               ($(TMODE_E) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=0 & thv_c0808=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=1) ) & fbits & Qd & Qm
{
	Qd = VectorSignedFixedToFloat(Qm,fbits);
}

:vcvt.f16.u16 Qd,Qm,fbits is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 &     c2121=1 &     c0911=0 &     c0808=0 &     c0707=0 &        Q6=1 &     c0404=1) |
                              ($(TMODE_F) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=0 & thv_c0808=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=1) ) & fbits & Qd & Qm
{
	Qd = VectorUnsignedFixedToFloat(Qm,fbits);
}

:vcvt.f32.s32 Dd,Dm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 &     c2121=1 &     c0911=7 &     c0808=0 &     c0707=0 &        Q6=0 &     c0404=1) |
                               ($(TMODE_E) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=7 & thv_c0808=0 & thv_c0707=0 & thv_c0606=0 & thv_c0404=1) ) & fbits & Dd & Dm
{
	Dd = VectorSignedFixedToFloat(Dm,fbits);
}

:vcvt.f32.u32 Dd,Dm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 &     c2121=1 &     c0911=7 &     c0808=0 &     c0707=0 &        Q6=0 &     c0404=1) |
                               ($(TMODE_F) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=7 & thv_c0808=0 & thv_c0707=0 & thv_c0606=0 & thv_c0404=1) ) & fbits & Dd & Dm
{
	Dd = VectorUnsignedFixedToFloat(Dm,fbits);
}

:vcvt.s32.f32 Qd,Qm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 &     c2121=1 &     c0911=7 &     c0808=1 &     c0707=0 &        Q6=1 &     c0404=1) |
                               ($(TMODE_E) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=7 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=1) ) & fbits & Qd & Qm
{
	Qd = VectorFloatToSignedFixed(Qm,fbits);
}

:vcvt.u32.f32 Qd,Qm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 &     c2121=1 &     c0911=7 &     c0808=1 &     c0707=0 &        Q6=1 &     c0404=1) |
                               ($(TMODE_F) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=7 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=1) ) & fbits & Qd & Qm
{
	Qd = VectorFloatToUnsignedFixed(Qm,fbits);
}

:vcvt.f32.s32 Qd,Qm,fbits  is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 &     c2121=1 &     c0911=7 &     c0808=0 &     c0707=0 &        Q6=1 &     c0404=1) |
                               ($(TMODE_E) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=7 & thv_c0808=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=1) ) & fbits & Qd & Qm
{
	Qd = VectorSignedFixedToFloat(Qm,fbits);
}

:vcvt.f32.u32 Qd,Qm,fbits is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 &     c2121=1 &     c0911=7 &     c0808=0 &     c0707=0 &        Q6=1 &     c0404=1) |
                              ($(TMODE_F) &                        thv_c2327=0x1f & thv_c2121=1 & thv_c0911=7 & thv_c0808=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=1) ) & fbits & Qd & Qm
{
	Qd = VectorUnsignedFixedToFloat(Qm,fbits);
}

@endif # ! VERSION_8

@endif # SIMD

@if defined(VFPv3)

@ifndef VERSION_8

#######
# VCVT (between floating-point and fixed-point, VFP)
#

fbits16: "#"^val	is TMode=0 & c0505 & c0003	[ val = 16 - ((c0003 << 1) + c0505); ] { tmp:1 = val; export tmp; }
fbits32: "#"^val	is TMode=0 & c0505 & c0003	[ val = 32 - ((c0003 << 1) + c0505); ] { tmp:1 = val; export tmp; }
fbits16: "#"^val	is TMode=1 & thv_c0505 & thv_c0003	[ val = 16 - ((thv_c0003 << 1) + thv_c0505); ] { tmp:1 = val; export tmp; }
fbits32: "#"^val	is TMode=1 & thv_c0505 & thv_c0003	[ val = 32 - ((thv_c0003 << 1) + thv_c0505); ] { tmp:1 = val; export tmp; }

:vcvt^COND^".s16.f16" Sd,Sd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=1 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0)) & COND & Sd & Sd2 & fbits16
{
	build COND;
	build Sd;
	build Sd2;
	build fbits16;
	Sd = VectorFloatToSignedFixed(Sd2,16:1,fbits16);
}

:vcvt^COND^".u16.f16" Sd,Sd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=1 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits16
{
	build COND;
	build Sd;
	build Sd2;
	build fbits16;
	Sd = VectorFloatToUnsignedFixed(Sd2,16:1,fbits16);
}

:vcvt^COND^".s32.f16" Sd,Sd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=1 &     c0707=1 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits32
{
	build COND;
	build Sd;
	build Sd2;
	build fbits32;
	Sd = VectorFloatToSignedFixed(Sd2,32:1,fbits32);
}

:vcvt^COND^".u32.f16" Sd,Sd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=1 &     c0707=1 &     c0606=1 &     c0404=0) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits32
{
	build COND;
	build Sd;
	build Sd2;
	build fbits32;
	Sd = VectorFloatToUnsignedFixed(Sd2,32:1,fbits32);
}

:vcvt^COND^".s16.f32" Sd,Sd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=2 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=2 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0)) & COND & Sd & Sd2 & fbits16
{
	build COND;
	build Sd;
	build Sd2;
	build fbits16;
	Sd = VectorFloatToSignedFixed(Sd2,16:1,fbits16);
}

:vcvt^COND^".u16.f32" Sd,Sd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=2 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=2 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits16
{
	build COND;
	build Sd;
	build Sd2;
	build fbits16;
	Sd = VectorFloatToUnsignedFixed(Sd2,16:1,fbits16);
}

:vcvt^COND^".s32.f32" Sd,Sd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=2 &     c0707=1 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=2 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits32
{
	build COND;
	build Sd;
	build Sd2;
	build fbits32;
	Sd = VectorFloatToSignedFixed(Sd2,32:1,fbits32);
}

:vcvt^COND^".u32.f32" Sd,Sd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=2 &     c0707=1 &     c0606=1 &     c0404=0) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=2 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits32
{
	build COND;
	build Sd;
	build Sd2;
	build fbits32;
	Sd = VectorFloatToUnsignedFixed(Sd2,32:1,fbits32);
}

:vcvt^COND^".s16.f64" Dd,Dd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=3 &     c0707=0 &     c0606=1 &     c0404=0) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=3 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & Dd2 & fbits16
{
	build COND;
	build Dd;
	build Dd2;
	build fbits16;
	Dd = VectorFloatToSignedFixed(Dd2,16:1,fbits16);
}

:vcvt^COND^".u16.f64" Dd,Dd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=3 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=3 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & Dd2 & fbits16
{
	build COND;
	build Dd;
	build Dd2;
	build fbits16;
	Dd = VectorFloatToUnsignedFixed(Dd2,16:1,fbits16);
}

:vcvt^COND^".s32.f64" Dd,Dd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=3 &     c0707=1 &     c0606=1 &     c0404=0) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=3 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & Dd2 & fbits32
{
	build COND;
	build Dd;
	build Dd2;
	build fbits32;
	Dd = VectorFloatToSignedFixed(Dd2,32:1,fbits32);
}

:vcvt^COND^".u32.f64" Dd,Dd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=1 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=3 &     c0707=1 &     c0606=1 &     c0404=0) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=1 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=3 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & Dd2 & fbits32
{
	build COND;
	build Dd;
	build Dd2;
	build fbits32;
	Dd = VectorFloatToUnsignedFixed(Dd2,32:1,fbits32);
}

:vcvt^COND^".f16.s16" Sd,Sd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=1 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0)) & COND & Sd & Sd2 & fbits16
{
	build COND;
	build Sd;
	build Sd2;
	build fbits16;
	Sd = VectorSignedFixedToFloat(Sd2,16:1,fbits16);
}

:vcvt^COND^".f16.u16" Sd,Sd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=1 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits16
{
	build COND;
	build Sd;
	build Sd2;
	build fbits16;
	Sd = VectorFloatToUnsignedFixed(Sd2,16:1,fbits16);
}

:vcvt^COND^".f16.s32" Sd,Sd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=1 &     c0707=1 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits32
{
	build COND;
	build Sd;
	build Sd2;
	build fbits32;
	Sd = VectorSignedFixedToFloat(Sd2,32:1,fbits32);
}

:vcvt^COND^".f16.u32" Sd,Sd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=1 &     c0707=1 &     c0606=1 &     c0404=0) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits32
{
	build COND;
	build Sd;
	build Sd2;
	build fbits32;
	Sd = VectorFloatToUnsignedFixed(Sd2,32:1,fbits32);
}

:vcvt^COND^".f32.s16" Sd,Sd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=2 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=2 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0)) & COND & Sd & Sd2 & fbits16
{
	build COND;
	build Sd;
	build Sd2;
	build fbits16;
	Sd = VectorSignedFixedToFloat(Sd2,16:1,fbits16);
}

:vcvt^COND^".f32.u16" Sd,Sd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=2 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=2 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits16
{
	build COND;
	build Sd;
	build Sd2;
	build fbits16;
	Sd = VectorFloatToUnsignedFixed(Sd2,16:1,fbits16);
}

:vcvt^COND^".f32.s32" Sd,Sd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=2 &     c0707=1 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=2 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits32
{
	build COND;
	build Sd;
	build Sd2;
	build fbits32;
	Sd = VectorSignedFixedToFloat(Sd2,32:1,fbits32);
}

:vcvt^COND^".f32.u32" Sd,Sd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=2 &     c0707=1 &     c0606=1 &     c0404=0) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=2 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Sd & Sd2 & fbits32
{
	build COND;
	build Sd;
	build Sd2;
	build fbits32;
	Sd = VectorFloatToUnsignedFixed(Sd2,32:1,fbits32);
}

:vcvt^COND^".f64.s16" Dd,Dd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=3 &     c0707=0 &     c0606=1 &     c0404=0) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=3 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & Dd2 & fbits16
{
	build COND;
	build Dd;
	build Dd2;
	build fbits16;
	Dd = VectorSignedFixedToFloat(Dd2,16:1,fbits16);
}

:vcvt^COND^".f64.u16" Dd,Dd2,fbits16 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=3 &     c0707=0 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=3 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & Dd2 & fbits16
{
	build COND;
	build Dd;
	build Dd2;
	build fbits16;
	Dd = VectorFloatToUnsignedFixed(Dd2,16:1,fbits16);
}

:vcvt^COND^".f64.s32" Dd,Dd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=0 &     c1011=2 &     c0809=3 &     c0707=1 &     c0606=1 &     c0404=0) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c1011=2 & thv_c0809=3 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & Dd2 & fbits32
{
	build COND;
	build Dd;
	build Dd2;
	build fbits32;
	Dd = VectorSignedFixedToFloat(Dd2,32:1,fbits32);
}

:vcvt^COND^".f64.u32" Dd,Dd2,fbits32 is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1921=7 &     c1818=0 &     c1717=1 &     c1616=1 &     c1011=2 &     c0809=3 &     c0707=1 &     c0606=1 &     c0404=0) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c1011=2 & thv_c0809=3 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & COND & Dd & Dd2 & fbits32
{
	build COND;
	build Dd;
	build Dd2;
	build fbits32;
	Dd = VectorFloatToUnsignedFixed(Dd2,32:1,fbits32);
}

@endif # ! VERSION_8

@endif # VFPv3

define pcodeop VectorFloatDoubleToSingle;
define pcodeop VectorFloatSingleToDouble;

@if defined(VFPv2) || defined(VFPv3)

@ifndef VERSION_8
#######
# VCVT (between double-precision and single-precision)
#

:vcvt^COND^".f32.f64" Sd,Dm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x37 &     c0911=5 &     c0808=1 &     c0607=3 &    c0404=0 ) |
                                ($(TMODE_E) &          thv_c2327=0x1d & thv_c1621=0x36 & thv_c0911=5 & thv_c0808=1 & thv_c0607=3 & thv_c0404=0 ) ) & COND & Sd & Dm
{
	build COND;
	build Sd;
	build Dm;
	Sd = float2float(Dm);
}

:vcvt^COND^".f64.f32" Dd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x37 &     c0911=5 &     c0808=0 &     c0607=3 &    c0404=0 ) |
                                ($(TMODE_E) &          thv_c2327=0x1d & thv_c1621=0x36 & thv_c0911=5 & thv_c0808=0 & thv_c0607=3 & thv_c0404=0 ) ) & COND & Dd & Sm
{
	build COND;
	build Dd;
	build Sm;
	Dd = float2float(Sm);
}

@endif # ! VERSION_8
@endif # VFPv2 || VFPv3

@if defined(SIMD)

@ifndef VERSION_8

define pcodeop VectorFloatSingleToBFloat16;
define pcodeop FloatSingleToBFloat16;

#######
# VCVT (between single-precision and BFloat16)
#

:vcvt.bf16.f32 Dd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x36 &     c0911=3 &     c0808=0 &     c0607=1 &     c0404=0 ) |
                         ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x36 & thv_c0911=3 & thv_c0808=0 & thv_c0607=1 & thv_c0404=0 ) ) & Dd & Qm

{
	Dd = VectorFloatSingleToBFloat16(Qm, 4:1, 16:1);
}

# VCVTB Convert Single-precision to BFloat16 in Bottom
:vcvtb^COND^".bf16.f32" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x33 &     c0611=0x25 &     c0404=0 ) |
	                              ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x33 & thv_c0611=0x25 & thv_c0404=0 ) ) & COND & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	local w:2 = FloatSingleToBFloat16(Sm);
	Sd[0,16] = w;
}


# VCVTT Convert Single-precision to BFloat16 in Top
:vcvtt^COND^".bf16.f32" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x33 &     c0611=0x27 &     c0404=0 ) |
	                              ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x33 & thv_c0611=0x27 & thv_c0404=0 ) ) & COND & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	w:2 = FloatSingleToBFloat16(Sm);
	Sd[16,16] = w;
}

define pcodeop VectorFloatSingleToHalf;
define pcodeop VectorFloatHalfToSingle;

#######
# VCVT (between half-precision and single-precision)
#
:vcvt.f16.f32 Dd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x36 &     c0911=3 &     c0808=0 &     c0607=0 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x36 & thv_c0911=3 & thv_c0808=0 & thv_c0607=0 & thv_c0404=0 ) ) & Dd & Qm

{
	Dd = VectorFloatSingleToHalf(Qm, 4:1, 16:1);
}

:vcvt.f16.f32 Qd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c1621=0x36 &     c0911=3 &     c0808=1 &     c0607=0 &     c0404=0 ) |
                        ( $(TMODE_F) &    thv_c2327=0x1f & thv_c1621=0x36 & thv_c0911=3 & thv_c0808=1 & thv_c0607=0 & thv_c0404=0 ) ) & Qd & Dm

{
	Qd = VectorFloatHalfToSingle(Dm, 4:1, 16:1);
}


define pcodeop VectorFloatToSignedRound;
define pcodeop VectorFloatToUnsignedRound;

# VCVTA/M/N/P Vector convert floating-point to integer with Rounding
:vcvt^roundType^".s16.f16" Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &     c1821=0xb &     c1011=0 &     c0707=0 &        Q6=0 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1f & thv_c1821=0xb & thv_c1011=0 & thv_c0707=0 & thv_c0606=0 & thv_c0404=0 ) ) & roundType & Dd & Dm
{
	Dd = VectorFloatToSignedRound(Dm, 0:1, roundType);
}

:vcvt^roundType^".u16.f16" Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &     c1821=0xb &     c1011=0 &     c0707=1 &        Q6=0 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1f & thv_c1821=0xb & thv_c1011=0 & thv_c0707=1 & thv_c0606=0 & thv_c0404=0 ) ) & roundType & Dd & Dm
{
	Dd = VectorFloatToUnsignedRound(Dm, 0:1, roundType);
}

:vcvt^roundType^".s32.f32" Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &     c1821=0xc &     c1011=0 &     c0707=0 &        Q6=0 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1f & thv_c1821=0xc & thv_c1011=0 & thv_c0707=0 & thv_c0606=0 & thv_c0404=0 ) ) & roundType & Dd & Dm
{
	Dd = VectorFloatToSignedRound(Dm, 1:1, roundType);
}

:vcvt^roundType^".u32.f32" Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &     c1821=0xc &     c1011=0 &     c0707=1 &        Q6=0 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1f & thv_c1821=0xc & thv_c1011=0 & thv_c0707=1 & thv_c0606=0 & thv_c0404=0 ) ) & roundType & Dd & Dm
{
	Dd = VectorFloatToUnsignedRound(Dm, 1:1, roundType);
}

:vcvt^roundType^".s16.f16" Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &     c1821=0xb &     c1011=0 &     c0707=0 &        Q6=1 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1f & thv_c1821=0xb & thv_c1011=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0 ) ) & roundType & Qd & Qm
{
	Qd = VectorFloatToSignedRound(Qm, 0:1, roundType);
}

:vcvt^roundType^".u16.f16" Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &     c1821=0xb &     c1011=0 &     c0707=1 &        Q6=1 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1f & thv_c1821=0xb & thv_c1011=0 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0 ) ) & roundType & Qd & Qm
{
	Qd = VectorFloatToUnsignedRound(Qm, 0:1, roundType);
}

:vcvt^roundType^".s32.f32" Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &     c1821=0xc &     c1011=0 &     c0707=0 &        Q6=1 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1f & thv_c1821=0xc & thv_c1011=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0 ) ) & roundType & Qd & Qm
{
	Qd = VectorFloatToSignedRound(Qm, 1:1, roundType);
}

:vcvt^roundType^".u32.f32" Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &     c1821=0xc &     c1011=0 &     c0707=1 &        Q6=1 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1f & thv_c1821=0xc & thv_c1011=0 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0 ) ) & roundType & Qd & Qm
{
	Qd = VectorFloatToUnsignedRound(Qm, 1:1, roundType);
}
@endif # ! VERSION_8
@endif # SIMD

@if defined(VFPv3)

@ifndef VERSION_8

define pcodeop FloatToSignedRound;
define pcodeop FloatToUnsignedRound;

# VCVTA/M/N/P Float convert floating-point to integer with Rounding

:vcvt^roundType^".s32.f16" Sd,Sm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c1821=0xf &     c0911=4 &     c0808=1 &     c0607=0 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1d & thv_c1821=0xf & thv_c0911=4 & thv_c0808=1 & thv_c0607=0 & thv_c0404=0 ) ) & roundType & Sd & Sm
{
	local sm16:2 = Sm(0);
	Sd = FloatToSignedRound(sm16, roundType);
}

:vcvt^roundType^".u32.f16" Sd,Sm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c1821=0xf &     c0911=4 &     c0808=1 &     c0607=1 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1d & thv_c1821=0xf & thv_c0911=4 & thv_c0808=1 & thv_c0607=1 & thv_c0404=0 ) ) & roundType & Sd & Sm
{
	local sm16:2 = Sm(0);
	Sd = FloatToUnsignedRound(sm16, roundType);
}

:vcvt^roundType^".s32.f32" Sd,Sm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c1821=0xf &     c0911=4 &     c0808=0 &     c0607=0 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1d & thv_c1821=0xf & thv_c0911=4 & thv_c0808=0 & thv_c0607=0 & thv_c0404=0 ) ) & roundType & Sd & Sm
{
	Sd = FloatToSignedRound(Sm, roundType);
}
:vcvt^roundType^".u32.f32" Sd,Sm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c1821=0xf &     c0911=4 &     c0808=0 &     c0607=1 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1d & thv_c1821=0xf & thv_c0911=4 & thv_c0808=0 & thv_c0607=1 & thv_c0404=0 ) ) & roundType & Sd & Sm
{
	Sd = FloatToUnsignedRound(Sm, roundType);
}

:vcvt^roundType^".s32.f64" Sd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c1821=0xf &     c0911=5 &     c0808=1 &     c0607=0 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1d & thv_c1821=0xf & thv_c0911=5 & thv_c0808=1 & thv_c0607=0 & thv_c0404=0 ) ) & roundType & Sd & Dm
{
		Sd = FloatToSignedRound(Dm, roundType);
}
:vcvt^roundType^".u32.f64" Sd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c1821=0xf &     c0911=5 &     c0808=1 &     c0607=1 &     c0404=0 ) |
                                     ( $(TMODE_F) &       thv_c2327=0x1d & thv_c1821=0xf & thv_c0911=5 & thv_c0808=1 & thv_c0607=1 & thv_c0404=0 ) ) & roundType & Sd & Dm
{
		Sd = FloatToUnsignedRound(Dm, roundType);
}

# VCVTB Convert Half-precision in Bottom to Single-precision

:vcvtb^COND^".f32.f16" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x32 &     c0611=0x29 &     c0404=0 ) |
	                             ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x32 & thv_c0611=0x29 & thv_c0404=0 ) ) & COND & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	Sd = float2float(Sm:2);
}

:vcvtb^COND^".f16.f32" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x33 &     c0611=0x29 &     c0404=0 ) |
	                             ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x33 & thv_c0611=0x29 & thv_c0404=0 ) ) & COND & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	local w:2 = float2float(Sm);
	Sd[0,16] = w;
}

:vcvtb^COND^".f64.f16" Dd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x32 &     c0611=0x2d &     c0404=0 ) |
	                             ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x32 & thv_c0611=0x2d & thv_c0404=0 ) ) & COND & Dd & Sm
{
	build COND;
	build Dd;
	build Sm;
	Dd = float2float(Sm:2);
}

:vcvtb^COND^".f16.f64" Sd,Dm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x33 &     c0611=0x2d &     c0404=0 ) |
	                             ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x33 & thv_c0611=0x2d & thv_c0404=0 ) ) & COND & Sd & Dm
{
	build COND;
	build Sd;
	build Dm;
	local w:2 = float2float(Dm);
	Sd[0,16] = w;
}

# VCVTT Convert Half-precision in Top to Single-precision

:vcvtt^COND^".f32.f16" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x32 &     c0611=0x2b &     c0404=0 ) |
	                             ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x32 & thv_c0611=0x2b & thv_c0404=0 ) ) & COND & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	w:2 = Sm(2);
	Sd = float2float(w);
}

:vcvtt^COND^".f16.f32" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x33 &     c0611=0x2b &     c0404=0 ) |
	                             ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x33 & thv_c0611=0x2b & thv_c0404=0 ) ) & COND & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	w:2 = float2float(Sm);
	Sd[16,16] = w;
}

:vcvtt^COND^".f64.f16" Dd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x32 &     c0611=0x2f &     c0404=0 ) |
	                             ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x32 & thv_c0611=0x2f & thv_c0404=0 ) ) & COND & Dd & Sm
{
	build COND;
	build Dd;
	build Sm;
	w:2 = Sm(2);
	Dd = float2float(w);
}

:vcvtt^COND^".f16.f64" Sd,Dm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x33 &     c0611=0x2f &     c0404=0 ) |
	                             ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x33 & thv_c0611=0x2f & thv_c0404=0 ) ) & COND & Sd & Dm
{
	build COND;
	build Sd;
	build Dm;
	w:2 = float2float(Dm);
	Sd[16,16] = w;
}

@endif # ! VERSION_8

@endif # VFPv3

@if defined(VFPv2) || defined(VFPv3)

:vdiv^COND^".f16" Sd,Sn,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=0 &     c0811=9 &     c0606=0 &     c0404=0 ) |
                               ($(TMODE_E) &         thv_c2327=0x1d & thv_c2021=0 & thv_c0811=9 & thv_c0606=0 & thv_c0404=0 ) ) & COND & Sn & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	build Sn;
	local sm16:2 = Sm(0);
	local sn16:2 = Sn(0);
	Sd = zext(sn16 f/ sm16);
}

:vdiv^COND^".f32" Sd,Sn,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=0 &     c0811=10 &     c0606=0 &     c0404=0 ) |
                               ($(TMODE_E) &         thv_c2327=0x1d & thv_c2021=0 & thv_c0811=10 & thv_c0606=0 & thv_c0404=0 ) ) & COND & Sn & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	build Sn;
	Sd = Sn f/ Sm;
}

:vdiv^COND^".f64" Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=0 &     c0811=11 &     c0606=0 &     c0404=0 ) |
                               ($(TMODE_E) &         thv_c2327=0x1d & thv_c2021=0 & thv_c0811=11 & thv_c0606=0 & thv_c0404=0 ) ) & COND & Dn & Dd & Dm
{
	build COND;
	build Dd;
	build Dm;
	build Dn;
	Dd = Dn f/ Dm;
}

@endif # VFPv2 || VFPv3

define pcodeop VectorHalvingAdd;
define pcodeop VectorHalvingSubtract;
define pcodeop VectorRoundHalvingAdd;
define pcodeop VectorRoundAddAndNarrow;
define pcodeop VectorDotProduct;
define pcodeop vectorFusedMultiplyAccumulate;
define pcodeop BfloatMultiplyAccumulate;
define pcodeop VectorMultiplyAddLongVector;
define pcodeop VectorMultiplyAddLongScalar;


@if defined(SIMD)

# F6.1.79 VDOT (vector) page F6-8052 line 467006
# xfc000d00/mask=xffb00f10 NOT MATCHED BY ANY CONSTRUCTOR
# b_0031=111111000.00........1101...0....

:vdot.bf16 Dd, Dn, Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=0 &     c0811=0xd &     Q6=0 &     c0404=0 ) |
                          ( $(TMODE_F) &       thv_c2327=0x18 & thv_c2021=0 & thv_c0811=0xd & thv_Q6=0 & thv_c0404=0 )  ) & Dm & Dn & Dd
{
	Dd = VectorDotProduct(Dn,Dm);
}

:vdot.bf16 Qd, Qn, Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=0 &     c0811=0xd &     Q6=1 &     c0404=0 ) |
                          ( $(TMODE_F) &       thv_c2327=0x18 & thv_c2021=0 & thv_c0811=0xd & thv_Q6=1 & thv_c0404=0 )  ) & Qm & Qn & Qd
{
	Qd = VectorDotProduct(Qn,Qm);
}

Mindex: "["^M5^"]" is     TMode=0 & M5 { local idx:1 = M5:1; export idx; }
Mindex: "["^thv_M5^"]" is TMode=1 & thv_M5 { local idx:1 = thv_M5:1; export idx; }

:vdot.bf16 Dd, Dn, Dm0^Mindex  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=0x1c &     c2021=0 &     c0811=0xd &     Q6=0 &     c0404=0 ) |
                                  ( $(TMODE_F) &       thv_c2327=0x1c & thv_c2021=0 & thv_c0811=0xd & thv_Q6=0 & thv_c0404=0 )  ) & Dm0 & Mindex & Dn & Dd
{
	Dd = VectorDotProduct(Dn,Dm0,Mindex);
}

:vdot.bf16 Qd, Qn, Qm0^Mindex  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=0x1c &     c2021=0 &     c0811=0xd &     Q6=1 &     c0404=0 ) |
                                  ( $(TMODE_F) &       thv_c2327=0x1c & thv_c2021=0 & thv_c0811=0xd & thv_Q6=1 & thv_c0404=0 )  ) & Qm0 & Mindex & Qn & Qd
{
	Qd = VectorDotProduct(Qn,Qm0,Mindex);
}

#######
# VDUP (scalar)
#

vdupIndex: c1719	is TMode=0 & c1616=1 & c1719	{ tmp:4 = c1719; export tmp; }
vdupIndex: c1819	is TMode=0 & c1617=2 & c1819	{ tmp:4 = c1819; export tmp; }
vdupIndex: c1919	is TMode=0 & c1618=4 & c1919	{ tmp:4 = c1919; export tmp; }

vdupIndex: thv_c1719	is TMode=1 & thv_c1616=1 & thv_c1719	{ tmp:4 = thv_c1719; export tmp; }
vdupIndex: thv_c1819	is TMode=1 & thv_c1617=2 & thv_c1819	{ tmp:4 = thv_c1819; export tmp; }
vdupIndex: thv_c1919	is TMode=1 & thv_c1618=4 & thv_c1919	{ tmp:4 = thv_c1919; export tmp; }

vdupSize: 8			is TMode=0 & c1616=1 		{ }
vdupSize: 16		is TMode=0 & c1617=2 		{ }
vdupSize: 32		is TMode=0 & c1618=4 		{ }
vdupSize: 8			is TMode=1 & thv_c1616=1 		{ }
vdupSize: 16		is TMode=1 & thv_c1617=2 		{ }
vdupSize: 32		is TMode=1 & thv_c1618=4 		{ }

vdupDm: Dm^"["^vdupIndex^"]"	is Dm & vdupIndex & ((TMode=0 & c1616=1) | (TMode=1 & thv_c1616=1))
{
	ptr:4 = &Dm + vdupIndex;
	val:8 = 0;
	replicate1to8(*[register]:1 ptr, val);
	export val;
}
vdupDm: Dm^"["^vdupIndex^"]"	is Dm & vdupIndex & ((TMode=0 & c1617=2) | (TMode=1 & thv_c1617=2))
{
	ptr:4 = &Dm + (2 * vdupIndex);
	val:8 = 0;
	replicate2to8(*[register]:2 ptr, val);
	export val;
}
vdupDm: Dm^"["^vdupIndex^"]"	is Dm & vdupIndex & ((TMode=0 & c1618=4) | (TMode=1 & thv_c1618=4))
{
	ptr:4 = &Dm + (4 * vdupIndex);
	val:8 = 0;
	replicate4to8(*[register]:4 ptr, val);
	export val;
}

vdupDm16: vdupDm	is vdupDm	
{ 
	val:16 = zext(vdupDm); 
	val = val & (val << 64); 
	export val; 
}

:vdup.^vdupSize Dd,vdupDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 & c2021=3 & vdupSize & c0711=0x18 & Q6=0 & c0404=0 ) |
                                 ($(TMODE_F)  &thv_c2327=0x1f & thv_c2021=3 & thv_c0711=0x18 & thv_Q6=0 & thv_c0404=0 ) ) & Dd & vdupDm
{
	Dd = vdupDm;
}

:vdup.^vdupSize Qd,vdupDm16	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 & c2021=3 & vdupSize & c0711=0x18 & Q6=1 & c0404=0  ) |
                                 ($(TMODE_F)  &thv_c2327=0x1f & thv_c2021=3 & thv_c0711=0x18 & thv_Q6=1 & thv_c0404=0) ) & Qd & vdupDm16
{
	Qd = vdupDm16;
}

#######
# VDUP (ARM core register)
#

vdupSize2: 8	is c2222=1 & c0505=0	{ }
vdupSize2: 16	is c2222=0 & c0505=1	{ }
vdupSize2: 32	is c2222=0 & c0505=0	{ }

vdupRd8: Rd	is Rd & c2222=1 & c0505=0
{
	val:8 = 0;
	local tmpRd = Rd;
	replicate1to8(tmpRd:1, val);
	export val;
}
vdupRd8: Rd	is Rd & c2222=0 & c0505=1
{
	val:8 = 0;
	local tmpRd = Rd;
	replicate2to8(tmpRd:2, val);
	export val;
}
vdupRd8: Rd	is Rd & c2222=0 & c0505=0
{
	val:8 = 0;
	local tmpRd = Rd;
	replicate4to8(tmpRd:4, val);
	export val;
}

vdupRd16: vdupRd8	is vdupRd8	
{ 
	val:16 = zext(vdupRd8); 
	val = val & (val << 64); 
	export val; 
}

:vdup^COND^"."^vdupSize2 Dn,vdupRd8  is (( $(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=0 &     c0811=11 &     c0606=0 &     c0004=0x10) |
                                        ($(TMODE_E) &         thv_c2327=0x1d & thv_c2021=0 & thv_c0811=11 & thv_c0606=0 & thv_c0004=0x10 ) ) & COND & Dn & vdupSize2 & vdupRd8
{
	build COND;
	build vdupRd8;
	build Dn;
	Dn = vdupRd8;
}

:vdup^COND^"."^vdupSize2 Qn,vdupRd16  is (( $(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=2 &     c0811=11 &     c0606=0 &     c0004=0x10) |
                                         ($(TMODE_E) &         thv_c2327=0x1d & thv_c2021=2 & thv_c0811=11 & thv_c0606=0 & thv_c0004=0x10 ) ) & COND & Qn & vdupSize2 & vdupRd16
{
	build COND;
	build vdupRd16;
	build Qn;
	Qn = vdupRd16;
}

:veor Dd,Dn,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x6 &  c2021=0 &     c0811=1 &     Q6=0 &     c0404=1) |
                     ($(TMODE_F)  &thv_c2327=0x1e & thv_c2021=0 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm

{
	Dd = Dn ^ Dm;
}

:veor Qd,Qn,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x6 &  c2021=0 &     c0811=1 &     Q6=1 &     c0404=1) |
                     ($(TMODE_F)  &thv_c2327=0x1e & thv_c2021=0 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qd & Qn & Qm
{
	Qd = Qn ^ Qm;
}

extImm: "#"^c0811	    is TMode=0 & c0811		{ tmp:1 = c0811; export tmp; }
extImm: "#"^thv_c0811	is TMode=1 & thv_c0811	{ tmp:1 = thv_c0811; export tmp; }

:vext.8 Dd,Dn,Dm,extImm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=5 &     c2021=3 &     c0606=0  &     c0404=0 ) |
                            ($(TMODE_E) &     thv_c2327=0x1f & thv_c2021=3 & thv_c0606=0  & thv_c0404=0) ) & Dd & Dn & Dm & extImm
{
	val:16 = (zext(Dm) << 64) | zext(Dn);
	local shift = extImm * 8;
	val = val >> shift;
	Dd = val:8;
}

:vext.8 Qd,Qn,Qm,extImm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=5 &     c2021=3 &     c0606=1 &     c0404=0 ) |
                            ($(TMODE_E) &     thv_c2327=0x1f & thv_c2021=3 & thv_c0606=1 & thv_c0404=0) ) & Qd & Qn & Qm & extImm
{
	val:32 = (zext(Qm) << 128) | zext(Qn);
	local shift = extImm * 8;
	val = val >> shift;
	Qd = val:16;
}

:vfma.f^fesize2020 Dd,Dn,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2121=0 &     c0811=0xc &     c0606=0  &     c0404=1 ) |
                                ($(TMODE_E) &     thv_c2327=0x1e & thv_c2121=0 & thv_c0811=0xc & thv_c0606=0  & thv_c0404=1) ) & fesize2020 & Dd & Dn & Dm
{
	Dd = vectorFusedMultiplyAccumulate(Dn, Dm, fesize2020);
}

:vfma.f^fesize2020 Qd,Qn,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2121=0 &     c0811=0xc &     c0606=1  &     c0404=1 ) |
                                ($(TMODE_E) &     thv_c2327=0x1e & thv_c2121=0 & thv_c0811=0xc & thv_c0606=1  & thv_c0404=1) ) & fesize2020 & Qd & Qn & Qm
{
	Qd = vectorFusedMultiplyAccumulate(Qn, Qm, fesize2020);
}


# Floating-point Multiply-Accumulate BFloat (vector)
:vfmab.BF16 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=0x3 &     c0811=8 &     c0606=0  &     c0404=1 ) |
                         ($(TMODE_F) &       thv_c2327=0x18 & thv_c2021=0x3 & thv_c0811=8 & thv_c0606=0  & thv_c0404=1) ) & Qd & Qn & Qm
{
	Qd = BfloatMultiplyAccumulate(Qn, Qm, 0:1);
}

:vfmat.BF16 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=0x3 &     c0811=8 &     c0606=1  &     c0404=1 ) |
                         ($(TMODE_F) &       thv_c2327=0x18 & thv_c2021=0x3 & thv_c0811=8 & thv_c0606=1  & thv_c0404=1) ) & Qd & Qn & Qm
{
	Qd = BfloatMultiplyAccumulate(Qn, Qm, 1:1);
}

vmfDm: Dm_3^"["^index^"]"		is TMode=0 &     Dm_3 &     M5 &     c0303 [ index = (M5 << 1) + c0303; ]			{ el:4 = VectorGetElement(Dm_3, index:1, 2:1, 0:1); export el; }
vmfDm: thv_Dm_3^"["^index^"]"	is TMode=1 & thv_Dm_3 & thv_M5 & thv_c0303 [ index = (thv_M5 << 1) + thv_c0303; ]	{ el:4 = VectorGetElement(thv_Dm_3, index:1, 2:1, 0:1); export el; }
vmfSm: Sm_3^"["^c0303^"]"		is TMode=0 &     c0404=1 & Sm_3 &     M5 & c0303	{ el:4 = VectorGetElement(Sm_3, M5:1, 4:1, 0:1); export el; }
vmfSm: Sm_3^"["^c0303^"]"		is TMode=1 & thv_c0404=1 & Sm_3 & thv_M5 & c0303	{ el:4 = VectorGetElement(Sm_3, thv_M5:1, 4:1, 0:1); export el; }

:vfmab.BF16 Qd,Qn,vmfDm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1c &     c2021=0x3 &     c0811=8 &     c0606=0  &     c0404=1 ) |
                            ($(TMODE_F) &       thv_c2327=0x1c & thv_c2021=0x3 & thv_c0811=8 & thv_c0606=0  & thv_c0404=1) ) & Qd & Qn & vmfDm
{
	Qd = BfloatMultiplyAccumulate(Qn, vmfDm, 0:1);
}

:vfmat.BF16 Qd,Qn,vmfDm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1c &     c2021=0x3 &     c0811=8 &     c0606=1  &     c0404=1 ) |
                            ($(TMODE_F) &       thv_c2327=0x1c & thv_c2021=0x3 & thv_c0811=8 & thv_c0606=1  & thv_c0404=1) ) & Qd & Qn & vmfDm
{
	Qd = BfloatMultiplyAccumulate(Qn, vmfDm, 1:1);
}

:vfmal.F16 Dd,Sn,Sm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=0x2 &     c0811=0x8 &     c0606=0  &     c0404=1 ) |
                        ($(TMODE_F) &       thv_c2327=0x18 & thv_c2021=0x2 & thv_c0811=0x8 & thv_c0606=0  & thv_c0404=1) ) & Dd & Sn & Sm
{
	Dd = VectorMultiplyAddLongVector(Sn, Sm, 0:1);
}

:vfmal.F16 Qd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=0x2 &     c0811=0x8 &     c0606=1  &     c0404=1 ) |
                        ($(TMODE_F) &       thv_c2327=0x18 & thv_c2021=0x2 & thv_c0811=0x8 & thv_c0606=1  & thv_c0404=1) ) & Qd & Dn & Dm
{
	Qd = VectorMultiplyAddLongVector(Dn, Dm, 1:1);
}

:vfmal.F16 Dd,Sn,vmfSm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1c &     c2021=0x2 &     c0811=8 &     c0606=0  &     c0404=1 ) |
                           ($(TMODE_F) &       thv_c2327=0x1c & thv_c2021=0x2 & thv_c0811=8 & thv_c0606=0  & thv_c0404=1) ) & Dd & Sn & vmfSm
{
	Dd = VectorMultiplyAddLongScalar(Sn, vmfSm, 0:1);
}

:vfmal.F16 Qd,Dn,vmfDm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1c &     c2021=0x2 &     c0811=8 &     c0606=1  &     c0404=1 ) |
                           ($(TMODE_F) &       thv_c2327=0x1c & thv_c2021=0x2 & thv_c0811=8 & thv_c0606=1  & thv_c0404=1) ) & Qd & Dn & vmfDm
{
	Qd = VectorMultiplyAddLongScalar(Dn, vmfDm, 1:1);
}




:vhadd.^udt^esize2021 Dd,Dn,Dm    is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=0 & Q6=0 & c0404=0) |
                                      ($(TMODE_EorF) &    thv_c2327=0x1e & thv_c2021<3  & thv_c0811=0 & thv_Q6=0 & thv_c0404=0) ) & udt & Dm & esize2021 & Dn & Dd
{
	Dd = VectorHalvingAdd(Dn,Dm,esize2021,udt);
}

:vhadd.^udt^esize2021 Qd,Qn,Qm    is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=0 & Q6=1 & c0404=0) |
                                      ($(TMODE_EorF) &    thv_c2327=0x1e & thv_c2021<3  & thv_c0811=0 & thv_Q6=1 & thv_c0404=0) ) & udt & Qm & esize2021 & Qn & Qd
{
	Qd = VectorHalvingAdd(Qn,Qm,esize2021,udt);
}


:vraddhn.i^esize2021x2 Dd,Qn,Qm    is (($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c2021<3  & c0811=4 & Q6=0 & c0404=0) |
	                                   ($(TMODE_F) & thv_c2327=0x1f & thv_c2021<3  & thv_c0811=4 & thv_Q6=0 & thv_c0404=0) ) & Qm & esize2021x2 & Qn & Dd
{
	Dd = VectorRoundAddAndNarrow(Qn,Qm,esize2021x2);
}

:vrhadd.^udt^esize2021 Dd,Dn,Dm    is (($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3  & c0811=1 & Q6=0 & c0404=0) |
	                                   ($(TMODE_EorF) &    thv_c2327=0x1e & thv_c2021<3  & thv_c0811=1 & thv_Q6=0 & thv_c0404=0) ) & udt & Dm & esize2021 & Dn & Dd
{
	Dd = VectorRoundHalvingAdd(Dn,Dm,esize2021,udt);
}

:vrhadd.^udt^esize2021 Qd,Qn,Qm    is (($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3  & c0811=1 & Q6=1 & c0404=0) |
	                                   ($(TMODE_EorF) &    thv_c2327=0x1e & thv_c2021<3  & thv_c0811=1 & thv_Q6=1 & thv_c0404=0) ) & udt & Qm & esize2021 & Qn & Qd
{
	Qd = VectorRoundHalvingAdd(Qn,Qm,esize2021,udt);
}

:vhsub.^udt^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=2 & Q6=0 & c0404=0) |
	                                   ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3  & thv_c0811=2 & thv_Q6=0 & thv_c0404=0) ) & udt & esize2021 & Dn & Dd & Dm
{
	Dd = VectorHalvingSubtract(Dn,Dm,esize2021,udt);
}

:vhsub.^udt^esize2021 Qd,Qn,Qm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=2 & Q6=1 & c0404=0) |
	                                   ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3  & thv_c0811=2 & thv_Q6=1 & thv_c0404=0) ) & udt & Qm & esize2021 & Qn & Qd
{
	Qd = VectorHalvingSubtract(Qn,Qm,esize2021,udt);
}

#######
# VFMA VFMS VFNMA and VFNMS
#

@if defined(VFPv4)

:vfma^COND^".f16" Sd,Sn,Sm	is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=2 & c1011=2 & c0809=1 & c0606=0 & c0404=0 ) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=2 & thv_c1011=2 & thv_c0809=1 & thv_c0606=0 & thv_c0404=0)) & Sm & Sn & Sd
{
	Sd = zext(Sd:2 f+ (Sn:2 f* Sm:2));
}

:vfma^COND^".f32" Sd,Sn,Sm	is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=2 & c1011=2 & c0809=2 & c0606=0 & c0404=0 ) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=2 & thv_c1011=2 & thv_c0809=2 & thv_c0606=0 & thv_c0404=0)) & Sm & Sn & Sd
{
	Sd = Sd f+ (Sn f* Sm);
}

:vfma^COND^".f64" Dd,Dn,Dm	is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=2 & c1011=2 & c0809=3 & c0606=0 & c0404=0) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=2 & thv_c1011=2 & thv_c0809=3 & thv_c0606=0 & thv_c0404=0)) & Dm & Dn & Dd
{
	Dd = Dd f+ (Dn f* Dm);
}

:vfms^COND^".f16" Sd,Sn,Sm	is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=2 & c1011=2 & c0809=1 & c0606=1 & c0404=0) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=2 & thv_c1011=2 & thv_c0809=1 & thv_c0606=1 & thv_c0404=0)) & Sm & Sn & Sd
{
	Sd = zext(Sd:2 f+ ((f- Sn:2) f* Sm:2));
}

:vfms^COND^".f32" Sd,Sn,Sm	is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=2 & c1011=2 & c0809=2 & c0606=1 & c0404=0) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=2 & thv_c1011=2 & thv_c0809=2 & thv_c0606=1 & thv_c0404=0)) & Sm & Sn & Sd
{
	Sd = Sd f+ ((f- Sn) f* Sm);
}

:vfms^COND^".f64" Dd,Dn,Dm  is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=2 & c1011=2 & c0809=3 & c0606=1 & c0404=0 ) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=2 & thv_c1011=2 & thv_c0809=3 & thv_c0606=1 & thv_c0404=0)) & Dm & Dn & Dd
{
	Dd = Dd f+ ((f- Dn) f* Dm);
}

:vfnma^COND^".f16" Sd,Sn,Sm is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=1 & c1011=2 & c0809=1 & c0606=1 & c0404=0 ) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=1 & thv_c1011=2 & thv_c0809=1 & thv_c0606=1 & thv_c0404=0)) & Sm & Sn & Sd
{
	Sd = zext((f- Sd:2) f+ ((f- Sn:2) f* Sm:2));
}

:vfnma^COND^".f32" Sd,Sn,Sm is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=1 & c1011=2 & c0809=2 & c0606=1 & c0404=0 ) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=1 & thv_c1011=2 & thv_c0809=2 & thv_c0606=1 & thv_c0404=0)) & Sm & Sn & Sd
{
	Sd = (f- Sd) f+ ((f- Sn) f* Sm);
}

:vfnma^COND^".f64" Dd,Dn,Dm	is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=1 & c1011=2 & c0809=3 & c0606=1 & c0404=0) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=1 & thv_c1011=2 & thv_c0809=3 & thv_c0606=1 & thv_c0404=0)) & Dm & Dn & Dd
{
	Dd = (f- Dd) f+ ((f- Dn) f* Dm);
}

:vfnms^COND^".f16" Sd,Sn,Sm	is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=1 & c1011=2 & c0809=1 & c0606=0 & c0404=0 ) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=1 & thv_c1011=2 & thv_c0809=1 & thv_c0606=0 & thv_c0404=0)) & Sm & Sn & Sd
{
	Sd = zext((f- Sd:2) f+ (Sn:2 f* Sm:2));
}

:vfnms^COND^".f32" Sd,Sn,Sm	is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=1 & c1011=2 & c0809=2 & c0606=0 & c0404=0 ) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=1 & thv_c1011=2 & thv_c0809=2 & thv_c0606=0 & thv_c0404=0)) & Sm & Sn & Sd
{
	Sd = (f- Sd) f+ (Sn f* Sm);
}

:vfnms^COND^".f64" Dd,Dn,Dm	is ( ( $(AMODE) & ARMcond=1 & COND & c2327=0x1d & c2021=1 & c1011=2 & c0809=3 & c0606=0 & c0404=0 ) |
						           ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=1 & thv_c1011=2 & thv_c0809=3 & thv_c0606=0 & thv_c0404=0)) & Dm & Dn & Dd
{
	Dd = (f- Dd) f+ (Dn f* Dm);
}

@endif # VFPv4

#######
# VLD1 (multiple single elements)
#

buildVld1DdList: Dreg					is Dreg & counter=1 					[ counter=0; regNum=regNum+1; ]
{
	Dreg = * mult_addr;
}
buildVld1DdList: Dreg,buildVld1DdList	is Dreg & buildVld1DdList               [ counter=counter-1; regNum=regNum+1; ]
{
	Dreg = * mult_addr;
	mult_addr = mult_addr + 8;
	build buildVld1DdList;
}

vld1DdList: "{"^buildVld1DdList^"}"	is TMode=0 & c0811=7 & D22 & c1215 & buildVld1DdList [ regNum=(D22<<4)+c1215-1; counter=1; ] { export 1:4; }
vld1DdList: "{"^buildVld1DdList^"}"	is TMode=0 & c0811=10 & D22 & c1215 & buildVld1DdList [ regNum=(D22<<4)+c1215-1; counter=2; ] { export 2:4; }
vld1DdList: "{"^buildVld1DdList^"}"	is TMode=0 & c0811=6 & D22 & c1215 & buildVld1DdList [ regNum=(D22<<4)+c1215-1; counter=3; ] { export 3:4; }
vld1DdList: "{"^buildVld1DdList^"}"	is TMode=0 & c0811=2 & D22 & c1215 & buildVld1DdList [ regNum=(D22<<4)+c1215-1; counter=4; ] { export 4:4; }
vld1DdList: "{"^buildVld1DdList^"}"	is TMode=1 & thv_c0811=7 & thv_D22 & thv_c1215 & buildVld1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=1; ] { export 1:4; }
vld1DdList: "{"^buildVld1DdList^"}"	is TMode=1 & thv_c0811=10 & thv_D22 & thv_c1215 & buildVld1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=2; ] { export 2:4; }
vld1DdList: "{"^buildVld1DdList^"}"	is TMode=1 & thv_c0811=6 & thv_D22 & thv_c1215 & buildVld1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=3; ] { export 3:4; }
vld1DdList: "{"^buildVld1DdList^"}"	is TMode=1 & thv_c0811=2 & thv_D22 & thv_c1215 & buildVld1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=4; ] { export 4:4; }

@define Vld1DdList "(c0811=2 | c0811=6 | c0811=7 | c0811=10)"
@define thv_Vld1DdList "(thv_c0811=2 | thv_c0811=6 | thv_c0811=7 | thv_c0811=10)"

vldAlign45:			is TMode=0 & c0405=0  		{ }
vldAlign45: "@64"	is TMode=0 & c0405=1		{ }
vldAlign45: "@128"	is TMode=0 & c0405=2		{ }
vldAlign45: "@256"	is TMode=0 & c0405=3		{ }
vldAlign45:			is TMode=1 & thv_c0405=0  	{ }
vldAlign45: "@64"	is TMode=1 & thv_c0405=1	{ }
vldAlign45: "@128"	is TMode=1 & thv_c0405=2	{ }
vldAlign45: "@256"	is TMode=1 & thv_c0405=3	{ }

RnAligned45: "["^VRn^vldAlign45^"]" 	is TMode=0 & VRn & vldAlign45	{ export VRn; }
RnAligned45: "["^VRn^vldAlign45^"]" 	is TMode=1 & VRn & vldAlign45	{ export VRn; }


:vld1.^esize0607 vld1DdList,RnAligned45		is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8    &     c2021=2 &     c0003=15 & $(Vld1DdList)) |
                                                 ($(TMODE_F)  &    thv_c2327=0x12 & thv_c2021=2 & thv_c0003=15 & $(thv_Vld1DdList)) ) & esize0607 & RnAligned45 & vld1DdList
{
 	mult_addr = RnAligned45;
 	build vld1DdList;
}

:vld1.^esize0607 vld1DdList,RnAligned45^"!"	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8    &     c2021=2 &     c0003=13 & $(Vld1DdList)) |
                                                 ($(TMODE_F)  &    thv_c2327=0x12 & thv_c2021=2 & thv_c0003=13 & $(thv_Vld1DdList)) ) & esize0607 & RnAligned45 & vld1DdList
{
	mult_addr = RnAligned45;
	build vld1DdList;
	RnAligned45 = RnAligned45 + (8 * vld1DdList);
}

:vld1.^esize0607 vld1DdList,RnAligned45,VRm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8    &     c2021=2 & $(Vld1DdList)) |
                                                 ($(TMODE_F)  &    thv_c2327=0x12 & thv_c2021=2 & $(thv_Vld1DdList)) ) & VRm & esize0607 & RnAligned45 & vld1DdList
{
	mult_addr = RnAligned45;
	build vld1DdList;
	RnAligned45 = RnAligned45 + VRm;
}


#######
# VLD1 (single element to one lane)
#

vld1Index: val	is TMode=0 & c0507 & c1011	        [ val = c0507 >> c1011; ]           { tmp:4 = val; export tmp; }
vld1Index: val	is TMode=1 & thv_c0507 & thv_c1011	[ val = thv_c0507 >> thv_c1011; ]   { tmp:4 = val; export tmp; }

vld1DdElement2: Dd^"["^vld1Index^"]"	is Dd & vld1Index & ((TMode=0 & c1011=0) | (TMode=1 & thv_c1011=0))
{
	ptr:4 = &Dd + vld1Index;
	*[register]:1 ptr = *:1 mult_addr;
}
vld1DdElement2: Dd^"["^vld1Index^"]"	is Dd & vld1Index & ((TMode=0 & c1011=1) | (TMode=1 & thv_c1011=1))
{
	ptr:4 = &Dd + (2 * vld1Index);
	*[register]:2 ptr = *:2 mult_addr;
}
vld1DdElement2: Dd^"["^vld1Index^"]"	is Dd & vld1Index & ((TMode=0 & c1011=2) | (TMode=1 & thv_c1011=2))
{
	ptr:4 = &Dd + (4 * vld1Index);
	*[register]:4 ptr = *:4 mult_addr;
}

@define Vld1DdElement2 "((c1011=0 & c0404=0) | (c1011=1 &  c0505=0) | (c1011=2 &  (c0406=0 | c0406=3)))"
@define T_Vld1DdElement2 "((thv_c1011=0 & thv_c0404=0) | (thv_c1011=1 &  thv_c0505=0) | (thv_c1011=2 &  (thv_c0406=0 | thv_c0406=3)))"


vld1Align2: 		is TMode=0 & c0404=0				{ }
vld1Align2: "@16"	is TMode=0 & c1011=1 & c0404=1	{ }
vld1Align2: "@32"	is TMode=0 & c1011=2 & c0404=1	{ }
vld1Align2: 		is TMode=1 & thv_c0404=0				{ }
vld1Align2: "@16"	is TMode=1 & thv_c1011=1 & thv_c0404=1	{ }
vld1Align2: "@32"	is TMode=1 & thv_c1011=2 & thv_c0404=1	{ }

RnAligned2: "["^VRn^vld1Align2^"]" 	is VRn & vld1Align2	{ export VRn; }

:vld1.^esize1011 vld1DdElement2,RnAligned2		is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9     & c2021=2     & c0809=0     & c0003=15 & $(Vld1DdElement2) ) |
												   ($(TMODE_F)  &         thv_c2327=0x13 & thv_c2021=2 & thv_c0809=0 & thv_c0003=15 & $(T_Vld1DdElement2) ) ) & RnAligned2 & esize1011  & vld1DdElement2
{
 	mult_addr = RnAligned2;
	build vld1DdElement2;
}

:vld1.^esize1011 vld1DdElement2,RnAligned2^"!"	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9     & c2021=2     & c0809=0     & c0003=13 & $(Vld1DdElement2) ) |
												   ($(TMODE_F)  &         thv_c2327=0x13 & thv_c2021=2 & thv_c0809=0 & thv_c0003=13 & $(T_Vld1DdElement2) ) ) & RnAligned2 & esize1011  & vld1DdElement2
{
	mult_addr = RnAligned2;
	build vld1DdElement2;
	RnAligned2 = RnAligned2 + esize1011;
}

:vld1.^esize1011 vld1DdElement2,RnAligned2,VRm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9     & c2021=2     & c0809=0       & $(Vld1DdElement2) ) |
												   ($(TMODE_F)  &         thv_c2327=0x13 & thv_c2021=2 & thv_c0809=0 & $(T_Vld1DdElement2) ) ) & VRm & RnAligned2 & esize1011  & vld1DdElement2
{
	mult_addr = RnAligned2;
	build vld1DdElement2;
	RnAligned2 = RnAligned2 + VRm;
}


#######
# VLD1 (single element to all lanes)
#

vld1RnReplicate:	is Rn & c0607=0
{
	val:8 = 0;
	replicate1to8(*:1 Rn, val);
	export val;
}
vld1RnReplicate:	is Rn & c0607=1
{
	val:8 = 0;
	replicate2to8(*:2 Rn, val);
	export val;
}
vld1RnReplicate:	is Rn & c0607=2
{
	val:8 = 0;
	replicate4to8(*:4 Rn, val);
	export val;
}

vld1Dd3: Dreg^"[]"		is Dreg		{ export Dreg; }

buildVld1DdList3:					is counter=0			{ }
buildVld1DdList3: vld1Dd3			is counter=1	& vld1Dd3		[ counter=0; regNum=regNum+1; ] 
{ 
	vld1Dd3 = mult_dat8;
}
buildVld1DdList3: vld1Dd3,buildVld1DdList3		is vld1Dd3 & buildVld1DdList3	[ counter=counter-1; regNum=regNum+1; ] 
{
	vld1Dd3 = mult_dat8;
	build buildVld1DdList3;
}

vld1DdList3: "{"^buildVld1DdList3^"}"	is c0505=0 & D22 & c1215 & buildVld1DdList3 [ regNum=(D22<<4)+c1215-1; counter=1; ] { export 1:4; }
vld1DdList3: "{"^buildVld1DdList3^"}"	is c0505=1 & D22 & c1215 & buildVld1DdList3 [ regNum=(D22<<4)+c1215-1; counter=2; ] { export 2:4; }

vld1Align3:			is c0404=0				{ }
vld1Align3: "@16" 	is c0404=1 & c0607=1	{ }
vld1Align3: "@32" 	is c0404=1 & c0607=2	{ }

RnAligned3: "["^Rn^vld1Align3^"]" 	is Rn & vld1Align3	{ export Rn; }

@define vld1Constrain "((c0607=0 & c0404=0) | c0607=1 | c0607=2)"

:vld1.^esize0607 vld1DdList3,RnAligned3		is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & RnAligned3 & vld1RnReplicate & vld1DdList3 & c0811=12 & esize0607 & c0003=15 & $(vld1Constrain)
{
	mult_dat8 = vld1RnReplicate;
 	build vld1DdList3;
}

:vld1.^esize0607 vld1DdList3,RnAligned3^"!"	is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & RnAligned3 & vld1RnReplicate & vld1DdList3 & c0811=12 & esize0607 & c0003=13 & $(vld1Constrain)
{
	mult_dat8 = vld1RnReplicate;
	build vld1DdList3;
	RnAligned3 = RnAligned3 + vld1DdList3;
}

:vld1.^esize0607 vld1DdList3,RnAligned3,VRm	is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & RnAligned3 & vld1RnReplicate & vld1DdList3 & c0811=12 & esize0607 & VRm & $(vld1Constrain)
{
	mult_dat8 = vld1RnReplicate;
	build vld1DdList3;
	RnAligned3 = RnAligned3 + VRm;
}

thv_vld1RnReplicate:	is VRn & thv_c0607=0
{
	val:8 = 0;
	replicate1to8(*:1 VRn, val);
	export val;
}
thv_vld1RnReplicate:	is VRn & thv_c0607=1
{
	val:8 = 0;
	replicate2to8(*:2 VRn, val);
	export val;
}
thv_vld1RnReplicate:	is VRn & thv_c0607=2
{
	val:8 = 0;
	replicate4to8(*:4 VRn, val);
	export val;
}

thv_vld1DdList3: "{"^buildVld1DdList3^"}"	is thv_c0505=0 & thv_D22 & thv_c1215 & buildVld1DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; counter=1; ] { export 1:4; }
thv_vld1DdList3: "{"^buildVld1DdList3^"}"	is thv_c0505=1 & thv_D22 & thv_c1215 & buildVld1DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; counter=2; ] { export 2:4; }

thv_vld1Align3:			is thv_c0404=0					{ }
thv_vld1Align3: "@16" 	is thv_c0404=1 & thv_c0607=1	{ }
thv_vld1Align3: "@32" 	is thv_c0404=1 & thv_c0607=2	{ }

VRnAligned3: "["^VRn^thv_vld1Align3^"]" 	is VRn & thv_vld1Align3	{ export VRn; }

@define T_vld1Constrain "((thv_c0607=0 & thv_c0404=0) | thv_c0607=1 | thv_c0607=2)"

:vld1.^esize0607 thv_vld1DdList3,VRnAligned3		is $(TMODE_F)  &thv_c2327=19 & thv_c2021=2 & VRnAligned3 & thv_vld1RnReplicate & thv_vld1DdList3 & thv_c0811=12 & esize0607 & thv_c0003=15 & $(T_vld1Constrain)
{
	mult_dat8 = thv_vld1RnReplicate;
 	build thv_vld1DdList3;
}

:vld1.^esize0607 thv_vld1DdList3,VRnAligned3^"!"	is $(TMODE_F)  &thv_c2327=19 & thv_c2021=2 & VRnAligned3 & thv_vld1RnReplicate & thv_vld1DdList3 & thv_c0811=12 & esize0607 & thv_c0003=13 & $(T_vld1Constrain)
{
	mult_dat8 = thv_vld1RnReplicate;
	build thv_vld1DdList3;
	VRnAligned3 = VRnAligned3 + thv_vld1DdList3;
}

:vld1.^esize0607 thv_vld1DdList3,VRnAligned3,VRm	is $(TMODE_F)  &thv_c2327=19 & thv_c2021=2 & VRnAligned3 & thv_vld1RnReplicate & thv_vld1DdList3 & thv_c0811=12 & esize0607 & VRm & $(T_vld1Constrain)
{
	mult_dat8 = thv_vld1RnReplicate;
	build thv_vld1DdList3;
	VRnAligned3 = VRnAligned3 + VRm;
}

#######
# VLD2 (multiple 2-element structures)
#

vld2Dd: Dreg		is (($(AMODE) & c0607=0) | ($(TMODE_F) & thv_c0607=0)) & Dreg & regInc
{
	ptr1:4 = &Dreg;
@if ENDIAN == "little"
  	ptr2:4 = &Dreg + (regInc * 8);
@else # ENDIAN == "big"
  	ptr2:4 = &Dreg - (regInc * 8);
@endif # ENDIAN = "big"
	mult_dat8 = 8;
<loop>
	*[register]:1 ptr1 = *:1 mult_addr;
	mult_addr = mult_addr + 1;
	*[register]:1 ptr2 = *:1 mult_addr;
	mult_addr = mult_addr + 1;
	mult_dat8 = mult_dat8 - 1;
	if(mult_dat8 == 0) goto <loop_end>;
	ptr1 = ptr1 + 1;
	ptr2 = ptr2 + 1;
	goto <loop>;
<loop_end>
}
vld2Dd: Dreg		is (($(AMODE) & c0607=1) | ($(TMODE_F) & thv_c0607=1)) & Dreg & regInc
{
	ptr1:4 = &Dreg;
@if ENDIAN == "little"
  	ptr2:4 = &Dreg + (regInc * 8);
@else # ENDIAN == "big"
  	ptr2:4 = &Dreg - (regInc * 8);
@endif # ENDIAN = "big"
	mult_dat8 = 4;
<loop>
	*[register]:2 ptr1 = *:2 mult_addr;
	mult_addr = mult_addr + 2;
	*[register]:2 ptr2 = *:2 mult_addr;
	mult_addr = mult_addr + 2;
	mult_dat8 = mult_dat8 - 1;
	if(mult_dat8 == 0) goto <loop_end>;
	ptr1 = ptr1 + 2;
	ptr2 = ptr2 + 2;
	goto <loop>;
<loop_end>	
}
vld2Dd: Dreg		is (($(AMODE) & c0607=2) | ($(TMODE_F) & thv_c0607=2)) & Dreg & regInc
{
	ptr1:4 = &Dreg;
@if ENDIAN == "little"
  	ptr2:4 = &Dreg + (regInc * 8);
@else # ENDIAN == "big"
  	ptr2:4 = &Dreg - (regInc * 8);
@endif # ENDIAN = "big"
	mult_dat8 = 2;
<loop>
	*[register]:4 ptr1 = *:4 mult_addr;
	mult_addr = mult_addr + 4;
	*[register]:4 ptr2 = *:4 mult_addr;
	mult_addr = mult_addr + 4;
	mult_dat8 = mult_dat8 - 1;
	if(mult_dat8 == 0) goto <loop_end>;
	ptr1 = ptr1 + 4;
	ptr2 = ptr2 + 4;
	goto <loop>;
<loop_end>	
}

buildVld2DdListA:							is counter=0								{ }
buildVld2DdListA: vld2Dd,buildVld2DdListA	is vld2Dd & buildVld2DdListA & esize0607	[ counter=counter-1; regNum=regNum+1; ] 
{
	build vld2Dd;
	build buildVld2DdListA;
}

buildVld2DdListB:							is counter2=0								{ }
buildVld2DdListB: Dreg2						is Dreg2 & counter2=1 & esize0607			[ counter2=0; reg2Num=reg2Num+1; ] { }
buildVld2DdListB: Dreg2,buildVld2DdListB	is Dreg2 & buildVld2DdListB & esize0607		[ counter2=counter2-1; reg2Num=reg2Num+1; ] { }

vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}"	is TMode=0 & c0811=8 & D22 & c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(D22<<4)+c1215-1; regInc=1; reg2Num=regNum+1; counter=1; counter2=1; ] { build buildVld2DdListA; build buildVld2DdListB; export 2:4; }
vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}"	is TMode=0 & c0811=9 & D22 & c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(D22<<4)+c1215-1; regInc=2; reg2Num=regNum+2; counter=1; counter2=1; ] { build buildVld2DdListA; build buildVld2DdListB; export 2:4; }
vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}"	is TMode=0 & c0811=3 & D22 & c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(D22<<4)+c1215-1; regInc=2; reg2Num=regNum+2; counter=2; counter2=2; ] { build buildVld2DdListA; build buildVld2DdListB; export 4:4; }
vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}"	is TMode=1 & thv_c0811=8 & thv_D22 & thv_c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; reg2Num=regNum+1; counter=1; counter2=1; ] { build buildVld2DdListA; build buildVld2DdListB; export 2:4; }
vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}"	is TMode=1 & thv_c0811=9 & thv_D22 & thv_c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=2; reg2Num=regNum+2; counter=1; counter2=1; ] { build buildVld2DdListA; build buildVld2DdListB; export 2:4; }
vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}"	is TMode=1 & thv_c0811=3 & thv_D22 & thv_c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=2; reg2Num=regNum+2; counter=2; counter2=2; ] { build buildVld2DdListA; build buildVld2DdListB; export 4:4; }

@define Vld2DdList "(c0811=3 | c0811=8 | c0811=9)"
@define thv_Vld2DdList "(thv_c0811=3 | thv_c0811=8 | thv_c0811=9)"

:vld2.^esize0607 vld2DdList,RnAligned45	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=2  & c0607<3 & c0003=15 & $(Vld2DdList) ) |
	                                         ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2  & thv_c0607<3 & thv_c0003=15 & $(thv_Vld2DdList) ) ) & RnAligned45 & esize0607 & vld2DdList
{
 	mult_addr = RnAligned45;
 	build vld2DdList;
}

:vld2.^esize0607 vld2DdList,RnAligned45^"!"	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=2  & c0607<3 & c0003=13 & $(Vld2DdList) ) |
	                                         ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2  & thv_c0607<3 & thv_c0003=13 & $(thv_Vld2DdList) ) ) & RnAligned45 & esize0607 & vld2DdList
{
	mult_addr = RnAligned45;
	build vld2DdList;
	RnAligned45 = RnAligned45 + (8 * vld2DdList);
}

:vld2.^esize0607 vld2DdList,RnAligned45,VRm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=2  & c0607<3 & c0003 & $(Vld2DdList) ) |
	                                         ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2  & thv_c0607<3 & thv_c0003 & $(thv_Vld2DdList) ) ) & VRm & RnAligned45 & esize0607 & vld2DdList
{
	mult_addr = RnAligned45;
	build vld2DdList;
	RnAligned45 = RnAligned45 + VRm;
}

#######
# VLD2 (single 2-element structure to one lane)
#

vld2Index: val	is TMode=0 & c0507 & c1011	[ val = c0507 >> c1011; ]	{ tmp:4 = val; export tmp; }
vld2Index: val	is TMode=1 & thv_c0507 & thv_c1011	[ val = thv_c0507 >> thv_c1011; ]	{ tmp:4 = val; export tmp; }

vld2DdElement2: Dreg^"["^vld2Index^"]"	is Dreg & vld2Index
{
}

vld2Align2: 		is TMode=0 & c0404=0 & (c1111=0 | c0505=0)	{ }
vld2Align2: "@16"	is TMode=0 & c1011=0 & c0404=1				{ }
vld2Align2: "@32"	is TMode=0 & c1011=1 & c0404=1				{ }
vld2Align2: "@64"	is TMode=0 & c1011=2 & c0405=1				{ }
vld2Align2: 		is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0)	{ }
vld2Align2: "@16"	is TMode=1 & thv_c1011=0 & thv_c0404=1				{ }
vld2Align2: "@32"	is TMode=1 & thv_c1011=1 & thv_c0404=1				{ }
vld2Align2: "@64"	is TMode=1 & thv_c1011=2 & thv_c0405=1				{ }

vld2RnAligned2: "["^VRn^vld2Align2^"]" 	is VRn & vld2Align2	{ export VRn; }

buildVld2DdList2:					is counter=0			{ }
buildVld2DdList2: vld2DdElement2	is counter=1 & vld2DdElement2		[ counter=0; regNum=regNum+regInc; ] { }
buildVld2DdList2: vld2DdElement2,buildVld2DdList2		is vld2DdElement2 & buildVld2DdList2	[ counter=counter-1; regNum=regNum+regInc; ] { }

vld2DdList2: "{"^buildVld2DdList2^"}"	is TMode=0 & D22 & c1215 & buildVld2DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=2; ] { } # Single
vld2DdList2: "{"^buildVld2DdList2^"}"	is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVld2DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=2; ] { } # Double
vld2DdList2: "{"^buildVld2DdList2^"}"	is TMode=1 & thv_D22 & thv_c1215 & buildVld2DdList2 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=2; ] { } # Single
vld2DdList2: "{"^buildVld2DdList2^"}"	is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildVld2DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=2; ] { } # Double


:vld2.^esize1011 vld2DdList2,vld2RnAligned2		is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=1 & c0003=15 ) | 
	                                                  ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=1 & thv_c0003=15 ) ) & esize1011 & VRm & vld2RnAligned2 & vld2DdList2
	unimpl

:vld2.^esize1011 vld2DdList2,vld2RnAligned2^"!"	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=1 & c0003=13 ) | 
	                                                  ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=1 & thv_c0003=13 ) ) & esize1011 & VRm & vld2RnAligned2 & vld2DdList2
	unimpl

:vld2.^esize1011 vld2DdList2,vld2RnAligned2,VRm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=1 & c0003 ) | 
	                                                  ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=1 & thv_c0003 ) ) & esize1011 & VRm & vld2RnAligned2 & vld2DdList2
	unimpl

#######
# VLD2 (single 2-element structure to all lanes)
#

vld2Align3:			is TMode=0 & c0404=0				{ }
vld2Align3:	"@16"	is TMode=0 & c0404=1 & c0607=0	{ }
vld2Align3: "@32" 	is TMode=0 & c0404=1 & c0607=1	{ }
vld2Align3: "@64" 	is TMode=0 & c0404=1 & c0607=2	{ }
vld2Align3:			is TMode=1 & thv_c0404=0				{ }
vld2Align3:	"@16"	is TMode=1 & thv_c0404=1 & thv_c0607=0	{ }
vld2Align3: "@32" 	is TMode=1 & thv_c0404=1 & thv_c0607=1	{ }
vld2Align3: "@64" 	is TMode=1 & thv_c0404=1 & thv_c0607=2	{ }

vld2RnAligned3: "["^VRn^vld2Align3^"]" 	is VRn & vld2Align3	{ export VRn; }

buildVld2DdList3:									is counter=0			{ }
buildVld2DdList3: Dreg^"[]"							is counter=1 & Dreg		[ counter=0; regNum=regNum+regInc; ] { }
buildVld2DdList3: Dreg^"[]",buildVld2DdList3		is Dreg & buildVld2DdList3	[ counter=counter-1; regNum=regNum+regInc; ] { }

vld2DdList3: "{"^buildVld2DdList3^"}"	is TMode=0 & c0505=0 & D22 & c1215 & buildVld2DdList3 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=2; ] { } # Single
vld2DdList3: "{"^buildVld2DdList3^"}"	is TMode=0 & c0505=1 & D22 & c1215 & buildVld2DdList3 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=2; ] { } # Double
vld2DdList3: "{"^buildVld2DdList3^"}"	is TMode=1 & thv_c0505=0 & thv_D22 & thv_c1215 & buildVld2DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=2; ] { } # Single
vld2DdList3: "{"^buildVld2DdList3^"}"	is TMode=1 & thv_c0505=1 & thv_D22 & thv_c1215 & buildVld2DdList3 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=2; ] { } # Double

:vld2.^esize0607 vld2DdList3,vld2RnAligned3		is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c0811=13 & c0607<3 & c0003=15 ) | 
	                                                  ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=13 & thv_c0607<3 & thv_c0003=15 ) ) & esize0607 & VRm & vld2RnAligned3 & vld2DdList3
	unimpl

:vld2.^esize0607 vld2DdList3,vld2RnAligned3^"!"	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c0811=13 & c0607<3 & c0003=13 ) | 
	                                                  ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=13 & thv_c0607<3 & thv_c0003=13 ) ) & esize0607 & VRm & vld2RnAligned3 & vld2DdList3
	unimpl

:vld2.^esize0607 vld2DdList3,vld2RnAligned3,VRm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c0811=13 & c0607<3 & c0003) | 
	                                                  ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=13 & thv_c0607<3 & thv_c0003 ) ) & esize0607 & VRm & vld2RnAligned3 & vld2DdList3
	unimpl

#######
# VLD3 (multiple 3-element structures)
#

vld3Align:			is TMode=0 & c0404=0 { }
vld3Align: "@64"	is TMode=0 & c0404=1 { }
vld3Align:			is TMode=1 & thv_c0404=0 { }
vld3Align: "@64"	is TMode=1 & thv_c0404=1 { }


vld3RnAligned: "["^VRn^vld3Align^"]" 	is VRn & vld3Align	{ export VRn; }

buildVld3DdList:							is counter=0			{ }
buildVld3DdList: Dreg						is counter=1 & Dreg		[ counter=0; regNum=regNum+regInc; ] { }
buildVld3DdList: Dreg,buildVld3DdList		is Dreg & buildVld3DdList	[ counter=counter-1; regNum=regNum+regInc; ] { }

vld3DdList: "{"^buildVld3DdList^"}"	is TMode=0 & c0811=4 & D22 & c1215 & buildVld3DdList [ regNum=(D22<<4)+c1215-1; regInc=1; counter=3; ] { } # Single
vld3DdList: "{"^buildVld3DdList^"}"	is TMode=0 & c0811=5 & D22 & c1215 & buildVld3DdList [ regNum=(D22<<4)+c1215-2; regInc=2; counter=3; ] { } # Double
vld3DdList: "{"^buildVld3DdList^"}"	is TMode=1 & thv_c0811=4 & thv_D22 & thv_c1215 & buildVld3DdList [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=3; ] { } # Single
vld3DdList: "{"^buildVld3DdList^"}"	is TMode=1 & thv_c0811=5 & thv_D22 & thv_c1215 & buildVld3DdList [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=3; ] { } # Double

:vld3.^esize0607 vld3DdList,vld3RnAligned		is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=2 & (c0811=4 | c0811=5) & c0607<3 & c0505=0 & c0003=15 ) |
													 ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & (thv_c0811=4 | thv_c0811=5) & thv_c0607<3 & thv_c0505=0 & thv_c0003=15) ) & vld3RnAligned & esize0607 & vld3DdList	unimpl

:vld3.^esize0607 vld3DdList,vld3RnAligned^"!"	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=2 & (c0811=4 | c0811=5) & c0607<3 & c0505=0 & c0003=13 ) |
													 ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & (thv_c0811=4 | thv_c0811=5) & thv_c0607<3 & thv_c0505=0 & thv_c0003=13) ) & vld3RnAligned & esize0607 & vld3DdList unimpl

:vld3.^esize0607 vld3DdList,vld3RnAligned,VRm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=2 & (c0811=4 | c0811=5) & c0607<3 & c0505=0 ) |
													 ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & (thv_c0811=4 | thv_c0811=5) & thv_c0607<3 & thv_c0505=0 ) ) & VRm & vld3RnAligned & esize0607 & vld3DdList unimpl

#######
# VLD3 (single 3-element structure to one lane)
#

vld3Index: val	is TMode=0 & c0507 & c1011	[ val = c0507 >> c1011; ]	{ tmp:4 = val; export tmp; }
vld3Index: val	is TMode=1 & thv_c0507 & thv_c1011	[ val = thv_c0507 >> thv_c1011; ]	{ tmp:4 = val; export tmp; }

vld3DdElement2: Dreg^"["^vld3Index^"]"	is Dreg & vld3Index
{
}

vld3Rn: "["^VRn^"]" 	is VRn { export VRn; }

buildVld3DdList2:										is counter=0							{ }
buildVld3DdList2: vld3DdElement2						is counter=1 & vld3DdElement2			[ counter=0; regNum=regNum+regInc; ] { }
buildVld3DdList2: vld3DdElement2,buildVld3DdList2		is vld3DdElement2 & buildVld3DdList2	[ counter=counter-1; regNum=regNum+regInc; ] { }

vld3DdList2: "{"^buildVld3DdList2^"}"	is TMode=0 & D22 & c1215 & buildVld3DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=3; ] { } # Single
vld3DdList2: "{"^buildVld3DdList2^"}"	is TMode=0 & ((c1011=1 & c0405=2) | (c1011=2 & c0406=4)) & D22 & c1215 & buildVld3DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=3; ] { } # Double
vld3DdList2: "{"^buildVld3DdList2^"}"	is TMode=1 & thv_D22 & thv_c1215 & buildVld3DdList2 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=3; ] { } # Single
vld3DdList2: "{"^buildVld3DdList2^"}"	is TMode=1 & ((thv_c1011=1 & thv_c0405=2) | (thv_c1011=2 & thv_c0406=4)) & thv_D22 & thv_c1215 & buildVld3DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=3; ] { } # Double


:vld3.^esize1011 vld3DdList2,vld3Rn		is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=2 & c0003=15) |
											 ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=2 & thv_c0003=15) ) & vld3Rn & esize1011 & vld3DdList2	unimpl

:vld3.^esize1011 vld3DdList2,vld3Rn^"!"	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=2 & c0003=13) |
											 ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=2 & thv_c0003=13) ) & vld3Rn & esize1011 & vld3DdList2	unimpl

:vld3.^esize1011 vld3DdList2,vld3Rn,VRm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=2) |
											 ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=2) ) & VRm & vld3Rn & esize1011 & vld3DdList2	unimpl

#######
# VLD3 (single 3-element structure to all lanes)
#

buildVld3DdList3:									is counter=0			{ }
buildVld3DdList3: Dreg^"[]"							is counter=1 & Dreg		[ counter=0; regNum=regNum+regInc; ] { }
buildVld3DdList3: Dreg^"[]",buildVld3DdList3		is Dreg & buildVld3DdList3	[ counter=counter-1; regNum=regNum+regInc; ] { }

vld3DdList3: "{"^buildVld3DdList3^"}"	is TMode=0 & c0505=0 & D22 & c1215 & buildVld3DdList3 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=3; ] { } # Single
vld3DdList3: "{"^buildVld3DdList3^"}"	is TMode=0 & c0505=1 & D22 & c1215 & buildVld3DdList3 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=3; ] { } # Double
vld3DdList3: "{"^buildVld3DdList3^"}"	is TMode=1 & thv_c0505=0 & thv_D22 & thv_c1215 & buildVld3DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=3; ] { } # Single
vld3DdList3: "{"^buildVld3DdList3^"}"	is TMode=1 & thv_c0505=1 & thv_D22 & thv_c1215 & buildVld3DdList3 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=3; ] { } # Double

:vld3.^esize0607 vld3DdList3,vld3Rn		is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c0811=14 & c0607<3 & c0404=0 & c0003=15) |
											( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=14 & thv_c0404=0 & thv_c0003=15) ) & vld3Rn & esize0607 & vld3DdList3	unimpl

:vld3.^esize0607 vld3DdList3,vld3Rn^"!"	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c0811=14 & c0607<3 & c0404=0 & c0003=13) |
											( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=14 & thv_c0404=0 & thv_c0003=13) ) & vld3Rn & esize0607 & vld3DdList3 unimpl

:vld3.^esize0607 vld3DdList3,vld3Rn,VRm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c0811=14 & c0607<3 & c0404=0) |
											( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=14 & thv_c0404=0) ) & VRm & vld3Rn & esize0607 & vld3DdList3 unimpl


#######
# VLD4 (single 4-element structure to one lane)
#

vld4Index: val	is TMode=0 & c0507 & c1011	[ val = c0507 >> c1011; ]	{ tmp:4 = val; export tmp; }
vld4Index: val	is TMode=1 & thv_c0507 & thv_c1011	[ val = thv_c0507 >> thv_c1011; ]	{ tmp:4 = val; export tmp; }

vld4DdElement2: Dreg^"["^vld4Index^"]"	is Dreg & vld4Index
{
}

vld4Align2: 		is TMode=0 & c0404=0 & (c1111=0 | c0505=0)				{ }
vld4Align2: "@32"	is TMode=0 & c1011=0 & c0404=1							{ }
vld4Align2: "@64"	is TMode=0 & ((c1011=1 & c0404=1) | (c1011=2 & c0405=1))	{ }
vld4Align2: "@128"	is TMode=0 & c1011=2 & c0405=2							{ }
vld4Align2: 		is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0)				{ }
vld4Align2: "@32"	is TMode=1 & thv_c1011=0 & thv_c0404=1							{ }
vld4Align2: "@64"	is TMode=1 & ((thv_c1011=1 & thv_c0404=1) | (thv_c1011=2 & thv_c0405=1))	{ }
vld4Align2: "@128"	is TMode=1 & thv_c1011=2 & thv_c0405=2							{ }

vld4RnAligned2: "["^Rn^vld4Align2^"]" 	is Rn & vld4Align2	{ export Rn; }

buildVld4DdList2:					is counter=0			{ }
buildVld4DdList2: vld4DdElement2	is counter=1 & vld4DdElement2		[ counter=0; regNum=regNum+regInc; ] { }
buildVld4DdList2: vld4DdElement2,buildVld4DdList2		is vld4DdElement2 & buildVld4DdList2	[ counter=counter-1; regNum=regNum+regInc; ] { }

vld4DdList2: "{"^buildVld4DdList2^"}"	is TMode=0 & D22 & c1215 & buildVld4DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single
vld4DdList2: "{"^buildVld4DdList2^"}"	is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVld4DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double
vld4DdList2: "{"^buildVld4DdList2^"}"	is TMode=1 & thv_D22 & thv_c1215 & buildVld4DdList2 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=4; ] { } # Single
vld4DdList2: "{"^buildVld4DdList2^"}"	is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildVld4DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=4; ] { } # Double


:vld4.^esize1011 vld4DdList2,vld4RnAligned2	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3  & c0809=3 & c0003=15) |
	                                             ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3  & thv_c0809=3 & thv_c0003=15 ) ) & esize1011 & vld4RnAligned2 & vld4DdList2
unimpl

:vld4.^esize1011 vld4DdList2,vld4RnAligned2^"!"	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3  & c0809=3 & c0003=13) |
	                                             ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3  & thv_c0809=3 & thv_c0003=13 ) ) & esize1011 & vld4RnAligned2 & vld4DdList2
unimpl

:vld4.^esize1011 vld4DdList2,vld4RnAligned2,VRm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3  & c0809=3 & c0003) |
	                                             ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3  & thv_c0809=3 & thv_c0003 ) ) & esize1011 & VRm & vld4RnAligned2 & vld4DdList2
 unimpl

#######
# VLD4 (single 4-element structure to all lanes)
#

vld4Align3:			is c0404=0							{ }
vld4Align3:	"@32"	is c0404=1 & c0607=0				{ }
vld4Align3: "@64" 	is c0404=1 & (c0607=1 | c0607=2)	{ }
vld4Align3: "@128" 	is c0404=1 & c0607=3				{ }

vld4RnAligned3: "["^Rn^vld4Align3^"]" 	is Rn & vld4Align3	{ export Rn; }

buildVld4DdList3:									is counter=0			{ }
buildVld4DdList3: Dreg^"[]"							is counter=1 & Dreg		[ counter=0; regNum=regNum+regInc; ] { }
buildVld4DdList3: Dreg^"[]",buildVld4DdList3		is Dreg & buildVld4DdList3	[ counter=counter-1; regNum=regNum+regInc; ] { }

vld4DdList3: "{"^buildVld4DdList3^"}"	is c0505=0 & D22 & c1215 & buildVld4DdList3 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single
vld4DdList3: "{"^buildVld4DdList3^"}"	is c0505=1 & D22 & c1215 & buildVld4DdList3 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double

:vld4.^esize0607 vld4DdList3,vld4RnAligned3		is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & vld4RnAligned3 & c0811=15 & esize0607 & c0003=15 & vld4DdList3	unimpl
#thv_2327=0x12

:vld4.^esize0607 vld4DdList3,vld4RnAligned3^"!"	is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & vld4RnAligned3 & c0811=15 & esize0607 & c0003=13 & vld4DdList3 unimpl

:vld4.^esize0607 vld4DdList3,vld4RnAligned3,VRm	is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & vld4RnAligned3 & c0811=15 & esize0607 & VRm & vld4DdList3 unimpl

#######
# VLD4 (multiple 4-element structures)
#

vld4Align:			is TMode=0 & c0405=0		{ }
vld4Align: "@64"	is TMode=0 & c0405=1		{ }
vld4Align: "@128" 	is TMode=0 & c0405=2 	{ }
vld4Align: "@256" 	is TMode=0 & c0405=3 	{ }
vld4Align:			is TMode=1 & thv_c0405=0	{ }
vld4Align: "@64"	is TMode=1 & thv_c0405=1	{ }
vld4Align: "@128" 	is TMode=1 & thv_c0405=2 { }
vld4Align: "@256" 	is TMode=1 & thv_c0405=3 { }

vld4RnAligned: "["^VRn^vld4Align^"]" 	is VRn & vld4Align	{ export VRn; }

buildVld4DdList:							is counter=0			{ }
buildVld4DdList: Dreg						is counter=1 & Dreg		[ counter=0; regNum=regNum+regInc; ] { }
buildVld4DdList: Dreg,buildVld4DdList		is Dreg & buildVld4DdList	[ counter=counter-1; regNum=regNum+regInc; ] { }

vld4DdList: "{"^buildVld4DdList^"}"	is TMode=0 & c0808=0 & D22 & c1215 & buildVld4DdList [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single
vld4DdList: "{"^buildVld4DdList^"}"	is TMode=0 & c0808=1 & D22 & c1215 & buildVld4DdList [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double
vld4DdList: "{"^buildVld4DdList^"}"	is TMode=1 & thv_c0808=0 & thv_D22 & thv_c1215 & buildVld4DdList [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=4; ] { } # Single
vld4DdList: "{"^buildVld4DdList^"}"	is TMode=1 & thv_c0808=1 & thv_D22 & thv_c1215 & buildVld4DdList [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=4; ] { } # Double

:vld4.^esize0607 vld4DdList,vld4RnAligned		is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=2 & c0911=0 & c0607<3 & c0003=15 ) | 
	                                                  ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0911=0 & thv_c0607<3 & thv_c0003=15 ) ) & esize0607 & VRm & vld4RnAligned & vld4DdList
	unimpl

:vld4.^esize0607 vld4DdList,vld4RnAligned^"!"	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=2 & c0911=0 & c0607<3 & c0003=13 ) | 
	                                                  ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0911=0 & thv_c0607<3 & thv_c0003=13 ) ) & esize0607 & VRm & vld4RnAligned & vld4DdList
	unimpl

:vld4.^esize0607 vld4DdList,vld4RnAligned,VRm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=2 & c0911=0 & c0607<3) | 
	                                                  ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0911=0 & thv_c0607<3 ) ) & esize0607 & VRm & vld4RnAligned & vld4DdList
	unimpl


@endif # SIMD

@if defined(VFPv2) || defined(VFPv3) || defined(SIMD)

#######
# VLDM (A1)
#

vldmRn: Rn		is TMode=0 & Rn & c2121=0		{ export Rn; }
vldmRn: Rn^"!"	is TMode=0 & Rn & c2121=1		{ export Rn; }
vldmRn: thv_Rn		is TMode=1 & thv_Rn & thv_c2121=0		{ export thv_Rn; }
vldmRn: thv_Rn^"!"	is TMode=1 & thv_Rn & thv_c2121=1		{ export thv_Rn; }
vldmOffset: value is $(AMODE) & immed     [ value= immed << 2; ]		{ export *[const]:4 value; }
vldmOffset: value is TMode=1 & thv_immed  [ value= thv_immed << 2; ]	{ export *[const]:4 value; }
vldmUpdate: immed is TMode=0 & vldmRn & c2121=0 & immed { }
vldmUpdate: immed is TMode=0 & vldmRn & c2121=1 & immed { vldmRn = vldmRn + (immed << 2); }
vldmUpdate: thv_immed is TMode=1 & vldmRn & thv_c2121=0 & thv_immed { }
vldmUpdate: thv_immed is TMode=1 & vldmRn & thv_c2121=1 & thv_immed { vldmRn = vldmRn + (thv_immed << 2); }

buildVldmDdList:						is counter=0				{ }
buildVldmDdList: Dreg					is counter=1 & Dreg		[ counter=0; regNum=regNum+1; ]
{
	Dreg = *mult_addr;
	mult_addr = mult_addr + 8;
}

buildVldmDdList: Dreg,buildVldmDdList	is Dreg & buildVldmDdList	[ counter=counter-1; regNum=regNum+1; ]
{
	Dreg = *mult_addr;
	mult_addr = mult_addr + 8;
	build buildVldmDdList;
}

vldmDdList: "{"^buildVldmDdList^"}"	is TMode=0 & D22 & c1215 & c0007 & buildVldmDdList [ regNum=(D22<<4)+c1215 - 1; counter=c0007>>1; ] { }
vldmDdList: "{"^buildVldmDdList^"}"	is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVldmDdList [ regNum=(thv_D22<<4)+thv_c1215 - 1; counter=thv_c0007>>1; ] { }

:vldmia^COND vldmRn,vldmDdList	is ( ($(AMODE) &     c2327=0x19 &     c2121 &     c2020=1 &     c0811=11 &     c0000=0) | 
                                   ($(TMODE_E) & thv_c2327=0x19 & thv_c2121 & thv_c2020=1 & thv_c0811=11 & thv_c0000=0) ) & COND & vldmRn & vldmDdList & vldmOffset & vldmUpdate
{
	mult_addr = vldmRn;
	build vldmDdList;
	build vldmUpdate;
}

:vldmdb^COND vldmRn,vldmDdList	is ( ($(AMODE) &     c2327=0x1a &     c2121=1 &     c2020=1 &     c0811=11 &     c0000=0) |
                                   ($(TMODE_E) & thv_c2327=0x1a & thv_c2121=1 & thv_c2020=1 & thv_c0811=11 & thv_c0000=0 ) ) & COND & vldmRn & vldmDdList & vldmOffset
{
	local start_addr = vldmRn - vldmOffset;
	mult_addr = start_addr;
	build vldmDdList;
	vldmRn = start_addr;
}

@endif # VFPv2 | VFPv3 | SIMD

@if defined(VERSION_8)

with : TMode=0 {
fldmSet1: Dd_1 is Rn & Dd_1 { Dd_1 = * Rn; }
fldmSet2: Dd_2 is Rn & Dd_2 & fldmSet1 { build fldmSet1; Dd_2 = *:8 (Rn + 8:4); }
fldmSet3: Dd_3 is Rn & Dd_3 & fldmSet2 { build fldmSet2; Dd_3 = *:8 (Rn + 16:4); }
fldmSet4: Dd_4 is Rn & Dd_4 & fldmSet3 { build fldmSet3; Dd_4 = *:8 (Rn + 24:4); }
fldmSet5: Dd_5 is Rn & Dd_5 & fldmSet4 { build fldmSet4; Dd_5 = *:8 (Rn + 32:4); }
fldmSet6: Dd_6 is Rn & Dd_6 & fldmSet5 { build fldmSet5; Dd_6 = *:8 (Rn + 40:4); }
fldmSet7: Dd_7 is Rn & Dd_7 & fldmSet6 { build fldmSet6; Dd_7 = *:8 (Rn + 48:4); }
fldmSet8: Dd_8 is Rn & Dd_8 & fldmSet7 { build fldmSet7; Dd_8 = *:8 (Rn + 56:4); }
fldmSet9: Dd_9 is Rn & Dd_9 & fldmSet8 { build fldmSet8; Dd_9 = *:8 (Rn + 64:4); }
fldmSet10: Dd_10 is Rn & Dd_10 & fldmSet9 { build fldmSet9; Dd_10 = *:8 (Rn + 72:4); }
fldmSet11: Dd_11 is Rn & Dd_11 & fldmSet10 { build fldmSet10; Dd_11 = *:8 (Rn + 80:4); }
fldmSet12: Dd_12 is Rn & Dd_12 & fldmSet11 { build fldmSet11; Dd_12 = *:8 (Rn + 88:4); }
fldmSet13: Dd_13 is Rn & Dd_13 & fldmSet12 { build fldmSet12; Dd_13 = *:8 (Rn + 96:4); }
fldmSet14: Dd_14 is Rn & Dd_14 & fldmSet13 { build fldmSet13; Dd_14 = *:8 (Rn + 104:4); }
fldmSet15: Dd_15 is Rn & Dd_15 & fldmSet14 { build fldmSet14; Dd_15 = *:8 (Rn + 112:4); }
fldmSet16: Dd_16 is Rn & Dd_16 & fldmSet15 { build fldmSet15; Dd_16 = *:8 (Rn + 120:4); }

fldmSet: "{"^Dd_1^"}" is Dd_1 & c0007=3 & fldmSet1 { build fldmSet1; }
fldmSet: "{"^Dd_1^"-"^fldmSet2^"}" is Dd_1 & c0007=5 & fldmSet2 { build fldmSet2; }
fldmSet: "{"^Dd_1^"-"^fldmSet3^"}" is Dd_1 & c0007=7 & fldmSet3 { build fldmSet3; }
fldmSet: "{"^Dd_1^"-"^fldmSet4^"}" is Dd_1 & c0007=9 & fldmSet4 { build fldmSet4; }
fldmSet: "{"^Dd_1^"-"^fldmSet5^"}" is Dd_1 & c0007=11 & fldmSet5 { build fldmSet5; }
fldmSet: "{"^Dd_1^"-"^fldmSet6^"}" is Dd_1 & c0007=13 & fldmSet6 { build fldmSet6; }
fldmSet: "{"^Dd_1^"-"^fldmSet7^"}" is Dd_1 & c0007=15 & fldmSet7 { build fldmSet7; }
fldmSet: "{"^Dd_1^"-"^fldmSet8^"}" is Dd_1 & c0007=17 & fldmSet8 { build fldmSet8; }
fldmSet: "{"^Dd_1^"-"^fldmSet9^"}" is Dd_1 & c0007=19 & fldmSet9 { build fldmSet9; }
fldmSet: "{"^Dd_1^"-"^fldmSet10^"}" is Dd_1 & c0007=21 & fldmSet10 { build fldmSet10; }
fldmSet: "{"^Dd_1^"-"^fldmSet11^"}" is Dd_1 & c0007=23 & fldmSet11 { build fldmSet11; }
fldmSet: "{"^Dd_1^"-"^fldmSet12^"}" is Dd_1 & c0007=25 & fldmSet12 { build fldmSet12; }
fldmSet: "{"^Dd_1^"-"^fldmSet13^"}" is Dd_1 & c0007=27 & fldmSet13 { build fldmSet13; }
fldmSet: "{"^Dd_1^"-"^fldmSet14^"}" is Dd_1 & c0007=29 & fldmSet14 { build fldmSet14; }
fldmSet: "{"^Dd_1^"-"^fldmSet15^"}" is Dd_1 & c0007=31 & fldmSet15 { build fldmSet15; }
fldmSet: "{"^Dd_1^"-"^fldmSet16^"}" is Dd_1 & c0007=33 & fldmSet16 { build fldmSet16; }


fldmWback: Rn^"!" is c2121=1 & c2323=1 & c0007 & Rn { Rn = Rn + (4 * c0007:4); }
fldmWback: Rn^"!" is c2121=1 & c2323=0 & c0007 & Rn { Rn = Rn - (4 * c0007:4); }
fldmWback: Rn is c2121=0 & Rn { }
}

with : TMode=1 {
fldmSet1: thv_Dd_1 is thv_Rn & thv_Dd_1 { thv_Dd_1 = * thv_Rn; }
fldmSet2: thv_Dd_2 is thv_Rn & thv_Dd_2 & fldmSet1 { build fldmSet1; thv_Dd_2 = *:8 (thv_Rn + 8:4); }
fldmSet3: thv_Dd_3 is thv_Rn & thv_Dd_3 & fldmSet2 { build fldmSet2; thv_Dd_3 = *:8 (thv_Rn + 16:4); }
fldmSet4: thv_Dd_4 is thv_Rn & thv_Dd_4 & fldmSet3 { build fldmSet3; thv_Dd_4 = *:8 (thv_Rn + 24:4); }
fldmSet5: thv_Dd_5 is thv_Rn & thv_Dd_5 & fldmSet4 { build fldmSet4; thv_Dd_5 = *:8 (thv_Rn + 32:4); }
fldmSet6: thv_Dd_6 is thv_Rn & thv_Dd_6 & fldmSet5 { build fldmSet5; thv_Dd_6 = *:8 (thv_Rn + 40:4); }
fldmSet7: thv_Dd_7 is thv_Rn & thv_Dd_7 & fldmSet6 { build fldmSet6; thv_Dd_7 = *:8 (thv_Rn + 48:4); }
fldmSet8: thv_Dd_8 is thv_Rn & thv_Dd_8 & fldmSet7 { build fldmSet7; thv_Dd_8 = *:8 (thv_Rn + 56:4); }
fldmSet9: thv_Dd_9 is thv_Rn & thv_Dd_9 & fldmSet8 { build fldmSet8; thv_Dd_9 = *:8 (thv_Rn + 64:4); }
fldmSet10: thv_Dd_10 is thv_Rn & thv_Dd_10 & fldmSet9 { build fldmSet9; thv_Dd_10 = *:8 (thv_Rn + 72:4); }
fldmSet11: thv_Dd_11 is thv_Rn & thv_Dd_11 & fldmSet10 { build fldmSet10; thv_Dd_11 = *:8 (thv_Rn + 80:4); }
fldmSet12: thv_Dd_12 is thv_Rn & thv_Dd_12 & fldmSet11 { build fldmSet11; thv_Dd_12 = *:8 (thv_Rn + 88:4); }
fldmSet13: thv_Dd_13 is thv_Rn & thv_Dd_13 & fldmSet12 { build fldmSet12; thv_Dd_13 = *:8 (thv_Rn + 96:4); }
fldmSet14: thv_Dd_14 is thv_Rn & thv_Dd_14 & fldmSet13 { build fldmSet13; thv_Dd_14 = *:8 (thv_Rn + 104:4); }
fldmSet15: thv_Dd_15 is thv_Rn & thv_Dd_15 & fldmSet14 { build fldmSet14; thv_Dd_15 = *:8 (thv_Rn + 112:4); }
fldmSet16: thv_Dd_16 is thv_Rn & thv_Dd_16 & fldmSet15 { build fldmSet15; thv_Dd_16 = *:8 (thv_Rn + 120:4); }

fldmSet: "{"^thv_Dd_1^"}" is thv_Dd_1 & thv_c0007=3 & fldmSet1 { build fldmSet1; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet2^"}" is thv_Dd_1 & thv_c0007=5 & fldmSet2 { build fldmSet2; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet3^"}" is thv_Dd_1 & thv_c0007=7 & fldmSet3 { build fldmSet3; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet4^"}" is thv_Dd_1 & thv_c0007=9 & fldmSet4 { build fldmSet4; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet5^"}" is thv_Dd_1 & thv_c0007=11 & fldmSet5 { build fldmSet5; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet6^"}" is thv_Dd_1 & thv_c0007=13 & fldmSet6 { build fldmSet6; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet7^"}" is thv_Dd_1 & thv_c0007=15 & fldmSet7 { build fldmSet7; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet8^"}" is thv_Dd_1 & thv_c0007=17 & fldmSet8 { build fldmSet8; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet9^"}" is thv_Dd_1 & thv_c0007=19 & fldmSet9 { build fldmSet9; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet10^"}" is thv_Dd_1 & thv_c0007=21 & fldmSet10 { build fldmSet10; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet11^"}" is thv_Dd_1 & thv_c0007=23 & fldmSet11 { build fldmSet11; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet12^"}" is thv_Dd_1 & thv_c0007=25 & fldmSet12 { build fldmSet12; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet13^"}" is thv_Dd_1 & thv_c0007=27 & fldmSet13 { build fldmSet13; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet14^"}" is thv_Dd_1 & thv_c0007=29 & fldmSet14 { build fldmSet14; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet15^"}" is thv_Dd_1 & thv_c0007=31 & fldmSet15 { build fldmSet15; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet16^"}" is thv_Dd_1 & thv_c0007=33 & fldmSet16 { build fldmSet16; }


fldmWback: thv_Rn^"!" is thv_bit21=1 & thv_bit23=1 & thv_c0007 & thv_Rn { thv_Rn = thv_Rn + (4 * thv_c0007:4); }
fldmWback: thv_Rn^"!" is thv_bit21=1 & thv_bit23=0 & thv_c0007 & thv_Rn { thv_Rn = thv_Rn - (4 * thv_c0007:4); }
fldmWback: thv_Rn is thv_bit21=0 & thv_Rn { }
}

:fldmdbx^COND fldmWback, fldmSet is $(AMODE) & COND & ARMcond=1 & c2327=0x1a & c2021=3 & c0811=0xb & c0000=1 & fldmWback & fldmSet
{
	build fldmWback;
	build fldmSet;
}

:fldmiax^COND fldmWback, fldmSet is $(AMODE) & COND & ARMcond=1 & c2327=0x19 & c2020=1 & c0811=0xb & c0000=1 & fldmWback & fldmSet
{
	build fldmSet;
	build fldmWback;
}

:fldmdbx^ItCond fldmWback, fldmSet is TMode=1 & ItCond & thv_c2331=0x1da & thv_c2021=3 & thv_c0811=0xb & fldmWback & fldmSet
{
	build fldmWback;
	build fldmSet;
}

:fldmiax^ItCond fldmWback, fldmSet is TMode=1 & ItCond & thv_c2331=0x1d9 & thv_bit20=1 & thv_c0811=0xb & fldmWback & fldmSet
{
	build fldmSet;
	build fldmWback;
}

with : TMode=0 {
fstmSet1: Dd_1 is Rn & Dd_1 { * Rn = Dd_1; }
fstmSet2: Dd_2 is Rn & Dd_2 & fstmSet1 { build fstmSet1; *:8 (Rn + 8:4) = Dd_2; }
fstmSet3: Dd_3 is Rn & Dd_3 & fstmSet2 { build fstmSet2; *:8 (Rn + 16:4) = Dd_3; }
fstmSet4: Dd_4 is Rn & Dd_4 & fstmSet3 { build fstmSet3; *:8 (Rn + 24:4) = Dd_4; }
fstmSet5: Dd_5 is Rn & Dd_5 & fstmSet4 { build fstmSet4; *:8 (Rn + 32:4) = Dd_5; }
fstmSet6: Dd_6 is Rn & Dd_6 & fstmSet5 { build fstmSet5; *:8 (Rn + 40:4) = Dd_6; }
fstmSet7: Dd_7 is Rn & Dd_7 & fstmSet6 { build fstmSet6; *:8 (Rn + 48:4) = Dd_7; }
fstmSet8: Dd_8 is Rn & Dd_8 & fstmSet7 { build fstmSet7; *:8 (Rn + 56:4) = Dd_8; }
fstmSet9: Dd_9 is Rn & Dd_9 & fstmSet8 { build fstmSet8; *:8 (Rn + 64:4) = Dd_9; }
fstmSet10: Dd_10 is Rn & Dd_10 & fstmSet9 { build fstmSet9; *:8 (Rn + 72:4) = Dd_10; }
fstmSet11: Dd_11 is Rn & Dd_11 & fstmSet10 { build fstmSet10; *:8 (Rn + 80:4) = Dd_11; }
fstmSet12: Dd_12 is Rn & Dd_12 & fstmSet11 { build fstmSet11; *:8 (Rn + 88:4) = Dd_12; }
fstmSet13: Dd_13 is Rn & Dd_13 & fstmSet12 { build fstmSet12; *:8 (Rn + 96:4) = Dd_13; }
fstmSet14: Dd_14 is Rn & Dd_14 & fstmSet13 { build fstmSet13; *:8 (Rn + 104:4) = Dd_14; }
fstmSet15: Dd_15 is Rn & Dd_15 & fstmSet14 { build fstmSet14; *:8 (Rn + 112:4) = Dd_15; }
fstmSet16: Dd_16 is Rn & Dd_16 & fstmSet15 { build fstmSet15; *:8 (Rn + 120:4) = Dd_16; }

fstmSet: "{"^Dd_1^"}" is Dd_1 & c0007=3 & fstmSet1 { build fstmSet1; }
fstmSet: "{"^Dd_1^"-"^fstmSet2^"}" is Dd_1 & c0007=5 & fstmSet2 { build fstmSet2; }
fstmSet: "{"^Dd_1^"-"^fstmSet3^"}" is Dd_1 & c0007=7 & fstmSet3 { build fstmSet3; }
fstmSet: "{"^Dd_1^"-"^fstmSet4^"}" is Dd_1 & c0007=9 & fstmSet4 { build fstmSet4; }
fstmSet: "{"^Dd_1^"-"^fstmSet5^"}" is Dd_1 & c0007=11 & fstmSet5 { build fstmSet5; }
fstmSet: "{"^Dd_1^"-"^fstmSet6^"}" is Dd_1 & c0007=13 & fstmSet6 { build fstmSet6; }
fstmSet: "{"^Dd_1^"-"^fstmSet7^"}" is Dd_1 & c0007=15 & fstmSet7 { build fstmSet7; }
fstmSet: "{"^Dd_1^"-"^fstmSet8^"}" is Dd_1 & c0007=17 & fstmSet8 { build fstmSet8; }
fstmSet: "{"^Dd_1^"-"^fstmSet9^"}" is Dd_1 & c0007=19 & fstmSet9 { build fstmSet9; }
fstmSet: "{"^Dd_1^"-"^fstmSet10^"}" is Dd_1 & c0007=21 & fstmSet10 { build fstmSet10; }
fstmSet: "{"^Dd_1^"-"^fstmSet11^"}" is Dd_1 & c0007=23 & fstmSet11 { build fstmSet11; }
fstmSet: "{"^Dd_1^"-"^fstmSet12^"}" is Dd_1 & c0007=25 & fstmSet12 { build fstmSet12; }
fstmSet: "{"^Dd_1^"-"^fstmSet13^"}" is Dd_1 & c0007=27 & fstmSet13 { build fstmSet13; }
fstmSet: "{"^Dd_1^"-"^fstmSet14^"}" is Dd_1 & c0007=29 & fstmSet14 { build fstmSet14; }
fstmSet: "{"^Dd_1^"-"^fstmSet15^"}" is Dd_1 & c0007=31 & fstmSet15 { build fstmSet15; }
fstmSet: "{"^Dd_1^"-"^fstmSet16^"}" is Dd_1 & c0007=33 & fstmSet16 { build fstmSet16; }


fstmWback: Rn^"!" is c2121=1 & c2323=1 & c0007 & Rn { Rn = Rn + (4 * c0007:4); }
fstmWback: Rn^"!" is c2121=1 & c2323=0 & c0007 & Rn { Rn = Rn - (4 * c0007:4); }
fstmWback: Rn is c2121=0 & Rn { }
}

with : TMode=1 {
fstmSet1: thv_Dd_1 is thv_Rn & thv_Dd_1 { * thv_Rn = thv_Dd_1; }
fstmSet2: thv_Dd_2 is thv_Rn & thv_Dd_2 & fstmSet1 { build fstmSet1; *:8 (thv_Rn + 8:4) = thv_Dd_2; }
fstmSet3: thv_Dd_3 is thv_Rn & thv_Dd_3 & fstmSet2 { build fstmSet2; *:8 (thv_Rn + 16:4) = thv_Dd_3; }
fstmSet4: thv_Dd_4 is thv_Rn & thv_Dd_4 & fstmSet3 { build fstmSet3; *:8 (thv_Rn + 24:4) = thv_Dd_4; }
fstmSet5: thv_Dd_5 is thv_Rn & thv_Dd_5 & fstmSet4 { build fstmSet4; *:8 (thv_Rn + 32:4) = thv_Dd_5; }
fstmSet6: thv_Dd_6 is thv_Rn & thv_Dd_6 & fstmSet5 { build fstmSet5; *:8 (thv_Rn + 40:4) = thv_Dd_6; }
fstmSet7: thv_Dd_7 is thv_Rn & thv_Dd_7 & fstmSet6 { build fstmSet6; *:8 (thv_Rn + 48:4) = thv_Dd_7; }
fstmSet8: thv_Dd_8 is thv_Rn & thv_Dd_8 & fstmSet7 { build fstmSet7; *:8 (thv_Rn + 56:4) = thv_Dd_8; }
fstmSet9: thv_Dd_9 is thv_Rn & thv_Dd_9 & fstmSet8 { build fstmSet8; *:8 (thv_Rn + 64:4) = thv_Dd_9; }
fstmSet10: thv_Dd_10 is thv_Rn & thv_Dd_10 & fstmSet9 { build fstmSet9; *:8 (thv_Rn + 72:4) = thv_Dd_10; }
fstmSet11: thv_Dd_11 is thv_Rn & thv_Dd_11 & fstmSet10 { build fstmSet10; *:8 (thv_Rn + 80:4) = thv_Dd_11; }
fstmSet12: thv_Dd_12 is thv_Rn & thv_Dd_12 & fstmSet11 { build fstmSet11; *:8 (thv_Rn + 88:4) = thv_Dd_12; }
fstmSet13: thv_Dd_13 is thv_Rn & thv_Dd_13 & fstmSet12 { build fstmSet12; *:8 (thv_Rn + 96:4) = thv_Dd_13; }
fstmSet14: thv_Dd_14 is thv_Rn & thv_Dd_14 & fstmSet13 { build fstmSet13; *:8 (thv_Rn + 104:4) = thv_Dd_14; }
fstmSet15: thv_Dd_15 is thv_Rn & thv_Dd_15 & fstmSet14 { build fstmSet14; *:8 (thv_Rn + 112:4) = thv_Dd_15; }
fstmSet16: thv_Dd_16 is thv_Rn & thv_Dd_16 & fstmSet15 { build fstmSet15; *:8 (thv_Rn + 120:4) = thv_Dd_16; }

fstmSet: "{"^thv_Dd_1^"}" is thv_Dd_1 & thv_c0007=3 & fstmSet1 { build fstmSet1; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet2^"}" is thv_Dd_1 & thv_c0007=5 & fstmSet2 { build fstmSet2; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet3^"}" is thv_Dd_1 & thv_c0007=7 & fstmSet3 { build fstmSet3; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet4^"}" is thv_Dd_1 & thv_c0007=9 & fstmSet4 { build fstmSet4; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet5^"}" is thv_Dd_1 & thv_c0007=11 & fstmSet5 { build fstmSet5; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet6^"}" is thv_Dd_1 & thv_c0007=13 & fstmSet6 { build fstmSet6; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet7^"}" is thv_Dd_1 & thv_c0007=15 & fstmSet7 { build fstmSet7; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet8^"}" is thv_Dd_1 & thv_c0007=17 & fstmSet8 { build fstmSet8; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet9^"}" is thv_Dd_1 & thv_c0007=19 & fstmSet9 { build fstmSet9; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet10^"}" is thv_Dd_1 & thv_c0007=21 & fstmSet10 { build fstmSet10; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet11^"}" is thv_Dd_1 & thv_c0007=23 & fstmSet11 { build fstmSet11; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet12^"}" is thv_Dd_1 & thv_c0007=25 & fstmSet12 { build fstmSet12; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet13^"}" is thv_Dd_1 & thv_c0007=27 & fstmSet13 { build fstmSet13; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet14^"}" is thv_Dd_1 & thv_c0007=29 & fstmSet14 { build fstmSet14; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet15^"}" is thv_Dd_1 & thv_c0007=31 & fstmSet15 { build fstmSet15; }
fstmSet: "{"^thv_Dd_1^"-"^fstmSet16^"}" is thv_Dd_1 & thv_c0007=33 & fstmSet16 { build fstmSet16; }


fstmWback: thv_Rn^"!" is thv_bit21=1 & thv_bit23=1 & thv_c0007 & thv_Rn { thv_Rn = thv_Rn + (4 * thv_c0007:4); }
fstmWback: thv_Rn^"!" is thv_bit21=1 & thv_bit23=0 & thv_c0007 & thv_Rn { thv_Rn = thv_Rn - (4 * thv_c0007:4); }
fstmWback: thv_Rn is thv_bit21=0 & thv_Rn { }
}

:fstmdbx^COND fstmSet, fstmWback is $(AMODE) & COND & ARMcond=1 & c2327=0x1a & c2021=2 & c0811=0xb & c0000=1 & fstmWback & fstmSet
{
	build fstmWback;
	build fstmSet;
}

:fstmiax^COND fstmSet, fstmWback is $(AMODE) & COND & ARMcond=1 & c2327=0x19 & c2020=0 & c0811=0xb & c0000=1 & fstmWback & fstmSet
{
	build fstmSet;
	build fstmWback;
}

:fstmdbx^ItCond fstmSet, fstmWback is TMode=1 & ItCond & thv_c2331=0x1da & thv_c2021=2 & thv_c0811=0xb & fstmWback & fstmSet
{
	build fstmWback;
	build fstmSet;
}

:fstmiax^ItCond fstmSet, fstmWback is TMode=1 & ItCond & thv_c2331=0x1d9 & thv_bit20=0 & thv_c0811=0xb & fstmWback & fstmSet
{
	build fstmSet;
	build fstmWback;
}

@endif

@if defined(VFPv2) || defined(VFPv3)

#######
# VLDM (A2)
#

buildVldmSdList:						is counter=0 { }
buildVldmSdList: Sreg					is counter=1 & Sreg [ counter=0; regNum=regNum+1; ]
{
	Sreg = *mult_addr;
	mult_addr = mult_addr + 4;
}
buildVldmSdList: Sreg,buildVldmSdList	is Sreg & buildVldmSdList [ counter=counter-1; regNum=regNum+1; ]
{
	Sreg = *mult_addr;
	mult_addr = mult_addr + 4;
	build buildVldmSdList;
}

vldmSdList: "{"^buildVldmSdList^"}"	is TMode=0   & D22 & c1215 & c0007 & buildVldmSdList [ regNum=(c1215<<1) + D22 - 1; counter=c0007; ] { }
vldmSdList: "{"^buildVldmSdList^"}"	is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVldmSdList [ regNum=(thv_c1215<<1) + thv_D22 - 1; counter=thv_c0007; ] { }

:vldmia^COND vldmRn,vldmSdList	is ( ($(AMODE) & ARMcond=1 & c2327=0x19 &     c2020=1 &     c0811=10 ) |
                                   ($(TMODE_E) &         thv_c2327=0x19 & thv_c2020=1 & thv_c0811=10 ) ) & COND & vldmRn & vldmSdList & vldmOffset & vldmUpdate
{
	mult_addr = vldmRn;
	build vldmSdList;
	build vldmUpdate;
}

:vldmdb^COND vldmRn,vldmSdList	is ( ($(AMODE) & ARMcond=1 & c2327=0x1a &     c2121=1 &     c2020=1 &     c0811=10 ) |
                                   ($(TMODE_E) &         thv_c2327=0x1a & thv_c2121=1 & thv_c2020=1 & thv_c0811=10 ) ) & COND & vldmRn & vldmSdList & vldmOffset
{
	local start_addr = vldmRn - vldmOffset;
	mult_addr = start_addr;
	build vldmSdList;
	vldmRn = start_addr;
}

#######
# VLDR
#

vldrRn: "["^Rn^"]"				is TMode=0 & Rn & immed=0 & c2323=0				{ ptr:4 = Rn; export ptr; }
vldrRn: "["^Rn^"]"				is TMode=0 & Rn & immed=0 & c2323=1				{ ptr:4 = Rn; export ptr; }
vldrRn: "["^Rn^",#-"^vldrImm^"]"	is TMode=0 & Rn & immed & c2323=0 [ vldrImm = immed * 4; ]	{ ptr:4 = Rn - vldrImm; export ptr; }
vldrRn: "["^Rn^",#"^vldrImm^"]"	is TMode=0 & Rn & immed & c2323=1	  [ vldrImm = immed * 4; ]	{ ptr:4 = Rn + vldrImm; export ptr; }
vldrRn: "["^pc^"]"	is TMode=0 & Rn=15 & pc & immed=0 & c2323=0		{ ptr:4 = ((inst_start + 8) & 0xfffffffc); export ptr; }
vldrRn: "["^pc^"]"	is TMode=0 & Rn=15 & pc & immed=0 & c2323=1		{ ptr:4 = ((inst_start + 8) & 0xfffffffc); export ptr; }
vldrRn: "["^pc^",#-"^vldrImm^"]"	is TMode=0 & Rn=15 & pc & immed & c2323=0 [ vldrImm = immed * 4; ]	{ ptr:4 = ((inst_start + 8) & 0xfffffffc) - vldrImm; export ptr; }
vldrRn: "["^pc^",#"^vldrImm^"]"	is TMode=0 & Rn=15 & pc & immed & c2323=1	  [ vldrImm = immed * 4; ]	{ ptr:4 = ((inst_start + 8) & 0xfffffffc) + vldrImm; export ptr; }
vldrRn: "["^VRn^"]"				is TMode=1 & VRn & thv_immed=0 & thv_c2323=0				{ ptr:4 = VRn; export ptr; }
vldrRn: "["^VRn^"]"				is TMode=1 & VRn & thv_immed=0 & thv_c2323=1				{ ptr:4 = VRn; export ptr; }
vldrRn: "["^VRn^",#-"^vldrImm^"]"	is TMode=1 & VRn & thv_immed & thv_c2323=0	[ vldrImm = thv_immed * 4; ]	{ ptr:4 = VRn - vldrImm; export ptr; }
vldrRn: "["^VRn^",#"^vldrImm^"]"	is TMode=1 & VRn & thv_immed & thv_c2323=1	[ vldrImm = thv_immed * 4; ]	{ ptr:4 = VRn + vldrImm; export ptr; }
vldrRn: "["^pc^"]"	is TMode=1 & thv_Rn=15 & pc & thv_immed=0 & thv_c2323=0		{ ptr:4 = ((inst_start + 4) & 0xfffffffc); export ptr; }
vldrRn: "["^pc^"]"	is TMode=1 & thv_Rn=15 & pc & thv_immed=0 & thv_c2323=1		{ ptr:4 = ((inst_start + 4) & 0xfffffffc); export ptr; }
vldrRn: "["^pc^",#-"^vldrImm^"]"	is TMode=1 & thv_Rn=15 & pc & thv_immed & thv_c2323=0	[ vldrImm = thv_immed * 4; ]	{ ptr:4 = ((inst_start + 4) & 0xfffffffc) - vldrImm; export ptr; }
vldrRn: "["^pc^",#"^vldrImm^"]"	is TMode=1 & thv_Rn=15 & pc & thv_immed & thv_c2323=1	[ vldrImm = thv_immed * 4; ]	{ ptr:4 = ((inst_start + 4) & 0xfffffffc) + vldrImm; export ptr; }

:vldr^COND^".64" Dd,vldrRn	is COND & ( ($(AMODE) & ARMcond=1 & c2427=13 & c2021=1 & c0811=11) | ($(TMODE_E) &  thv_c2427=13 & thv_c2021=1 & thv_c0811=11)) & Dd & vldrRn
{
	Dd = *:8 vldrRn;
}

:vldr^COND^".32" Sd,vldrRn	is COND & ( ($(AMODE) & ARMcond=1 & c2427=13 & c2021=1 & c0811=10) | ($(TMODE_E) &  thv_c2427=13 & thv_c2021=1 & thv_c0811=10)) & Sd & vldrRn
{
	Sd = *:4 vldrRn;
}

@endif # VFPv2 | VFPv3

define pcodeop VectorMin;
define pcodeop VectorMax;
define pcodeop FloatVectorMin;
define pcodeop FloatVectorMax;
define pcodeop VectorMultiplyAccumulate;
define pcodeop VectorMultiplySubtract;
define pcodeop VectorMultiplySubtractLong;
define pcodeop VectorDoubleMultiplyHighHalf;
define pcodeop VectorRoundDoubleMultiplyHighHalf;
define pcodeop VectorDoubleMultiplyLong;
define pcodeop VectorDoubleMultiplyAccumulateLong;
define pcodeop VectorDoubleMultiplySubtractLong;
define pcodeop FloatVectorMultiplyAccumulate;
define pcodeop FloatVectorMultiplySubtract;

@if defined(SIMD)

:vmax.^udt^esize2021 Dd, Dn, Dm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=6 & Q6=0 & c0404=0 ) |
                                      ( $(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c2021<3 & thv_c0811=6 & thv_Q6=0 & thv_c0404=0 )  ) & esize2021 & udt & Dm & Dn & Dd
{
	Dd = VectorMax(Dn,Dm,esize2021,udt);
}

:vmax.^udt^esize2021 Qd, Qn, Qm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=6 & Q6=1 & c0404=0 ) |
                                      ( $(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c2021<3 & thv_c0811=6 & thv_Q6=1 & thv_c0404=0 )  ) & esize2021 & udt & Qm & Qn & Qd
{
	Qd = VectorMax(Qn,Qm,esize2021,udt);
}

:vmax.f32 Dd,Dn,Dm	is (($(AMODE) & ARMcond=0 & cond=15 & c2327=4 & c2021=0 & c0811=15 & Q6=0 & c0404=0) |
						($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=15 & thv_Q6=0 & thv_c0404=0)) & Dm & Dn & Dd
{
	Dd = FloatVectorMax(Dn,Dm,2:4,32:1);
}

:vmax.f32 Qd,Qn,Qm	is (($(AMODE) & ARMcond=0 & cond=15 & c2327=4 & c2021=0 & c0811=15 & Q6=1 & c0404=0) |
						($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=15 & thv_Q6=1 & thv_c0404=0)) & Qm & Qn & Qd
{
	Qd = FloatVectorMax(Qn,Qm,2:4,32:1);
}

:vmin.^udt^esize2021 Dd, Dn, Dm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=6 & Q6=0 & c0404=1 ) |
                                      ( $(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c2021<3 & thv_c0811=6 & thv_Q6=0 & thv_c0404=1 ) ) & esize2021 & udt & Dm & Dn & Dd

{
	Dd = VectorMin(Dn,Dm,esize2021,udt);
}

:vmin.^udt^esize2021 Qd, Qn, Qm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=6 & Q6=1 & c0404=1 ) |
                                      ( $(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c2021<3 & thv_c0811=6 & thv_Q6=1 & thv_c0404=1 ) ) & esize2021 & udt & Qm & Qn & Qd

{
	Qd = VectorMin(Qn,Qm,esize2021,udt);
}

:vmin.f32 Dd,Dn,Dm	is (($(AMODE) & ARMcond=0 & cond=15 & c2327=4 & c2021=2 & c0811=15 & Q6=0 & c0404=0) |
						($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=15 & thv_Q6=0 & thv_c0404=0)) & Dm & Dn & Dd
{
	Dd = FloatVectorMin(Dn,Dm,2:4,32:1);
}

:vmin.f32 Qd,Qn,Qm	is (($(AMODE) & ARMcond=0 & cond=15 & c2327=4 & c2021=2 & c0811=15 & Q6=1 & c0404=0) |
						($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=15 & thv_Q6=1 & thv_c0404=0)) & Qm & Qn & Qd
{
	Qd = FloatVectorMin(Qn,Qm,2:4,32:1);
}

:vmla.i^esize2021 Dd,Dn,Dm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=4 & c2021<3 & c0811=9 & Q6=0 & c0404=0 ) |
						           ($(TMODE_E) &    thv_c2327=0x1e & thv_c2021<3 & thv_c0811=9 & thv_Q6=0 & thv_c0404=0)) & esize2021 & Dm & Dn & Dd
{
	Dd = VectorMultiplyAccumulate(Dn,Dm,esize2021,0:1);
}  

:vmla.i^esize2021 Qd,Qn,Qm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=4 & c2021<3 & c0811=9 & Q6=1 & c0404=0) |
						           ($(TMODE_E) &    thv_c2327=0x1e & thv_c2021<3 & thv_c0811=9 & thv_Q6=1 & thv_c0404=0)) & esize2021 & Qm & Qn & Qd
{
	Qd = VectorMultiplyAccumulate(Qn,Qm,esize2021,0:1);
}  

:vmls.i^esize2021 Dd,Dn,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 & c2424=1 & c2021<3 & c0811=9 & Q6=0 & c0404=0) |
						           ($(TMODE_F) &   thv_c2327=0x1e & thv_c2021<3 & thv_c0811=9 & thv_Q6=0 & thv_c0404=0)) & esize2021 & Dm & Dn & Dd
{
	Dd = VectorMultiplySubtract(Dn,Dm,esize2021,0:1);
}  

:vmls.i^esize2021 Qd,Qn,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 & c2424=1 & c2021<3 & c0811=9 & Q6=1 & c0404=0) |
						           ($(TMODE_F) &   thv_c2327=0x1e & thv_c2021<3 & thv_c0811=9 & thv_Q6=1 & thv_c0404=0)) & esize2021 & Qm & Qn & Qd
{
	Qd = VectorMultiplySubtract(Qn,Qm,esize2021,0:1);
}  

:vmlal.^udt^esize2021 Qd,Dn,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 &      c2323=1    & c2021<3 &      c0811=8 &     Q6=0 & c0404=0) |
                                     ($(TMODE_EorF) &  thv_c2327=0x1f & thv_c2021<3 & thv_c0811=8 & thv_Q6=0 & thv_c0404=0 ) ) & Dm & Dn & Qd & udt & esize2021
{
	Qd = VectorMultiplyAccumulate(Dn,Dm,esize2021,udt);
}  

:vmlsl.^udt^esize2021 Qd,Dn,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1    & c2323=1 & c2021<3 & c0811=10 & Q6=0 & c0404=0) |
                                     ($(TMODE_EorF) &  thv_c2327=0x1f & thv_c2021<3 & thv_c0811=10 & thv_Q6=0 & thv_c0404=0 ) ) & Dm & Dn & Qd & udt & esize2021
{
	Qd = VectorMultiplySubtractLong(Dn,Dm,esize2021,udt);
}  

:vmla.f^fesize2020 Dd,Dn,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2121=0 &     c0811=13 &        Q6=0 &     c0404=1) |
	                           ($(TMODE_E) &    thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_c0606=0 & thv_c0404=1)) & fesize2020 & Dn & Dd & Dm
{
	Dd = FloatVectorMultiplyAccumulate(Dn,Dm,fesize2020,8:1);
}

:vmla.f^fesize2020 Qd,Qn,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2121=0 &     c0811=13 &        Q6=1 &     c0404=1) | 
	                           ($(TMODE_E) &    thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_c0606=1 & thv_c0404=1)) & fesize2020 & Qn & Qd & Qm
{
	Qd = FloatVectorMultiplyAccumulate(Qn,Qm,fesize2020,16:1);
}

:vmls.f^fesize2020 Dd,Dn,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2121=1 &     c0811=13 &        Q6=0 &     c0404=1) |
                               ($(TMODE_E) &    thv_c2327=0x1e & thv_c2121=1 & thv_c0811=13 & thv_c0606=0 & thv_c0404=1)) & fesize2020 & Dn & Dd & Dm
{
	Dd = FloatVectorMultiplySubtract(Dn,Dm,fesize2020,8:1);
}

:vmls.f^fesize2020 Qd,Qn,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2121=1 &     c0811=13 &        Q6=1 &     c0404=1) | 
	                           ($(TMODE_E) &    thv_c2327=0x1e & thv_c2121=1 & thv_c0811=13 & thv_c0606=1 & thv_c0404=1)) & fesize2020 & Qn & Qd & Qm
{
	Qd = FloatVectorMultiplySubtract(Qn,Qm,fesize2020,16:1);
}

@endif # SIMD

@if defined(VFPv2) || defined(VFPv3)

:vmla^COND^".f32" Sd,Sn,Sm	is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=0 &     c0811=10 &     c0606=0 &     c0404=0 ) |
						       ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=0 & thv_c0811=10 & thv_c0606=0 & thv_c0404=0)) & COND & Sm & Sn & Sd
{
	Sd = Sd f+ (Sn f* Sm);
}

:vmla^COND^".f64" Dd,Dn,Dm	is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=0 &     c0811=11 &     c0606=0 &     c0404=0) |
						       ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=0 & thv_c0811=11 & thv_c0606=0 & thv_c0404=0)) & COND & Dm & Dn & Dd
{
	Dd = Dd f+ (Dn f* Dm);
}

:vmls^COND^".f32" Sd,Sn,Sm	is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=0 &     c0811=10 &     c0606=1 &     c0404=0) |
						       ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=0 & thv_c0811=10 & thv_c0606=1 & thv_c0404=0)) & COND & Sm & Sn & Sd
{
	Sd = Sd f- (Sn f* Sm);
}

:vmls^COND^".f64" Dd,Dn,Dm	is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=0 &     c0811=11 &     c0606=1 &     c0404=0 ) |
						       ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=0 & thv_c0811=11 & thv_c0606=1 & thv_c0404=0)) & COND & Dm & Dn & Dd
{
	Dd = Dd f- (Dn f* Dm);
}

@endif # VFPv2 || VFPv3

@if defined(SIMD)

#####
# VML* (by scalar) (A1)
#

vmlDm: Dm_3^"["^index^"]"	is TMode=0 & c2021=1 & Dm_3 & M5 & c0303 [ index = (M5 << 1) + c0303; ]	{ el:4 = VectorGetElement(Dm_3, index:1, 2:1, 0:1); export el; }
vmlDm: Dm_4^"["^M5^"]"		is TMode=0 & c2021=2 & Dm_4 & M5											{ el:4 = VectorGetElement(Dm_4, M5:1, 4:1, 0:1); export el; }
vmlDm: thv_Dm_3^"["^index^"]"	is TMode=1 & thv_c2021=1 & thv_Dm_3 & thv_M5 & thv_c0303 [ index = (thv_M5 << 1) + thv_c0303; ]	{ el:4 = VectorGetElement(thv_Dm_3, index:1, 2:1, 0:1); export el; }
vmlDm: thv_Dm_4^"["^thv_M5^"]"		is TMode=1 & thv_c2021=2 & thv_Dm_4 & thv_M5											{ el:4 = VectorGetElement(thv_Dm_4, thv_M5:1, 4:1, 0:1); export el; }


:vmla.i^esize2021 Dd,Dn,vmlDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 & (c2021=1 | c2021=2)  & c0811=0 & c0606=1 & c0404=0) |
	                               ($(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0 & thv_c0606=1 & thv_c0404=0)) & esize2021 & Dn & Dd & vmlDm
{
	Dd = VectorMultiplyAccumulate(Dn,vmlDm,esize2021);
}

:vmla.i^esize2021 Qd,Qn,vmlDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 & (c2021=1 | c2021=2) & c0811=0 & c0606=1 & c0404=0) |
	                               ($(TMODE_F) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0 & thv_c0606=1 & thv_c0404=0)) & esize2021 & Qn & Qd & vmlDm
{
	Qd = VectorMultiplyAccumulate(Qn,vmlDm,esize2021);
}

:vmla.f32 Dd,Dn,vmlDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2021=2 & c0811=1 & c0606=1 & c0404=0) |
	                       ($(TMODE_E) & thv_c2327=0x1f & thv_c2021=2 & thv_c0811=1 & thv_c0606=1 & thv_c0404=0)) & Dn & Dd & vmlDm
{
	Dd = FloatVectorMultiplyAccumulate(Dn,vmlDm,2:4,32:1);
}

:vmla.f32 Qd,Qn,vmlDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2021=2 & c0811=1 & c0606=1 & c0404=0) |
	                       ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=2 & thv_c0811=1 & thv_c0606=1 & thv_c0404=0)) & Qn & Qd & vmlDm
{
	Qd = FloatVectorMultiplyAccumulate(Qn,vmlDm,2:4,32:1);
}

:vmls.i^esize2021 Dd,Dn,vmlDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 & (c2021=1 | c2021=2) & c0811=4 & c0606=1 & c0404=0) |
	                               ($(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=4 & thv_c0606=1 & thv_c0404=0)) & esize2021 & Dn & Dd & vmlDm
{
	Dd = VectorMultiplySubtract(Dn,vmlDm,esize2021);
}

:vmls.i^esize2021 Qd,Qn,vmlDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 & (c2021=1 | c2021=2)& c0811=4 & c0606=1 & c0404=0) |
	                               ($(TMODE_F) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=4 & thv_c0606=1 & thv_c0404=0)) & esize2021 & Qn & Qd  & vmlDm
{
	Qd = VectorMultiplySubtract(Qn,vmlDm,esize2021);
}

:vmls.f32 Dd,Dn,vmlDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2021=2 & c0811=5 & c0606=1 & c0404=0) |
	                       ($(TMODE_E) & thv_c2327=0x1f & thv_c2021=2 & thv_c0811=5 & thv_c0606=1 & thv_c0404=0)) & Dn & Dd  & vmlDm
{
	Dd = FloatVectorMultiplySubtract(Dn,vmlDm,2:4,32:1);
}

:vmls.f32 Qd,Qn,vmlDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2021=2 & c0811=5 & c0606=1 & c0404=0) |
	                       ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=2 & thv_c0811=5 & thv_c0606=1 & thv_c0404=0)) & Qn & Qd  & vmlDm
{
	Qd = FloatVectorMultiplySubtract(Qn,vmlDm,2:4,32:1);
}

#####
# VML* (by scalar) (A2)
#



:vmlal.^udt^esize2021 Qd,Dn,vmlDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1    & c2323=1 & (c2021=1 | c2021=2) & c0811=2 & Q6=1 & c0404=0) |
                                     ($(TMODE_EorF) &  thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=2 & thv_Q6=1 & thv_c0404=0 ) ) & udt & esize2021 & Dn & Qd & vmlDm
{
	Qd = VectorMultiplyAccumulate(Dn,vmlDm,esize2021,udt);
}

:vmlsl.^udt^esize2021 Qd,Dn,vmlDm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1    & c2323=1 & (c2021=1 | c2021=2) & c0811=6 & Q6=1 & c0404=0) |
                                     ($(TMODE_EorF) &  thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=6 & thv_Q6=1 & thv_c0404=0 ) ) & udt & esize2021 & Dn & Qd & vmlDm
{
	Qd = VectorMultiplySubtract(Dn,vmlDm,esize2021,udt);
}

# Addresses all versions of F6.1.134 except A2/T2 with Q=0
:vmov.^simdExpImmDT Dd,simdExpImm_8 is (( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 & c0707=0 & Q6=0 & c0404=1 ) | 
										( $(TMODE_EorF) & thv_c2327=0x1f & thv_c1921=0 & thv_c0707=0 & thv_Q6=0 & thv_c0404=1 )) & Dd & simdExpImmDT & simdExpImm_8
{
	Dd = simdExpImm_8;
}

# Addresses all versions of F6.1.134 except At/T2 with Q=1
:vmov.^simdExpImmDT Qd,simdExpImm_16 is (( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 & c0707=0 & Q6=1 & c0404=1 ) |
										( $(TMODE_EorF) & thv_c2327=0x1f & thv_c1921=0 & thv_c0707=0 & thv_Q6=1 & thv_c0404=1 )) & Qd & simdExpImmDT & simdExpImm_16
{
	Qd = simdExpImm_16;
}

@endif # SIMD

@if defined(VFPv3)

#  F6.1.134 vmov A2/T2

:vmov^COND^".f16" Sd,vfpExpImm_4  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=3 &     c0411=0x90 ) |
									 ( $(TMODE_E) &         thv_c2327=0x1d & thv_c2021=3 & thv_c0411=0x90 ) ) & COND & Sd & vfpExpImm_4
{
	build COND;
	Sd = vfpExpImm_4;
}

:vmov^COND^".f32" Sd,vfpExpImm_4  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=3 &     c0411=0xa0 ) |
									 ( $(TMODE_E) &         thv_c2327=0x1d & thv_c2021=3 & thv_c0411=0xa0 ) ) & COND & Sd & vfpExpImm_4
{
	build COND;
	Sd = vfpExpImm_4;
}

#  F6.1.134 vmov A2/T2
:vmov^COND^".f64" Dd,vfpExpImm_8  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c2021=3 &     c0411=0xb0 ) |
								     ( $(TMODE_E) &         thv_c2327=0x1d & thv_c2021=3 & thv_c0411=0xb0 ) ) & COND & Dd & vfpExpImm_8 
{
	build COND;
	Dd = vfpExpImm_8;
}

@endif # VFPv3

@if defined(SIMD)

:vmov Dd,Dm		is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &   c2021=2 &         c1619=c0003 &     c0811=1      & c0707=c0505 &     Q6=0 &      c0404=1 ) |
                   ($(TMODE_E) &  thv_c2327=0x1e & thv_c2021=2 & thv_c1619=thv_c0003 & thv_c0811=1 & thv_c0707=thv_c0505 & thv_c0606=0 & thv_c0404=1) ) & Dd & Dm
{
	Dd = Dm;
}

:vmov Qd,Qm		is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2021=2 &         c1619=c0003 &     c0811=1 &         c0707=c0505 &        Q6=1 & c0404=1 ) |
                     ($(TMODE_E) &      thv_c2327=0x1e & thv_c2021=2 & thv_c1619=thv_c0003 & thv_c0811=1 & thv_c0707=thv_c0505 & thv_c0606=1 & thv_c0404=1) ) & Qd & Qm
{
	Qd = Qm;
}

@endif # SIMD

@if defined(VFPv2) || defined(VFPv3)

:vmov^COND^".f32" Sd,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x30 &     c0611=0x29  &    c0404=0 ) |
                            ($(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x30 & thv_c0611=0x29 & thv_c0404=0) ) & COND & Sd & Sm 
{
	Sd = Sm;
}

:vmov^COND^".f64" Dd,Dm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x30 &     c0611=0x2d &     c0404=0  ) |
                            ($(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x30 & thv_c0611=0x2d & thv_c0404=0) ) & COND & Dd & Dm
{
	Dd = Dm;
}

@endif # VFPv2 || VFPv3

define pcodeop VectorSetElement;

@if defined(SIMD)

vmovIndex: val	is TMode=0 &     c2222=1 &     c2121 &     c0506					[ val = (c2121 << 2) + c0506; ]	{ tmp:1 = val; export tmp; }
vmovIndex: val	is TMode=0 &     c2222=0 &     c2121 &     c0606   &     c0505=1	[ val = (c2121 << 1) + c0606; ]	{ tmp:1 = val; export tmp; }

vmovIndex: val	is TMode=1 & thv_c2222=1 & thv_c2121 & thv_c0506					[ val = (thv_c2121 << 2) + thv_c0506; ]	{ tmp:1 = val; export tmp; }
vmovIndex: val	is TMode=1 & thv_c2222=0 & thv_c2121 & thv_c0606   & thv_c0505=1	[ val = (thv_c2121 << 1) + thv_c0606; ]	{ tmp:1 = val; export tmp; }

@if defined(VFPv2) || defined(VFPv3) || defined(SIMD)

vmovIndex: c2121     is TMode=0 &     c2222=0 &     c2121 &     c0506=0				{ tmp:1 = c2121; export tmp; }
vmovIndex: thv_c2121 is TMode=1 & thv_c2222=0 & thv_c2121 & thv_c0506=0				{ tmp:1 = thv_c2121; export tmp; }

@endif #  VFPv2 || VFPv3 || SIMD


dNvmovIndex: Dn^"["^vmovIndex^"]"   is Dn & vmovIndex     { }


:vmov^COND^".8" dNvmovIndex,VRd	is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2222=1 &     c2020=0 &     c0811=11 &     c0404=1 &     c0003=0 ) |
                                   ($(TMODE_E) &         thv_c2327=0x1c & thv_c2222=1 & thv_c2020=0 & thv_c0811=11 & thv_c0404=1 & thv_c0003=0 ) ) & COND & Dn & VRd & vmovIndex & dNvmovIndex
{
	el:1 = VRd(0);
	vmask:8 = 0xf << (vmovIndex*8);
	Dn = (Dn & ~vmask) | (zext(el) & vmask);
	#VectorSetElement(VRd,Dn,vmovIndex);
}

:vmov^COND^".16" dNvmovIndex,VRd	is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2222=0 &     c2020=0 &     c0811=11 &     c0505=1 &     c0404=1 &     c0003=0 ) |
                                       ($(TMODE_E) &         thv_c2327=0x1c & thv_c2222=0 & thv_c2020=0 & thv_c0811=11 & thv_c0505=1 & thv_c0404=1 & thv_c0003=0 ) ) & COND & Dn & VRd & vmovIndex & dNvmovIndex
{
	el:2 = VRd(0);
	vmask:8 = 0xff << (vmovIndex*16);
	Dn = (Dn & ~vmask) | (zext(el) & vmask);
	#VectorSetElement(VRd,Dn,vmovIndex,vmovSize);
}


:vmov^COND^".32" dNvmovIndex,VRd	is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2222=0 &     c2020=0 &     c0811=11 &     c0506=0 &     c0404=1 &     c0003=0 ) |
                                       ($(TMODE_E) &         thv_c2327=0x1c & thv_c2222=0 & thv_c2020=0 & thv_c0811=11 & thv_c0506=0 & thv_c0404=1 & thv_c0003=0 ) ) & COND & Dn & VRd & vmovIndex & dNvmovIndex
{
	el:4 = VRd;
	vmask:8 = 0xffff << (vmovIndex*32);
	Dn = (Dn & ~vmask) | (zext(el) & vmask);
	#VectorSetElement(VRd,Dn,vmovIndex,vmovSize);
}


:vmov^COND^".u8" VRd,dNvmovIndex	is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c2222=1 &     c2020=1 &     c0811=11 &     c0404=1 &     c0003=0 ) |
                                       ($(TMODE_E) &         thv_c2327=0x1d & thv_c2222=1 & thv_c2020=1 & thv_c0811=11 & thv_c0404=1 & thv_c0003=0 ) ) & COND & Dn & VRd & vmovIndex & dNvmovIndex
{
	val:8 = Dn >> (vmovIndex*8);
	result:1 = val(0);
	VRd = zext(result);
	#VRd = VectorGetElement(Dn,vmovIndex,vmovSize,0:1);
}

:vmov^COND^".u16" VRd,dNvmovIndex	is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c2222=0 &     c2020=1 &     c0811=11 &     c0505=1 &     c0404=1 &     c0003=0 ) |
                                       ($(TMODE_E) &         thv_c2327=0x1d & thv_c2222=0 & thv_c2020=1 & thv_c0811=11 & thv_c0505=1 & thv_c0404=1 & thv_c0003=0 ) ) & COND & Dn & VRd & vmovIndex & dNvmovIndex
{
	val:8 = Dn >> (vmovIndex*16);
	result:2 = val(0);
	VRd = zext(result);
	#VRd = VectorGetElement(Dn,vmovIndex,vmovSize,0:1);
}

:vmov^COND^".u32" VRd,dNvmovIndex	is ( ($(AMODE) & ARMcond=1 & c2327=0x1d &     c2222=0 &     c2020=1 &     c0811=11 &     c0506=0 &     c0404=1 &     c0003=0 ) |
                                       ($(TMODE_E) &         thv_c2327=0x1d & thv_c2222=0 & thv_c2020=1 & thv_c0811=11 & thv_c0506=0 & thv_c0404=1 & thv_c0003=0 ) ) & COND & Dn & VRd & vmovIndex & dNvmovIndex
{
	val:8 = Dn >> (vmovIndex*32);
	result:4 = val(0);
	VRd = zext(result);
	#VRd = VectorGetElement(Dn,vmovIndex,vmovSize,0:1);
}

:vmov^COND^".s8" VRd,dNvmovIndex	is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2222=1 &     c2020=1 &     c0811=11 &     c0404=1 &     c0003=0 ) |
                                       ($(TMODE_E) &         thv_c2327=0x1c & thv_c2222=1 & thv_c2020=1 & thv_c0811=11 & thv_c0404=1 & thv_c0003=0 ) ) & COND & Dn & VRd & vmovIndex & dNvmovIndex
{
	val:8 = Dn >> (vmovIndex*8);
	result:1 = val(0);
	VRd = sext(result);
	#VRd = VectorGetElement(Dn,vmovIndex,vmovSize,0:1);
}

:vmov^COND^".s16" VRd,dNvmovIndex	is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2222=0 &     c2020=1 &     c0811=11 &     c0505=1 &     c0404=1 &     c0003=0 ) |
                                       ($(TMODE_E) &         thv_c2327=0x1c & thv_c2222=0 & thv_c2020=1 & thv_c0811=11 & thv_c0505=1 & thv_c0404=1 & thv_c0003=0 ) ) & COND & Dn & VRd & vmovIndex & dNvmovIndex
{
	val:8 = Dn >> (vmovIndex*16);
	result:2 = val(0);
	VRd = sext(result);
	#VRd = VectorGetElement(Dn,vmovIndex,vmovSize,0:1);
}

:vmov^COND^".s32" VRd,dNvmovIndex	is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2222=0 &     c2020=1 &     c0811=11 &     c0506=0 &     c0404=1 &     c0003=0 ) |
                                       ($(TMODE_E) &         thv_c2327=0x1c & thv_c2222=0 & thv_c2020=1 & thv_c0811=11 & thv_c0506=0 & thv_c0404=1 & thv_c0003=0 ) ) & COND & Dn & VRd & vmovIndex & dNvmovIndex
{
	val:8 = Dn >> (vmovIndex*32);
	result:4 = val(0);
	VRd = sext(result);
	#VRd = VectorGetElement(Dn,vmovIndex,vmovSize,0:1);
}

@endif # SIMD


@if defined(VFPv2) || defined(VFPv3)

:vmov^COND Sn,VRd  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2122=0 &     c2020=0 &     c0811=10 &     c0006=0x10) |
                      ($(TMODE_E) &         thv_c2327=0x1c & thv_c2122=0 & thv_c2020=0 & thv_c0811=10 & thv_c0006=0x10) ) & COND & Sn & VRd
{
	Sn = VRd;
}

:vmov^COND VRd,Sn  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2122=0 &     c2020=1 &     c0811=10 &     c0006=0x10) |
                      ($(TMODE_E) &         thv_c2327=0x1c & thv_c2122=0 & thv_c2020=1 & thv_c0811=10 & thv_c0006=0x10) ) & COND & Sn & VRd
{
	VRd = Sn;
}

:vmov^COND Sm,SmNext,VRd,VRn  is ( ($(AMODE) & ARMcond=1 & c2027=0xc4 &     c0611=0x28 &     c0404=1) |
                                 ($(TMODE_E) &         thv_c2027=0xc4 & thv_c0611=0x28 & thv_c0404=1) ) & COND & VRn & VRd & Sm & SmNext
{
	Sm = VRd;
	SmNext = VRn;
}

:vmov^COND VRd,VRn,Sm,SmNext  is ( ($(AMODE) & ARMcond=1 & c2027=0xc5 &     c0611=0x28 &     c0404=1) |
                                 ($(TMODE_E) &         thv_c2027=0xc5 & thv_c0611=0x28 & thv_c0404=1) ) & COND & VRn & VRd & Sm & SmNext
{
	VRd = Sm;
	VRn = SmNext;
}

@endif # VFPv2 || VFPv3

@if defined(VFPv2) || defined(VFPv3) || defined(SIMD)

:vmov^COND Dm,VRd,VRn	is COND & ( ($(AMODE) & ARMcond=1 & c2027=0xc4 & c0611=0x2c & c0404=1) | ($(TMODE_E) &  thv_c2027=0xc4 & thv_c0611=0x2c & thv_c0404=1) ) & Dm & VRn & VRd
{
	Dm = (zext(VRn) << 32) + zext(VRd);
}

:vmov^COND VRd,VRn,Dm	is COND & ( ($(AMODE) & ARMcond=1 & c2027=0xc5 & c0611=0x2c & c0404=1) | ($(TMODE_E) &  thv_c2027=0xc5 & thv_c0611=0x2c & thv_c0404=1) ) & Dm & VRn & VRd
{
	VRn = Dm(4);
	VRd = Dm:4;
}

@endif #  VFPv2 || VFPv3 || SIMD

define pcodeop VectorCopyLong;
define pcodeop VectorCopyNarrow;

@if defined(SIMD)

:vmovl.^udt^esize2021 Qd,Dm	is (($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & (c1921=1 | c1921=2 | c1921=4) &        c1618=0 &     c0611=0x28 &     c0404=1) |
                               ($(TMODE_EorF) & thv_c2327=0x1f & (thv_c1921=1 | thv_c1921=2 | thv_c1921=4) & thv_c1618=0 & thv_c0611=0x28 & thv_c0404=1) ) & esize2021 & udt & Qd & Dm
{
	Qd = VectorCopyLong(Dm,esize2021,udt);
}

:vmovn.i^esize1819x2 Dd,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3  &     c1617=2 &     c0611=8 &     c0404=0) |
                               ($(TMODE_F)  &   thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3  & thv_c1617=2 & thv_c0611=8 & thv_c0404=0) ) & esize1819x2 & Dd & Qm
{
	Dd = VectorCopyNarrow(Qm,esize1819x2);
}

:vmovx.F16 Sd,Sm  is (($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c1921=0x6 &     c1618=0 &     c0611=0x29 &     c0404=0) |
                     ($(TMODE_F) &     thv_c2327=0x1d & thv_c1921=0x6 & thv_c1618=0 & thv_c0611=0x29 & thv_c0404=0) ) & Sd & Sm
{
	local SmUpper:2 = Sm(2);
	Sd = zext(SmUpper);
}

@endif # SIMD

@if defined(VFPv2) || defined(VFPv3) || defined(SIMD)

:vmrs^COND VRd,fpscr  is COND & ( ($(AMODE) & ARMcond=1 & c1627=0xef1 &     c0011=0xa10) |
                                ($(TMODE_E) &         thv_c1627=0xef1 & thv_c0011=0xa10)) & fpscr & VRd
{
	VRd = fpscr;
}

apsr:   "apsr"  is epsilon {}

:vmrs^COND apsr,fpscr  is ( ($(AMODE) & ARMcond=1 & c1627=0xef1 &     c1215=15 &     c0011=0xa10) |
                          ($(TMODE_E) &         thv_c1627=0xef1 & thv_c1215=15 & thv_c0011=0xa10) 
) & COND & apsr & fpscr
{
	NG = $(FPSCR_N);
	ZR = $(FPSCR_Z);
	CY = $(FPSCR_C);
	OV = $(FPSCR_V);
}

:vmsr^COND fpscr,VRd  is ( ($(AMODE) & ARMcond=1 & c1627=0xee1 &     c0011=0xa10) |
                         ($(TMODE_E) &         thv_c1627=0xee1 & thv_c0011=0xa10)
) & COND & VRd & fpscr
{
	fpscr = VRd;
}

@endif #  VFPv2 || VFPv3 || SIMD

@if defined(SIMD)

###
# VMUL (floating Point)
#

define pcodeop FloatVectorMult;
define pcodeop VectorMultiply;
define pcodeop PolynomialMultiply;

:vmul.f32 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x06 &     c2121=0 &     c2020=0 &     c0811=0xd &     Q6=0 &     c0404=1) |
                       ($(TMODE_F) &       thv_c2327=0x1e & thv_c2121=0 & thv_c2020=0 & thv_c0811=0xd & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm
{
	Dd = FloatVectorMult(Dn,Dm,2:1,32:1);
}

:vmul.f32 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x06 &     c2121=0 &     c2020=0 &     c0811=0xd &     Q6=1 &     c0404=1) |
                       ($(TMODE_F) &       thv_c2327=0x1e & thv_c2121=0 & thv_c2020=0 & thv_c0811=0xd & thv_Q6=1 & thv_c0404=1) ) & Qm & Qn & Qd
{
	Qd = FloatVectorMult(Qn,Qm,2:1,32:1);
}

:vmul.f16 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x06 &     c2121=0 &     c2020=1 &     c0811=13 &     Q6=0 &     c0404=1) |
                       ($(TMODE_F) &       thv_c2327=0x1e & thv_c2121=0 & thv_c2020=1 & thv_c0811=13 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm
{
	Dd = FloatVectorMult(Dn,Dm,4:1,16:1);
}

:vmul.f16 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x06 &     c2121=0 &     c2020=1 &     c0811=13 &     Q6=1 &     c0404=1) |
                       ($(TMODE_F) &       thv_c2327=0x1e & thv_c2121=0 & thv_c2020=1 & thv_c0811=13 & thv_Q6=1 & thv_c0404=1) ) & Qm & Qn & Qd
{
	Qd = FloatVectorMult(Qn,Qm,4:1,16:1);
}

:vmul^COND^".f64" Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=2 &     c0811=11 &     c0606=0 &     c0404=0) |
                               ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=2 & thv_c0811=11 & thv_c0606=0 & thv_c0404=0) ) & COND & Dm & Dn & Dd 
{
	Dd = Dn f* Dm;
}

:vmul^COND^".f32" Sd,Sn,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=2 &     c0811=10 &     c0606=0 &     c0404=0) |
                               ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=2 & thv_c0811=10 & thv_c0606=0 & thv_c0404=0) ) & COND & Sm & Sn & Sd 
{
	Sd = Sn f* Sm;
}

:vmul^COND^".f16" Sd,Sn,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=2 &     c0811=9 &     c0606=0 &     c0404=0) |
                               ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=2 & thv_c0811=9 & thv_c0606=0 & thv_c0404=0) ) & COND & Sm & Sn & Sd 
{
    product:2 = Sn:2 f* Sm:2;
    Sd = zext(product);
}

###
# VMUL (Integer and polynomial)
#

:vmul.i^esize2021 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c0811=9 &     Q6=0 &     c0404=1) |
                               ($(TMODE_E) &    thv_c2327=0x1e & thv_c0811=9 & thv_Q6=0 & thv_c0404=1)) & esize2021 & Dn & Dd & Dm
{
	Dd = VectorMultiply(Dn,Dm,esize2021);
}

:vmul.i^esize2021 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c0811=9 &     Q6=1 &     c0404=1) |
                               ($(TMODE_E) &    thv_c2327=0x1e & thv_c0811=9 & thv_Q6=1 & thv_c0404=1)) & esize2021 & Qm & Qn & Qd
{
	Qd = VectorMultiply(Qn,Qm,esize2021);
}

:vmul.p8 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2021=0 &     c0811=9 &     Q6=0 &     c0404=1) |
                      ($(TMODE_F) &    thv_c2327=0x1e & thv_c2021=0 & thv_c0811=9 & thv_Q6=0 & thv_c0404=1) ) & Dn & Dd & Dm
{
	Dd = PolynomialMultiply(Dn,Dm,1:1);
}

:vmul.p8 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c2021=0 &     c0811=9 &     Q6=1 &     c0404=1) |
                      ($(TMODE_F) &    thv_c2327=0x1e & thv_c2021=0 & thv_c0811=9 & thv_Q6=1 & thv_c0404=1) ) & Qm & Qn & Qd
{
	Qd = PolynomialMultiply(Qn,Qm,1:1);
}

:vmull.^udt^esize2021 Qd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 &     c2021<3 &     c0811=0xc &     Q6=0 &     c0404=0) |
                                   ($(TMODE_EorF) &           thv_c2327=0x1f & thv_c2021<3 & thv_c0811=0xc & thv_Q6=0 & thv_c0404=0) ) & esize2021 & Dm & Dn & Qd & udt
{
	Qd = VectorMultiply(Dn,Dm,esize2021,udt);
}

:vmull.p8 Qd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x5 &     c2021=0 &     c0811=0xe &     Q6=0 &     c0404=0) |
                       ($(TMODE_F) &      thv_c2327=0x1f & thv_c2021=0 & thv_c0811=0xe & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Qd
{
	Qd = PolynomialMultiply(Dn,Dm,1:1);
}

:vmull.p64 Qd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x5 &     c2021=2 &     c0811=0xe &     Q6=0 &     c0404=0) |
                        ($(TMODE_E) &      thv_c2327=0x1f & thv_c2021=2 & thv_c0811=0xe & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Qd
{
	Qd = PolynomialMultiply(Dn,Dm,8:1);
}

# The below is confusing but these sub-constructors are used in a combination of F6.1.148 VMUL (by scalar) and F6.1.150 VMULL (by Scalar)

etype: "I"     is TMode=0 & c0909=0 & c0808=0 {}
etype: "F"     is TMode=0 & c0909=0 & c0808=1 {}
etype: "S"     is TMode=0 & c0909=1 & c2424=0 {}
etype: "U"     is TMode=0 & c0909=1 & c2424=1 {}
etype: "I"     is TMode=1 & thv_c0909=0 & thv_c0808=0 {}
etype: "F"     is TMode=1 & thv_c0909=0 & thv_c0808=1 {}
etype: "S"     is TMode=1 & thv_c0909=1 & thv_c2828=0 {}
etype: "U"     is TMode=1 & thv_c0909=1 & thv_c2828=1 {}

vmlDmA: Dm_3^"["^index^"]"	is TMode=0 & c2021=1 & Dm_3 & M5 & c0303 [ index = (M5 << 1) + c0303; ]				{ el:4 = VectorGetElement(Dm_3, index:1, 2:1, 0:1); export el; }
vmlDmA: Dm_4^"["^M5^"]"		is TMode=0 & c2021=2 & Dm_4 & M5													{ el:4 = VectorGetElement(Dm_4, M5:1, 4:1, 0:1); export el; }
vmlDmA: Dm_3^"["^index^"]"	is TMode=1 & thv_c2021=1 & Dm_3 & thv_M5 & c0303 [ index = (thv_M5 << 1) + c0303; ]	{ el:4 = VectorGetElement(Dm_3, index:1, 2:1, 0:1); export el; }
vmlDmA: Dm_4^"["^thv_M5^"]"	is TMode=1 & thv_c2021=2 & Dm_4 & thv_M5											{ el:4 = VectorGetElement(Dm_4, thv_M5:1, 4:1, 0:1); export el; }

:vmul.^etype^esize2021 Qd,Qn,vmlDmA  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x07 &     (c2021=1 | c2021=2)     &     c0911=4 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_F) &       thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0911=4 & thv_c0606=1 & thv_c0404=0 ) ) & etype & esize2021 & Qn & Qd & vmlDmA
{
	Qd = VectorMultiply(Qn,vmlDmA,esize2021);
}

:vmul.^etype^esize2021 Dd,Dn,vmlDmA  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x5 &     (c2021=1 | c2021=2)     &     c0911=4 &     c0606=1 &     c0404=0) | 
                                        ($(TMODE_E) &      thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0911=4 & thv_c0606=1 & thv_c0404=0 ) ) & etype & esize2021 & Dn & Dd & vmlDmA
{
	Dd = VectorMultiply(Dn,vmlDmA,esize2021);
}

:vmull.^etype^esize2021 Qd,Dn,vmlDmA  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & (c2021=1 | c2021=2)     &     c0811=10 &     c0606=1 &     c0404=0) |
                                         ($(TMODE_EorF) & thv_c2327=0x1f &       (thv_c2021=1 | thv_c2021=2) & thv_c0811=10 & thv_c0606=1 & thv_c0404=0 ) ) & Dd & Dm & esize1819 & etype & esize2021 & Dn & Qd & vmlDmA
{
	Qd = VectorMultiply(Dn,vmlDmA,esize2021);
}

###
# VMVN (immediate)
#

:vmvn.i32 Dd,simdExpImm_8	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1011=0 &     c0808=0 &     c0407=3 ) |
                                 ($(TMODE_EorF) &  thv_c2327=0x1f &    thv_c1921=0 & thv_c1011=0 & thv_c0808=0 & thv_c0407=3) ) & Dd & simdExpImm_8
{
	Dd = ~simdExpImm_8;
}

:vmvn.i32 Qd,simdExpImm_16	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1011=0 &     c0808=0 &     c0407=7 ) |
                                 ($(TMODE_EorF) &  thv_c2327=0x1f &    thv_c1921=0 & thv_c1011=0 & thv_c0808=0 & thv_c0407=7) ) & Qd & simdExpImm_16
{
	Qd = ~simdExpImm_16;
}

:vmvn.i16 Dd,simdExpImm_8	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1011=2 &     c0808=0 &     c0407=3 ) |
                                 ($(TMODE_EorF) &  thv_c2327=0x1f &    thv_c1921=0 & thv_c1011=2 & thv_c0808=0 & thv_c0407=3) ) & Dd & simdExpImm_8
{
	Dd = ~simdExpImm_8;
}

:vmvn.i16 Qd,simdExpImm_16	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1011=2 &     c0808=0 &     c0407=7 ) |
                                 ($(TMODE_EorF) &  thv_c2327=0x1f &    thv_c1921=0 & thv_c1011=2 & thv_c0808=0 & thv_c0407=7) ) & Qd & simdExpImm_16
{
	Qd = ~simdExpImm_16;
}

:vmvn.i32 Dd,simdExpImm_8	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c0911=6 &     c0808=0 &     c0407=3 ) |
                                 ($(TMODE_EorF) &           thv_c2327=0x1f &       thv_c1921=0 & thv_c0911=6 & thv_c0808=0 & thv_c0407=3) ) & Dd & simdExpImm_8
{
	Dd = ~simdExpImm_8;
}

:vmvn.i32 Qd,simdExpImm_16	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c0911=6 &     c0808=0 &     c0407=7 ) |
                                 ($(TMODE_EorF) &           thv_c2327=0x1f &       thv_c1921=0 & thv_c0911=6 & thv_c0808=0 & thv_c0407=7) ) & Qd & simdExpImm_16
{
	Qd = ~simdExpImm_16;
}

###
# VMVN (register)
#

:vmvn Dd,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1619=0 &     c0811=5     & c0707=1 &     Q6=0 &     c0404=0 ) |
                ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0 & thv_c0811=5 & thv_c0707=1 & thv_Q6=0 & thv_c0404=0) ) & Dd & Dm
{
	Dd = ~Dm;
}

:vmvn Qd,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1619=0 &     c0811=5     & c0707=1 &     Q6=1 &     c0404=0 ) |
                ($(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0 & thv_c0811=5 & thv_c0707=1 & thv_Q6=1 & thv_c0404=0) ) & Qd & Qm
{
	tmp1:8 = Qm:8;
	tmp2:8 = Qm(8);
	tmp1 = ~ tmp1;
	tmp2 = ~ tmp2;
	Qd = (zext(tmp1) << 8) | zext(tmp2);
}

define pcodeop FloatVectorNeg;


:vneg.s^esize1819 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=7 &        Q6=0 &     c0404=0 ) |
                            ($(TMODE_F) &     thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=7 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm & esize1819
{
	Dd = FloatVectorNeg(Dm,1:1,esize1819);
}

:vneg.s^esize1819 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=1 &     c0711=7 &        Q6=1 &     c0404=0 ) |
                            ($(TMODE_F) &     thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=7 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm & esize1819
{
	Qd = FloatVectorNeg(Qm,1:1,esize1819);
}

:vneg.f^fesize1819 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1617=1 &     c0711=0xf &        Q6=0 &     c0404=0 ) |
                             ($(TMODE_F) &     thv_c2327=0x1f & thv_c2021=3 & thv_c1617=1 & thv_c0711=0xf & thv_c0606=0 & thv_c0404=0 ) ) & fesize1819 & Dm & Dd
{
	Dd = FloatVectorNeg(Dm,2:1,fesize1819);
}

:vneg.f^fesize1819 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819=2 &     c1617=1 &     c0711=0xf &        Q6=1 &     c0404=0 ) |
                             ($(TMODE_F) &     thv_c2327=0x1f & thv_c2021=3 & thv_c1819=2 & thv_c1617=1 & thv_c0711=0xf & thv_c0606=1 & thv_c0404=0 ) ) & fesize1819 & Qd & Qm
{
	Qd = FloatVectorNeg(Qm,2:1,fesize1819);
}

@endif # SIMD

@if defined(VFPv2) || defined(VFPv3)


:vnmla^COND^".f64" Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=1 &     c0811=11 &     c0606=1 &     c0404=0) |
                                ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=1 & thv_c0811=11 & thv_c0606=1 & thv_c0404=0) ) & COND & Dm & Dn & Dd
{
	build COND;
    product:8 = Dn f* Dm;
    Dd = (f- Dd) f+ (f- product);
}

:vnmla^COND^".f32" Sd,Sn,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=1 &     c0811=10 &     c0606=1 &     c0404=0) |
                                ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=1 & thv_c0811=10 & thv_c0606=1 & thv_c0404=0) ) & COND & Sm & Sn & Sd
{
	build COND;
    product:4 = Sn f* Sm;
    Sd = (f- Sd) f+ (f- product);
}

:vnmla^COND^".f16" Sd,Sn,Sm          is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=1 &     c0811=9 &     c0606=1 &     c0404=0) |
                                ($(TMODE_E) &        thv_c2327=0x1c & thv_c2021=1 & thv_c0811=9 & thv_c0606=1 & thv_c0404=0) ) & COND & Sm & Sn & Sd
{
	build COND;
    product:2 = Sn:2 f* Sm:2;
    product = (f- Sd:2) f+ (f- product);
    Sd = zext(product);
}

:vnmls^COND^".f64" Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=1 &     c0811=11 &     c0606=0 &     c0404=0) |
                                ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=1 & thv_c0811=11 & thv_c0606=0 & thv_c0404=0) ) & COND & Dm & Dn & Dd
{
	build COND;
    product:8 = Dn f* Dm;
    Dd = product f- Dd;
}

:vnmls^COND^".f32" Sd,Sn,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=1 &     c0811=10 &     c0606=0 &     c0404=0) |
                                ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=1 & thv_c0811=10 & thv_c0606=0 & thv_c0404=0) ) & COND & Sm & Sn & Sd
{
	build COND;
    product:4 = Sn f* Sm;
    Sd = product f- Sd;
}

:vnmls^COND^".f16" Sd,Sn,Sm          is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=1 &     c0811=9 &     c0606=0 &     c0404=0) |
                                ($(TMODE_E) &        thv_c2327=0x1c & thv_c2021=1 & thv_c0811=9 & thv_c0606=0 & thv_c0404=0) ) & COND & Sm & Sn & Sd 
{
	build COND;
    product:2 = Sn:2 f* Sm:2;
    product = product f- Sd:2;
    Sd = zext(product);
}

:vnmul^COND^".f64" Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=2 &     c0811=11 &     c0606=1 &     c0404=0) |
                                ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=2 & thv_c0811=11 & thv_c0606=1 & thv_c0404=0) ) & COND & Dm & Dn & Dd
{
	build COND;
    product:8 = Dn f* Dm;
    Dd = f- product;
}

:vnmul^COND^".f32" Sd,Sn,Sm  is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=2 &     c0811=10 &     c0606=1 &     c0404=0) |
                                ($(TMODE_E) &         thv_c2327=0x1c & thv_c2021=2 & thv_c0811=10 & thv_c0606=1 & thv_c0404=0) ) & COND & Sm & Sn & Sd
{
    product:4 = Sn f* Sm;
    Sd = f- product;
}

:vnmul^COND^".f16" Sd,Sn,Sm          is ( ($(AMODE) & ARMcond=1 & c2327=0x1c &     c2021=2 &     c0811=9 &     c0606=1 &     c0404=0) |
                                ($(TMODE_E) &        thv_c2327=0x1c & thv_c2021=2 & thv_c0811=9 & thv_c0606=1 & thv_c0404=0) ) & COND & Sm & Sn & Sd
{
	build COND;
    product:2 = Sn:2 f* Sm:2;
    product = f- product;
    Sd = zext(product);
}

:vneg^COND^".f16" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x31 &     c0611=0x25 &     c0404=0 ) |
                            ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x31 & thv_c0611=0x25 & thv_c0404=0 ) ) & COND & Sm & Sd
{
	build COND;
	build Sd;
	build Sm;
	local tmp:2 = Sm(0);
	Sd = zext(f- tmp);
}

:vneg^COND^".f32" Sd,Sm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x31 &     c0611=0x29 &     c0404=0 ) |
                            ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x31 & thv_c0611=0x29 & thv_c0404=0 ) ) & COND & Sm & Sd
{
	build COND;
	build Sd;
	build Sm;
	Sd =  f- Sm;
}

:vneg^COND^".f64" Dd,Dm  is ( ( $(AMODE) & ARMcond=1 & c2327=0x1d &     c1621=0x31 &     c0611=0x2d &     c0404=0 ) |
                            ( $(TMODE_E) &         thv_c2327=0x1d & thv_c1621=0x31 & thv_c0611=0x2d & thv_c0404=0 ) ) & COND & Dd & Dm
{
	build COND;
	build Dd;
	build Dm;
	Dd = f- Dm;
}

@endif # VFPv2 || VFPv3

@if defined(SIMD)

#F6.1.141 VORR (register) 64-bit SIMD vector variant (A1 and T1)
:vorr Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &  c2021=2 &     c0811=1 &     Q6=0 &     c0404=1) |
                     ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm

{
	Dd = Dn | Dm;
}

#F6.1.141 VORR (register) 128-bit SIMD vector variant (A1 and T1)
:vorr Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &  c2021=2 &     c0811=1 &       Q6=1 &     c0404=1) |
                   ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qd & Qn & Qm
{
	Qd = Qn | Qm;
}

#F6.1.140 VORR and F6.1.138 VORN (immediate) 64-bit SIMD vector variant
:vorr Dd,simdExpImm_8  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1011<3 &     c0808=1 &     c0407=1 ) |
                          ($(TMODE_EorF) & thv_c2327=0x1f &       thv_c1921=0 & thv_c1011<3 & thv_c0808=1 & thv_c0407=1) ) & Dd & simdExpImm_8
{
	Dd = Dd | simdExpImm_8;
}

#F6.1.140 VORR and F6.1.138 VORN (immediate) 128-bit SIMD vector variant
:vorr Qd,simdExpImm_16  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1011<3 &     c0808=1 &     c0407=5 ) |
                           ($(TMODE_EorF) & thv_c2327=0x1f &       thv_c1921=0 & thv_c1011<3 & thv_c0808=1 & thv_c0407=5) ) & Qd & simdExpImm_16
{
	Qd = Qd | simdExpImm_16;
}

#F6.1.139 VORN (register) 64-bit SIMD vector variant (A1 and T1)
:vorn Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2021=3 &     c0811=1 &     Q6=0 &     c0404=1) |
                   ($(TMODE_E) &    thv_c2327=0x1e & thv_c2021=3 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm

{
	Dd = Dn | ~Dm;
}

#F6.1.139 VORN (register) 128-bit SIMD vector variant (A1 and T1)
:vorn Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &     c2021=3 &     c0811=1 &       Q6=1 &     c0404=1) |
                   ($(TMODE_E) &    thv_c2327=0x1e & thv_c2021=3 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qd & Qn & Qm
{
	Qd = Qn | ~Qm;
}

@endif # SIMD


#######
# VPUSH (A2)
#

@if defined(VFPv2) || defined(VFPv3) || defined(SIMD)

buildVpushSdList: Sreg					is counter=0 & Sreg			[ regNum=regNum+1; ] { * mult_addr = Sreg; mult_addr = mult_addr + 4; }
buildVpushSdList: Sreg,buildVpushSdList	is Sreg & buildVpushSdList	[ counter=counter-1; regNum=regNum+1; ] { * mult_addr = Sreg; mult_addr = mult_addr + 4; }

vpushSdList: "{"^buildVpushSdList^"}"	is TMode=0 & D22 & c1215 & c0007 & buildVpushSdList [ regNum=(c1215<<1)+D22-1; counter=c0007-1; ] { sp = sp - c0007 * 4; mult_addr = sp; build buildVpushSdList; }
vpushSdList: "{"^buildVpushSdList^"}"	is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVpushSdList [ regNum=(thv_c1215<<1)+thv_D22-1; counter=thv_c0007-1; ] { sp = sp - thv_c0007 * 4; mult_addr = sp; build buildVpushSdList; }

buildVpushSd64List: Dreg					is counter=0 & Dreg			[ regNum=regNum+1; ] { * mult_addr = Dreg:8; mult_addr = mult_addr + 8; }
buildVpushSd64List: Dreg,buildVpushSd64List	is Dreg & buildVpushSd64List	[ counter=counter-1; regNum=regNum+1; ] { * mult_addr = Dreg:8; mult_addr = mult_addr + 8; build buildVpushSd64List; }

vpushSd64List: "{"^buildVpushSd64List^"}"	is TMode=0 & D22 & c1215 & c0007 & buildVpushSd64List [ regNum=(D22<<4)+c1215-1; counter=c0007 / 2 - 1; ] { sp = sp - c0007 * 4; mult_addr = sp; build buildVpushSd64List; }
vpushSd64List: "{"^buildVpushSd64List^"}"	is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVpushSd64List [ regNum=(thv_D22<<4)+thv_c1215-1; counter=thv_c0007 / 2 - 1; ] { sp = sp - thv_c0007 * 4; mult_addr = sp; build buildVpushSd64List; }


:vpush^COND vpushSd64List  is ( ($(AMODE) & ARMcond=1 & c2327=0x1a &     c1619=13 &     c2021=2 &     c0811=11 &     c0000=0) | 
                              ($(TMODE_E) &         thv_c2327=0x1a & thv_c1619=13 & thv_c2021=2 & thv_c0811=11 & thv_c0000=0) ) & COND & vpushSd64List
{
	build vpushSd64List;
}

:vpush^COND vpushSdList  is ( ($(AMODE) & ARMcond=1 & c2327=0x1a &     c1619=13 &     c2021=2 &     c0811=10) |
                            ($(TMODE_E) &         thv_c2327=0x1a & thv_c1619=13 & thv_c2021=2 & thv_c0811=10) ) & COND & vpushSdList
{
	build vpushSdList;
}

buildVpopSdList: Sreg					is counter=0 & Sreg			[ regNum=regNum+1; ]
   { tmp:4 = *mult_addr; Sreg = zext(tmp); mult_addr = mult_addr + 4; }
buildVpopSdList: Sreg,buildVpopSdList	is Sreg & buildVpopSdList	[ counter=counter-1; regNum=regNum+1; ]
   { tmp:4 = *mult_addr; Sreg = zext(tmp); mult_addr = mult_addr + 4; }

vpopSdList: "{"^buildVpopSdList^"}"	is TMode=0 & D22 & c1215 & c0007 & buildVpopSdList [ regNum=(c1215<<1)+D22-1; counter=c0007-1; ]
   { mult_addr = sp; sp = sp + c0007 * 4; build buildVpopSdList; }
vpopSdList: "{"^buildVpopSdList^"}"	is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVpopSdList [ regNum=(thv_c1215<<1)+thv_D22-1; counter=thv_c0007-1; ]
   { mult_addr = sp; sp = sp + thv_c0007 * 4; build buildVpopSdList; }

buildVpopSd64List: Dreg					is counter=0 & Dreg			[ regNum=regNum+1; ]
   { Dreg = *mult_addr; mult_addr = mult_addr + 8; }
buildVpopSd64List: Dreg,buildVpopSd64List	is Dreg & buildVpopSd64List	[ counter=counter-1; regNum=regNum+1; ]
   { Dreg = *mult_addr; mult_addr = mult_addr + 8; build buildVpopSd64List; }

vpopSd64List: "{"^buildVpopSd64List^"}"	is TMode=0 & D22 & c1215 & c0007 & buildVpopSd64List [ regNum=(D22<<4)+c1215-1; counter=c0007 / 2 - 1; ]
   {  mult_addr = sp; sp = sp + c0007 * 4; build buildVpopSd64List; }
vpopSd64List: "{"^buildVpopSd64List^"}"	is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVpopSd64List [ regNum=(thv_D22<<4)+thv_c1215-1; counter=thv_c0007 / 2 - 1; ]
   { mult_addr = sp; sp = sp + thv_c0007 * 4; build buildVpopSd64List; }

:vpop^COND vpopSd64List  is ( ($(AMODE) & ARMcond=1 & c2327=0x19 &     c1619=13 &     c2021=3 &     c0811=11 &     c0000=0) | 
                            ($(TMODE_E) &         thv_c2327=0x19 & thv_c1619=13 & thv_c2021=3 & thv_c0811=11 & thv_c0000=0) ) & COND & vpopSd64List
{
	build vpopSd64List;
}

:vpop^COND vpopSdList  is ( ($(AMODE) & ARMcond=1 & c2327=0x19 &     c1619=13 &     c2021=3 &     c0811=10) |
                          ($(TMODE_E) &         thv_c2327=0x19 & thv_c1619=13 & thv_c2021=3 & thv_c0811=10) ) & COND & vpopSdList
{
	build vpopSdList;
}

@endif #  VFPv2 || VFPv3 || SIMD

@if defined(SIMD)

define pcodeop SatQ;
define pcodeop SignedSatQ;

:vqabs^".s"^esize1819 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1617=0 &     c0811=7 &     Q6=0 &     c0404=0) |
                               ($(TMODE_F) &                    thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0811=7 & thv_Q6=0 & thv_c0404=0)) & esize1819 & Dn & Dd & Dm
{
	Dd = VectorAbs(Dn,Dm,esize1819);
	Dd = SatQ(Dd, esize1819, 0:1);
}

:vqabs^".s"^esize1819 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1617=0 &     c0811=7 &     Q6=1 &     c0404=0) |
                               ($(TMODE_F) &                    thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0811=7 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qn & Qd
{
	Qd = VectorAbs(Qn,Qm,esize1819);
	Qd = SatQ(Qd, esize1819, 0:1);
}

:vqadd.^udt^esize2021 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 &     c2323=0 &     c0811=0 &     Q6=0 &     c0404=1) |
                                   ($(TMODE_EorF) & thv_c2327=0x1e               & thv_c0811=0 & thv_Q6=0 & thv_c0404=1)) & udt & esize2021 & Dn & Dd & Dm
{
	Dd = VectorAdd(Dn,Dm,esize2021,udt);
	Dd = SatQ(Dd, esize2021, udt);
}

:vqadd.^udt^esize2021 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 &     c2323=0 &     c0811=0 &     Q6=1 &     c0404=1) |
                                   ($(TMODE_EorF) & thv_c2327=0x1e &               thv_c0811=0 & thv_Q6=1 & thv_c0404=1) ) & udt & esize2021 & Qm & Qn & Qd
{
	Qd = VectorAdd(Qn,Qm,esize2021,udt);
	Qd = SatQ(Qd, esize2021, udt);
}

:vqmovn.i^esize1819x2 Dd,Qm  is ( ($(AMODE) &  ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3  &     c1617=2 &     c0711=5 & c0606 &     c0404=0) |
                                ($(TMODE_F) &     thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3  & thv_c1617=2 & thv_c0711=5 & thv_c0404=0) ) & esize1819x2 & Dd & Qm
{
	Dd = VectorCopyNarrow(Qm,esize1819x2,c0606:1);
	Dd = SatQ(Dd, esize1819x2,0:1);
}

:vqmovun.i^esize1819x2 Dd,Qm  is ( ($(AMODE) &  ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3  &     c1617=2 &     c0611=9 &     c0404=0) |
                                 ($(TMODE_F) &     thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3  & thv_c1617=2 & thv_c0611=9 & thv_c0404=0) ) & esize1819x2 & Dd & Qm
{
	Dd = VectorCopyNarrow(Qm,esize1819x2,0:1);
	Dd = SatQ(Dd, esize1819x2,0:1);
}

:vqdmlal.S^esize2021 Qd,Dn,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=5 &     (c2021=1 | c2021=2)     &     c0811=0x9 &     c0606=0 &     c0404=0 ) |
                                  ( $(TMODE_E) &    thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0x9 & thv_c0606=0 & thv_c0404=0 ) ) & esize2021 & Dm & Dn & Qd

{
	Qd = VectorDoubleMultiplyAccumulateLong(Dn,Dm,esize2021,0:1);
	Qd = SatQ(Qd, esize2021,0:1);
}

:vqdmlal.S^esize2021 Qd,Dn,vmlDmA  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=5 &     (c2021=1 | c2021=2)     &     c0811=0x3 &     c0606=1 &     c0404=0) |
                                      ( $(TMODE_E) &    thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0x3 & thv_c0606=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Dn & Qd

{
	Qd = VectorDoubleMultiplyAccumulateLong(Dn,vmlDmA,esize2021,0:1);
	Qd = SatQ(Qd, esize2021,0:1);
}

:vqdmlsl.S^esize2021 Qd, Dn, Dm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=5 & (c2021=1 | c2021=2) & c0811=0xb & c0606=0 & c0404=0 ) |
                                      ( $(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xb & thv_c0606=0 & thv_c0404=0 ) ) & esize2021 & Dm & Dn & Qd

{
	Qd = VectorDoubleMultiplySubtractLong(Dn,Dm,esize2021,0:1);
	Qd = SatQ(Qd, esize2021,0:1);
}

:vqdmlsl.S^esize2021 Qd, Dn, vmlDmA	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=5 & (c2021=1 | c2021=2)& c0811=0x7 & c0606=1 & c0404=0) |
                                      ( $(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0x7 & thv_c0606=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Dn & Qd

{
	Qd = VectorDoubleMultiplySubtractLong(Dn,vmlDmA,esize2021,0:1);
	Qd = SatQ(Qd, esize2021,0:1);
}

:vqdmulh.S^esize2021 Dd, Dn, Dm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2324=0 & (c2021=1 | c2021=2) & c0811=0xb & Q6=0 & c0404=0 ) |
                                      ( $(TMODE_E) & thv_c2327=0x1e & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xb & thv_c0606=0 & thv_c0404=0 ) ) & esize2021 & Dm & Dn & Dd

{
	Dd = VectorDoubleMultiplyHighHalf(Dn,Dm,esize2021,0:1);
	Dd = SatQ(Dd, esize2021,0:1);
}

:vqdmulh.S^esize2021 Qd, Qn, Qm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2324=0 & (c2021=1 | c2021=2) & c0811=0xb & Q6=1 & c0404=0 ) |
                                      ( $(TMODE_E) & thv_c2327=0x1e & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xb & thv_c0606=1 & thv_c0404=0 ) ) & esize2021 & Qm & Qn & Qd

{
	Qd = VectorDoubleMultiplyHighHalf(Qn,Qm,esize2021,0:1);
	Qd = SatQ(Qd, esize2021,0:1);
}

:vqdmulh.S^esize2021 Dd, Dn, vmlDmA	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 & (c2021=1 | c2021=2)& c0811=0xc & c0606=1 & c0404=0) |
                                      ( $(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xc & thv_c0606=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Dn & Dd

{
	Dd = VectorDoubleMultiplyLong(Dn,vmlDmA,esize2021,0:1);
	Dd = SatQ(Dd, esize2021,0:1);
}

:vqdmulh.S^esize2021 Qd, Qn, vmlDmA	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 & (c2021=1 | c2021=2) & c0811=0xc & c0606=1 & c0404=0) |
                                      ( $(TMODE_F) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xc & thv_c0606=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Qn & Qd

{
	Qd = VectorDoubleMultiplyLong(Qn,vmlDmA,esize2021,0:1);
	Qd = SatQ(Qd, esize2021,0:1);
}

:vqdmull.S^esize2021 Qd, Dn, Dm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=5 & c2021<3 & c0811=0xD & Q6=0 & c0404=0 ) |
                                      ( $(TMODE_E) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=0xD & thv_Q6=0 & thv_c0404=0 ) ) & esize2021 & Dm & Dn & Qd

{
	Qd = VectorDoubleMultiplyLong(Dn,Dm,esize2021,0:1);
	Qd = SatQ(Qd, esize2021,0:1);
}

:vqdmull.S^esize2021 Qd, Dn, vmlDmA	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=5 & c2021<3 & c0811=0xb & Q6=1 & c0404=0 ) |
                                      ( $(TMODE_E) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=0xb & thv_Q6=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Dn & Qd

{
	Qd = VectorDoubleMultiplyLong(Dn,vmlDmA,esize2021,0:1);
	Qd = SatQ(Qd, esize2021,0:1);
}

:vqrdmulh.S^esize2021 Dd, Dn, Dm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2324=2 & (c2021=1 | c2021=2) & c0811=0xb & Q6=0 & c0404=0 ) |
                                      ( $(TMODE_F) & thv_c2327=0x1e & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xb & thv_Q6=0 & thv_c0404=0 ) ) & esize2021 & Dm & Dn & Dd

{
	Dd = VectorRoundDoubleMultiplyHighHalf(Dn,Dm,esize2021,0:1);
	Dd = SatQ(Dd, esize2021,0:1);
}

:vqrdmulh.S^esize2021 Qd, Qn, Qm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2324=2 & (c2021=1 | c2021=2) & c0811=0xb & Q6=1 & c0404=0 ) |
                                      ( $(TMODE_F) & thv_c2327=0x1e & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xb & thv_Q6=1 & thv_c0404=0 ) ) & esize2021 & Qm & Qn & Qd

{
	Qd = VectorRoundDoubleMultiplyHighHalf(Qn,Qm,esize2021,0:1);
	Qd = SatQ(Qd, esize2021,0:1);
}

:vqrdmulh.S^esize2021 Dd, Dn, vmlDmA	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=0 & c2323=1 & (c2021=1 | c2021=2)& c0811=0xd & Q6=1 & c0404=0) |
                                      ( $(TMODE_E) & thv_c2327=0x1f & thv_c2323=1 & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xd & thv_Q6=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Dn & Dd

{
	Dd = VectorRoundDoubleMultiplyHighHalf(Dn,vmlDmA,esize2021,0:1);
	Dd = SatQ(Dd, esize2021,0:1);
}

:vqrdmulh.S^esize2021 Qd, Qn, vmlDmA	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 & (c2021=1 | c2021=2) & c0811=0xd & Q6=1 & c0404=0) |
                                      ( $(TMODE_F) & thv_c2327=0x1f & thv_c2323=1 & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xd & thv_Q6=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Qn & Qd

{
	Qd = VectorRoundDoubleMultiplyHighHalf(Qn,vmlDmA,esize2021,0:1);
	Qd = SatQ(Qd, esize2021,0:1);
}


:vqsub.^udt^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c0811=2 & Q6=0 & c0404=1) |
                                   ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c0811=2 & thv_Q6=0 & thv_c0404=1)) & udt & esize2021 & Dn & Dd & Dm
{
	Dd = VectorSub(Dn,Dm,esize2021,udt);
	Dd = SatQ(Dd, esize2021, udt);
}

:vqsub.^udt^esize2021 Qd,Qn,Qm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c0811=2 & Q6=1 & c0404=1) |
                                   ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c0811=2 & thv_Q6=1 & thv_c0404=1) ) & udt & esize2021 & Qm & Qn & Qd
{
	Qd = VectorSub(Qn,Qm,esize2021,udt);
	Qd = SatQ(Qd, esize2021, udt);
}

#######
# VRECPE
define pcodeop VectorReciprocalEstimate;

:vrecpe.^fdt^32 Qd,Qm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x7 & c2021=3 & c1619=0xb & c0911=2 & c0707=0 & Q6=1 & c0404=0) |
                         ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0xb & thv_c0911=2 & thv_c0707=0 & thv_Q6=1 & thv_c0404=0) ) & fdt & Qm & Qd
{
	Qd = VectorReciprocalEstimate(Qm,fdt);
}

:vrecpe.^fdt^32 Dd,Dm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x7 & c2021=3 & c1619=0xb & c0911=2 & c0707=0 & Q6=0 & c0404=0) |
                         ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0xb & thv_c0911=2 & thv_c0707=0 & thv_Q6=0 & thv_c0404=0) ) & fdt & Dm & Dd
{
	Dd = VectorReciprocalEstimate(Dm,fdt);
}

#######
# VRECPS
define pcodeop VectorReciprocalStep;

:vrecps.f32 Qd,Qn,Qm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x4 & c2021=0 & c0811=0xf & Q6=1 & c0404=1) |
                                   ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=0xf  & thv_Q6=1 & thv_c0404=1) ) & Qn & Qm & Qd
{
	Qd = VectorReciprocalStep(Qn,Qm);
}

:vrecps.f32 Dd,Dn,Dm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x4 & c2021=0 & c0811=0xf & Q6=0 & c0404=1) |
                                   ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=0xf & thv_Q6=0 & thv_c0404=1) ) & Dn & Dm & Dd
{
	Dd = VectorReciprocalStep(Dn,Dm);
}

#######
# VREV
#

define pcodeop vrev;

:vrev16.^esize1819x3 Qd,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=7 &        c2021=3   &   c1617=0  &     c0911=0 &     c0708=2   &   c0606=1     & c0404=0) |
                                    ($(TMODE_F)  &      thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0  & thv_c0911=0 & thv_c0708=2 & thv_c0606=1 & thv_c0404=0) ) & Qd & Qm & esize1819x3
{
	Qd = vrev(Qm,esize1819x3);
}

:vrev32.^esize1819x3 Qd,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=7 &        c2021=3   &   c1617=0  &     c0911=0 &     c0708=1   &   c0606=1     & c0404=0) |
                                    ($(TMODE_F)  &      thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0  & thv_c0911=0 & thv_c0708=1 & thv_c0606=1 & thv_c0404=0) ) & Qd & Qm & esize1819x3
{
	Qd = vrev(Qm,esize1819x3);
}

:vrev64.^esize1819x3 Qd,Qm	is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=7 &        c2021=3   &   c1617=0  &     c0911=0 &     c0708=0   &   c0606=1     & c0404=0) |
                                    ($(TMODE_F)  &      thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0  & thv_c0911=0 & thv_c0708=0 & thv_c0606=1 & thv_c0404=0) ) & Qd & Qm & esize1819x3
{
	Qd = vrev(Qm,esize1819x3);
}

:vrev16.^esize1819x3 Dd,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=7 &        c2021=3   &   c1617=0  &     c0911=0 &     c0708=2   &   c0606=0     & c0404=0) |
                                    ($(TMODE_F)  &      thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0  & thv_c0911=0 & thv_c0708=2 & thv_c0606=0 & thv_c0404=0) ) & Dd & Dm & esize1819x3
{
	Dd = vrev(Dm,esize1819x3);
}

:vrev32.^esize1819x3 Dd,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=7 &        c2021=3   &   c1617=0  &     c0911=0 &     c0708=1   &   c0606=0     & c0404=0) |
                                    ($(TMODE_F)  &      thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0  & thv_c0911=0 & thv_c0708=1 & thv_c0606=0 & thv_c0404=0) ) & Dd & Dm & esize1819x3
{
	Dd = vrev(Dm,esize1819x3);
}

:vrev64.^esize1819x3 Dd,Dm	is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=7 &        c2021=3   &   c1617=0  &     c0911=0 &     c0708=0   &   c0606=0     & c0404=0) |
                                    ($(TMODE_F)  &      thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0  & thv_c0911=0 & thv_c0708=0 & thv_c0606=0 & thv_c0404=0) ) & Dd & Dm & esize1819x3
{
	Dd = vrev(Dm,esize1819x3);
}

#######
# VSH
#

define pcodeop VectorShiftLeft;
define pcodeop VectorRoundShiftLeft;
define pcodeop VectorShiftRight;
define pcodeop VectorShiftLeftInsert;
define pcodeop VectorShiftRightInsert;
define pcodeop VectorShiftRightNarrow;
define pcodeop VectorShiftRightAccumulate;
define pcodeop VectorRoundShiftRight;
define pcodeop VectorRoundShiftRightNarrow;
define pcodeop VectorRoundShiftRightAccumulate;

ShiftSize: "8" is  TMode=0 & c1921=1 & L7=0 { export 8:8; }
ShiftSize: "16" is TMode=0 & c2021=1 & L7=0 { export 16:8; }
ShiftSize: "32" is TMode=0 & c2121=1 & L7=0 { export 32:8; }
ShiftSize: "64" is TMode=0 &           L7=1 { export 64:8; }
ShiftSize: "8" is  TMode=1 & thv_c1921=1 & thv_L7=0 { export 8:8; }
ShiftSize: "16" is TMode=1 & thv_c2021=1 & thv_L7=0 { export 16:8; }
ShiftSize: "32" is TMode=1 & thv_c2121=1 & thv_L7=0 { export 32:8; }
ShiftSize: "64" is TMode=1 &               thv_L7=1 { export 64:8; }


ShiftImmRLI: "#"^shift_amt is TMode=0 & c1921=1 & L7=0 & c1621  [ shift_amt = 16 - c1621; ] { export *[const]:8 shift_amt; }
ShiftImmRLI: "#"^shift_amt is TMode=0 & c2021=1 & L7=0 & c1621  [ shift_amt = 32 - c1621; ] { export *[const]:8 shift_amt; }
ShiftImmRLI: "#"^shift_amt is TMode=0 & c2121=1 & L7=0 & c1621  [ shift_amt = 64 - c1621; ] { export *[const]:8 shift_amt; }
ShiftImmRLI: "#"^shift_amt is TMode=0 &           L7=1 & c1621  [ shift_amt = 64 - c1621; ] { export *[const]:8 shift_amt; }
ShiftImmRLI: "#"^shift_amt is TMode=1 & thv_c1921=1 & thv_L7=0 & thv_c1621  [ shift_amt = 16 - thv_c1621; ] { export *[const]:8 shift_amt; }
ShiftImmRLI: "#"^shift_amt is TMode=1 & thv_c2021=1 & thv_L7=0 & thv_c1621  [ shift_amt = 32 - thv_c1621; ] { export *[const]:8 shift_amt; }
ShiftImmRLI: "#"^shift_amt is TMode=1 & thv_c2121=1 & thv_L7=0 & thv_c1621  [ shift_amt = 64 - thv_c1621; ] { export *[const]:8 shift_amt; }
ShiftImmRLI: "#"^shift_amt is TMode=1 &               thv_L7=1 & thv_c1621  [ shift_amt = 64 - thv_c1621; ] { export *[const]:8 shift_amt; }

ShiftImmLLI: "#"^shift_amt is TMode=0 & c1921=1 & L7=0 & c1621  [ shift_amt = c1621 - 8; ] { export *[const]:8 shift_amt; }
ShiftImmLLI: "#"^shift_amt is TMode=0 & c2021=1 & L7=0 & c1621  [ shift_amt = c1621 - 16; ] { export *[const]:8 shift_amt; }
ShiftImmLLI: "#"^shift_amt is TMode=0 & c2121=1 & L7=0 & c1621  [ shift_amt = c1621 - 32; ] { export *[const]:8 shift_amt; }
ShiftImmLLI: "#"^shift_amt is TMode=0 &           L7=1 & c1621  [ shift_amt = c1621 - 0; ] { export *[const]:8 shift_amt; }
ShiftImmLLI: "#"^shift_amt is TMode=1 & thv_c1921=1 & thv_L7=0 & thv_c1621  [ shift_amt = thv_c1621 - 8; ] { export *[const]:8 shift_amt; }
ShiftImmLLI: "#"^shift_amt is TMode=1 & thv_c2021=1 & thv_L7=0 & thv_c1621  [ shift_amt = thv_c1621 - 16; ] { export *[const]:8 shift_amt; }
ShiftImmLLI: "#"^shift_amt is TMode=1 & thv_c2121=1 & thv_L7=0 & thv_c1621  [ shift_amt = thv_c1621 - 32; ] { export *[const]:8 shift_amt; }
ShiftImmLLI: "#"^shift_amt is TMode=1 &               thv_L7=1 & thv_c1621  [ shift_amt = thv_c1621 - 0; ] { export *[const]:8 shift_amt; }

:vqrshl.^udt^ShiftSize Qd, Qm, ShiftImmLLI  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c0811=5 &     c0606=1 &     c0404=1) |
                                               ($(TMODE_EorF) & thv_c2327=0x1e &       thv_c0811=5 & thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Qd & Qm
{
	Qd = VectorRoundShiftLeft(Qm,ShiftImmLLI,ShiftSize,udt);
}

:vqrshl.^udt^ShiftSize Dd, Dm, ShiftImmLLI  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=0 & c0811=5 &     c0606=0 &     c0404=1) |
                                               ($(TMODE_EorF) & thv_c2327=0x1e &       thv_c0811=5 & thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Dd & Dm
{
	Dd = VectorRoundShiftLeft(Dm,ShiftImmLLI,ShiftSize,udt);
}


:vqshrn.^udt^esize2021 Dd,Qm, ShiftImmRLI  is ( ($(AMODE) &  ARMcond=0 & cond=15 & c2527=1 & c2323=1 &  (c1919=1 | c2020=1 | c2121=1) &     c0611=0x24  &     c0404=1) |
                                              ($(TMODE_EorF) &  thv_c2327=0x1f & (thv_c1919=1 | thv_c2020=1 | thv_c2121=1) & thv_c0611=0x24 & thv_c0404=1) ) & udt & esize2021 & ShiftSize & ShiftImmRLI & Dd & Qm
{
	Dd = VectorShiftRightNarrow(Qm,ShiftImmRLI,esize2021,udt);
	Dd = SatQ(Dd,esize2021,udt);
}

:vqshrun.^udt^esize2021 Dd,Qm, ShiftImmRLI  is ( ($(AMODE) &  ARMcond=0 & cond=15 & c2327=7 &       (c1919=1 | c2020=1 | c2121=1)       &    c0611=0x20 &      c0404=1) |
                                               ($(TMODE_F) &     thv_c2327=0x1f & (thv_c1919=1 | thv_c2020=1 | thv_c2121=1) & thv_c0611=0x20 & thv_c0404=1) ) & udt & esize2021 & ShiftSize & ShiftImmRLI & Dd & Qm
{
	Dd = VectorShiftRightNarrow(Qm,ShiftImmRLI,esize2021,udt);
	Dd = SatQ(Dd,esize2021,udt);
}

:vqrshrn.^udt^esize2021 Dd,Qm, ShiftImmRLI		is ( ($(AMODE) &  ARMcond=0 & cond=15 & c2527=1 & c2323=1 &  (c1919=1 | c2020=1 | c2121=1) &     c0611=0x25  &     c0404=1) |
                                                 ($(TMODE_EorF) & thv_c2327=0x1f & (thv_c1919=1 | thv_c2020=1 | thv_c2121=1) & thv_c0611=0x25 & thv_c0404=1) ) & udt & esize2021 & ShiftSize & ShiftImmRLI & Dd & Qm
{
	Dd = VectorRoundShiftRightNarrow(Qm,ShiftImmRLI,esize2021,udt);
	Dd = SatQ(Dd,esize2021,udt);
}

:vqrshrun.^udt^esize2021 Dd,Qm, ShiftImmRLI	is ( ($(AMODE) &  ARMcond=0 & cond=15 & c2527=1 & c2424=1 & c2323=1 &  (c1919=1 | c2020=1 | c2121=1) &   c0611=0x21 &     c0404=1) |
                                                 ($(TMODE_F) & thv_c2327=0x1f & (thv_c1919=1 | thv_c2020=1 | thv_c2121=1) & thv_c0611=0x21 & thv_c0404=1) ) & udt & esize2021 & ShiftImmRLI & Dd & Qm
{
	Dd = VectorRoundShiftRightNarrow(Qm,ShiftImmRLI,esize2021,udt);
	Dd = SatQ(Dd,esize2021,udt);
}


:vqshl.^udt^ShiftSize Qd, Qm, ShiftImmLLI is ( ($(AMODE) & ARMcond=0 & cond=15 &    c2527=1 &  c2323=1 & c1621 &   c0811=7 &  c0606=1     & c0404=1) |
                                       ($(TMODE_EorF) &       thv_c2327=0x1f & thv_c1621 &  thv_c0811=7 &  thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Qd & Qm
{
	Qd = VectorShiftLeft(Qm,ShiftImmLLI,ShiftSize,udt);
}

:vqshl.^udt^ShiftSize Dd, Dm, ShiftImmLLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 &  c2323=1 & c1621 &  c0811=7 &      c0606=0     & c0404=1) |
                                       ($(TMODE_EorF) &       thv_c2327=0x1f & thv_c1621 &  thv_c0811=7 &  thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Dd & Dm
{
	Dd = VectorShiftLeft(Dm,ShiftImmLLI,ShiftSize,udt);
}

:vqshlu.^udt^ShiftSize Qd, Qm, ShiftImmLLI is ( ($(AMODE) & ARMcond=0 & cond=15 &    c2527=1 &  c2323=1  &  c1621 & c0811=6 &  c0606=1     & c0404=1) |
                                       ($(TMODE_EorF) &   thv_c2828=1 & thv_c2327=0x1f & thv_c1621 &  thv_c0811=6 &  thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Qd & Qm
{
	Qd = VectorShiftLeft(Qm,ShiftImmLLI,ShiftSize,udt);
}

:vqshlu.^udt^ShiftSize Dd, Dm, ShiftImmLLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 &  c2323=1 & c1621 &  c0811=6 &      c0606=0     & c0404=1) |
                                       ($(TMODE_EorF) &  thv_c2828=1 & thv_c2327=0x1f & thv_c1621 & thv_c0811=6 &  thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Dd & Dm
{
	Dd = VectorShiftLeft(Dm,ShiftImmLLI,ShiftSize,udt);
}


:vqshl.^udt^esize2021 Qd, Qm, Qn is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 & c2323=0 &     c0811=4 &      c0606=1     & c0404=1) |
                                       ($(TMODE_EorF) &    thv_c2327=0x1e &         thv_c0811=4 &  thv_c0606=1 & thv_c0404=1) ) & udt & esize2021 & Qd & Qm & Qn
{
	Qd = VectorShiftLeft(Qm,Qn,esize2021,udt);
}

:vqshl.^udt^esize2021 Dd, Dm, Dn is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 & c2323=0 &   c0811=4 &      c0606=0     & c0404=1) |
                                       ($(TMODE_EorF) &    thv_c2327=0x1e &       thv_c0811=4 &  thv_c0606=0 & thv_c0404=1) ) & udt & esize2021 & Dd & Dm & Dn
{
	Dd = VectorShiftLeft(Dm,Dn,esize2021,udt);
}


:vshl.I^ShiftSize Qd, Qm, ShiftImmLLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=5 &       c0811=5 &      c0606=1     & c0404=1) |
                                       ($(TMODE_E) &       thv_c2327=0x1f &  thv_c0811=5 &  thv_c0606=1 & thv_c0404=1) ) & ShiftSize & ShiftImmLLI & Qd & Qm
{
	Qd = VectorShiftLeft(Qm,ShiftImmLLI,ShiftSize,0:1);
}

:vshl.I^ShiftSize Dd, Dm, ShiftImmLLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=5 &       c0811=5 &      c0606=0     & c0404=1) |
                                       ($(TMODE_E) &       thv_c2327=0x1f &  thv_c0811=5 &  thv_c0606=0 & thv_c0404=1) ) & ShiftSize & ShiftImmLLI & Dd & Dm
{
	Dd = VectorShiftLeft(Dm,ShiftImmLLI,ShiftSize,0:1);
}


:vshl.^udt^esize2021 Qd, Qm, Qn is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 & c2323=0 &     c0811=4 &      c0606=1     & c0404=0) |
                                       ($(TMODE_EorF) &    thv_c2327=0x1e &         thv_c0811=4 &  thv_c0606=1 & thv_c0404=0) ) & udt & esize2021 & Qd & Qm & Qn
{
	Qd = VectorShiftLeft(Qm,Qn,esize2021,udt);
}

:vshl.^udt^esize2021 Dd, Dm, Dn is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 & c2323=0 &   c0811=4 &      c0606=0     & c0404=0) |
                                       ($(TMODE_EorF) &    thv_c2327=0x1e &       thv_c0811=4 &  thv_c0606=0 & thv_c0404=0) ) & udt & esize2021 & Dd & Dm & Dn
{
	Dd = VectorShiftLeft(Dm,Dn,esize2021,udt);
}

define pcodeop VectorShiftLongLeft;

:vshll.^udt^ShiftSize Qd, Dm, ShiftImmLLI is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 &      c0811=10 &      c0607=0     & c0404=1) |
                                       ($(TMODE_EorF) &        thv_c2327=0x1f &         thv_c0811=10 &  thv_c0607=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Qd & Dm
{
	Qd = VectorShiftLongLeft(Dm,ShiftImmLLI);
}

:vshll.^udt^esize1819 Qd, Dm, "#"^esize1819x3 is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 & c2021=3 & c1617=2 &     c0811=3 &      c0607=0     & c0404=0) |
                                       ($(TMODE_F)  &      thv_c2327=0x1f & thv_c2021=3 & thv_c1617=2 & thv_c0811=3 &  thv_c0607=0 & thv_c0404=0) ) & udt & esize1819 & esize1819x3 & Qd & Dm
{
	Qd = VectorShiftLongLeft(Dm,esize1819x3);
}

:vrshl.^udt^esize2021 Qd, Qm, Qn is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 & c2323=0 &     c0811=5 &      c0606=1     & c0404=0) |
                                       ($(TMODE_EorF) &    thv_c2327=0x1e &         thv_c0811=5 &  thv_c0606=1 & thv_c0404=0) ) & udt & esize2021 & Qd & Qm & Qn
{
	Qd = VectorRoundShiftLeft(Qm,esize2021,Qn);
}

:vrshl.^udt^esize2021 Dd, Dm, Dn is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 & c2323=0 &   c0811=5 &      c0606=0     & c0404=0) |
                                       ($(TMODE_EorF) &    thv_c2327=0x1e &       thv_c0811=5 &  thv_c0606=0 & thv_c0404=0) ) & udt & esize2021 & Dd & Dm & Dn
{
	Dd = VectorRoundShiftLeft(Dm,esize2021,Dn);
}

:vrshr.^udt^ShiftSize Qd, Qm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 &  c2323=1 &     c0811=2 &      c0606=1     & c0404=1) |
                                       ($(TMODE_EorF) &     thv_c2327=0x1f &  thv_c0811=2 &  thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Qd & Qm
{
	Qd = VectorRoundShiftRight(Qm,ShiftImmRLI);
}

:vrshr.^udt^ShiftSize Dd, Dm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 &  c2323=1 &     c0811=2 &      c0606=0     & c0404=1) |
                                       ($(TMODE_EorF) &     thv_c2327=0x1f &  thv_c0811=2 &  thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Dd & Dm
{
	Dd = VectorRoundShiftRight(Dm,ShiftImmRLI);
}

:vrshrn.^ShiftSize Dd, Qm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=5 &     c0811=8 & c0707=0 & c0606=1     & c0404=1) |
                                       ($(TMODE_E) &       thv_c2327=0x1f &  thv_c0811=8 & thv_c0707=0 &  thv_c0606=1 & thv_c0404=1) ) & ShiftSize & ShiftImmRLI & Dd & Qm
{
	Dd = VectorRoundShiftRightNarrow(Qm,ShiftImmRLI);
}

:vrsra.^udt^ShiftSize Qd, Qm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 &  c2323=1 &     c0811=3 &      c0606=1     & c0404=1) |
                                       ($(TMODE_EorF) &       thv_c2327=0x1f &  thv_c0811=3 &  thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Qd & Qm
{
	Qd = VectorRoundShiftRightAccumulate(Qd, Qm,ShiftImmRLI);
}

:vrsra.^udt^ShiftSize Dd, Dm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 &  c2323=1 &     c0811=3 &      c0606=0     & c0404=1) |
                                       ($(TMODE_EorF) &       thv_c2327=0x1f &  thv_c0811=3 &  thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Dd & Dm
{
	Dd = VectorRoundShiftRightAccumulate(Dd, Dm,ShiftImmRLI);
}

:vsli.^ShiftSize Dd, Dm, ShiftImmLLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=7 &     c0811=5  &    c0606=0     & c0404=1) |
                                       ($(TMODE_F) &    thv_c2327=0x1f &  thv_c0811=5 & thv_c0606=0 & thv_c0404=1) ) & ShiftSize & ShiftImmLLI & Dd & Dm
{
	Dd = VectorShiftLeftInsert(Dd, Dm,ShiftImmLLI);
}

:vsli.^ShiftSize Qd, Qm, ShiftImmLLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2327=7 &     c0811=5  &    c0606=1     & c0404=1) |
                                       ($(TMODE_F) &    thv_c2327=0x1f &  thv_c0811=5 & thv_c0606=1 & thv_c0404=1) ) & ShiftSize & ShiftImmLLI & Qd & Qm
{
	Qd = VectorShiftLeftInsert(Qd, Qm,ShiftImmLLI);
}

define pcodeop VectorWidenMultipyAccumulate;
:vsmmla.s8 Dd, Dm, Dn  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=2 &     c0811=0xc &      c0606=0     & c0404=0) |
                          ($(TMODE_F) &       thv_c2327=0x18 & thv_c2021=2 & thv_c0811=0xc &  thv_c0606=0 & thv_c0404=0) ) & Dd & Dm & Dn
{
	Dd = VectorWidenMultipyAccumulate(Dm,Dn,0:1);
}

:vsmmla.s8 Qd, Qm, Qn  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=2 &     c0811=0xc &      c0606=1     & c0404=0) |
                          ($(TMODE_F) &       thv_c2327=0x18 & thv_c2021=2 & thv_c0811=0xc &  thv_c0606=1 & thv_c0404=0) ) & Qd & Qm & Qn
{
	Qd = VectorWidenMultipyAccumulate(Qm,Qn,0:1);
}

:vummla.u8 Dd, Dm, Dn is  ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=2 &     c0811=0xc &      c0606=0     & c0404=1) |
                          ($(TMODE_F) &       thv_c2327=0x18 & thv_c2021=2 & thv_c0811=0xc &  thv_c0606=0 & thv_c0404=1) ) & Dd & Dm & Dn
{
	Dd = VectorWidenMultipyAccumulate(Dm,Dn,1:1);
}

:vummla.u8 Qd, Qm, Qn  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=2 &     c0811=0xc &      c0606=1     & c0404=1) |
                          ($(TMODE_F) &       thv_c2327=0x18 & thv_c2021=2 & thv_c0811=0xc &  thv_c0606=1 & thv_c0404=1) ) & Qd & Qm & Qn
{
	Qd = VectorWidenMultipyAccumulate(Qm,Qn,1:1);
}

:vusmmla.s8 Dd, Dm, Dn  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x19 &     c2021=2 &     c0811=0xc &      c0606=0     & c0404=0) |
                           ($(TMODE_F) &       thv_c2327=0x19 & thv_c2021=2 & thv_c0811=0xc &  thv_c0606=0 & thv_c0404=0) ) & Dd & Dm & Dn
{
	Dd = VectorWidenMultipyAccumulate(Dm,Dn,2:1);
}

:vusmmla.s8 Qd, Qm, Qn  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x19 &     c2021=2 &     c0811=0xc &      c0606=1     & c0404=0) |
                           ($(TMODE_F) &       thv_c2327=0x19 & thv_c2021=2 & thv_c0811=0xc &  thv_c0606=1 & thv_c0404=0) ) & Qd & Qm & Qn
{
	Qd = VectorWidenMultipyAccumulate(Qm,Qn,2:1);
}

:vsqrt^COND^".f32" Sd,Sm		is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c2021=3 & c1619=1 & c0811=10 & c0607=3 & c0404=0) |
                                        ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c1619=1 & thv_c0811=10 & thv_c0606=1 & thv_c0404=0) ) & Sm & Sd
{
	build COND;
	build Sd;
	build Sm;
	Sd = sqrt(Sm);
}

:vsqrt^COND^".f64" Dd,Dm		is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c2021=3 & c1619=1 & c0811=11 & c0606=1 & c0404=0 ) |
                                        ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c1619=1 & thv_c0811=11 & thv_c0606=1 & thv_c0404=0) ) & Dm & Dd
{
	build COND;
	build Dd;
	build Dm;
	Dd = sqrt(Dm);
}

:vsra.^udt^ShiftSize Qd, Qm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 &  c2323=1 &     c0811=1 &      c0606=1     & c0404=1) |
                                       ($(TMODE_EorF) &       thv_c2327=0x1f &  thv_c0811=1 &  thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Qd & Qm
{
	Qd = VectorShiftRightAccumulate(Qd, Qm,ShiftImmRLI);
}

:vsra.^udt^ShiftSize Dd, Dm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 &  c2323=1 &     c0811=1 &      c0606=0     & c0404=1) |
                                       ($(TMODE_EorF) &       thv_c2327=0x1f &  thv_c0811=1 &  thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Dd & Dm
{
	Dd = VectorShiftRightAccumulate(Dd, Dm,ShiftImmRLI);
}

:vsri.^ShiftSize Qd, Qm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 & c2424=1 & c2323=1 &     c0811=4 &      c0606=1     & c0404=1) |
                                       ($(TMODE_F) &       thv_c2327=0x1f &  thv_c0811=4 &  thv_c0606=1 & thv_c0404=1) ) & ShiftSize & ShiftImmRLI & Qd & Qm
{
	Qd = VectorShiftRightInsert(Qd, Qm,ShiftImmRLI);
}

:vsri.^ShiftSize Dd, Dm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &     c2527=1 & c2424=1 &  c2323=1 &     c0811=4 &      c0606=0     & c0404=1) |
                                       ($(TMODE_F) &       thv_c2327=0x1f &  thv_c0811=4 &  thv_c0606=0 & thv_c0404=1) ) & ShiftSize & ShiftImmRLI & Dd & Dm
{
	Dd = VectorShiftRightInsert(Dd, Dm,ShiftImmRLI);
}

#######
# VSHR
#

:vshr.^udt^ShiftSize Qd, Qm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &   c2527=1 & c2323=1 & c0811=0 &      c0606=1     & c0404=1) |
                                            ($(TMODE_EorF) &    thv_c2327=0x1f  &   thv_c0811=0 &  thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Qd & Qm
{
	Qd = VectorShiftRight(Qm,ShiftImmRLI);
}

:vshr.^udt^ShiftSize Dd, Dm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 &   c2527=1 & c2323=1 & c0811=0 &      c0606=0     & c0404=1) |
                                            ($(TMODE_EorF) &    thv_c2327=0x1f  &   thv_c0811=0 &  thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Dd & Dm
{
	Dd = VectorShiftRight(Dm,ShiftImmRLI);
}

define pcodeop VectorShiftNarrowRight;

:vshrn.^ShiftSize Dd, Qm, ShiftImmRLI is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=5 &        c0811=8 &      c0607=0     & c0404=1) |
                                         ($(TMODE_E) &     thv_c2327=0x1f & thv_c0811=8 &  thv_c0607=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Dd & Qm
{ 
	Dd = VectorShiftNarrowRight(Qm,ShiftImmRLI);
}

#######
# VRSQRTE
define pcodeop VectorReciprocalSquareRootEstimate;

:vrsqrte.^fdt^32 Qd,Qm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x7 & c2021=3 & c1619=0xb & c0911=2 & c0707=1 & Q6=1 & c0404=0) |
                         ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0xb & thv_c0911=2 & thv_c0707=1 & thv_Q6=1 & thv_c0404=0) ) & fdt & Qm & Qd
{
	Qd = VectorReciprocalSquareRootEstimate(Qm,fdt);
}

:vrsqrte.^fdt^32 Dd,Dm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x7 & c2021=3 & c1619=0xb & c0911=2 & c0707=1 & Q6=0 & c0404=0) |
                         ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0xb & thv_c0911=2 & thv_c0707=1 & thv_Q6=0 & thv_c0404=0) ) & fdt & Dm & Dd
{
	Dd = VectorReciprocalSquareRootEstimate(Dm,fdt);
}

#######
# VRSQRTS
define pcodeop VectorReciprocalSquareRootStep;

:vrsqrts.f32 Qd,Qn,Qm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x4 & c2021=2 & c0811=0xf & Q6=1 & c0404=1) |
                                   ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=0xf  & thv_Q6=1 & thv_c0404=1) ) & Qn & Qm & Qd
{
	Qd = VectorReciprocalSquareRootStep(Qn,Qm);
}

:vrsqrts.f32 Dd,Dn,Dm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x4 & c2021=2 & c0811=0xf & Q6=0 & c0404=1) |
                                   ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=0xf & thv_Q6=0 & thv_c0404=1) ) & Dn & Dm & Dd
{
	Dd = VectorReciprocalSquareRootStep(Dn,Dm);
}


#######
# VST1 (multiple single elements)
#

buildVst1DdList: Dreg					is Dreg & counter=1 					[ counter=0; regNum=regNum+1; ]
{
	* mult_addr = Dreg;
}
buildVst1DdList: Dreg,buildVst1DdList	is Dreg & buildVst1DdList				[ counter=counter-1; regNum=regNum+1; ]
{
	* mult_addr = Dreg;
	mult_addr = mult_addr + 8;
	build buildVst1DdList;
}

vst1DdList: "{"^buildVst1DdList^"}"	is TMode = 0 & c0811=7 & D22 & c1215 & buildVst1DdList [ regNum=(D22<<4)+c1215-1; counter=1; ] { export 1:4; }
vst1DdList: "{"^buildVst1DdList^"}"	is TMode = 0 & c0811=10 & D22 & c1215 & buildVst1DdList [ regNum=(D22<<4)+c1215-1; counter=2; ] { export 2:4; }
vst1DdList: "{"^buildVst1DdList^"}"	is TMode = 0 & c0811=6 & D22 & c1215 & buildVst1DdList [ regNum=(D22<<4)+c1215-1; counter=3; ] { export 3:4; }
vst1DdList: "{"^buildVst1DdList^"}"	is TMode = 0 & c0811=2 & D22 & c1215 & buildVst1DdList [ regNum=(D22<<4)+c1215-1; counter=4; ] { export 4:4; }
vst1DdList: "{"^buildVst1DdList^"}"	is TMode = 1 & thv_c0811=7 & thv_D22 & thv_c1215 & buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=1; ] { export 1:4; }
vst1DdList: "{"^buildVst1DdList^"}"	is TMode = 1 & thv_c0811=10 & thv_D22 & thv_c1215 & buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=2; ] { export 2:4; }
vst1DdList: "{"^buildVst1DdList^"}"	is TMode = 1 & thv_c0811=6 & thv_D22 & thv_c1215 & buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=3; ] { export 3:4; }
vst1DdList: "{"^buildVst1DdList^"}"	is TMode = 1 & thv_c0811=2 & thv_D22 & thv_c1215 & buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=4; ] { export 4:4; }

@define Vst1DdList "(c0811=2 | c0811=6 | c0811=7 | c0811=10)"
@define T_Vst1DdList "(thv_c0811=2 | thv_c0811=6 | thv_c0811=7 | thv_c0811=10)"

:vst1.^esize0607 vst1DdList,RnAligned45		is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & c0003=15 & $(Vst1DdList)) |
												($(TMODE_F)  &thv_c2327=18 & thv_c2021=0 & thv_c0003=15 & $(T_Vst1DdList)) ) & RnAligned45 & esize0607 & vst1DdList
{
 	mult_addr = RnAligned45;
 	build vst1DdList;
}

:vst1.^esize0607 vst1DdList,RnAligned45^"!"	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & c0003=13 & $(Vst1DdList)) |
												($(TMODE_F)  &thv_c2327=18 & thv_c2021=0 & thv_c0003=13 & $(T_Vst1DdList)) ) & RnAligned45 & esize0607 & vst1DdList
{
	mult_addr = RnAligned45;
	build vst1DdList;
	RnAligned45 = RnAligned45 + (8 * vst1DdList);
}

:vst1.^esize0607 vst1DdList,RnAligned45,VRm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & $(Vst1DdList)) |
												($(TMODE_F)  &thv_c2327=18 & thv_c2021=0 & $(T_Vst1DdList)) ) & RnAligned45 & esize0607 & VRm & vst1DdList
{
	mult_addr = RnAligned45;
	build vst1DdList;
	RnAligned45 = RnAligned45 + VRm;
}

#######
# VST1 (single element to one lane)
#

vst1Index: val	is c0507 & c1011	[ val = c0507 >> c1011; ]	{ tmp:4 = val; export tmp; }

vst1DdElement2: Dd^"["^vst1Index^"]"	is Dd & vst1Index & c1011=0
{
	ptr:4 = &Dd + vst1Index;
	*:1 mult_addr = *[register]:1 ptr;
}
vst1DdElement2: Dd^"["^vst1Index^"]"	is Dd & vst1Index & c1011=1
{
	ptr:4 = &Dd + (2 * vst1Index);
	*:2 mult_addr = *[register]:2 ptr;
}
vst1DdElement2: Dd^"["^vst1Index^"]"	is Dd & vst1Index & c1011=2
{
	ptr:4 = &Dd + (4 * vst1Index);
	*:4 mult_addr = *[register]:4 ptr;
}

@define Vst1DdElement2 "((c1011=0 & c0404=0) | (c1011=1 &  c0505=0) | (c1011=2 &  (c0406=0 | c0406=3))) & vst1DdElement2"

:vst1.^esize1011 vst1DdElement2,RnAligned2		is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0 & RnAligned2 & esize1011 & c0809=0 & c0003=15 & $(Vst1DdElement2)
{
 	mult_addr = RnAligned2;
	build vst1DdElement2;
}

:vst1.^esize1011 vst1DdElement2,RnAligned2^"!"	is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0 & RnAligned2 & esize1011 & c0809=0 & c0003=13 & $(Vst1DdElement2)
{
	mult_addr = RnAligned2;
	build vst1DdElement2;
	RnAligned2 = RnAligned2 + esize1011;
}

:vst1.^esize1011 vst1DdElement2,RnAligned2,VRm	is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0 & RnAligned2 & esize1011 & c0809=0 & VRm & $(Vst1DdElement2)
{
	mult_addr = RnAligned2;
	build vst1DdElement2;
	RnAligned2 = RnAligned2 + VRm;
}

thv_vst1Index: val	is thv_c0507 & thv_c1011	[ val = thv_c0507 >> thv_c1011; ]	{ tmp:4 = val; export tmp; }

thv_vst1DdElement2: Dd^"["^thv_vst1Index^"]"	is Dd & thv_vst1Index & thv_c1011=0
{
	ptr:4 = &Dd + thv_vst1Index;
	*:1 mult_addr = *[register]:1 ptr;
}
thv_vst1DdElement2: Dd^"["^thv_vst1Index^"]"	is Dd & thv_vst1Index & thv_c1011=1
{
	ptr:4 = &Dd + (2 * thv_vst1Index);
	*:2 mult_addr = *[register]:2 ptr;
}
thv_vst1DdElement2: Dd^"["^thv_vst1Index^"]"	is Dd & thv_vst1Index & thv_c1011=2
{
	ptr:4 = &Dd + (4 * thv_vst1Index);
	*:4 mult_addr = *[register]:4 ptr;
}

@define T_Vst1DdElement2 "((thv_c1011=0 & thv_c0404=0) | (thv_c1011=1 &  thv_c0505=0) | (thv_c1011=2 &  (thv_c0406=0 | thv_c0406=3))) & thv_vst1DdElement2"

:vst1.^esize1011 thv_vst1DdElement2,RnAligned2		is $(TMODE_F)  &thv_c2327=19 & thv_c2021=0 & RnAligned2 & esize1011 & thv_c0809=0 & thv_c0003=15 & $(T_Vst1DdElement2)
{
 	mult_addr = RnAligned2;
	build thv_vst1DdElement2;
}

:vst1.^esize1011 thv_vst1DdElement2,RnAligned2^"!"	is $(TMODE_F)  &thv_c2327=19 & thv_c2021=0 & RnAligned2 & esize1011 & thv_c0809=0 & thv_c0003=13 & $(T_Vst1DdElement2)
{
	mult_addr = RnAligned2;
	build thv_vst1DdElement2;
	RnAligned2 = RnAligned2 + esize1011;
}

:vst1.^esize1011 thv_vst1DdElement2,RnAligned2,VRm	is $(TMODE_F)  &thv_c2327=19 & thv_c2021=0 & RnAligned2 & esize1011 & thv_c0809=0 & VRm & $(T_Vst1DdElement2)
{
	mult_addr = RnAligned2;
	build thv_vst1DdElement2;
	RnAligned2 = RnAligned2 + VRm;
}


#######
# VST2
#

#######
# VST2 (multiple 2-element structures)
#

vst2Dd: Dreg		is Dreg & ((TMode=0 & c0607=0) | (TMode=1 & thv_c0607=0))  & regInc
{
	ptr1:4 = &Dreg;
@if ENDIAN == "little"
  	ptr2:4 = &Dreg + (regInc * 8);
@else # ENDIAN == "big"
  	ptr2:4 = &Dreg - (regInc * 8);
@endif # ENDIAN = "big"
	mult_dat8 = 8;
<loop>
	*:1 mult_addr = *[register]:1 ptr1;
	mult_addr = mult_addr + 1;
	*:1 mult_addr = *[register]:1 ptr2;
	mult_addr = mult_addr + 1;
	mult_dat8 = mult_dat8 - 1;
	if(mult_dat8 == 0) goto <loop_end>;
	ptr1 = ptr1 + 1;
	ptr2 = ptr2 + 1;
	goto <loop>;
<loop_end>
}
vst2Dd: Dreg		is Dreg & ((TMode=0 & c0607=1) | (TMode=1 & thv_c0607=1))  & regInc
{
	ptr1:4 = &Dreg;
@if ENDIAN == "little"
  	ptr2:4 = &Dreg + (regInc * 8);
@else # ENDIAN == "big"
  	ptr2:4 = &Dreg - (regInc * 8);
@endif # ENDIAN = "big"
	mult_dat8 = 4;
<loop>
	*:2 mult_addr = *[register]:2 ptr1;
	mult_addr = mult_addr + 2;
	*:2 mult_addr = *[register]:2 ptr2;
	mult_addr = mult_addr + 2;
	mult_dat8 = mult_dat8 - 1;
	if(mult_dat8 == 0) goto <loop_end>;
	ptr1 = ptr1 + 2;
	ptr2 = ptr2 + 2;
	goto <loop>;
<loop_end>	
}
vst2Dd: Dreg		is Dreg & ((TMode=0 & c0607=2) | (TMode=1 & thv_c0607=2)) & regInc
{
	ptr1:4 = &Dreg;
@if ENDIAN == "little"
  	ptr2:4 = &Dreg + (regInc * 8);
@else # ENDIAN == "big"
  	ptr2:4 = &Dreg - (regInc * 8);
@endif # ENDIAN = "big"
	mult_dat8 = 2;
<loop>
	*:4 mult_addr = *[register]:4 ptr1;
	mult_addr = mult_addr + 4;
	*:4 mult_addr = *[register]:4 ptr2;
	mult_addr = mult_addr + 4;
	mult_dat8 = mult_dat8 - 1;
	if(mult_dat8 == 0) goto <loop_end>;
	ptr1 = ptr1 + 4;
	ptr2 = ptr2 + 4;
	goto <loop>;
<loop_end>	
}

buildVst2DdListA:							is counter=0								{ }
buildVst2DdListA: vst2Dd,buildVst2DdListA	is vst2Dd & buildVst2DdListA & esize0607	[ counter=counter-1; regNum=regNum+1; ] 
{
	build vst2Dd;
	build buildVst2DdListA;
}

buildVst2DdListB:							is counter2=0								{ }
buildVst2DdListB: Dreg2						is Dreg2 & counter2=1 & esize0607			[ counter2=0; reg2Num=reg2Num+1; ] { }
buildVst2DdListB: Dreg2,buildVst2DdListB	is Dreg2 & buildVst2DdListB & esize0607		[ counter2=counter2-1; reg2Num=reg2Num+1; ] { }

vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}"	is TMode=0 & c0811=8 & D22 & c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(D22<<4)+c1215-1; regInc=1; reg2Num=regNum+1; counter=1; counter2=1; ] { build buildVst2DdListA; build buildVst2DdListB; export 2:4; }
vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}"	is TMode=0 & c0811=9 & D22 & c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(D22<<4)+c1215-1; regInc=2; reg2Num=regNum+2; counter=1; counter2=1; ] { build buildVst2DdListA; build buildVst2DdListB; export 2:4; }
vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}"	is TMode=0 & c0811=3 & D22 & c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(D22<<4)+c1215-1; regInc=2; reg2Num=regNum+2; counter=2; counter2=2; ] { build buildVst2DdListA; build buildVst2DdListB; export 4:4; }
vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}"	is TMode=1 & thv_c0811=8 & thv_D22 & thv_c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; reg2Num=regNum+1; counter=1; counter2=1; ] { build buildVst2DdListA; build buildVst2DdListB; export 2:4; }
vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}"	is TMode=1 & thv_c0811=9 & thv_D22 & thv_c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=2; reg2Num=regNum+2; counter=1; counter2=1; ] { build buildVst2DdListA; build buildVst2DdListB; export 2:4; }
vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}"	is TMode=1 & thv_c0811=3 & thv_D22 & thv_c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=2; reg2Num=regNum+2; counter=2; counter2=2; ] { build buildVst2DdListA; build buildVst2DdListB; export 4:4; }


@define Vst2DdList "(c0811=3 | c0811=8 | c0811=9)"
@define T_Vst2DdList "(thv_c0811=3 | thv_c0811=8 | thv_c0811=9)"

:vst2.^esize0607 vst2DdList,RnAligned45		is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & c0607<3 & c0003=15 & $(Vst2DdList) ) |
												  ($(TMODE_F)  &    thv_c2327=0x12 & thv_c2021=0 & thv_c0607<3 & thv_c0003=15 & $(T_Vst2DdList) ) ) & RnAligned45 & esize0607  & vst2DdList
{
 	mult_addr = RnAligned45;
 	build vst2DdList;
}

:vst2.^esize0607 vst2DdList,RnAligned45^"!"	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & c0607<3 & c0003=13 & $(Vst2DdList) ) |
												  ($(TMODE_F)  &    thv_c2327=0x12 & thv_c2021=0 & thv_c0607<3 & thv_c0003=13 & $(T_Vst2DdList) ) ) & RnAligned45 & esize0607  & vst2DdList
{
	mult_addr = RnAligned45;
	build vst2DdList;
	RnAligned45 = RnAligned45 + (8 * vst2DdList);
}

:vst2.^esize0607 vst2DdList,RnAligned45,VRm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & c0607<3 & $(Vst2DdList) ) |
												  ($(TMODE_F)  &    thv_c2327=0x12 & thv_c2021=0 & thv_c0607<3 & $(T_Vst2DdList) ) ) & RnAligned45 & VRm & esize0607  & vst2DdList
{
	mult_addr = RnAligned45;
	build vst2DdList;
	RnAligned45 = RnAligned45 + VRm;
}

#######
# VST2 (single 2-element structure to one lane)
#

vst2DdElement2: Dreg^"["^vld2Index^"]"	is Dreg & vld2Index
{
}

vst2Align2: 		is TMode=0 & c0404=0 & (c1111=0 | c0505=0)	{ }
vst2Align2: "@16"	is TMode=0 & c1011=0 & c0404=1				{ }
vst2Align2: "@32"	is TMode=0 & c1011=1 & c0404=1				{ }
vst2Align2: "@64"	is TMode=0 & c1011=2 & c0405=1				{ }
vst2Align2: 		is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0)	{ }
vst2Align2: "@16"	is TMode=1 & thv_c1011=0 & thv_c0404=1				{ }
vst2Align2: "@32"	is TMode=1 & thv_c1011=1 & thv_c0404=1				{ }
vst2Align2: "@64"	is TMode=1 & thv_c1011=2 & thv_c0405=1				{ }

vst2RnAligned2: "["^VRn^vst2Align2^"]" 	is VRn & vst2Align2	{ export VRn; }

buildVst2DdList2:					is counter=0			{ }
buildVst2DdList2: vst2DdElement2	is counter=1 & vst2DdElement2		[ counter=0; regNum=regNum+regInc; ] { }
buildVst2DdList2: vst2DdElement2,buildVst2DdList2		is vst2DdElement2 & buildVst2DdList2	[ counter=counter-1; regNum=regNum+regInc; ] { }

vst2DdList2: "{"^buildVst2DdList2^"}"	is TMode=0 &  D22 & c1215 & buildVst2DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=2; ] { } # Single
vst2DdList2: "{"^buildVst2DdList2^"}"	is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVst2DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=2; ] { } # Double
vst2DdList2: "{"^buildVst2DdList2^"}"	is TMode=1 & thv_D22 & thv_c1215 & buildVst2DdList2 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=2; ] { } # Single
vst2DdList2: "{"^buildVst2DdList2^"}"	is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildVst2DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=2; ] { } # Double

:vst2.^esize1011 vst2DdList2,vst2RnAligned2		is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0  & c1011<3 & c0809=1 & c0003=15 )  |
                                                     ( $(TMODE_F)  &    thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=1 & thv_c0003=15 ) ) & vst2RnAligned2 & esize1011 & vst2DdList2 
	unimpl

:vst2.^esize1011 vst2DdList2,vst2RnAligned2^"!"	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0  & c1011<3 & c0809=1 & c0003=13 )  |
                                                     ( $(TMODE_F)  &    thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=1 & thv_c0003=13 ) ) & vst2RnAligned2 & esize1011 & vst2DdList2
    unimpl

:vst2.^esize1011 vst2DdList2,vst2RnAligned2,VRm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0  & c1011<3 & c0809=1 )  |
                                                     ( $(TMODE_F)  &    thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=1 ) ) & vst2RnAligned2 & esize1011 & vst2DdList2 & VRm
    unimpl


#######
# VST3
#

#######
# VST3 (multiple 3-element structures)
#


vst3Align:			is TMode=0 & c0404=0 { }
vst3Align: "@64"	is TMode=0 & c0404=1 { }
vst3Align:			is TMode=1 & thv_c0404=0 { }
vst3Align: "@64"	is TMode=1 & thv_c0404=1 { }


vst3RnAligned: "["^VRn^vst3Align^"]" 	is VRn & vst3Align	{ export VRn; }

buildvst3DdList:							is counter=0			{ }
buildvst3DdList: Dreg						is counter=1 & Dreg		[ counter=0; regNum=regNum+regInc; ] { }
buildvst3DdList: Dreg,buildvst3DdList		is Dreg & buildvst3DdList	[ counter=counter-1; regNum=regNum+regInc; ] { }

vst3DdList: "{"^buildvst3DdList^"}"	is TMode=0 & c0811=4 & D22 & c1215 & buildvst3DdList [ regNum=(D22<<4)+c1215-1; regInc=1; counter=3; ] { } # Single
vst3DdList: "{"^buildvst3DdList^"}"	is TMode=0 & c0811=5 & D22 & c1215 & buildvst3DdList [ regNum=(D22<<4)+c1215-2; regInc=2; counter=3; ] { } # Double
vst3DdList: "{"^buildvst3DdList^"}"	is TMode=1 & thv_c0811=4 & thv_D22 & thv_c1215 & buildvst3DdList [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=3; ] { } # Single
vst3DdList: "{"^buildvst3DdList^"}"	is TMode=1 & thv_c0811=5 & thv_D22 & thv_c1215 & buildvst3DdList [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=3; ] { } # Double


:vst3.^esize0607 vst3DdList,vst3RnAligned		is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & c0003=15 )  |
                                                     ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 & thv_c0003=15 ) ) & vst3RnAligned & esize0607 & vst3DdList
	unimpl

:vst3.^esize0607 vst3DdList,vst3RnAligned^"!"	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & c0003=13 )  |
                                                     ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 & thv_c0003=13 ) ) & vst3RnAligned & esize0607 & vst3DdList
    unimpl

:vst3.^esize0607 vst3DdList,vst3RnAligned,VRm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0)  |
                                                     ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 ) ) & vst3RnAligned & esize0607 & vst3DdList & VRm
    unimpl


#######
# VST3 (single 3-element structure to one lane)
#

vst3Rn: "["^VRn^"]"	is VRn	{ export VRn; }

vst3DdList2: "{"^buildvst3DdList^"}"	is TMode=0 &  D22 & c1215 & buildvst3DdList [ regNum=(D22<<4)+c1215-1; regInc=1; counter=2; ] { } # Single
vst3DdList2: "{"^buildvst3DdList^"}"	is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildvst3DdList [ regNum=(D22<<4)+c1215-2; regInc=2; counter=2; ] { } # Double
vst3DdList2: "{"^buildvst3DdList^"}"	is TMode=1 & thv_D22 & thv_c1215 & buildvst3DdList [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=2; ] { } # Single
vst3DdList2: "{"^buildvst3DdList^"}"	is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildvst3DdList [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=2; ] { } # Double

:vst3.^esize1011 vst3DdList2,vst3Rn		is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0  & c1011<3 & c0809=2 & c0003=15 )  |
                                                     ( $(TMODE_F)  &    thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=2 & thv_c0003=15 ) ) & vst3Rn & esize1011 & vst3DdList2 
	unimpl

:vst3.^esize1011 vst3DdList2,vst3Rn^"!"	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0  & c1011<3 & c0809=2 & c0003=13 )  |
                                                     ( $(TMODE_F)  &    thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=2 & thv_c0003=13 ) ) & vst3Rn & esize1011 & vst3DdList2
    unimpl

:vst3.^esize1011 vst3DdList2,vst3Rn,VRm	is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0  & c1011<3 & c0809=2 )  |
                                                     ( $(TMODE_F)  &    thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=2 ) ) & vst3Rn & esize1011 & vst3DdList2 & VRm
    unimpl

#######
# VST4 (multiple 4-element structures)
#

vst4Align:			is TMode=0 & c0405=0	{ }
vst4Align: "@64"	is TMode=0 & c0405=1	{ }
vst4Align: "@128" 	is TMode=0 & c0405=2 	{ }
vst4Align: "@256" 	is TMode=0 & c0405=3 	{ }
vst4Align:			is TMode=1 & thv_c0405=0	{ }
vst4Align: "@64"	is TMode=1 & thv_c0405=1	{ }
vst4Align: "@128" 	is TMode=1 & thv_c0405=2 	{ }
vst4Align: "@256" 	is TMode=1 & thv_c0405=3 	{ }

vst4RnAligned: "["^VRn^vst4Align^"]" 	is VRn & vst4Align	{ export VRn; }

buildVst4DdList:							is counter=0			{ }
buildVst4DdList: Dreg						is counter=1 & Dreg		[ counter=0; regNum=regNum+regInc; ] { }
buildVst4DdList: Dreg,buildVst4DdList		is Dreg & buildVst4DdList	[ counter=counter-1; regNum=regNum+regInc; ] { }

vst4DdList: "{"^buildVst4DdList^"}"	is TMode=0 & c0808=0 & D22 & c1215 & buildVst4DdList [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single
vst4DdList: "{"^buildVst4DdList^"}"	is TMode=0 & c0808=1 & D22 & c1215 & buildVst4DdList [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double
vst4DdList: "{"^buildVst4DdList^"}"	is TMode=1 & thv_c0808=0 & thv_D22 & thv_c1215 & buildVst4DdList [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=4; ] { } # Single
vst4DdList: "{"^buildVst4DdList^"}"	is TMode=1 & thv_c0808=1 & thv_D22 & thv_c1215 & buildVst4DdList [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=4; ] { } # Double

:vst4.^esize0607 vst4DdList,vst4RnAligned		is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & c0911=0 & c0607<3 & c0003=15) |
													 ($(TMODE_F)  & thv_c2327=0x12 & thv_c2021=0 & thv_c0911=0 & thv_c0607<3 & thv_c0003=15) ) & vst4RnAligned & esize0607 & vst4DdList	unimpl

:vst4.^esize0607 vst4DdList,vst4RnAligned^"!"	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & c0911=0 & c0607<3 & c0003=13) |
													 ($(TMODE_F)  & thv_c2327=0x12 & thv_c2021=0 & thv_c0911=0 & thv_c0607<3 & thv_c0003=13) ) & vst4RnAligned & esize0607 & vst4DdList	unimpl

:vst4.^esize0607 vst4DdList,vst4RnAligned,VRm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=8 & c2021=0 & c0911=0 & c0607<3) |
													 ($(TMODE_F)  & thv_c2327=0x12 & thv_c2021=0 & thv_c0911=0 & thv_c0607<3) ) & VRm & vst4RnAligned & esize0607 & vst4DdList	unimpl

#######
# VST4 (single 4-element structure from one lane)
#

vst4Index: val	is TMode=0 & c0507 & c1011	[ val = c0507 >> c1011; ]	{ tmp:4 = val; export tmp; }
vst4Index: val	is TMode=1 & thv_c0507 & thv_c1011	[ val = thv_c0507 >> thv_c1011; ]	{ tmp:4 = val; export tmp; }


vst4DdElement2: Dreg^"["^vst4Index^"]"	is Dreg & vst4Index
{
}

vst4Align2: 		is TMode=0 & c0404=0 & (c1111=0 | c0505=0)				{ }
vst4Align2: "@32"	is TMode=0 & c1011=0 & c0404=1							{ }
vst4Align2: "@64"	is TMode=0 & ((c1011=1 & c0404=1) | (c1011=2 & c0405=1))	{ }
vst4Align2: "@128"	is TMode=0 & c1011=2 & c0405=2							{ }
vst4Align2: 		is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0)	{ }
vst4Align2: "@32"	is TMode=1 & thv_c1011=0 & thv_c0404=1					{ }
vst4Align2: "@64"	is TMode=1 & ((thv_c1011=1 & thv_c0404=1) | (thv_c1011=2 & thv_c0405=1))	{ }
vst4Align2: "@128"	is TMode=1 & thv_c1011=2 & thv_c0405=2					{ }

vst4RnAligned2: "["^VRn^vst4Align2^"]" 	is VRn & vst4Align2	{ export VRn; }

buildVst4DdList2:					is counter=0			{ }
buildVst4DdList2: vst4DdElement2	is counter=1 & vst4DdElement2		[ counter=0; regNum=regNum+regInc; ] { }
buildVst4DdList2: vst4DdElement2,buildVst4DdList2		is vst4DdElement2 & buildVst4DdList2	[ counter=counter-1; regNum=regNum+regInc; ] { }

vst4DdList2: "{"^buildVst4DdList2^"}"	is TMode=0 & D22 & c1215 & buildVst4DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single
vst4DdList2: "{"^buildVst4DdList2^"}"	is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVst4DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double
vst4DdList2: "{"^buildVst4DdList2^"}"	is TMode=1 & thv_D22 & thv_c1215 & buildVst4DdList2 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=4; ] { } # Single
vst4DdList2: "{"^buildVst4DdList2^"}"	is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildVst4DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=4; ] { } # Double

:vst4.^esize1011 vst4DdList2,vst4RnAligned2		is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=3 & c0003=15) |
													 ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3 & thv_c0003=15) ) & vst4RnAligned2 & esize1011 & vst4DdList2	unimpl

:vst4.^esize1011 vst4DdList2,vst4RnAligned2^"!"	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=3 & c0003=13) |
													 ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3 & thv_c0003=13) ) & vst4RnAligned2 & esize1011 & vst4DdList2	unimpl

:vst4.^esize1011 vst4DdList2,vst4RnAligned2,VRm	is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=3) |
													 ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3) ) & VRm & vst4RnAligned2 & esize1011 & vst4DdList2 unimpl

@endif # SIMD

@if defined(VFPv2) || defined(VFPv3) || defined(SIMD)

#######
# VSTM (A1)
#

buildVstmDdList:						is counter=0				{ }
buildVstmDdList: Dreg					is counter=1 & Dreg		[ counter=0; regNum=regNum+1; ]
{
	*mult_addr = Dreg;
	mult_addr = mult_addr + 8;
}
buildVstmDdList: Dreg,buildVstmDdList	is Dreg & buildVstmDdList	[ counter=counter-1; regNum=regNum+1; ]
{
	*mult_addr = Dreg;
	mult_addr = mult_addr + 8;
	build buildVstmDdList;
}

vstmDdList: "{"^buildVstmDdList^"}"	is TMode=0 & D22 & c1215 & c0007 & buildVstmDdList [ regNum=(D22<<4)+c1215-1; counter=c0007>>1; ] { }
vstmDdList: "{"^buildVstmDdList^"}"	is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVstmDdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=thv_c0007>>1; ] { }

:vstmia^COND vldmRn,vstmDdList	is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x19 & c2121 & c2020=0 & c0811=11 & c0000=0) | 
                                     ($(TMODE_E) & thv_c2327=0x19 & thv_c2121 & thv_c2020=0 & thv_c0811=11 & thv_c0000=0) ) & vldmRn & vstmDdList & vldmOffset & vldmUpdate
{
	mult_addr = vldmRn;
	build vstmDdList;
	build vldmUpdate;
}

:vstmdb^COND vldmRn,vstmDdList	is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1a & c2121=1 & c2020=0 & c0811=11 & c0000=0) | 
                                     ($(TMODE_E) & thv_c2327=0x1a & thv_c2121=1 & thv_c2020=0 & thv_c0811=11 & thv_c0000=0) ) & vldmRn & vstmDdList & vldmOffset
{
	local start_addr = vldmRn - vldmOffset;
	mult_addr = start_addr;
	build vstmDdList;
	vldmRn = start_addr;
}

@endif # VFPv2 | VFPv3 | SIMD

@if defined(VFPv2) || defined(VFPv3)

#######
# VSTM (A2)
#

buildVstmSdList:						is counter=0				{ }
buildVstmSdList: Sreg					is counter=1 & Sreg		[ counter=0; regNum=regNum+1; ]
{
	*mult_addr = Sreg;
	mult_addr = mult_addr + 4;
}
buildVstmSdList: Sreg,buildVstmSdList	is Sreg & buildVstmSdList	[ counter=counter-1; regNum=regNum+1; ]
{
	*mult_addr = Sreg;
	mult_addr = mult_addr + 4;
	build buildVstmSdList;
}

vstmSdList: "{"^buildVstmSdList^"}"	is TMode=0 & D22 & c1215 & c0007 & buildVstmSdList [ regNum=(c1215<<1) + D22 -1; counter=c0007; ] { }
vstmSdList: "{"^buildVstmSdList^"}"	is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVstmSdList [ regNum=(thv_c1215<<1) + thv_D22 -1; counter=thv_c0007; ] { }

:vstmia^COND vldmRn,vstmSdList	is COND & ( ( $(AMODE) & ARMcond=1 & c2327=0x19 & c2121 & c2020=0 & c0811=10 ) |
                                      ($(TMODE_E) & thv_c2327=0x19 & thv_c2121 & thv_c2020=0 & thv_c0811=10 ) ) & vldmRn & vstmSdList & vldmOffset & vldmUpdate
{
	mult_addr = vldmRn;
	build vstmSdList;
	build vldmUpdate;
}

:vstmdb^COND vldmRn,vstmSdList	is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1a & c2121=1 & c2020=0 & c0811=10 ) |
                                      ($(TMODE_E) &  thv_c2327=0x1a & thv_c2121=1 & thv_c2020=0 & thv_c0811=10) ) & vldmRn & vstmSdList & vldmOffset
{
	local start_addr = vldmRn - vldmOffset;
	mult_addr = start_addr;
	build vstmSdList;
	vldmRn = start_addr;
}


#######
# VSTR
#

:vstr^COND^".64" Dd,vldrRn	is COND & ( ($(AMODE) & ARMcond=1 & c2427=13 & c2021=0 & c0811=11) | ($(TMODE_E) &  thv_c2427=13 & thv_c2021=0 & thv_c0811=11)) & Dd & vldrRn
{
	*vldrRn = Dd;
}

:vstr^COND^".32" Sd,vldrRn	is COND & ( ($(AMODE) & ARMcond=1 & c2427=13 & c2021=0 & c0811=10) | ($(TMODE_E) &  thv_c2427=13 & thv_c2021=0 & thv_c0811=10)) & Sd & vldrRn
{
	*vldrRn = Sd;
}

@endif #  VFPv2 || VFPv3 || SIMD


#######
# VSUB
#

@if defined(SIMD)

define pcodeop FloatVectorSub;
define pcodeop VectorSubAndNarrow;

:vsub.i^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &     c0811=8 &     Q6=0 &     c0404=0) |
                                   ($(TMODE_F)  & thv_c2327=0x1e & thv_c0811=8 & thv_Q6=0 & thv_c0404=0)) & esize2021 & Dn & Dd & Dm
{
	Dd = VectorSub(Dn,Dm,esize2021);
}

:vsub.i^esize2021 Qd,Qn,Qm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=6 &    c0811=8 &     Q6=1 &     c0404=0) |
                                   ($(TMODE_F)  &thv_c2327=0x1e & thv_c0811=8 & thv_Q6=1 & thv_c0404=0) ) & esize2021 & Qm & Qn & Qd
{
	Qd = VectorSub(Qn,Qm,esize2021);
}

:vsub.f32 Dd,Dn,Dm		is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 & c2121=1 & c0811=13 & Q6=0 & c0404=0) |
                             ($(TMODE_E) & thv_c2327=0x1e & thv_c2121=1 & thv_c0811=13 & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Dd 
{
	Dd = FloatVectorSub(Dn,Dm,2:1,32:1);
}

:vsub.f32 Qd,Qn,Qm		is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 & c2121=1 & c0811=13 & Q6=1 & c0404=0) |
                             ($(TMODE_E) & thv_c2327=0x1e & thv_c2121=1 & thv_c0811=13 & thv_Q6=1 & thv_c0404=0) ) & Qn & Qd & Qm
{
	Qd = FloatVectorSub(Qn,Qm,2:1,32:1);
}

:vsubhn.i^esize2021x2 Dd,Qn,Qm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=5 & c0811=6 & Q6=0 &  c0404=0) |
                             		   ($(TMODE_E)  & thv_c2327=0x1f & thv_c0811=6 & thv_Q6=0 & thv_c0404=0)) & esize2021x2 & Dd & Qn & Qm
{
	Dd = VectorSubAndNarrow(Qn,Qm,esize2021x2);
}

:vsubl.^udt^esize2021 Qd,Dn,Dm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c2021<3  &    c0811=2 &      c0606=0 &     c0404=0) |
                                       ($(TMODE_EorF) &  thv_c2327=0x1f &    thv_c2021<3 & thv_c0811=2  & thv_c0606=0 & thv_c0404=0) ) & esize2021 & udt & Dn & Qd & Dm
{
	Qd = VectorSub(Dn,Dm,esize2021,udt);
}

:vsubw.^udt^esize2021 Qd,Qn,Dm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2527=1 & c2323=1 & c2021<3  &    c0811=3 &      c0606=0 &     c0404=0) |
                                       ($(TMODE_EorF) &  thv_c2327=0x1f &    thv_c2021<3 & thv_c0811=3  & thv_c0606=0 & thv_c0404=0) ) & esize2021 & udt & Qn & Qd & Dm
{
	Qd = VectorSub(Qn,Dm,esize2021,udt);
}

@endif # SIMD

@if defined(VFPv2) || defined(VFPv3)

:vsub^COND^".f32" Sd,Sn,Sm		is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=3 & c0811=10 & c0606=1 & c0404=0) |
                                        ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=3 & thv_c0811=10 & thv_c0606=1 & thv_c0404=0) ) & Sm & Sn & Sd
{
	build COND;
	build Sd;
	build Sm;
	build Sn;
	Sd = Sn f- Sm;
}

:vsub^COND^".f64" Dd,Dn,Dm		is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=3 & c0811=11 & c0606=1 & c0404=0 ) |
                                        ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=3 & thv_c0811=11 & thv_c0606=1 & thv_c0404=0) ) & Dm & Dn & Dd
{
	build COND;
	build Dd;
	build Dm;
	build Dn;
	Dd = Dn f- Dm;
}

@endif # VFPv2 || VFPv3

@if defined(SIMD)


#######
# VSWP
#

:vswp Dd,Dm    is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &        c2021=3 &     c1819<3 &     c1617=2 &     c0711=0 &        Q6=0 &     c0404=0 ) |
                    ( $(TMODE_F)  &       thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=0 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm
{
	tmp:8 = Dm;
	Dm = Dd;
	Dd = tmp;
}

:vswp Qd,Qm    is ( ( $(AMODE) & ARMcond=0 & cond=15 &    c2327=7 &        c2021=3 &     c1819<3 &     c1617=2 &     c0711=0 &        Q6=1 &     c0404=0 ) |
                    ( $(TMODE_F)  &       thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=0 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm
{
	tmp:16 = Qm;
	Qm = Qd;
	Qd = tmp;
}


###########
# VTBL/VTBX
#

define pcodeop VectorTableLookup;

buildVtblDdList:						    is counter=0							{ }
buildVtblDdList: Dreg					is Dreg & counter=1 		  [ counter=0; regNum=regNum+1; ] { }
buildVtblDdList: Dreg,buildVtblDdList	is Dreg & buildVtblDdList  [ counter=counter-1; regNum=regNum+1; ] 
{
	build buildVtblDdList;
}

vtblDdList: "{"^buildVtblDdList^"}"	is TMode=0 & c0809=0 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=1; ] { export 1:4; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=0 & c0809=1 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=2; ] { export 2:4; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=0 & c0809=2 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=3; ] { export 3:4; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=0 & c0809=3 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=4; ] { export 4:4; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=1 & thv_c0809=0 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=1; ] { export 1:4; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=1 & thv_c0809=1 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=2; ] { export 2:4; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=1 & thv_c0809=2 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=3; ] { export 3:4; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=1 & thv_c0809=3 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=4; ] { export 4:4; }


:vtbl.8 VRd,vtblDdList,VRm is ( ($(AMODE) &  ARMcond=0 & cond=15 & c2327=7 & c2021=3 & c1011=2 & c0606=0 & c0404=0) |
                                    ($(TMODE_F)  &      thv_c2327=0x1f & thv_c2021=3 & thv_c1011=2 & thv_c0606=0 & thv_c0404=0 ) ) & VRm & VRd & VRn & vtblDdList
{
	VRd = VectorTableLookup(VRm,VRn,vtblDdList);
}

:vtbx.8 VRd,vtblDdList,VRm is ( ($(AMODE) &  ARMcond=0 & cond=15 & c2327=7 & c2021=3 & c1011=2 & c0606=1 & c0404=0) |
                                    ($(TMODE_F)  &      thv_c2327=0x1f & thv_c2021=3 & thv_c1011=2 & thv_c0606=1 & thv_c0404=0 ) ) & VRm & VRd & VRn & vtblDdList
{
	VRd = VectorTableLookup(VRm,VRn,vtblDdList);
}


######
# VTST
#

define pcodeop VectorTest;

:vtst.^esize2021 Qd, Qn, Qm   is ( ($(AMODE) & ARMcond=0 & cond=15 &  c2327=4 &        c0811=8 &     c0606=1 &     c0404=1) |
                                   ($(TMODE_E) &      thv_c2327=0x1e & thv_c0811=8 & thv_c0606=1 & thv_c0404=1) ) & esize2021 & Qm & Qn & Qd
{
   Qd = VectorTest(Qn, Qm);
}

:vtst.^esize2021 Dd, Dn, Dm   is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=4 &        c0811=8 &     c0606=0 &     c0404=1) |
                                   ($(TMODE_E) &     thv_c2327=0x1e & thv_c0811=8 & thv_c0606=0 & thv_c0404=1) ) & esize2021 & Dm & Dn & Dd
{
   Dd = VectorTest(Dn, Dm);
}

define pcodeop VectorTranspose;

:vtrn^"."^esize1819 Dd,Dm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &        c2021=3 &     c1617=2 &     c0811=0 &     c0707=1 &     Q6=0 &     c0404=0) |
                                             ($(TMODE_F)  & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=2 & thv_c0811=0 & thv_c0707=1 & thv_Q6=0 & thv_c0404=0)) & esize1819 & Dd & Dm
{
	Dd = VectorTranspose(Dm,esize1819);
}

:vtrn^"."^esize1819 Qd,Qm    is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=7 &        c2021=3 &     c1617=2 &    c0811=0 &     c0707=1  &     Q6=1 &     c0404=0) |
                                   ($(TMODE_F)  & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=2 & thv_c0811=0 & thv_c0707=1 &  thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd
{
	Qd = VectorTranspose(Qm,esize1819);
}

#####
# V[SU]DOT
define pcodeop VectorSignedDotProduct;
define pcodeop VectorUnsignedDotProduct;
define pcodeop VectorSignedUnsignedDotProduct;
define pcodeop VectorUnsignedSignedDotProduct;

:vsdot.s8 Dd,Dn,Dm0^Mindex  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1c &     c2021=2 &     c0811=0xd &     c0606=0 &     c0404=0) |
                               ($(TMODE_F) &                   thv_c2327=0x1c & thv_c2021=2 & thv_c0811=0xd & thv_c0606=0 & thv_c0404=0) ) & Dm0 & Mindex & Dn & Dd
{
	Dd = VectorSignedDotProduct(Dn,Dm0,Mindex);
}

:vsdot.s8 Qd,Qn,Dm0^Mindex  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1c &     c2021=2 &     c0811=0xd &     c0606=1 &     c0404=0) |
                               ($(TMODE_F) &                   thv_c2327=0x1c & thv_c2021=2 & thv_c0811=0xd & thv_c0606=1 & thv_c0404=0) ) & Dm0 & Mindex & Qn & Qd
{
	Qd = VectorSignedDotProduct(Qn,Dm0,Mindex);
}

:vsdot.s8 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=2 &     c0811=0xd &     c0606=0 &     c0404=0) |
                       ($(TMODE_F) &                   thv_c2327=0x18 & thv_c2021=2 & thv_c0811=0xd & thv_c0606=0 & thv_c0404=0) ) & Dm & Dn & Dd
{
	Dd = VectorSignedDotProduct(Dn,Dm);
}

:vsdot.s8 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=2 &     c0811=0xd &     c0606=1 &     c0404=0) |
                       ($(TMODE_F) &                   thv_c2327=0x18 & thv_c2021=2 & thv_c0811=0xd & thv_c0606=1 & thv_c0404=0) ) & Qm & Qn & Qd
{
	Qd = VectorSignedDotProduct(Qn,Qm);
}

:vudot.u8 Dd,Dn,Dm0^Mindex  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1c &     c2021=2 &     c0811=0xd &     c0606=0 &     c0404=1) |
                               ($(TMODE_F) &                   thv_c2327=0x1c & thv_c2021=2 & thv_c0811=0xd & thv_c0606=0 & thv_c0404=1) ) & Dm0 & Mindex & Dn & Dd
{
	Dd = VectorUnsignedDotProduct(Dn,Dm0,Mindex);
}

:vudot.u8 Qd,Qn,Dm0^Mindex  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1c &     c2021=2 &     c0811=0xd &     c0606=1 &     c0404=1) |
                               ($(TMODE_F) &                   thv_c2327=0x1c & thv_c2021=2 & thv_c0811=0xd & thv_c0606=1 & thv_c0404=1) ) & Dm0 & Mindex & Qn & Qd
{
	Qd = VectorUnsignedDotProduct(Qn,Dm0,Mindex);
}

:vudot.u8 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=2 &     c0811=0xd &     c0606=0 &     c0404=1) |
                       ($(TMODE_F) &                   thv_c2327=0x18 & thv_c2021=2 & thv_c0811=0xd & thv_c0606=0 & thv_c0404=1) ) & Dm & Dn & Dd
{
	Dd = VectorUnsignedDotProduct(Dn,Dm);
}

:vudot.u8 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x18 &     c2021=2 &     c0811=0xd &     c0606=1 &     c0404=1) |
                       ($(TMODE_F) &                   thv_c2327=0x18 & thv_c2021=2 & thv_c0811=0xd & thv_c0606=1 & thv_c0404=1) ) & Qm & Qn & Qd
{
	Qd = VectorUnsignedDotProduct(Qn,Qm);
}

:vsudot.u8 Dd,Dn,Dm0^Mindex  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c2021=0 &     c0811=0xd &     c0606=0 &     c0404=1) |
                                ($(TMODE_F) &                   thv_c2327=0x1d & thv_c2021=0 & thv_c0811=0xd & thv_c0606=0 & thv_c0404=1) ) & Dm0 & Mindex & Dn & Dd
{
	Dd = VectorSignedUnsignedDotProduct(Dn,Dm0,Mindex);
}

:vsudot.u8 Qd,Qn,Dm0^Mindex  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c2021=0 &     c0811=0xd &     c0606=1 &     c0404=1) |
                                ($(TMODE_F) &                   thv_c2327=0x1d & thv_c2021=0 & thv_c0811=0xd & thv_c0606=1 & thv_c0404=1) ) & Dm0 & Mindex & Qn & Qd
{
	Qd = VectorSignedUnsignedDotProduct(Qn,Dm0,Mindex);
}

:vusdot.u8 Dd,Dn,Dm0^Mindex  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c2021=0 &     c0811=0xd &     c0606=0 &     c0404=0) |
                                ($(TMODE_F) &                   thv_c2327=0x1d & thv_c2021=0 & thv_c0811=0xd & thv_c0606=0 & thv_c0404=0) ) & Dm0 & Mindex & Dn & Dd
{
	Dd = VectorUnsignedSignedDotProduct(Dn,Dm0,Mindex);
}

:vusdot.u8 Qd,Qn,Dm0^Mindex  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x1d &     c2021=0 &     c0811=0xd &     c0606=1 &     c0404=0) |
                                ($(TMODE_F) &                   thv_c2327=0x1d & thv_c2021=0 & thv_c0811=0xd & thv_c0606=1 & thv_c0404=0) ) & Dm0 & Mindex & Qn & Qd
{
	Qd = VectorUnsignedSignedDotProduct(Qn,Dm0,Mindex);
}

:vusdot.u8 Dd,Dn,Dm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x19 &     c2021=2 &     c0811=0xd &     c0606=0 &     c0404=0) |
                        ($(TMODE_F) &                   thv_c2327=0x19 & thv_c2021=2 & thv_c0811=0xd & thv_c0606=0 & thv_c0404=0) ) & Dm & Dn & Dd
{
	Dd = VectorUnsignedSignedDotProduct(Dn,Dm);
}

:vusdot.u8 Qd,Qn,Qm  is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=0x19 &     c2021=2 &     c0811=0xd &     c0606=1 &     c0404=0) |
                        ($(TMODE_F) &                   thv_c2327=0x19 & thv_c2021=2 & thv_c0811=0xd & thv_c0606=1 & thv_c0404=0) ) & Qm & Qn & Qd
{
	Qd = VectorUnsignedSignedDotProduct(Qn,Qm);
}

#######
# VUZP
#

define pcodeop VectorUnzip;

:vuzp^esize1819 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=2 &     c0711=2 &        Q6=0 &     c0404=0 ) |
                          ( $(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=2 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm & esize1819
{
	Dd = VectorUnzip(Dm,esize1819);
}

:vuzp^esize1819 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=2 &     c0711=2 &        Q6=1 &     c0404=0 ) |
                          ( $(TMODE_F) &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=2 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm & esize1819
{
	Qd = VectorUnzip(Qm,esize1819);
}


#######
# VZIP
#

define pcodeop VectorZip;

:vzip^esize1819 Dd,Dm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=2 &     c0711=3 &        Q6=0 &     c0404=0 ) |
                          ($(TMODE_F)  &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=3 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm & esize1819
{
	Dd = VectorZip(Dm,esize1819);
}

:vzip^esize1819 Qd,Qm  is ( ( $(AMODE) & ARMcond=0 & cond=15 & c2327=7 &     c2021=3 &     c1819<3 &     c1617=2 &     c0711=3 &        Q6=1 &     c0404=0 ) |
                           ($(TMODE_F)  &   thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=3 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm & esize1819
{
	Qd = VectorZip(Qm,esize1819);
}


@endif # SIMD

