|  | 
| 35 | 35 | }; | 
| 36 | 36 | 
 | 
| 37 | 37 | # Common pattern for the basic shift and rotate instructions | 
|  | 38 | +# Separate legacy and EVEX versions because additional patterns are | 
|  | 39 | +# needed to handle the -X VEX versions | 
| 38 | 40 | $macros{'shift'} = { | 
| 39 | 41 |     'def' => *def_eightfold, | 
| 40 | 42 | 	'txt' => <<'EOL' | 
| 41 | 43 | $$bwdq $op	rm#,unity			[m-:	o# d0# /$n]				]	8086,FL | 
| 42 | 44 | $$bwdq $op	rm#,reg_cl			[m-:	o# d2# /$n]				]	8086,FL | 
|  | 45 | +$$bwdq $op	rm#,reg_cx			[m-:	o# d2# /$n]				]	8086,FL,ND | 
|  | 46 | +$$bwdq $op	rm#,reg_ecx			[m-:	o# d2# /$n]				]	8086,FL,ND | 
|  | 47 | +$$bwdq $op	rm#,reg_rcx			[m-:	o# d2# /$n]				]	8086,FL,ND | 
| 43 | 48 | $$bwdq $op	rm#,imm8			[mi:	o# c0# /$n ib,u]			]	186,FL | 
|  | 49 | +EOL | 
|  | 50 | +}; | 
|  | 51 | + | 
|  | 52 | +# APX EVEX versions | 
|  | 53 | +$macros{'eshift'} = { | 
|  | 54 | +    'def' => *def_eightfold, | 
|  | 55 | +	'txt' => <<'EOL' | 
| 44 | 56 | $$bwdq $op	reg#?,rm#,unity			[vm-:	evex.ndx.nf.l0.m4.o#  d0# /$n		]	$apx,FL,SM0-1 | 
| 45 | 57 | $$bwdq $op	reg#?,rm#,reg_cl		[vm-:	evex.ndx.nf.l0.m4.o#  d2# /$n		]	$apx,FL,SM0-1 | 
|  | 58 | +$$bwdq $op	reg#?,rm#,reg_cx		[vm-:	evex.ndx.nf.l0.m4.o#  d2# /$n		]	$apx,FL,SM0-1,ND | 
|  | 59 | +$$bwdq $op	reg#?,rm#,reg_ecx		[vm-:	evex.ndx.nf.l0.m4.o#  d2# /$n		]	$apx,FL,SM0-1,ND | 
|  | 60 | +$$bwdq $op	reg#?,rm#,reg_rcx		[vm-:	evex.ndx.nf.l0.m4.o#  d2# /$n		]	$apx,FL,SM0-1,ND | 
| 46 | 61 | $$bwdq $op	reg#?,rm#,imm8			[vmi:	evex.ndx.nf.l0.m4.o#  c0# /$n ib,u	]	$apx,FL,SM0-1 | 
| 47 | 62 | EOL | 
| 48 | 63 | }; | 
| 49 | 64 | 
 | 
|  | 65 | +# -X shifts | 
|  | 66 | +$macros{'xshift'} = { | 
|  | 67 | +    'func' => sub { | 
|  | 68 | +	my($mac, $args, $rawargs) = @_; | 
|  | 69 | +	my @ol; | 
|  | 70 | +	my $vex = 'vex'; | 
|  | 71 | +	my $vfl = ''; | 
|  | 72 | +	if (grep { /^evex=1$/ } @$rawargs) { | 
|  | 73 | +	    $vex = 'evex'; | 
|  | 74 | +	    $vfl = 'APX'; | 
|  | 75 | +	} | 
|  | 76 | +	foreach my $xf (['X',"$vfl"], ['', "$vfl,ND,NF!,OPT"]) { | 
|  | 77 | +	    my($x,$fl) = @$xf; | 
|  | 78 | +	    foreach my $os (32, 64) { | 
|  | 79 | +		my $w = ($os eq 32) ? 'w0' : 'w1'; | 
|  | 80 | +		my $ixor = sprintf('%02x', $os-1); | 
|  | 81 | +		push(@ol, "ROR$x reg$os,rm$os,imm8       [rmi: $vex.lz.f2.0f3a.$w f0 /r ib] BMI2,SM0-1,!FL,$fl"); | 
|  | 82 | +		push(@ol, "ROL$x reg$os,rm$os,imm_known8 [rmi: $vex.lz.f2.0f3a.$w f0 /r ib^$ixor] BMI2,SM0-1,!FL,$fl"); | 
|  | 83 | +		foreach my $ss (8, 16, 32, 64) { | 
|  | 84 | +		    foreach my $opp (['SHL','66'], ['SAL','66'], ['SAR','f3'], ['SHR','f2']) { | 
|  | 85 | +			my($op,$pp) = @$opp; | 
|  | 86 | +			my $ndss = ',ND' unless ($ss == $os && $op ne 'SAR'); | 
|  | 87 | +			push(@ol, "$op$x reg$os,rm${os}*,reg$ss [rmv: $vex.lz.$pp.0f38.$w f7 /r] BMI2,SM0-1,!FL,$fl,$ndss"); | 
|  | 88 | +		    } | 
|  | 89 | +		} | 
|  | 90 | +	    } | 
|  | 91 | +	} | 
|  | 92 | +	return @ol; | 
|  | 93 | +    } | 
|  | 94 | +}; | 
|  | 95 | + | 
| 50 | 96 | # | 
| 51 | 97 | # Common pattern for multiple 32/64, 16/32/64, or 8/16/32/64 instructions. | 
| 52 | 98 | # 'z' is used for a null-prefixed default-sized instruction (osm/osd) | 
|  | 
| 433 | 479 | ## XXX: check: CMPSS, CMPSD | 
| 434 | 480 | ## XXX: check VEX encoded instructions that do not write | 
| 435 | 481 | 
 | 
| 436 |  | -# Instructions which (possibly) change the flags | 
|  | 482 | +# Instructions which (possibly) change the flags without annotations | 
|  | 483 | +# The FL or !FL flags will override this | 
| 437 | 484 | my $flaggy = '^(aa[adms]|ad[dc]|ad[co]x|aes\w*kl|and|andn|arpl|bextr|bl[sc]ic?|bl[sc]msk|bl[sc]r|\ | 
| 438 | 485 | bs[rf]|bt|bt[crs]|bzhi|clac|clc|cld|cli|clrssbsy|cmc|cmp|cmpxchg.*|da[as]|dec|div|\ | 
| 439 | 486 | encodekey.*|enqcmd.*|fu?comip?|idiv|imul|inc|iret.*|kortest.*|ktest.*|lar|loadiwkey|\ | 
|  | 
0 commit comments