|
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