# 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 				{ tmp:8 = 0; export tmp; }

@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 ] [ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 ];
attach variables [ thv_Dd_2 ] [ d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ ];
attach variables [ thv_Dd_3 ] [ d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ ];
attach variables [ thv_Dd_4 ] [ d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ ];
attach variables [ thv_Dd_5 ] [ d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ ];
attach variables [ thv_Dd_6 ] [ d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ ];
attach variables [ thv_Dd_7 ] [ d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ ];
attach variables [ thv_Dd_8 ] [ d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_9 ] [ d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_10 ] [ d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_11 ] [ d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_12 ] [ d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_13 ] [ d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_14 ] [ d13 d14 d15 _ _ _ _ _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_Dd_15 ] [ d14 d15 _ _ _ _ _ _ _ _ _ _ _ _ _ _ ];
attach variables [ thv_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; }

@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) || defined(VFPv2)
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; }
@endif
@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; }
@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			{ tmp:1 = 0; export tmp; }
udt: "u"	is TMode=0 & c2424=1			{ tmp:1 = 1; export tmp; }
udt: "s"	is TMode=1 & thv_c2828=0		{ tmp:1 = 0; export tmp; }
udt: "u"	is TMode=1 & thv_c2828=1		{ tmp:1 = 1; export tmp; }


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

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

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

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

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

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

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

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

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

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) {
	val:8 = zext(bytes);
	val = val | (val << 8);
	val = val | (val << 16);
	dest = val | (val << 32);
}

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

macro replicate4to8(bytes, dest) {
	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)

# TODO: watch out for c2021=3

:vaba.^udt^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & 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) & 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) & 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) & 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) & 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) & 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.f32 Dd,Dn,Dm    is ( ( $(AMODE) & cond=15 &  c2327=6 &        c2021=2 &     c0811=13 &        Q6=0 &     c0404=0 ) |
                          ($(TMODE_F)  &       thv_c2327=0x1e & thv_c2021=2 & thv_c0811=13 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm & Dn
{
	Dd = FloatVectorAbsoluteDifference(Dn,Dm,2:1,32:1);
}

:vabd.f32 Qd,Qn,Qm    is ( ( $(AMODE) & cond=15 &   c2327=6 &        c2021=2 &     c0811=13 &        Q6=1 &     c0404=0 ) | 
                           ($(TMODE_F)  &       thv_c2327=0x1e & thv_c2021=2 & thv_c0811=13 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm & Qn
{
	Qd = FloatVectorAbsoluteDifference(Qn,Qm,2:1,32:1);
}

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

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

@endif # SIMD

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

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

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

@endif # VFPv2 || VFPv3

define pcodeop FloatCompareGE;
define pcodeop FloatCompareGT;
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;

@if defined(SIMD)

:vacge.f32 Dd,Dn,Dm		is $(AMODE) & cond=15 & c2327=6 & c2021=0 & Dn & Dd & c0811=14 & Q6=0 & c0404=1 & Dm
{
	Dd = FloatCompareGE(Dn,Dm,2:1,32:1);
}

:vacge.f32 Qd,Qn,Qm		is $(AMODE) & cond=15 & c2327=6 & c2021=0 & Qn & Qd & c0811=14 & Q6=1 & c0404=1 & Qm
{
	Qd = FloatCompareGE(Qn,Qm,2:1,32:1);
}

:vacgt.f32 Dd,Dn,Dm		is $(AMODE) & cond=15 & c2327=6 & c2021=2 & Dn & Dd & c0811=14 & Q6=0 & c0404=1 & Dm
{
	Dd = FloatCompareGT(Dn,Dm,2:1,32:1);
}

:vacgt.f32 Qd,Qn,Qm		is $(AMODE) & cond=15 & c2327=6 & c2021=2 & Qn & Qd & c0811=14 & Q6=1 & c0404=1 & Qm
{
	Qd = FloatCompareGT(Qn,Qm,2:1,32:1);
}

:vadd.i^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & 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) & 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.f32 Dd,Dn,Dm		is ( ($(AMODE) & cond=15 & c2327=4 & c2021=0 & c0811=13 & Q6=0 & c0404=0) |
                             ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=13 & thv_Q6=0 & thv_c0404=0) ) & Dm& Dn & Dd 
{
	Dd = FloatVectorAdd(Dn,Dm,2:1,32:1);
}

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


:vpadd.i^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & 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) & 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^fesize2021 Dd,Dn,Dm		is ( ($(AMODE) & 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) ) & fesize2021 & Dm& Dn & Dd 
{
	Dd = FloatVectorPairwiseAdd(Dn,Dm,fesize2021:1);
}


:vpmax.^udt^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & 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^fesize2021 Dd,Dn,Dm		is ( ($(AMODE) & 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) ) & fesize2021 & Dm & Dn & Dd 
{
	Dd = FloatVectorPairwiseMax(Dn,Dm,fesize2021:1);
}

:vpmin.^udt^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & 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^fesize2021 Dd,Dn,Dm		is ( ($(AMODE) & 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) ) & fesize2021 & Dm & Dn & Dd 
{
	Dd = FloatVectorPairwiseMin(Dn,Dm,fesize2021:1);
}

:vpadal.^udt7^esize1819 Dd,Dm    is ( ($(AMODE) & 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) & 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) & 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) & 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^".f32" Sd,Sn,Sm		is ( ( $(AMODE) & COND & 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) ) & Sm & Sd & Sn
{
	build COND;
	build Sd;
	build Sm;
	build Sn;
	Sd = Sn f+ Sm;
}

:vadd^COND^".f64" Dd,Dn,Dm		is ( ( $(AMODE) & COND & 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) )  & 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;

@if defined(SIMD)

:vaddhn.i^esize2021x2 Dd,Qn,Qm    is ( ($(AMODE) & cond=15 & c2327=5 &     c2021<3 &     c0811=4 &     c0606=0 &     c0404=0) |
                                       ($(TMODE_F)  &    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) & 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) & 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) & 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) & 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.i16 Dd,simdExpImm_8	is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c1921=0 &     c1011<3 &     c0808=1 &     c0407=3 ) |
                                 ($(TMODE_EorF) &  thv_c2327=0x1f &    thv_c1921=0 & thv_c1011<3 & thv_c0808=1 & thv_c0407=3) ) & Dd & simdExpImm_8
{
	Dd = Dd & ~simdExpImm_8;
}

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

:vbic Dd,Dn,Dm	is ( ($(AMODE) & 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) & 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) & 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) & 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) & 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) & 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) & 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) & 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);
}

:vceq.i^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & 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) & 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.f32 Dd,Dn,Dm    is ( ($(AMODE) & cond=15 & c2327=4 &        c2021=0 &     c0811=14 &     Q6=0 &     c0404=0) |
                           ($(TMODE_E) &     thv_c2327=0x1e & thv_c2021=0 & thv_c0811=14 & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Dd
{
	Dd = FloatVectorCompareEqual(Dn,Dm,2:1,32:1);
}

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

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

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

:vcge.^udt^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & 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) & 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.f32 Dd,Dn,Dm    is ( ($(AMODE) & cond=15 & c2327=6 &        c2021=0 &     c0811=14 &     Q6=0 &     c0404=0) |
                           ($(TMODE_F)  &    thv_c2327=0x1e & thv_c2021=0 & thv_c0811=14 & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Dd
{
	Dd = FloatVectorCompareGreaterThanOrEqual(Dn,Dm,2:1,32:1);
}

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

:vcge.s^esize1819 Dd,Dm,zero    is ( ($(AMODE) & 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) & 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.f32 Dd,Dm,zero    is ( ($(AMODE) & cond=15 & c2327=7 &        c2021=3 &     c1819<3 &     c1617=1 &     c0711=9 &     Q6=0 &     c0404=0) |
                             ($(TMODE_F)  &    thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=9 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero
{
	Dd = FloatVectorCompareGreaterThanOrEqual(Dm,zero,2:1,32:1);
}

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

:vcgt.^udt^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & 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) & 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.f32 Dd,Dn,Dm    is  ( ($(AMODE) & cond=15 & c2327=6 & c2021=2 & c0811=14 & Q6=0 & c0404=0) |
                            ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=14 & thv_Q6=0 & thv_c0404=0) )  &  Dm & Dn & Dd
{
	Dd = FloatVectorCompareGreaterThan(Dn,Dm,2:1,32:1);
}

:vcgt.f32 Qd,Qn,Qm    is ( ($(AMODE) & cond=15 & c2327=6 & c2021=2 & c0811=14 & Q6=1 & c0404=0) |
                            ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=14 & thv_Q6=1 & thv_c0404=0) )  &  Qm & Qn & Qd
{
	Qd = FloatVectorCompareGreaterThan(Qn,Qm,2:1,32:1);
}

:vcgt.i^esize1819 Dd,Dm,zero    is ( ($(AMODE) & 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) & 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.f32 Dd,Dm,zero    is ( ($(AMODE) & cond=15 &     c2327=7 &        c2021=3 &     c1819<3 &     c1617=1 &     c0711=8 &     Q6=0 &     c0404=0) |
                             ($(TMODE_F)  &        thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=8 & thv_Q6=0 & thv_c0404=0 ) ) & esize1819 & Dd & Dm & zero
{
	Dd = FloatVectorCompareGreaterThan(Dm,zero,2:1,32:1);
}

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

:vcle.s^esize1819 Dd,Dm,zero    is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & esize1819 & c1617=1 & Dd & c0711=3 & Q6=0 & c0404=0 & Dm & zero
{
	Dd = VectorCompareGreaterThanOrEqual(zero,Dm,esize1819);
}

:vcle.s^esize1819 Qd,Qm,zero    is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & esize1819 & c1617=1 & Qd & c0711=3 & Q6=1 & c0404=0 & Qm & zero
{
	Qd = VectorCompareGreaterThanOrEqual(zero,Qm,esize1819);
}

:vcle.f32 Dd,Dm,zero    is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & esize1819 & c1617=1 & Dd & c0711=11 & Q6=0 & c0404=0 & Dm & zero
{
	Dd = FloatVectorCompareGreaterThanOrEqual(zero,Dm,2:1,32:1);
}

:vcle.f32 Qd,Qm,zero    is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & esize1819 & c1617=1 & Qd & c0711=11 & Q6=1 & c0404=0 & Qm & zero
{
	Qd = FloatVectorCompareGreaterThanOrEqual(zero,Qm,2:1,32:1);
}

:vcls.s^esize1819 Dd,Dm    is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & esize1819 & c1617=0 & Dd & c0711=8 & Q6=0 & c0404=0 & Dm
{
	Dd = VectorCountLeadingSignBits(Dm,esize1819);
}

:vcls.s^esize1819 Qd,Qm    is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & esize1819 & c1617=0 & Qd & c0711=8 & Q6=1 & c0404=0 & Qm
{
	Qd = VectorCountLeadingSignBits(Qm,esize1819);
}

:vclt.s^esize1819 Dd,Dm,zero    is ( ( $(AMODE) & 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) & 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.f32 Dd,Dm,zero    is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=12 & Q6=0 & c0404=0) |
                            ( $(TMODE_F)  &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=12 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero
{
	Dd = FloatVectorCompareGreaterThan(zero,Dm,2:1,32:1);
}

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

:vclz.i^esize1819 Dd,Dm    is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & esize1819 & c1617=0 & Dd & c0711=9 & Q6=0 & c0404=0 & Dm
{
	Dd = VectorCountLeadingZeros(Dm,esize1819);
}

:vclz.i^esize1819 Qd,Qm    is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & esize1819 & c1617=0 & Qd & c0711=9 & Q6=1 & c0404=0 & Qm
{
	Qd = VectorCountLeadingZeros(Qm,esize1819);
}

@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	{ tmp:1 = 1; export tmp; }
nanx: 		is c0707=0	{ tmp:1 = 0; export tmp; }

:vcmp^nanx^COND^".f32" Sd,Sm		is ( ( $(AMODE) & COND & 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) ) & Sd & nanx & Sm
{
	build COND;
	build Sd;
	build Sm;

	FloatVectorCompare(Sd,Sm,nanx);
}

:vcmp^nanx^COND^".f64" Dd,Dm		is ( ( $(AMODE) & COND & 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) ) & Dd & nanx & Dm
{
	build COND;
	build Dd;
	build Dm;
	FloatVectorCompare(Dd,Dm,nanx);
}

:vcmp^nanx^COND^".f32" Sd,zero		is ( ( $(AMODE) & COND & 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 ) ) & Sd & nanx & zero
{
	build COND;
	build Sd;
	local Zero:4 = 0;
	FloatVectorCompare(Sd,Zero,nanx);
}

:vcmp^nanx^COND^".f64" Dd,zero		is ( ( $(AMODE) & COND & 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 ) ) & Dd & nanx & zero
{
	build COND;
	build Dd;
	local Zero:8 = 0;
	FloatVectorCompare(Dd,Zero,nanx);
}

@endif # VFPv2 || VFPv3

define pcodeop VectorCountOneBits;

@if defined(SIMD)
@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

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

:vcnt.8 Dd,Dm   is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819=0 & c1617=0 & Dd & c0711=10 & Q6=0 & c0404=0 & Dm
{
	Dd = VectorCountOneBits(Dm,8:1,8:1);
}

:vcnt.8 Qd,Qm   is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819=0 & c1617=0 & Qd & c0711=10 & Q6=1 & c0404=0 & Qm
{
	Qd = VectorCountOneBits(Qm,8:1,8:1);
}

@ifndef VERSION_8
:vcvt.s32.f32 Dd,Dm   is ( ( $(AMODE) & 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) & 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) & 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) & 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.s32.f32 Qd,Qm   is ( ( $(AMODE) & 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,3:1);
}

:vcvt.u32.f32 Qd,Qm   is ( ( $(AMODE) & 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,3:1);
}

:vcvt.f32.s32 Qd,Qm   is ( ( $(AMODE) & 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,0:1);
}

:vcvt.f32.u32 Qd,Qm   is ( ( $(AMODE) & 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,0: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		{ tmp:1 = 3; export tmp; } # Round towards zero
roundMode: "r"	is TMode=1 & thv_c0707=0	{ tmp:1 = $(FPSCR_RMODE); export tmp; }
roundMode: 		is TMode=1 & thv_c0707=1	{ tmp:1 = 3; export tmp; } # Round towards zero

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

:vcvt^roundMode^COND^".s32.f64" Sd,Dm	is COND & ( ($(AMODE) & 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) ) & Sd & roundMode & Dm
{
	build COND;
	build Sd;
	build Dm;
	build roundMode;
	Sd = VectorFloatToSigned(Dm,roundMode);
}

:vcvt^roundMode^COND^".u32.f32" Sd,Sm	is COND & ( ($(AMODE) & 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) ) & roundMode & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	build roundMode;
	Sd = VectorFloatToUnsigned(Sm,roundMode);
}

:vcvt^roundMode^COND^".u32.f64" Sd,Dm	is COND & ( ($(AMODE) & 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)) & roundMode& Sd & Dm
{
	build COND;
	build Sd;
	build Dm;
	build roundMode;
	Sd = VectorFloatToUnsigned(Dm,roundMode);
}

:vcvt^COND^".f32.s32" Sd,Sm	is  COND & ( ($(AMODE) & 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) ) & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	mode:1 = $(FPSCR_RMODE);
	Sd = VectorSignedToFloat(Sm,mode);
}

:vcvt^COND^".f64.s32" Dd,Sm	is COND & ( ($(AMODE) & 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) ) & Dd & Sm
{
	build COND;
	build Dd;
	build Sm;
	mode:1 = $(FPSCR_RMODE);
	Dd = VectorSignedToFloat(Sm,mode);
}

:vcvt^COND^".f32.u32" Sd,Sm	is COND & ( ($(AMODE) & 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) ) & Sd  & Sm
{
	build COND;
	build Sd;
	build Sm;
	mode:1 = $(FPSCR_RMODE);
	Sd = VectorUnsignedToFloat(Sm,mode);
}

:vcvt^COND^".f64.u32" Dd,Sm	is COND & ( ($(AMODE) & 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) )& 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 c1620 [ val = 32 - c1620; ] { tmp:1 = val; export tmp; }

:vcvt.s32.f32 Dd,Dm,fbits	is $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2121=1 & fbits & Dd & c0911=7 & c0808=1 & c0707=0 & Q6=0 & c0404=1 & Dm
{
	Dd = VectorFloatToSignedFixed(Dm,fbits);
}

:vcvt.u32.f32 Dd,Dm,fbits	is $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2121=1 & fbits & Dd & c0911=7 & c0808=1 & c0707=0 & Q6=0 & c0404=1 & Dm
{
	Dd = VectorFloatToUnsignedFixed(Dm,fbits);
}

:vcvt.f32.s32 Dd,Dm,fbits	is $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2121=1 & fbits & Dd & c0911=7 & c0808=0 & c0707=0 & Q6=0 & c0404=1 & Dm
{
	Dd = VectorSignedFixedToFloat(Dm,fbits);
}

:vcvt.f32.u32 Dd,Dm,fbits	is $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2121=1 & fbits & Dd & c0911=7 & c0808=0 & c0707=0 & Q6=0 & c0404=1 & Dm
{
	Dd = VectorUnsignedFixedToFloat(Dm,fbits);
}

:vcvt.s32.f32 Qd,Dm,fbits	is $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2121=1 & fbits & Qd & c0911=7 & c0808=1 & c0707=0 & Q6=1 & c0404=1 & Dm
{
	Qd = VectorFloatToSignedFixed(Dm,fbits);
}

:vcvt.u32.f32 Qd,Dm,fbits	is $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2121=1 & fbits & Qd & c0911=7 & c0808=1 & c0707=0 & Q6=1 & c0404=1 & Dm
{
	Qd = VectorFloatToUnsignedFixed(Dm,fbits);
}

:vcvt.f32.s32 Qd,Dm,fbits	is $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2121=1 & fbits & Qd & c0911=7 & c0808=0 & c0707=0 & Q6=1 & c0404=1 & Dm
{
	Qd = VectorSignedFixedToFloat(Dm,fbits);
}

:vcvt.f32.u32 Qd,Dm,fbits	is $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2121=1 & fbits & Qd & c0911=7 & c0808=0 & c0707=0 & Q6=1 & c0404=1 & Dm
{
	Qd = VectorUnsignedFixedToFloat(Dm,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 - ((c0505 << 4) + c0003); ] { tmp:1 = val; export tmp; }
fbits32: "#"^val	is TMode=0 & c0505 & c0003	[ val = 32 - ((c0505 << 4) + c0003); ] { tmp:1 = val; export tmp; }
fbits16: "#"^val	is TMode=1 & thv_c0505 & thv_c0003	[ val = 16 - ((thv_c0505 << 4) + thv_c0003); ] { tmp:1 = val; export tmp; }
fbits32: "#"^val	is TMode=1 & thv_c0505 & thv_c0003	[ val = 32 - ((thv_c0505 << 4) + thv_c0003); ] { tmp:1 = val; export tmp; }

:vcvt^COND^".s16.f32" Sd,Sd2,fbits16 is COND & ( ($(AMODE) & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=0 & c0911=5 & c0808=0 & c0707=0 & c0606=1 & c0404=0) | 
                                                 ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c0911=5 & thv_c0808=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0)) & 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 COND & ( ($(AMODE) & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=1 & c0911=5 & c0808=0 & c0707=0 & c0606=1 & c0404=0) | 
                                                  ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c0911=5 & thv_c0808=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & 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 COND & ( ($(AMODE) & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=0 & c0911=5 & c0808=0 & c0707=1 & c0606=1 & c0404=0) | 
                                                 ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c0911=5 & thv_c0808=0 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & 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 COND & ( ($(AMODE) & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=1 & c0911=5 & c0808=0 & c0707=1 & c0606=1 & c0404=0) |
                                                 ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c0911=5 & thv_c0808=0 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & 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 COND & ( ($(AMODE) & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=0 & c0911=5 & c0808=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_c0911=5 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & 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 COND & ( ($(AMODE) & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=1 & c0911=5 & c0808=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_c0911=5 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & 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 COND & ( ($(AMODE) & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=0 & c0911=5 & c0808=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_c0911=5 & thv_c0808=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & 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 COND & ( ($(AMODE) & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=1 & c0911=5 & c0808=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_c0911=5 & thv_c0808=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & Dd & Dd2 & fbits32
{
	build COND;
	build Dd;
	build Dd2;
	build fbits32;
	Dd = VectorFloatToUnsignedFixed(Dd2,32:1,fbits32);
}

:vcvt^COND^".f32.s16" Sd,Sd2,fbits16 is $(AMODE) & COND & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=0 & Sd & Sd2 & c0911=5 & c0808=0 & c0707=0 & c0606=1 & c0404=0 & fbits16
{
	build COND;
	build Sd;
	build Sd2;
	build fbits16;
	Sd = VectorSignedFixedToFloat(Sd2,32:1,fbits16);
}

:vcvt^COND^".f32.u16" Sd,Sd2,fbits16 is $(AMODE) & COND & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=1 & Sd & Sd2 & c0911=5 & c0808=0 & c0707=0 & c0606=1 & c0404=0 & fbits16
{
	build COND;
	build Sd;
	build Sd2;
	build fbits16;
	Sd = VectorUnsignedFixedToFloat(Sd2,32:1,fbits16);
}

:vcvt^COND^".f32.s32" Sd,Sd2,fbits32 is $(AMODE) & COND & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=0 & Sd & Sd2 & c0911=5 & c0808=0 & c0707=1 & c0606=1 & c0404=0 & fbits32
{
	build COND;
	build Sd;
	build Sd2;
	build fbits32;
	Sd = VectorSignedFixedToFloat(Sd2,32:1,fbits32);
}

:vcvt^COND^".f32.u32" Sd,Sd2,fbits32 is $(AMODE) & COND & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=1 & Sd & Sd2 & c0911=5 & c0808=0 & c0707=1 & c0606=1 & c0404=0 & fbits32
{
	build COND;
	build Sd;
	build Sd2;
	build fbits32;
	Sd = VectorUnsignedFixedToFloat(Sd2,32:1,fbits32);
}

:vcvt^COND^".f64.s16" Dd,Dd2,fbits16 is $(AMODE) & COND & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=0 & Dd & Dd2 & c0911=5 & c0808=1 & c0707=0 & c0606=1 & c0404=0 & fbits16
{
	build COND;
	build Dd;
	build Dd2;
	build fbits16;
	Dd = VectorSignedFixedToFloat(Dd2,64:1,fbits16);
}

:vcvt^COND^".f64.u16" Dd,Dd2,fbits16 is $(AMODE) & COND & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=1 & Dd & Dd2 & c0911=5 & c0808=1 & c0707=0 & c0606=1 & c0404=0 & fbits16
{
	build COND;
	build Dd;
	build Dd2;
	build fbits16;
	Dd = VectorUnsignedFixedToFloat(Dd2,64:1,fbits16);
}

:vcvt^COND^".f64.s32" Dd,Dd2,fbits32 is $(AMODE) & COND & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=0 & Dd & Dd2 & c0911=5 & c0808=1 & c0707=1 & c0606=1 & c0404=0 & fbits32
{
	build COND;
	build Dd;
	build Dd2;
	build fbits32;
	Dd = VectorSignedFixedToFloat(Dd2,64:1,fbits32);
}

:vcvt^COND^".f64.u32" Dd,Dd2,fbits32 is $(AMODE) & COND & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=1 & Dd & Dd2 & c0911=5 & c0808=1 & c0707=1 & c0606=1 & c0404=0 & fbits32
{
	build COND;
	build Dd;
	build Dd2;
	build fbits32;
	Dd = VectorUnsignedFixedToFloat(Dd2,64: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) & COND & c2327=0x1d & c1621=0x37 & Sd & c0911=5 & c0808=1 & c0607=3 & c0404=0 & Dm
{
	build COND;
	build Sd;
	build Dm;
	Sd = float2float(Dm);
}

:vcvt^COND^".f64.f32" Dd,Sm		is $(AMODE) & COND & c2327=0x1d & c1621=0x37 & Dd & c0911=5 & c0808=0 & c0607=3 & c0404=0 & Sm
{
	build COND;
	build Dd;
	build Sm;
	Dd = float2float(Sm);
}

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

@if defined(SIMD)

@ifndef VERSION_8
define pcodeop VectorFloatSingleToHalf;
define pcodeop VectorFloatHalfToSingle;

#######
# VCVT (between half-precision and single-precision)
#
:vcvt.f16.f32 Dd,Qm		is ( ( $(AMODE) & 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) & 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);
}

@endif # ! VERSION_8
@endif # SIMD

@if defined(VFPv3)

@ifndef VERSION_8
:vcvtb^COND^".f32.f16" Sd,Sm	is $(AMODE) & COND & c2327=0x1d & c1621=0x32 & Sd & c0611=0x29 & c0404=0 & Sm
{
	build COND;
	build Sd;
	build Sm;
	Sd = float2float(Sm:2);
}

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

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

:vcvtt^COND^".f16.f32" Sd,Sm	is $(AMODE) & COND & c2327=0x1d & c1621=0x33 & Sd & c0611=0x2b & c0404=0 & Sm
{
	build COND;
	build Sd;
	build Sm;
	w:2 = float2float(Sm);
	Sd[16,16] = w;
}
@endif # ! VERSION_8

@endif # VFPv3

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

:vdiv^COND^".f32" Sd,Sn,Sm	is ( ($(AMODE) & COND & 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 ) ) & Sn & Sd & Sm
{
	build COND;
	build Sd;
	build Sm;
	build Sn;
	Sd = Sn f/ Sm;
}

:vdiv^COND^".f64" Dd,Dn,Dm	is ( ( $(AMODE) & COND & 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 ) ) & 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;

@if defined(SIMD)

#######
# 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) & 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) & 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) & COND & c2327=0x1d & c2121=0 & c2020=0 & c0811=11 & c0606=0 & c0004=0x10) |
                                  ($(TMODE_E)  & thv_c2327=0x1d & thv_c2021=0 & thv_c0811=11 & thv_c0606=0 & thv_c0004=0x10 ) ) & Dn & vdupSize2 & vdupRd8
{
	build COND;
	build vdupRd8;
	build Dn;
	Dn = vdupRd8;
}

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

:veor Dd,Dn,Dm	is ( ($(AMODE) & 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) & 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) & 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) & 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;
}

:vhadd.^udt^esize2021 Dd,Dn,Dm    is ( ( $(AMODE) & 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) & 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);
}

:vrhadd.^udt^esize2021 Dd,Dn,Dm    is (($(AMODE) & 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) & 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) & cond=15 & c2527=1 & udt & c2323=0 & c2021<3 & esize2021 & Dn & Dd & c0811=2 & Q6=0 & c0404=0 & Dm
{
	Dd = VectorHalvingSubtract(Dn,Dm,esize2021,udt);
}

:vhsub.^udt^esize2021 Qd,Qn,Qm    is ( ($(AMODE) & 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);
}

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

vld1Dd: Dreg		is Dreg & ((TMode=0 & c0607=0) | (TMode=1 & thv_c0607=0))
{
	replicate1to8(*:1 mult_addr, Dreg);
}
vld1Dd: Dreg		is Dreg & ((TMode=0 & c0607=1) | (TMode=1 & thv_c0607=1))
{
	replicate2to8(*:2 mult_addr, Dreg);
}
vld1Dd: Dreg		is Dreg & ((TMode=0 & c0607=2) | (TMode=1 & thv_c0607=2))
{
	replicate4to8(*:4 mult_addr, Dreg);
}
vld1Dd: Dreg		is Dreg & ((TMode=0 & c0607=3) | (TMode=1 & thv_c0607=3))
{
	Dreg = *:8 mult_addr;
}



buildVld1DdList:						is counter=0							{ }
buildVld1DdList: vld1Dd					is vld1Dd & counter=1 					[ counter=0; regNum=regNum+1; ] { }
buildVld1DdList: vld1Dd,buildVld1DdList	is vld1Dd & buildVld1DdList & esize0607 [ counter=counter-1; regNum=regNum+1; ] 
{
	build vld1Dd;
	mult_addr = mult_addr + esize0607;
	build buildVld1DdList;
}

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

@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) & 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) & 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) & 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) & 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) & 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) & 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; ] { tmp:4 = 1; export tmp; }
vld1DdList3: "{"^buildVld1DdList3^"}"	is c0505=1 & D22 & c1215 & buildVld1DdList3 [ regNum=(D22<<4)+c1215-1; counter=2; ] { tmp:4 = 2; export tmp; }

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) & 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) & 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) & 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; ] { tmp:4 = 1; export tmp; }
thv_vld1DdList3: "{"^buildVld1DdList3^"}"	is thv_c0505=1 & thv_D22 & thv_c1215 & buildVld1DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; counter=2; ] { tmp:4 = 2; export tmp; }

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; tmp:4 = 2; export tmp; }
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; tmp:4 = 2; export tmp; }
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; tmp:4 = 4; export tmp; }
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; tmp:4 = 2; export tmp; }
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; tmp:4 = 2; export tmp; }
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; tmp:4 = 4; export tmp; }

@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) & 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) & 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) & 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) & 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) & 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) & 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: "["^Rn^vld2Align3^"]" 	is Rn & vld2Align3	{ export Rn; }

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) & 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) & 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) & 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 c0404=0		{ }
vld3Align: "@64"	is c0404=1		{ }

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

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

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

@define Vld3DdList "(c0811=4 | c0811=5) & vld3DdList"

:vld3.^esize0607 vld3DdList,vld3RnAligned		is $(AMODE) & cond=15 & c2327=8 & c2021=2 & vld3RnAligned & c0607<3 & esize0607 & c0505=0 & c0003=15 & $(Vld3DdList)	unimpl

:vld3.^esize0607 vld3DdList,vld3RnAligned^"!"	is $(AMODE) & cond=15 & c2327=8 & c2021=2 & vld3RnAligned & c0607<3 & esize0607 & c0505=0 & c0003=13 & $(Vld3DdList) unimpl

:vld3.^esize0607 vld3DdList,vld3RnAligned,VRm	is $(AMODE) & cond=15 & c2327=8 & c2021=2 & vld3RnAligned & c0607<3 & esize0607 & c0505=0 & VRm & $(Vld3DdList) unimpl

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

vld3Index: val	is c0507 & c1011	[ val = c0507 >> 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  D22 & c1215 & buildVld3DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=3; ] { } # Single
vld3DdList2: "{"^buildVld3DdList2^"}"	is  ((c1011=1 & c0405=2) | (c1011=2 & c0406=4)) & D22 & c1215 & buildVld3DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=3; ] { } # Double

:vld3.^esize1011 vld3DdList2,vld3Rn		is $(AMODE) & cond=15 & c2327=9 & c2021=2 & vld3Rn & c1011<3 & esize1011 & c0809=2 & c0003=15 & vld3DdList2	unimpl

:vld3.^esize1011 vld3DdList2,vld3Rn^"!"	is $(AMODE) & cond=15 & c2327=9 & c2021=2 & vld3Rn & c1011<3 & esize1011 & c0809=2 & c0003=13 & vld3DdList2 unimpl

:vld3.^esize1011 vld3DdList2,vld3Rn,VRm	is $(AMODE) & cond=15 & c2327=9 & c2021=2 & vld3Rn & c1011<3 & esize1011 & c0809=2 & VRm & 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  c0505=0 & D22 & c1215 & buildVld3DdList3 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=3; ] { } # Single
vld3DdList3: "{"^buildVld3DdList3^"}"	is  c0505=1 & D22 & c1215 & buildVld3DdList3 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=3; ] { } # Double

:vld3.^esize0607 vld3DdList3,vld3Rn		is $(AMODE) & cond=15 & c2327=9 & c2021=2 & vld3Rn & c0811=14 & c0607<3 & esize0607 & c0404=0 & c0003=15 & vld3DdList3	unimpl

:vld3.^esize0607 vld3DdList3,vld3Rn^"!"	is $(AMODE) & cond=15 & c2327=9 & c2021=2 & vld3Rn & c0811=14 & c0607<3 & esize0607 & c0404=0 & c0003=13 & vld3DdList3 unimpl

:vld3.^esize0607 vld3DdList3,vld3Rn,VRm	is $(AMODE) & cond=15 & c2327=9 & c2021=2 & vld3Rn & c0811=14 & c0607<3 & esize0607 & c0404=0 & VRm & 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) & 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) & 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) & 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) & cond=15 & c2327=9 & c2021=2 & vld4RnAligned3 & c0811=15 & esize0607 & c0003=15 & vld4DdList3	unimpl
#thv_2327=0x12

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

:vld4.^esize0607 vld4DdList3,vld4RnAligned3,VRm	is $(AMODE) & 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 buildVld4DdList & Dreg	[ 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) & 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) & 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) & 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 Rn & c2121=0		{ }
vldmRn: Rn^"!"	is Rn & c2121=1		{ }

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

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

:vldmia^COND vldmRn,vldmDdList	is $(AMODE) & COND & c2327=0x19 & c2121 & c2020=1 & vldmRn & c0811=11 &  vldmDdList & c0000=0 unimpl

:vldmdb^COND vldmRn,vldmDdList	is $(AMODE) & COND & c2327=0x1a & c2121=1 & c2020=1 & vldmRn & c0811=11 &  vldmDdList & c0000=0 unimpl

@endif # VFPv2 | VFPv3 | SIMD

@if defined(VERSION_8)

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

fldmSet: "{"^thv_Dd_1^"}" is TMode=1 & thv_Dd_1 & thv_c0007=3 & fldmSet1 { build fldmSet1; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet2^"}" is TMode=1 & thv_Dd_1 & thv_c0007=5 & fldmSet2 { build fldmSet2; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet3^"}" is TMode=1 & thv_Dd_1 & thv_c0007=7 & fldmSet3 { build fldmSet3; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet4^"}" is TMode=1 & thv_Dd_1 & thv_c0007=9 & fldmSet4 { build fldmSet4; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet5^"}" is TMode=1 & thv_Dd_1 & thv_c0007=11 & fldmSet5 { build fldmSet5; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet6^"}" is TMode=1 & thv_Dd_1 & thv_c0007=13 & fldmSet6 { build fldmSet6; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet7^"}" is TMode=1 & thv_Dd_1 & thv_c0007=15 & fldmSet7 { build fldmSet7; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet8^"}" is TMode=1 & thv_Dd_1 & thv_c0007=17 & fldmSet8 { build fldmSet8; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet9^"}" is TMode=1 & thv_Dd_1 & thv_c0007=19 & fldmSet9 { build fldmSet9; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet10^"}" is TMode=1 & thv_Dd_1 & thv_c0007=21 & fldmSet10 { build fldmSet10; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet11^"}" is TMode=1 & thv_Dd_1 & thv_c0007=23 & fldmSet11 { build fldmSet11; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet12^"}" is TMode=1 & thv_Dd_1 & thv_c0007=25 & fldmSet12 { build fldmSet12; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet13^"}" is TMode=1 & thv_Dd_1 & thv_c0007=27 & fldmSet13 { build fldmSet13; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet14^"}" is TMode=1 & thv_Dd_1 & thv_c0007=29 & fldmSet14 { build fldmSet14; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet15^"}" is TMode=1 & thv_Dd_1 & thv_c0007=31 & fldmSet15 { build fldmSet15; }
fldmSet: "{"^thv_Dd_1^"-"^fldmSet16^"}" is TMode=1 & 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^ItCond fldmWback, fldmSet is TMode=1 & ItCond & thv_c2331=0b111011010 & thv_bit21=1 & thv_bit20=1 & thv_c0811=0b1011 & fldmWback & fldmSet
{
	build fldmWback;
	build fldmSet;
}

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

@endif

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

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

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

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) & COND & c2327=0x19 & c2121 & c2020=1 & c0811=10 ) |
                                      ($(TMODE_E) & thv_c2327=0x19 & thv_c2121 & thv_c2020=1 & thv_c0811=10 ) ) & vldmRn & vldmSdList unimpl

:vldmdb^COND vldmRn,vldmSdList	is ( ( $(AMODE) & COND & c2327=0x1a & c2121=1 & c2020=1 & c0811=10 ) |
                                      ($(TMODE_E) & thv_c2327=0x1a & thv_c2121=1 & thv_c2020=1 & thv_c0811=10 ) ) & vldmRn & vldmSdList unimpl

#######
# 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^",#-"^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^",#-"^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) & 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) & 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 FloatVectorMultiplyAccumulate;
define pcodeop FloatVectorMultiplySubtract;
define pcodeop VectorGetElement;

@if defined(SIMD)

:vmax.^udt^esize2021 Dd, Dn, Dm	is ( ( $(AMODE) & 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) & 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) & 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) & 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) & 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) & 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) & 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) & 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) & 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) & 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) & 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) & 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) & 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) & 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^fesize2021 Dd,Dn,Dm	is ( ($(AMODE) & cond=15 & c2327=4 & c2121=0 & c0811=13 & Q6=0 & c0404=1) |
	                              ($(TMODE_E) & thv_c2327=0x1c & thv_c2121=0 & thv_c0811=13 & thv_c0606=0 & thv_c0404=1)) & fesize2021 & Dn & Dd & Dm
{
	Dd = FloatVectorMultiplyAccumulate(Dn,Dm,fesize2021,8:1);
}

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

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

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

@endif # SIMD

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

:vmla^COND^".f32" Sd,Sn,Sm	is ( ( $(AMODE) & COND & 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)) & Sm & Sn & Sd
{
	Sd = Sd f+ (Sn f* Sm);
}

:vmla^COND^".f64" Dd,Dn,Dm	is ( ( $(AMODE) & COND & 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)) & Dm & Dn & Dd
{
	Dd = Dd f+ (Dn f* Dm);
}

:vmls^COND^".f32" Sd,Sn,Sm	is ( ( $(AMODE) & COND & 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)) & Sm & Sn & Sd
{
	Sd = Sd f- (Sn f* Sm);
}

:vmls^COND^".f64" Dd,Dn,Dm	is ( ( $(AMODE) & COND & 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)) & 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) & 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) & 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.f^esize2021 Dd,Dn,vmlDm	is ( ($(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & (c2021=1 | c2021=2)  & c0811=1 & c0606=1 & c0404=0) |
	                                 ($(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=1 & thv_c0606=1 & thv_c0404=0)) & esize2021 & Dn & Dd & vmlDm
{
	Dd = FloatVectorMultiplyAccumulate(Dn,vmlDm,2:4,esize2021);
}

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

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

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

:vmls.f32 Dd,Dn,vmlDm	is $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2021=2 & Dn & Dd & c0811=5 & c0606=1 & c0404=0 & vmlDm
{
	Dd = FloatVectorMultiplySubtract(Dn,vmlDm,2:4,32:1);
}

:vmls.f32 Qd,Qn,vmlDm	is $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2021=2 & Qn & Qd & c0811=5 & c0606=1 & c0404=0 & vmlDm
{
	Qd = FloatVectorMultiplySubtract(Qn,vmlDm,2:4,32:1);
}

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



:vmlal.^udt^esize2021 Qd,Dn,vmlDm	is ( ($(AMODE) & 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) & 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);
}

:vmov.^simdExpImmDT Dd,simdExpImm_8 is (( $(AMODE) & 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;
}

:vmov.^simdExpImmDT Qd,simdExpImm_16 is (( $(AMODE) & 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)

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

:vmov^COND^".f64" Dd,vfpExpImm_8	is ( ( $(AMODE) & COND & c2327=0x1d & c2021=3 & c0411=0xb0 ) |
								     ( $(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c0411=0xb0 ) ) & Dd & vfpExpImm_8 
{
	Dd = vfpExpImm_8;
}

@endif # VFPv3

@if defined(SIMD)

:vmov Dd,Dm		is ( ($(AMODE) & 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) & 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) & COND &   c2327=0x1d &     c1621=0x30 &     c0611=0x29  &    c0404=0 ) |
                                  ($(TMODE_E) &    thv_c2327=0x1d & thv_c1621=0x30 & thv_c0611=0x29 & thv_c0404=0) ) & Sd & Sm 
{
	Sd = Sm;
}

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

@endif # VFPv2 || VFPv3

define pcodeop VectorSetElement;

@if defined(SIMD)

vmovSize: 8		is TMode=0 & c2222=1				{ tmp:1 = 1; export tmp; }
vmovSize: 16	is TMode=0 & c2222=0 & c0505=1		{ tmp:1 = 2; export tmp; }
vmovSize: 8		is TMode=1 & thv_c2222=1				{ tmp:1 = 1; export tmp; }
vmovSize: 16	is TMode=1 & thv_c2222=0 & thv_c0505=1		{ tmp:1 = 2; export tmp; }

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

vmovSize: 32	is TMode=0 & c2222=0 & c0506=0		{ tmp:1 = 4; export tmp; }
vmovSize: 32	is TMode=1 & thv_c2222=0 & thv_c0506=0		{ tmp:1 = 4; export tmp; }

@endif #  VFPv2 || VFPv3 || 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 &     c0606=0 &     c0506=0									{ tmp:1 = c2121; export tmp; }
vmovIndex: thv_c2121 is TMode=1 & thv_c2222=0 & thv_c2121 & thv_c0606=0 & thv_c0506=0									{ tmp:1 = thv_c2121; export tmp; }

@endif #  VFPv2 || VFPv3 || SIMD


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


:vmov^COND^"."^vmovSize dNvmovIndex,VRd	is ( ($(AMODE) & COND &  c2327=0x1c &     c2020=0 &     c0811=11 &     c0404=1 &     c0003=0 ) |
													($(TMODE_E) &    thv_c2327=0x1c & thv_c2020=0 & thv_c0811=11 & thv_c0404=1 & thv_c0003=0 ) ) & Dn & VRd & vmovSize & vmovIndex & dNvmovIndex
{
	VectorSetElement(VRd,Dn,vmovIndex,vmovSize);
}

:vmov^COND^".u"^vmovSize VRd,dNvmovIndex	is ( ($(AMODE) & COND &      c2327=0x1d &     c2020=1 &     c0811=11 &     c0404=1 &     c0003=0 ) |
															($(TMODE_E) &    thv_c2327=0x1c & thv_c2020=1 & thv_c0811=11 & thv_c0404=1 & thv_c0003=0 ) ) & Dn & VRd & vmovSize & vmovIndex & dNvmovIndex
{
	VRd = VectorGetElement(Dn,vmovIndex,vmovSize,0:1);
}

:vmov^COND^".s"^vmovSize VRd,dNvmovIndex	is ( ( $(AMODE) & COND &     c2327=0x1c &     c2020=1 &     c0811=11 &     c0404=1 &     c0003=0 ) |
															($(TMODE_E) &    thv_c2327=0x1d & thv_c2020=1 & thv_c0811=11 & thv_c0404=1 & thv_c0003=0 ) ) & Dn & VRd & vmovSize & vmovIndex & dNvmovIndex
{
	VRd = VectorGetElement(Dn,vmovIndex,vmovSize,1:1);
}

@endif # SIMD


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

:vmov^COND Sn,VRd	is COND & ( ($(AMODE) & 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) ) & Sn & VRd
{
	Sn = VRd;
}

:vmov^COND VRd,Sn	is  COND & ( ($(AMODE) & 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) ) & Sn & VRd
{
	VRd = Sn;
}

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

:vmov^COND VRd,VRn,Sm,SmNext	is COND & ( ($(AMODE) & c2027=0xc5 & c0611=0x28 & c0404=1) |
                                            ($(TMODE_E) &  thv_c2027=0xc5 & thv_c0611=0x28 & thv_c0404=1) ) & 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) & 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) & 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) & cond=15 & c2527=1 & udt & c2323=1 & (c1921=1 | c1921=2 | c1921=4) & esize2021 & c1618=0 & Qd & c0611=0x28 & c0404=1 & Dm
{
	Qd = VectorCopyLong(Dm,esize2021,udt);
}

:vmovn.i^esize1819x2 Dd,Qm		is ( ($(AMODE) &  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);
}

@endif # SIMD

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

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

apsr:   "apsr"  is TMode=1 {}

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

:vmsr^COND fpscr,VRd	is COND & ( ($(AMODE) & c1627=0xee1 & c0011=0xa10) | ($(TMODE_E) &  thv_c1627=0xee1 & thv_c0011=0xa10) ) & 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) & cond=15 & c2327=0x06 & c2121=0 & c0811=13 & Q6=0 & c0404=1) |
                           ($(TMODE_F)  &thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm
{
	Dd = FloatVectorMult(Dn,Dm,2:1,32:1);
}

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

:vmul.f64 Dd,Dn,Dm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Dm & Dn & Dd 
{
	Dd = Dn f* Dm;
}

:vmul.f32 Sd,Sn,Sm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Sm & Sn & Sd 
{
	Sd = Sn f* Sm;
}

:vmul.i^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & 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) & 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) & 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) & 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) & 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) & cond=15 & c2527=1 & c2424=0 & c2323=1 & 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) & cond=15 & c2527=1 & c2424=0 & c2323=1 & 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);
}

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) & cond=15 & c2424=1 & c2527=1 & c2323=1 & (c2021=1 | c2021=2) & c0911=4 & c0606=1 & c0404=0) | 
                                     ($(TMODE_F) &  thv_c2828=1 & 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) & cond=15 & c2424=0 & c2527=1 & c2323=1 & (c2021=1 | c2021=2) & c0911=4 & c0606=1 & c0404=0) | 
                                     ($(TMODE_E) &  thv_c2828=0 & 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) & 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 Dd,Dm		is ( ($(AMODE) & 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) & 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);
}

@endif # SIMD



define pcodeop FloatVectorNeg;

@if defined(SIMD)

:vneg.s^esize1819 Dd,Dm    is ( ( $(AMODE) & 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,esize1819);
}

:vneg.s^esize1819 Qd,Qm    is ( ( $(AMODE) & 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,esize1819);
}


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

:vneg.f32 Qd,Qm    is ( ( $(AMODE) & 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 ) ) & Qd & Qm
{
	Qd = FloatVectorNeg(Qm,2:1,32:1);
}

@endif # SIMD

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


:vnmls.f64 Dd,Dn,Dm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Dm & Dn & Dd 
{
	product:8 = Dn f* Dm;
	Dd = 0 f- product f- Dd;
}

:vnmls.f32 Sd,Sn,Sm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Sm & Sn & Sd 
{
	product:4 = Sn f* Sm;
	Sd = 0 f- product f- Sd;
}

:vnmls.f16 Sd,Sn,Sm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Sm & Sn & Sd 
{
	product:2 = Sn:2 f* Sm:2;
	product = 0:2 f- product f- Sd:2;
	Sd = zext(product);
}

:vnmls.f64 Dd,Dn,Dm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Dm & Dn & Dd 
{
	product:8 = Dn f* Dm;
	Dd = product f- Dd;
}

:vnmls.f32 Sd,Sn,Sm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Sm & Sn & Sd 
{
	product:4 = Sn f* Sm;
	Sd = product f- Sd;
}

:vnmls.f16 Sd,Sn,Sm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Sm & Sn & Sd 
{
	product:2 = Sn:2 f* Sm:2;
	product = product f- Sd:2;
	Sd = zext(product);
}

:vnmul.f64 Dd,Dn,Dm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Dm & Dn & Dd 
{
	product:8 = Dn f* Dm;
	Dd = 0 f- product;
}

:vnmul.f32 Sd,Sn,Sm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Sm & Sn & Sd 
{
	product:4 = Sn f* Sm;
	Sd = 0 f- product;
}

:vnmul.f16 Sd,Sn,Sm		is COND & ( ($(AMODE) & cond=15 & 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) ) & Sm & Sn & Sd 
{
	product:2 = Sn:2 f* Sm:2;
	product = 0 f- product;
	Sd = zext(product);
}

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

:vneg^COND^".f64" Dd,Dm		is ( ( $(AMODE) & COND &       c2327=0x1d &     c1621=0x31 &     c0611=0x2d &     c0404=0 ) |
                               ( $(TMODE_E) &          thv_c2327=0x1d & thv_c1621=0x31 & thv_c0611=0x2d & thv_c0404=0 ) ) & Dd & Dm
{
	build COND;
	build Dd;
	build Dm;
	Dd = 0 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) & 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) & 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) & 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) & 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) & 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) & 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 COND & ( ($(AMODE) & c2327=0x1a & c1619=13 & c2121=1 & c2020=0 & c0811=11) | 
                                    ($(TMODE_E) &  thv_c2327=0x1a & thv_c1619=13 & thv_c2121=1 & thv_c2020=0 & thv_c0811=11) ) &  vpushSd64List
{
	build vpushSd64List;
}

:vpush^COND vpushSdList	is COND & ( ($(AMODE) & c2327=0x1a & c1619=13 & c2121=1 & c2020=0 & c0811=10) |
                                    ($(TMODE_E) &  thv_c2327=0x1a & thv_c1619=13 & thv_c2121=1 & thv_c2020=0 & thv_c0811=10) ) & 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 COND & ( ($(AMODE) & c2327=0x19 & c1619=13 & c2121=1 & c2020=1 & c0811=11 & c0000=0) | 
                                    ($(TMODE_E) &  thv_c2327=0x19 & thv_c1619=13 & thv_c2121=1 & thv_c2020=1 & thv_c0811=11 & thv_c0000=0) ) &  vpopSd64List
{
	build vpopSd64List;
}

:vpop^COND vpopSdList	is COND & ( ($(AMODE) & c2327=0x19 & c1619=13 & c2121=1 & c2020=1 & c0811=10) |
                                    ($(TMODE_E) &  thv_c2327=0x19 & thv_c1619=13 & thv_c2121=1 & thv_c2020=1 & thv_c0811=10) ) & vpopSdList
{
	build vpopSdList;
}

define pcodeop SatQ;
define pcodeop SignedSatQ;

:vqadd.^udt^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=0 & Q6=0 & c0404=1) |
                                   ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & 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) & cond=15 & c2527=1 & c2323=0 & c0811=0 & Q6=1 & c0404=1) |
                                   ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & 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) &  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) &  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);
}

:vqdmulh.S^esize2021 Qd, Dn, Dm	is ( ( $(AMODE) & 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 & Qd

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

:vqdmulh.S^esize2021 Qd, Qn, Qm	is ( ( $(AMODE) & 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) & 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) & 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) & cond=15 & c2527=1 & c2324=1 & c2021<3 & c0811=0xb & Q6=0 & c0404=0 ) |
                                      ( $(TMODE_E) & thv_c2327=0x1f & thv_c2324=1 & thv_c2021<3 & thv_c0811=0xb & 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) & cond=15 & c2527=1 & c2324=1 & c2021<3 & c0811=0xb & Q6=1 & c0404=1 ) |
                                      ( $(TMODE_E) & thv_c2327=0x1e & thv_c2324=1 & thv_c2021<3 & thv_c0811=0xb & thv_Q6=1 & thv_c0404=1 ) ) & esize2021 & vmlDmA & Dn & Qd

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

:vqrdmulh.S^esize2021 Qd, Dn, Dm	is ( ( $(AMODE) & 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 & Qd

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

:vqrdmulh.S^esize2021 Qd, Qn, Qm	is ( ( $(AMODE) & 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) & 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) & 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) & 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) & 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);
}

@endif #  VFPv2 || VFPv3 || SIMD

@if defined(SIMD)

#######
# TODO: lots of missing stuff
#

#######
# VREV
#

define pcodeop vrev;

:vrev16.^esize1819x3 Qd,Qm	is  ( ($(AMODE) & 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) & 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) & 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) & 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) & 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) & 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 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; }


ShiftImm: "#"^c1618 is  TMode=0 & c1921=1 & L7=0 & c1618  { tmp:8 = c1618; export tmp; }
ShiftImm: "#"^c1619 is  TMode=0 & c2021=1 & L7=0 & c1619  { tmp:8 = c1619; export tmp; }
ShiftImm: "#"^c1620 is  TMode=0 & c2121=1 & L7=0 & c1620  { tmp:8 = c1620; export tmp; }
ShiftImm: "#"^c1621 is  TMode=0 &           L7=1 & c1621  { tmp:8 = c1621; export tmp; }
ShiftImm: "#"^thv_c1618 is  TMode=1 & thv_c1921=1 & thv_L7=0 & thv_c1618  { tmp:8 = thv_c1618; export tmp; }
ShiftImm: "#"^thv_c1619 is  TMode=1 & thv_c2021=1 & thv_L7=0 & thv_c1619  { tmp:8 = thv_c1619; export tmp; }
ShiftImm: "#"^thv_c1620 is  TMode=1 & thv_c2121=1 & thv_L7=0 & thv_c1620  { tmp:8 = thv_c1620; export tmp; }
ShiftImm: "#"^thv_c1621 is  TMode=1 &               thv_L7=1 & thv_c1621  { tmp:8 = thv_c1621; export tmp; }

:vqshrn.^udt^esize2021 Dd,Qm, ShiftImm		is ( ($(AMODE) &  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 & ShiftImm & Dd & Qm
{
	Dd = VectorShiftRightNarrow(Qm,ShiftImm,esize2021,udt);
	Dd = SatQ(Dd,esize2021,udt);
}

:vqshrun.^udt^esize2021 Dd,Qm, ShiftImm		is ( ($(AMODE) &  cond=15 & c2527=1 & c2424=1 & c2323=1 &  (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 & ShiftImm & Dd & Qm
{
	Dd = VectorShiftRightNarrow(Qm,ShiftImm,esize2021,udt);
	Dd = SatQ(Dd,esize2021,udt);
}

:vqrshrn.^udt^esize2021 Dd,Qm, ShiftImm		is ( ($(AMODE) &  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 & ShiftImm & Dd & Qm
{
	Dd = VectorRoundShiftRightNarrow(Qm,ShiftImm,esize2021,udt);
	Dd = SatQ(Dd,esize2021,udt);
}

:vqrshrun.^udt^esize2021 Dd,Qm, ShiftImm	is ( ($(AMODE) &  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 & ShiftImm & Dd & Qm
{
	Dd = VectorRoundShiftRightNarrow(Qm,ShiftImm,esize2021,udt);
	Dd = SatQ(Dd,esize2021,udt);
}


:vqshl.^udt^ShiftSize Qd, Qm, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Qd & Qm
{
	Qd = VectorShiftLeft(Qm,ShiftImm,ShiftSize,udt);
}

:vqshl.^udt^ShiftSize Dd, Dm, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Dd & Dm
{
	Dd = VectorShiftLeft(Dm,ShiftImm,ShiftSize,udt);
}

:vqshlu.^udt^ShiftSize Qd, Qm, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Qd & Qm
{
	Qd = VectorShiftLeft(Qm,ShiftImm,ShiftSize,udt);
}

:vqshlu.^udt^ShiftSize Dd, Dm, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Dd & Dm
{
	Dd = VectorShiftLeft(Dm,ShiftImm,ShiftSize,udt);
}


:vqshl.^udt^esize2021 Qd, Qm, Qn is  ( ($(AMODE) & 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) & 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, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Qd & Qm
{
	Qd = VectorShiftLeft(Qm,ShiftImm,ShiftSize,0:1);
}

:vshl.I^ShiftSize Dd, Dm, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Dd & Dm
{
	Dd = VectorShiftLeft(Dm,ShiftImm,ShiftSize,0:1);
}


:vshl.^udt^esize2021 Qd, Qm, Qn is  ( ($(AMODE) & 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) & 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, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Qd & Dm
{
	Qd = VectorShiftLongLeft(Dm,ShiftImm);
}

:vshll.^udt^esize1819 Qd, Dm, "#"^esize1819x3 is  ( ($(AMODE) & 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) & 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) & 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.^ShiftSize Qd, Qm, ShiftImm is  ( ($(AMODE) & cond=15 &     c2527=1 &  c2323=1 &     c0811=2 &      c0606=1     & c0404=1) |
                                       ($(TMODE_E) &       thv_c2327=0x1f &  thv_c0811=2 &  thv_c0606=1 & thv_c0404=1) ) & ShiftSize & ShiftImm & Qd & Qm
{
	Qd = VectorRoundShiftRight(Qm,ShiftImm);
}

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

:vrshrn.^ShiftSize Dd, Qm, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Dd & Qm
{
	Dd = VectorRoundShiftRightNarrow(Qm,ShiftImm);
}

:vrsra.^ShiftSize Qd, Qm, ShiftImm is  ( ($(AMODE) & 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) ) & ShiftSize & ShiftImm & Qd & Qm
{
	Qd = VectorRoundShiftRightAccumulate(Qd, Qm,ShiftImm);
}

:vrsra.^ShiftSize Dd, Dm, ShiftImm is  ( ($(AMODE) & 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) ) & ShiftSize & ShiftImm & Dd & Dm
{
	Dd = VectorRoundShiftRightAccumulate(Dd, Dm,ShiftImm);
}

:vsqrt^COND^".f32" Sd,Sm		is COND & ( ($(AMODE) & 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) & 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.^ShiftSize Qd, Qm, ShiftImm is  ( ($(AMODE) & 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) ) & ShiftSize & ShiftImm & Qd & Qm
{
	Qd = VectorShiftRightAccumulate(Qd, Qm,ShiftImm);
}

:vsra.^ShiftSize Dd, Dm, ShiftImm is  ( ($(AMODE) & 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) ) & ShiftSize & ShiftImm & Dd & Dm
{
	Dd = VectorShiftRightAccumulate(Dd, Dm,ShiftImm);
}

#######
# VSHR
#

:vshr.^udt^ShiftSize Qd, Qm, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Qd & Qm
{
	Qd = VectorShiftRight(Qm,ShiftImm);
}

:vshr.^udt^ShiftSize Dd, Dm, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Dd & Dm
{
	Dd = VectorShiftRight(Dm,ShiftImm);
}

define pcodeop VectorShiftNarrowRight;

:vshrn.^ShiftSize Dd, Qm, ShiftImm is  ( ($(AMODE) & 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 & ShiftImm & Dd & Qm
{ 
	Dd = VectorShiftNarrowRight(Qm,ShiftImm);
}


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

vst1Dd: Dreg		is Dreg & c0607=0
{
	local tmpDreg = Dreg;
	val:1 = tmpDreg:1;
	replicate1to8(val, *:8 mult_addr);
}
vst1Dd: Dreg		is Dreg & c0607=1
{
	local tmpDreg = Dreg;
	val:2 = tmpDreg:2;
	replicate2to8(val, *:8  mult_addr);
}
vst1Dd: Dreg		is Dreg & c0607=2
{
	local tmpDreg = Dreg;
	val:4 = tmpDreg:4;
	replicate4to8(val, *:8  mult_addr);
}
vst1Dd: Dreg		is Dreg & c0607=3
{
	*:8  mult_addr = Dreg;
}

buildVst1DdList:						is counter=0							{ }
buildVst1DdList: vst1Dd					is vst1Dd & counter=1 					[ counter=0; regNum=regNum+1; ] { }
buildVst1DdList: vst1Dd,buildVst1DdList	is vst1Dd & buildVst1DdList & esize0607	[ counter=counter-1; regNum=regNum+1; ] 
{
	build vst1Dd;
	mult_addr = mult_addr + esize0607;
	build buildVst1DdList;
}

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

@define Vst1DdList "(c0811=2 | c0811=6 | c0811=7 | c0811=10) & vst1DdList"

:vst1.^esize0607 vst1DdList,RnAligned45		is $(AMODE) & cond=15 & c2327=8 & c2021=0 & RnAligned45 & esize0607 & c0003=15 & $(Vst1DdList)
{
 	mult_addr = RnAligned45;
 	build vst1DdList;
}

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

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

thv_vst1Dd: Dreg		is Dreg & thv_c0607=0
{
	local tmpDreg = Dreg;
	val:1 = tmpDreg:1;
	replicate1to8(val, *:8 mult_addr);
}
thv_vst1Dd: Dreg		is Dreg & thv_c0607=1
{
	local tmpDreg = Dreg;
	val:2 = tmpDreg:2;
	replicate2to8(val, *:8  mult_addr);
}
thv_vst1Dd: Dreg		is Dreg & thv_c0607=2
{
	local tmpDreg = Dreg;
	val:4 = tmpDreg:4;
	replicate4to8(val, *:8  mult_addr);
}
thv_vst1Dd: Dreg		is Dreg & thv_c0607=3
{
	*:8 mult_addr = Dreg;
}

thv_buildVst1DdList:								is counter=0							{ }
thv_buildVst1DdList: thv_vst1Dd						is thv_vst1Dd & counter=1 						[ counter=0; regNum=regNum+1; ] { }
thv_buildVst1DdList: thv_vst1Dd,thv_buildVst1DdList	is thv_vst1Dd & thv_buildVst1DdList & esize0607	[ counter=counter-1; regNum=regNum+1; ] 
{
	build thv_vst1Dd;
	mult_addr = mult_addr + esize0607;
	build thv_buildVst1DdList;
}

thv_vst1DdList: "{"^thv_buildVst1DdList^"}"	is thv_c0811=7 & thv_D22 & thv_c1215 & thv_buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=1; ] { tmp:4 = 1; export tmp; }
thv_vst1DdList: "{"^thv_buildVst1DdList^"}"	is thv_c0811=10 & thv_D22 & thv_c1215 & thv_buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=2; ] { tmp:4 = 2; export tmp; }
thv_vst1DdList: "{"^thv_buildVst1DdList^"}"	is thv_c0811=6 & thv_D22 & thv_c1215 & thv_buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=3; ] { tmp:4 = 3; export tmp; }
thv_vst1DdList: "{"^thv_buildVst1DdList^"}"	is thv_c0811=2 & thv_D22 & thv_c1215 & thv_buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=4; ] { tmp:4 = 4; export tmp; }

@define T_Vst1DdList "(thv_c0811=2 | thv_c0811=6 | thv_c0811=7 | thv_c0811=10) & thv_vst1DdList"

:vst1.^esize0607 thv_vst1DdList,RnAligned45		is $(TMODE_F)  &thv_c2327=18 & thv_c2021=0 & RnAligned45 & esize0607 & thv_c0003=15 & $(T_Vst1DdList)
{
 	mult_addr = RnAligned45;
 	build thv_vst1DdList;
}

:vst1.^esize0607 thv_vst1DdList,RnAligned45^"!"	is $(TMODE_F)  &thv_c2327=18 & thv_c2021=0 & RnAligned45 & esize0607 & thv_c0003=13 & $(T_Vst1DdList)
{
	mult_addr = RnAligned45;
	build thv_vst1DdList;
	RnAligned45 = RnAligned45 + (8 * thv_vst1DdList);
}

:vst1.^esize0607 thv_vst1DdList,RnAligned45,VRm	is $(TMODE_F)  &thv_c2327=18 & thv_c2021=0 & RnAligned45 & esize0607 & VRm & $(T_Vst1DdList)
{
	mult_addr = RnAligned45;
	build thv_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) & cond=15 & c2327=9 & c2021=0 & RnAligned2 & esize1011 & c0809=0 & c0003=15 & $(Vst1DdElement2)
{
 	mult_addr = RnAligned2;
	build vst1DdElement2;
}

:vst1.^esize1011 vst1DdElement2,RnAligned2^"!"	is $(AMODE) & 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) & 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;
}


@endif # SIMD

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

#######
# 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; tmp:4 = 2; export tmp; }
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; tmp:4 = 2; export tmp; }
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; tmp:4 = 4; export tmp; }
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; tmp:4 = 2; export tmp; }
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; tmp:4 = 2; export tmp; }
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; tmp:4 = 4; export tmp; }


@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) & 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) & 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) & 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) & cond=15 & c2327=9 & c2021=0  & c1011<3 & c0809=1 & c0003=15 )  |
                                                     ( $(TMODE_F)  &    thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0003=15 ) ) & vst2RnAligned2 & esize1011 & vst2DdList2 
	unimpl

:vst2.^esize1011 vst2DdList2,vst2RnAligned2^"!"	is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=0  & c1011<3 & c0809=1 & c0003=13 )  |
                                                     ( $(TMODE_F)  &    thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0003=13 ) ) & vst2RnAligned2 & esize1011 & vst2DdList2
    unimpl

:vst2.^esize1011 vst2DdList2,vst2RnAligned2,VRm	is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=0  & c1011<3 & c0809=1 )  |
                                                     ( $(TMODE_F)  &    thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 ) ) & vst2RnAligned2 & esize1011 & vst2DdList2 & VRm
    unimpl


#######
# VST3
#

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

vst4Align:			is c0405=0	{ }
vst4Align: "@64"	is c0405=1	{ }
vst4Align: "@128" 	is c0405=2 	{ }
vst4Align: "@256" 	is c0405=3 	{ }

vst4RnAligned: "["^Rn^vst4Align^"]" 	is Rn & vst4Align	{ export Rn; }

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

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

:vst4.^esize0607 vst4DdList,vst4RnAligned		is $(AMODE) & cond=15 & c2327=8 & c2021=0 & vst4RnAligned & c0911=0 & c0607<3 & esize0607 & c0003=15 & vst4DdList	unimpl

:vst4.^esize0607 vst4DdList,vst4RnAligned^"!"	is $(AMODE) & cond=15 & c2327=8 & c2021=0 & vst4RnAligned & c0911=0 & c0607<3 & esize0607 & c0003=13 & vst4DdList unimpl

:vst4.^esize0607 vst4DdList,vst4RnAligned,VRm	is $(AMODE) & cond=15 & c2327=8 & c2021=0 & vst4RnAligned & c0911=0 & c0607<3 & esize0607 & VRm & vst4DdList unimpl

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

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

vst4DdElement2: Dreg^"["^vst4Index^"]"	is Dreg & vst4Index
{
}

vst4Align2: 		is c0404=0 & (c1111=0 | c0505=0)				{ }
vst4Align2: "@32"	is c1011=0 & c0404=1							{ }
vst4Align2: "@64"	is (c1011=1 & c0404=1) | (c1011=2 & c0405=1)	{ }
vst4Align2: "@128"	is c1011=2 & c0405=2							{ }

vst4RnAligned2: "["^Rn^vst4Align2^"]" 	is Rn & vst4Align2	{ export Rn; }

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  D22 & c1215 & buildVst4DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single
vst4DdList2: "{"^buildVst4DdList2^"}"	is  ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVst4DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double

:vst4.^esize1011 vst4DdList2,vst4RnAligned2		is $(AMODE) & cond=15 & c2327=9 & c2021=0 & vst4RnAligned2 & c1011<3 & esize1011 & c0809=3 & c0003=15 & vst4DdList2	unimpl

:vst4.^esize1011 vst4DdList2,vst4RnAligned2^"!"	is $(AMODE) & cond=15 & c2327=9 & c2021=0 & vst4RnAligned2 & c1011<3 & esize1011 & c0809=3 & c0003=13 & vst4DdList2 unimpl

:vst4.^esize1011 vst4DdList2,vst4RnAligned2,VRm	is $(AMODE) & cond=15 & c2327=9 & c2021=0 & vst4RnAligned2 & c1011<3 & esize1011 & c0809=3 & VRm & vst4DdList2 unimpl

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

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

vst4RnAligned3: "["^Rn^vst4Align3^"]" 	is Rn & vst4Align3	{ export Rn; }

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

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

:vst4.^esize0607 vst4DdList3,vst4RnAligned3		is $(AMODE) & cond=15 & c2327=9 & c2021=0 & vst4RnAligned3 & c0811=15 & esize0607 & c0003=15 & vst4DdList3	unimpl

:vst4.^esize0607 vst4DdList3,vst4RnAligned3^"!"	is $(AMODE) & cond=15 & c2327=9 & c2021=0 & vst4RnAligned3 & c0811=15 & esize0607 & c0003=13 & vst4DdList3 unimpl

:vst4.^esize0607 vst4DdList3,vst4RnAligned3,VRm	is $(AMODE) & cond=15 & c2327=9 & c2021=0 & vst4RnAligned3 & c0811=15 & esize0607 & VRm & vst4DdList3 unimpl



#######
# VSTM (A1)
#

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

vstmDdList: "{"^buildVstmDdList^"}"	is D22 & c1215 & c0007 & buildVstmDdList [ regNum=(D22<<4)+c1215-1; counter=c0007>>1; ] { }

:vstmia^COND vldmRn,vstmDdList	is $(AMODE) & COND & c2327=0x19 & c2121 & c2020=0 & vldmRn & c0811=11 &  vstmDdList & c0000=0 unimpl

:vstmdb^COND vldmRn,vstmDdList	is $(AMODE) & COND & c2327=0x1a & c2121=1 & c2020=0 & vldmRn & c0811=11 &  vstmDdList & c0000=0 unimpl

@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; ] { }
buildVstmSdList: Sreg,buildVstmSdList	is Sreg & buildVstmSdList	[ counter=counter-1; regNum=regNum+1; ] { }

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 ( ( $(AMODE) & COND & c2327=0x19 & c2121 & c2020=0 & c0811=10 & c0000 ) |
                                      ($(TMODE_E) & thv_c2327=0x19 & thv_c2121 & thv_c2020=0 & thv_c0811=10 ) ) & vstmSdList & vldmRn unimpl

:vstmdb^COND vldmRn,vstmSdList	is ( ($(AMODE) & COND & c2327=0x1a & c2121=1 & c2020=0 & c0811=10 ) |
                                      ($(TMODE_E) &  thv_c2327=0x1a & thv_c2121=1 & thv_c2020=0 & thv_c0811=10) ) & vstmSdList & vldmRn unimpl




#######
# VSTR
#

:vstr^COND^".64" Dd,vldrRn	is COND & ( ($(AMODE) & 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) & 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;

:vsub.i^esize2021 Dd,Dn,Dm    is ( ($(AMODE) & 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) & 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) & 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) & 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);
}

@endif # SIMD

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

:vsub^COND^".f32" Sd,Sm		is COND & ( ($(AMODE) & 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,Dm		is COND & ( ($(AMODE) & 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;
}

:vsubl.^udt^esize2021 Qd,Dn,Dm    is ( ($(AMODE) & 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) & 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);
}

######
# VTST
#

define pcodeop VectorTest;

:vtst.^esize2021 Qd, Qn, Qm   is ( ($(AMODE) & 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) & 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);
}


@endif # VFPv2 || VFPv3

@if defined(SIMD)

define pcodeop VectorTranspose;

:vtrn^COND^"."^esize1819 Dd,Dm    is COND & ( ($(AMODE) & 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^COND^"."^esize1819 Qd,Qm    is COND & ( ($(AMODE) & 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);
}

#######
# VSWP
#

:vswp Dd,Dm    is ( ( $(AMODE) & 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) & 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;
}


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; ] { tmp:4 = 1; export tmp; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=0 & c0809=1 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=2; ] { tmp:4 = 2; export tmp; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=0 & c0809=2 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=3; ] { tmp:4 = 3; export tmp; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=0 & c0809=3 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=4; ] { tmp:4 = 4; export tmp; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=1 & thv_c0809=0 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=1; ] { tmp:4 = 1; export tmp; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=1 & thv_c0809=1 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=2; ] { tmp:4 = 2; export tmp; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=1 & thv_c0809=2 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=3; ] { tmp:4 = 3; export tmp; }
vtblDdList: "{"^buildVtblDdList^"}"	is TMode=1 & thv_c0809=3 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=4; ] { tmp:4 = 4; export tmp; }


:vtbl.8 VRd,vtblDdList,VRm is ( ($(AMODE) &  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);
}

:vtblx.8 VRd,vtblDdList,VRm is ( ($(AMODE) &  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);
}

#######
# VUZP
#

define pcodeop VectorUnzip;

:vuzp^esize1819 Dd,Dm    is ( ( $(AMODE) & 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 = VectorUnzip(Dm,esize1819);
}

:vuzp^esize1819 Qd,Qm    is ( ( $(AMODE) & 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 = VectorUnzip(Qm,esize1819);
}


#######
# VZIP
#

define pcodeop VectorZip;

:vuzp^esize1819 Dd,Dm    is ( ( $(AMODE) & 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 = VectorZip(Dm,esize1819);
}

:vuzp^esize1819 Qd,Qm    is ( ( $(AMODE) & 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 = VectorZip(Qm,esize1819);
}


@endif # SIMD

