diff --git a/include/opflags.h b/include/opflags.h index f3ba4ddc..3bf1c3c7 100644 --- a/include/opflags.h +++ b/include/opflags.h @@ -246,9 +246,9 @@ static inline bool is_reg_class(opflags_t class, int reg) #define RN_NZERO GEN_SUBCLASS(7) /* Register number 1+ */ #define RN_1_15 (RN_NZERO | RN_L16) /* Register number 1-15 */ -#define RN_FLAGS(n) ((n) == 0 ? RN_ZERO : \ - (n) < 16 ? RN_1_15 : \ - 0) +#define RN_FLAGS(n) \ + (((n) == 0 ? RN_ZERO : RN_NZERO) | \ + ((n) < 16 ? RN_L16 : 0)) #define RM_L16 (RN_L16 | REGMEM) #define RM_ZERO (RN_ZERO | REGMEM) @@ -342,8 +342,15 @@ static inline bool is_reg_class(opflags_t class, int reg) #define REG_EDX (REG_DATA | BITS32) #define REG_RDX (REG_DATA | BITS64) +/* base: BL, BX, EBX, RBX */ +#define REG_BASE (REG_GPR | REG_1_15 | GEN_SUBCLASS(2)) +#define REG_BL (REG_BASE | BITS8 ) +#define REG_BX (REG_BASE | BITS16) +#define REG_EBX (REG_BASE | BITS32) +#define REG_RBX (REG_BASE | BITS64) + /* high 8-bit regs: AH, CH, DH, BH */ -#define REG_HIGH (REG8 | REG_1_15 | GEN_SUBCLASS(2)) +#define REG_HIGH (REG8 | REG_1_15 | GEN_SUBCLASS(3)) /* Non-accumulator registers */ #define REG_NA (REG_GPR | REG_NZERO) diff --git a/x86/insns-iflags.ph b/x86/insns-iflags.ph index ce11dcbd..48a51273 100644 --- a/x86/insns-iflags.ph +++ b/x86/insns-iflags.ph @@ -172,9 +172,21 @@ sub set_implied_flags($;$) { $flags->{'LONG'}++ if ($flags->{'APX'}); $flags->{'NOAPX'}++ if ($flags->{'NOLONG'}); + $flags->{'X86_64'}++ if ($flags->{'LONG'}); $flags->{'OBSOLETE'}++ if ($flags->{'NEVER'} || $flags->{'NOP'}); $flags->{'NF'}++ if ($flags->{'NF_R'} || $flags->{'NF_E'}); $flags->{'ZU'}++ if ($flags->{'ZU_R'} || $flags->{'ZU_E'}); + + # Retain only the highest CPU level flag + my $found = 0; + for (my $i = $flag_byname{'ANY'}->[0]; $i >= $flag_byname{'8086'}->[0]; $i--) { + my $f = $flag_bynum[$i]->[1]; + if ($found) { + delete $flags->{$f}; + } else { + $found = $flags->{$f}; + } + } } # Return the value of any assume-size flag if one exists; @@ -216,6 +228,8 @@ sub split_flags($) { $flagstr = uc($flagstr); foreach my $flag (split(',', $flagstr)) { + next if ($flag =~ /^\s*$/); # Null flag + # Somewhat nicer syntax for required flags (NF! -> NF_R) $flag =~ s/\!$/_R/; # Ditto for weak flags (SX- -> SX_W) @@ -250,7 +264,8 @@ sub merge_flags($;$) { clean_flags(\%flags); - my @flagslist = sort grep { !/^(\s*|\!.*)$/ } keys(%$flags); + my @flagslist = sort { $flag_byname{$a} <=> $flag_byname{$b} } + grep { !/^(\s*|\!.*)$/ } keys(%$flags); if ($merge) { # For possibe human consumption. Merge subsequent SM and AR @@ -282,11 +297,12 @@ sub merge_flags($;$) { $nstr .= $n; } } - $nstr =~ s/^\+/$pfx/; - push(@flagslist, $nstr); $n++; $mask >>= 1; } + + $nstr =~ s/^\+/$pfx/; + push(@flagslist, $nstr); } else { push(@flagslist, $fl); } diff --git a/x86/insns.dat b/x86/insns.dat index 36588a2d..34e1e78c 100644 --- a/x86/insns.dat +++ b/x86/insns.dat @@ -87,40 +87,21 @@ AAS void [ 3f] 8086,NOLONG ARPL rm16,reg16 [mr: 63 /r] 286,PROT,SM,NOLONG BB0_RESET void [ 0f 3a] PENT,CYRIX,NOLONG,OBSOLETE,ND BB1_RESET void [ 0f 3b] PENT,CYRIX,NOLONG,OBSOLETE,ND -BOUND reg16,mem [rm: o16 62 /r] 186,NOLONG -BOUND reg32,mem [rm: o32 62 /r] 386,NOLONG -BSF reg16,rm16 [rm: o16 nof3 0f bc /r] 386,SM -BSF reg32,rm32 [rm: o32 nof3 0f bc /r] 386,SM -BSF reg64,rm64 [rm: o64 nof3 0f bc /r] X86_64,LONG,SM -BSR reg16,rm16 [rm: o16 nof3 0f bd /r] 386,SM -BSR reg32,rm32 [rm: o32 nof3 0f bd /r] 386,SM -BSR reg64,rm64 [rm: o64 nof3 0f bd /r] X86_64,LONG,SM +$trio BOUND reg#,mem [rm: o# 62 /r] 186,NOLONG +$trio BSF reg#,rm# [rm: o# nof3 0f bc /r] 386,SM +$trio BSR reg#,rm# [rm: o# nof3 0f bd /r] 386,SM BSWAP reg32 [r: o32 0f c8+r] 486 BSWAP reg64 [r: o64 0f c8+r] X86_64,LONG -BT rm16,reg16 [mr: o16 0f a3 /r] 386,SM -BT rm32,reg32 [mr: o32 0f a3 /r] 386,SM -BT rm64,reg64 [mr: o64 0f a3 /r] X86_64,LONG,SM -BT rm16,imm8 [mi: o16 0f ba /4 ib,u] 386 -BT rm32,imm8 [mi: o32 0f ba /4 ib,u] 386 -BT rm64,imm8 [mi: o64 0f ba /4 ib,u] X86_64,LONG -BTC rm16,reg16 [mr: hle o16 0f bb /r] 386,SM,LOCK -BTC rm32,reg32 [mr: hle o32 0f bb /r] 386,SM,LOCK -BTC rm64,reg64 [mr: hle o64 0f bb /r] X86_64,LONG,SM,LOCK -BTC rm16,imm8 [mi: hle o16 0f ba /7 ib,u] 386,LOCK -BTC rm32,imm8 [mi: hle o32 0f ba /7 ib,u] 386,LOCK -BTC rm64,imm8 [mi: hle o64 0f ba /7 ib,u] X86_64,LONG,LOCK -BTR rm16,reg16 [mr: hle o16 0f b3 /r] 386,SM,LOCK -BTR rm32,reg32 [mr: hle o32 0f b3 /r] 386,SM,LOCK -BTR rm64,reg64 [mr: hle o64 0f b3 /r] X86_64,LONG,SM,LOCK -BTR rm16,imm8 [mi: hle o16 0f ba /6 ib,u] 386,LOCK -BTR rm32,imm8 [mi: hle o32 0f ba /6 ib,u] 386,LOCK -BTR rm64,imm8 [mi: hle o64 0f ba /6 ib,u] X86_64,LONG,LOCK -BTS rm16,reg16 [mr: hle o16 0f ab /r] 386,SM,LOCK -BTS rm32,reg32 [mr: o32 0f ab /r] 386 -BTS rm64,reg64 [mr: o64 0f ab /r] X86_64,LONG -BTS rm16,imm8 [mi: hle o16 0f ba /5 ib,u] 386,LOCK -BTS rm32,imm8 [mi: hle o32 0f ba /5 ib,u] 386,LOCK -BTS rm64,imm8 [mi: hle o64 0f ba /5 ib,u] X86_64,LONG,LOCK +; Basically a useless instruction; sets the 16-bit register to 0, but it executes +BSWAP reg16 [r: o16 0f c8+r] 486,UNDOC +$trio BT rm#,reg# [mr: o# 0f a3 /r] 386,SM +$trio BT rm#,imm8 [mi: o# 0f ba /4 ib,u] 386 +$trio BTC rm#,reg# [mr: o# 0f bb /r] 386,SM,LOCK +$trio BTC rm#,imm8 [mi: o# 0f ba /7 ib,u] 386,LOCK +$trio BTR rm#,reg# [mr: o# 0f b3 /r] 386,SM,LOCK +$trio BTR rm#,imm8 [mi: o# 0f ab /6 ib,u] 386,LOCK +$trio BTC rm#,reg# [mr: o# 0f ab /r] 386,SM,LOCK +$trio BTC rm#,imm8 [mi: o# 0f ba /5 ib,u] 386,LOCK CALL imm [i: odf e8 rel] 8086,BND,NOAPX,SIZE CALL imm|near [i: odf e8 rel] 8086,ND,BND,NOAPX,SIZE @@ -729,45 +710,6 @@ NOT rm8 [m: hle f6 /2] 8086,LOCK NOT rm16 [m: hle o16 f7 /2] 8086,LOCK NOT rm32 [m: hle o32 f7 /2] 386,LOCK NOT rm64 [m: hle o64 f7 /2] X86_64,LONG,LOCK -OR mem,reg8 [mr: hle 08 /r] 8086,SM,LOCK -OR reg8,reg8 [mr: 08 /r] 8086 -OR mem,reg16 [mr: hle o16 09 /r] 8086,SM,LOCK -OR reg16,reg16 [mr: o16 09 /r] 8086 -OR mem,reg32 [mr: hle o32 09 /r] 386,SM,LOCK -OR reg32,reg32 [mr: o32 09 /r] 386 -OR mem,reg64 [mr: hle o64 09 /r] X86_64,LONG,SM,LOCK -OR reg64,reg64 [mr: o64 09 /r] X86_64,LONG -OR reg8,mem [rm: 0a /r] 8086,SM -OR reg8,reg8 [rm: 0a /r] 8086 -OR reg16,mem [rm: o16 0b /r] 8086,SM -OR reg16,reg16 [rm: o16 0b /r] 8086 -OR reg32,mem [rm: o32 0b /r] 386,SM -OR reg32,reg32 [rm: o32 0b /r] 386 -OR reg64,mem [rm: o64 0b /r] X86_64,LONG,SM -OR reg64,reg64 [rm: o64 0b /r] X86_64,LONG -OR rm16,imm8 [mi: hle o16 83 /1 ib,s] 8086,LOCK -OR rm32,imm8 [mi: hle o32 83 /1 ib,s] 386,LOCK -OR rm64,imm8 [mi: hle o64 83 /1 ib,s] X86_64,LONG,LOCK -OR reg_al,imm [-i: 0c ib] 8086,SM -OR reg_ax,sbyteword [mi: o16 83 /1 ib,s] 8086,SM,ND -OR reg_ax,imm [-i: o16 0d iw] 8086,SM -OR reg_eax,sbytedword [mi: o32 83 /1 ib,s] 386,SM,ND -OR reg_eax,imm [-i: o32 0d id] 386,SM -OR reg_rax,sbytedword [mi: o64 83 /1 ib,s] X86_64,LONG,SM,ND -OR reg_rax,imm [-i: o64 0d id,s] X86_64,LONG,SM -OR rm8,imm [mi: hle 80 /1 ib] 8086,SM,LOCK -OR rm16,sbyteword [mi: hle o16 83 /1 ib,s] 8086,SM,LOCK,ND -OR rm16,imm [mi: hle o16 81 /1 iw] 8086,SM,LOCK -OR rm32,sbytedword [mi: hle o32 83 /1 ib,s] 386,SM,LOCK,ND -OR rm32,imm [mi: hle o32 81 /1 id] 386,SM,LOCK -OR rm64,sbytedword [mi: hle o64 83 /1 ib,s] X86_64,LONG,SM,LOCK,ND -OR rm64,imm [mi: hle o64 81 /1 id,s] X86_64,LONG,SM,LOCK -OR mem,imm8 [mi: hle 80 /1 ib] 8086,SM,LOCK -OR mem,sbyteword16 [mi: hle o16 83 /1 ib,s] 8086,SM,LOCK,ND -OR mem,imm16 [mi: hle o16 81 /1 iw] 8086,SM,LOCK -OR mem,sbytedword32 [mi: hle o32 83 /1 ib,s] 386,SM,LOCK,ND -OR mem,imm32 [mi: hle o32 81 /1 id] 386,SM,LOCK -OR rm8,imm [mi: hle 82 /1 ib] 8086,SM,LOCK,ND,NOLONG OUT imm,reg_al [i-: e6 ib,u] 8086,SB,NOAPX OUT imm,reg_ax [i-: o16 e7 ib,u] 8086,SB,NOAPX OUT imm,reg_eax [i-: o32 e7 ib,u] 386,SB,NOAPX @@ -909,30 +851,6 @@ PUSHFD void [ o32 9c] 386,NOLONG PUSHFQ void [ o32 9c] X86_64,LONG PUSHFW void [ o16 9c] 8086 PXOR mmxreg,mmxrm [rm: np 0f ef /r] PENT,MMX,SQ -RCL rm8,unity [m-: d0 /2] 8086 -RCL rm8,reg_cl [m-: d2 /2] 8086 -RCL rm8,imm8 [mi: c0 /2 ib,u] 186 -RCL rm16,unity [m-: o16 d1 /2] 8086 -RCL rm16,reg_cl [m-: o16 d3 /2] 8086 -RCL rm16,imm8 [mi: o16 c1 /2 ib,u] 186 -RCL rm32,unity [m-: o32 d1 /2] 386 -RCL rm32,reg_cl [m-: o32 d3 /2] 386 -RCL rm32,imm8 [mi: o32 c1 /2 ib,u] 386 -RCL rm64,unity [m-: o64 d1 /2] X86_64,LONG -RCL rm64,reg_cl [m-: o64 d3 /2] X86_64,LONG -RCL rm64,imm8 [mi: o64 c1 /2 ib,u] X86_64,LONG -RCR rm8,unity [m-: d0 /3] 8086 -RCR rm8,reg_cl [m-: d2 /3] 8086 -RCR rm8,imm8 [mi: c0 /3 ib,u] 186 -RCR rm16,unity [m-: o16 d1 /3] 8086 -RCR rm16,reg_cl [m-: o16 d3 /3] 8086 -RCR rm16,imm8 [mi: o16 c1 /3 ib,u] 186 -RCR rm32,unity [m-: o32 d1 /3] 386 -RCR rm32,reg_cl [m-: o32 d3 /3] 386 -RCR rm32,imm8 [mi: o32 c1 /3 ib,u] 386 -RCR rm64,unity [m-: o64 d1 /3] X86_64,LONG -RCR rm64,reg_cl [m-: o64 d3 /3] X86_64,LONG -RCR rm64,imm8 [mi: o64 c1 /3 ib,u] X86_64,LONG RDSHR rm32 [m: o32 0f 36 /0] P6,CYRIX,SMM,NOAPX RDMSR void [ 0f 32] PENT,PRIV,NOAPX RDPMC void [ 0f 33] P6,NOAPX @@ -963,79 +881,19 @@ RETFQ imm [i: o64 ca iw] X86_64,LONG,SW RETNQ void [ o64nw c3] X86_64,LONG,BND RETNQ imm [i: o64nw c2 iw] X86_64,LONG,SW,BND -ROL rm8,unity [m-: d0 /0] 8086 -ROL rm8,reg_cl [m-: d2 /0] 8086 -ROL rm8,imm8 [mi: c0 /0 ib,u] 186 -ROL rm16,unity [m-: o16 d1 /0] 8086 -ROL rm16,reg_cl [m-: o16 d3 /0] 8086 -ROL rm16,imm8 [mi: o16 c1 /0 ib,u] 186 -ROL rm32,unity [m-: o32 d1 /0] 386 -ROL rm32,reg_cl [m-: o32 d3 /0] 386 -ROL rm32,imm8 [mi: o32 c1 /0 ib,u] 386 -ROL rm64,unity [m-: o64 d1 /0] X86_64,LONG -ROL rm64,reg_cl [m-: o64 d3 /0] X86_64,LONG -ROL rm64,imm8 [mi: o64 c1 /0 ib,u] X86_64,LONG -ROR rm8,unity [m-: d0 /1] 8086 -ROR rm8,reg_cl [m-: d2 /1] 8086 -ROR rm8,imm8 [mi: c0 /1 ib,u] 186 -ROR rm16,unity [m-: o16 d1 /1] 8086 -ROR rm16,reg_cl [m-: o16 d3 /1] 8086 -ROR rm16,imm8 [mi: o16 c1 /1 ib,u] 186 -ROR rm32,unity [m-: o32 d1 /1] 386 -ROR rm32,reg_cl [m-: o32 d3 /1] 386 -ROR rm32,imm8 [mi: o32 c1 /1 ib,u] 386 -ROR rm64,unity [m-: o64 d1 /1] X86_64,LONG -ROR rm64,reg_cl [m-: o64 d3 /1] X86_64,LONG -ROR rm64,imm8 [mi: o64 c1 /1 ib,u] X86_64,LONG RDM void [ 0f 3a] P6,CYRIX,ND,NOLONG,OBSOLETE RSDC reg_sreg,mem80 [rm: 0f 79 /r] 486,CYRIX,SMM RSLDT mem80 [m: 0f 7b /0] 486,CYRIX,SMM RSM void [ 0f aa] PENT,SMM RSTS mem80 [m: 0f 7d /0] 486,CYRIX,SMM SAHF void [ 9e] 8086 -SAL rm8,unity [m-: d0 /4] 8086,ND -SAL rm8,reg_cl [m-: d2 /4] 8086,ND -SAL rm8,imm8 [mi: c0 /4 ib,u] 186,ND -SAL rm16,unity [m-: o16 d1 /4] 8086,ND -SAL rm16,reg_cl [m-: o16 d3 /4] 8086,ND -SAL rm16,imm8 [mi: o16 c1 /4 ib,u] 186,ND -SAL rm32,unity [m-: o32 d1 /4] 386,ND -SAL rm32,reg_cl [m-: o32 d3 /4] 386,ND -SAL rm32,imm8 [mi: o32 c1 /4 ib,u] 386,ND -SAL rm64,unity [m-: o64 d1 /4] X86_64,LONG,ND -SAL rm64,reg_cl [m-: o64 d3 /4] X86_64,LONG,ND -SAL rm64,imm8 [mi: o64 c1 /4 ib,u] X86_64,LONG,ND SALC void [ d6] 8086,UNDOC -SAR rm8,unity [m-: d0 /7] 8086 -SAR rm8,reg_cl [m-: d2 /7] 8086 -SAR rm8,imm8 [mi: c0 /7 ib,u] 186 -SAR rm16,unity [m-: o16 d1 /7] 8086 -SAR rm16,reg_cl [m-: o16 d3 /7] 8086 -SAR rm16,imm8 [mi: o16 c1 /7 ib,u] 186 -SAR rm32,unity [m-: o32 d1 /7] 386 -SAR rm32,reg_cl [m-: o32 d3 /7] 386 -SAR rm32,imm8 [mi: o32 c1 /7 ib,u] 386 -SAR rm64,unity [m-: o64 d1 /7] X86_64,LONG -SAR rm64,reg_cl [m-: o64 d3 /7] X86_64,LONG -SAR rm64,imm8 [mi: o64 c1 /7 ib,u] X86_64,LONG SCASB void [ repe ae] 8086,NOAPX SCASD void [ repe o32 af] 386,NOAPX SCASQ void [ repe o64 af] X86_64,LONG,NOAPX SCASW void [ repe o16 af] 8086,NOAPX SFENCE void [ np 0f ae f8] X86_64,LONG,AMD SGDT mem [m: 0f 01 /0] 286 -SHL rm8,unity [m-: d0 /4] 8086 -SHL rm8,reg_cl [m-: d2 /4] 8086 -SHL rm8,imm8 [mi: c0 /4 ib,u] 186 -SHL rm16,unity [m-: o16 d1 /4] 8086 -SHL rm16,reg_cl [m-: o16 d3 /4] 8086 -SHL rm16,imm8 [mi: o16 c1 /4 ib,u] 186 -SHL rm32,unity [m-: o32 d1 /4] 386 -SHL rm32,reg_cl [m-: o32 d3 /4] 386 -SHL rm32,imm8 [mi: o32 c1 /4 ib,u] 386 -SHL rm64,unity [m-: o64 d1 /4] X86_64,LONG -SHL rm64,reg_cl [m-: o64 d3 /4] X86_64,LONG -SHL rm64,imm8 [mi: o64 c1 /4 ib,u] X86_64,LONG SHLD mem,reg16,imm [mri: o16 0f a4 /r ib,u] 386,SM0-1,SB,AR2 SHLD reg16,reg16,imm [mri: o16 0f a4 /r ib,u] 386,SM0-1,SB,AR2 SHLD mem,reg32,imm [mri: o32 0f a4 /r ib,u] 386,SM0-1,SB,AR2 @@ -1048,18 +906,6 @@ SHLD mem,reg32,reg_cl [mr-: o32 0f a5 /r] 386,SM SHLD reg32,reg32,reg_cl [mr-: o32 0f a5 /r] 386 SHLD mem,reg64,reg_cl [mr-: o64 0f a5 /r] X86_64,LONG,SM SHLD reg64,reg64,reg_cl [mr-: o64 0f a5 /r] X86_64,LONG -SHR rm8,unity [m-: d0 /5] 8086 -SHR rm8,reg_cl [m-: d2 /5] 8086 -SHR rm8,imm8 [mi: c0 /5 ib,u] 186 -SHR rm16,unity [m-: o16 d1 /5] 8086 -SHR rm16,reg_cl [m-: o16 d3 /5] 8086 -SHR rm16,imm8 [mi: o16 c1 /5 ib,u] 186 -SHR rm32,unity [m-: o32 d1 /5] 386 -SHR rm32,reg_cl [m-: o32 d3 /5] 386 -SHR rm32,imm8 [mi: o32 c1 /5 ib,u] 386 -SHR rm64,unity [m-: o64 d1 /5] X86_64,LONG -SHR rm64,reg_cl [m-: o64 d3 /5] X86_64,LONG -SHR rm64,imm8 [mi: o64 c1 /5 ib,u] X86_64,LONG SHRD mem,reg16,imm [mri: o16 0f ac /r ib,u] 386,SM0-1,SB,AR2 SHRD reg16,reg16,imm [mri: o16 0f ac /r ib,u] 386,SM0-1,SB,AR2 SHRD mem,reg32,imm [mri: o32 0f ac /r ib,u] 386,SM0-1,SB,AR2 diff --git a/x86/preinsns.pl b/x86/preinsns.pl index fbc24f9b..4f086a78 100755 --- a/x86/preinsns.pl +++ b/x86/preinsns.pl @@ -19,35 +19,36 @@ our %macros; our($macro, $outfile, $infile, $line); # Public for error messages # Common pattern for the basic 8 arithmetric functions -$macros{'arith'} = sub { - return eightfold(<<'EOL', {}, @_); -$op rm8,reg8 [mr: $hle $o0 /r ] 8086,SM,$lock -$op rm16,reg16 [mr: $hle o16 $o1 /r ] 8086,SM,$lock -$op rm32,reg32 [mr: $hle o32 $o1 /r ] 386,SM,$lock,$zu -$op rm64,reg64 [mr: $hle o64 $o1 /r ] X86_64,LONG,SM,$lock,$zu -$op reg8,rm8 [rm: $o2 /r ] 8086,SM -$op reg16,rm16 [rm: o16 $o3 /r ] 8086,SM -$op reg32,rm32 [rm: o32 $o3 /r ] 386,SM,$zu -$op reg64,rm64 [rm: o64 $o3 /r ] X86_64,LONG,SM,$zu -$op reg_al,imm8 [-i: $o4 ib ] 8086,SM +$macros{'arith'} = { + 'def' => *def_eightfold, + 'txt' => <<'EOL' +$op rm8,reg8 [mr: $hle $00 /r ] 8086,SM,$lock +$op rm16,reg16 [mr: $hle o16 $01 /r ] 8086,SM,$lock +$op rm32,reg32 [mr: $hle o32 $01 /r ] 386,SM,$lock,$zu +$op rm64,reg64 [mr: $hle o64 $01 /r ] X86_64,LONG,SM,$lock,$zu +$op reg8,rm8 [rm: $02 /r ] 8086,SM +$op reg16,rm16 [rm: o16 $03 /r ] 8086,SM +$op reg32,rm32 [rm: o32 $03 /r ] 386,SM,$zu +$op reg64,rm64 [rm: o64 $03 /r ] X86_64,LONG,SM,$zu +$op reg_al,imm8 [-i: $04 ib ] 8086,SM $op rm8,imm8 [mi: $hle 80 /$n ib ] 8086,SM,$lock $op rm16,sbyteword16 [mi: $hle o16 83 /$n ib,s ] 8086,SM,$lock -$op reg_ax,imm16 [-i: o16 $o5 iw ] 8086,SM +$op reg_ax,imm16 [-i: o16 $05 iw ] 8086,SM $op rm16,imm16 [mi: $hle o16 81 /$n iw ] 8086,SM,$lock $op rm32,sbytedword32 [mi: $hle o32 83 /$n ib,s ] 386,SM,$lock,$zu -$op reg_eax,imm32 [-i: o32 $o5 id ] 386,SM,$zu +$op reg_eax,imm32 [-i: o32 $05 id ] 386,SM,$zu $op rm32,imm32 [mi: $hle o32 81 /$n id ] 386,SM,$lock,$zu $op rm64,sbytedword64 [mi: $hle o64 83 /$n ib,s ] X86_64,LONG,SM,$lock,$zu -$op reg_rax,sdword64 [-i: o64 $o5 id,s ] X86_64,LONG,SM,$zu +$op reg_rax,sdword64 [-i: o64 $05 id,s ] X86_64,LONG,SM,$zu $op rm64,sdword64 [mi: $hle o64 81 /$n id,s ] X86_64,LONG,SM,$lock,$zu -$op reg8?,reg8,rm8 [vrm: evex.ndx.nf.l0.m4.o8 $o2 /r ] $apx,SM -$op reg16?,reg16,rm16 [vrm: evex.ndx.nf.l0.m4.o16 $o3 /r ] $apx,SM -$op reg32?,reg32,rm32 [vrm: evex.ndx.nf.l0.m4.o32 $o3 /r ] $apx,SM -$op reg64?,reg64,rm64 [vrm: evex.ndx.nf.l0.m4.o64 $o3 /r ] $apx,SM -$op reg8?,rm8,reg8 [vmr: evex.ndx.nf.l0.m4.o8 $o0 /r ] $apx,SM -$op reg16?,rm16,reg16 [vmr: evex.ndx.nf.l0.m4.o16 $o1 /r ] $apx,SM -$op reg32?,rm32,reg32 [vmr: evex.ndx.nf.l0.m4.o32 $o1 /r ] $apx,SM,$zu -$op reg64?,rm64,reg64 [vmr: evex.ndx.nf.l0.m4.o64 $o1 /r ] $apx,SM,$zu +$op reg8?,reg8,rm8 [vrm: evex.ndx.nf.l0.m4.o8 $02 /r ] $apx,SM +$op reg16?,reg16,rm16 [vrm: evex.ndx.nf.l0.m4.o16 $03 /r ] $apx,SM +$op reg32?,reg32,rm32 [vrm: evex.ndx.nf.l0.m4.o32 $03 /r ] $apx,SM +$op reg64?,reg64,rm64 [vrm: evex.ndx.nf.l0.m4.o64 $03 /r ] $apx,SM +$op reg8?,rm8,reg8 [vmr: evex.ndx.nf.l0.m4.o8 $00 /r ] $apx,SM +$op reg16?,rm16,reg16 [vmr: evex.ndx.nf.l0.m4.o16 $01 /r ] $apx,SM +$op reg32?,rm32,reg32 [vmr: evex.ndx.nf.l0.m4.o32 $01 /r ] $apx,SM,$zu +$op reg64?,rm64,reg64 [vmr: evex.ndx.nf.l0.m4.o64 $01 /r ] $apx,SM,$zu $op reg8?,rm8,imm8 [vmi: evex.ndx.nf.l0.m4.o8 80 /$n ib ] $apx,SM $op reg16?,rm16,sbyteword16 [vmi: evex.ndx.nf.l0.m4.o16 83 /$n ib,s ] $apx,SM $op reg16?,rm16,imm16 [vmi: evex.ndx.nf.l0.m4.o16 81 /$n iw ] $apx,SM @@ -59,8 +60,9 @@ EOL }; # Common pattern for the basic shift and rotate instructions -$macros{'shift'} = sub { - return eightfold(<<'EOL', {}, @_); +$macros{'shift'} = { + 'def' => *def_eightfold, + 'txt' => <<'EOL' $op rm8,unity [m-: d0 /$n] 8086 $op rm8,reg_cl [m-: d2 /$n] 8086 $op rm8,imm8 [mi: c0 /$n ib,u] 186 @@ -92,34 +94,69 @@ $op reg64?,rm64,imm8 [vmi: evex.ndx.nf.l0.m4.o64 c1 /$n ib,u] $apx,SM0-1 EOL }; +# +# Common pattern for 8/16/32/64 or 16/32/64 instructions +# +$macros{'trio'} = { 'func' => *func_trio_quad, 'first' => 16 }; +$macros{'quad'} = { 'func' => *func_trio_quad, 'first' => 8 }; + +sub func_trio_quad($$$) { + my($mac, $args, $rawargs) = @_; + + my @ol; + + my %sizename = ( 8 => 'B', 16 => 'W', 32 => 'D', 64 => 'Q' ); + + for (my $i = $mac->{'first'}; $i <= 64; $i <<= 1) { + my $o; + my $ins = join("\t", @$rawargs); + while ($ins =~ /^(.*?)((?:\b[0-9a-f]{2})?\#|\%)(.*)$/) { + $o .= $1; + my $mw = $2; + $ins = $3; + if ($mw eq '%') { + $o .= $sizename{$i}; + } elsif ($mw =~ /^([0-9a-f]{2})\#$/) { + $o .= sprintf('%02x', hex($1) | ($i >= 16)); + } else { + $o .= $i; + } + } + $o .= $ins; + $o =~ s/\bNOLONG${i}\b/NOLONG/; + $o =~ s/\bNOLONG[0-9]+\b//; + if ($i >= 64) { + next if ($o =~ /\bNOLONG\b/); + $o .= ',X86_64,LONG'; + } elsif ($i >= 32) { + $o .= ',386'; + } + push(@ol, $o); + } + + return @ol; +} + # # Macro helper functions for common constructs # -# "8-fold" or similar sequential instruction patterns -sub eightfold($$@) { - my $pat = shift(@_); +# Parse arguments handling variable setting +sub parse_args($@) { my $uvars = shift(@_); - my @l; - - my $n = 0; - - my %initvars = ('shift' => 3, %$uvars); + my %initvars = defined($uvars) ? %$uvars : (); + my @oa; + my $n = 0; # Argument counter foreach my $ops (@_) { my %vars = %initvars; - $vars{'n'} = $n; - for (my $i = 0; $i < (1 << $vars{'shift'}); $i++) { - $vars{"o$i"} = sprintf("%02x", $vars{'base'}+($n << $vars{'shift'})+$i); - } - my $nd = 0; - my $outdata = 0; + $vars{'n'} = $n; + $vars{'nd'} = 0; + my @oaa; foreach my $op ($ops =~ /(?:[^\,\[\]\"]+|\[.*?\]|\".*?\")+/g) { $op =~ s/\"//g; - if ($op =~ s/^\@//) { - $nd = 1; - } + $vars{'nd'} = 'nd' if ($op =~ s/^\@//); if ($op =~ /^(\w+)\=(.*)$/) { $vars{$1} = $2; next; @@ -135,38 +172,63 @@ sub eightfold($$@) { } $vars{'op'} = $op; - my $sp = substitute($pat, \%vars); - if ($nd) { - $sp =~ s/^(\w.*)$/$1,ND/gm; - } - push(@l, $sp); - $outdata = $nd = 1; + push(@oaa, {%vars}); + $vars{'nd'} = 'nd'; } - if ($outdata) { - $n++; + if (scalar(@oaa)) { + push(@oa, [@oaa]); } else { + # Global variable setting %initvars = %vars; } } - return @l; + return @oa; +} + +# "8-fold" or similar sequential instruction patterns +sub def_eightfold($$$) { + my($var, $arg, $mac) = @_; + + my $shift = $arg->{'shift'}; + $shift = 3 unless (defined($shift)); + + if ($var =~ /^[0-9a-f]{1,2}$/) { + return sprintf('%02x', hex($var) + ($arg->{'n'} << $shift)); + } else { + return $var; + } } # # Substitute variables in a pattern # -sub substitute($$) { - my($pat, $vars) = @_; +sub substitute($$;$) { + my($pat, $vars, $defs) = @_; my $o = ''; + my $def; + my @defargs; - while ($pat =~ /^(.*?)\$(?:(\w+)\b|\{(\w+)\})(.*)$/s) { + if (defined($defs)) { + @defargs = @$defs; + $def = shift(@defargs); + } + + while ($pat =~ /^(.*?)\$(?:(\w+\b|\$+)|\{(\w+|\$+)\})(.*)$/s) { $o .= $1; $pat = $4; my $vn = $2.$3; - my $vv = $vars->{$vn}; - if (!defined($vv)) { -# warn "$0:$infile:$line: no variable \$$vn in macro \$$macro\n"; - $vv = $vn; + my $vv; + if ($vn =~ /^\$/) { + $vv = $vn; # Reduce by one $ + } else { + $vv = $vars->{$vn}; + if (!defined($vv)) { + if (defined($def)) { + $vv = $def->($vn, @defargs); + } + $vv = $vn unless(defined($vv)); + } } $vv =~ s/\s+$// if ($pat =~ /^\s/); $o .= $vv; @@ -176,23 +238,50 @@ sub substitute($$) { return $o; } +# +# Build output by substituting the variables for each argument, +# +sub subst_list($$;$$) { + my($pat, $args, $def, $mac) = @_; + my @o = (); + + foreach my $a0 (@$args) { + foreach my $arg (@$a0) { + push(@o, substitute($pat, $arg, [$def, $arg, $mac])); + } + } + + return @o; +} + +# +# Actually invoke a macro +# +sub process_macro(@) { + $macro = shift(@_); + my $mac = $macros{$macro}; + + if (!defined($mac)) { + die "$0:$infile:$line: no macro named \$$macro\n"; + } + + my @args = parse_args($mac->{'vars'}, @_); + my $func = $mac->{'func'}; + my @o; + if (defined($func)) { + @o = $func->($mac, \@args, \@_); + } else { + @o = subst_list($mac->{'txt'}, \@args, $mac->{'def'}, $mac); + } + return map { split(/\n/, $_) } @o; +} + # # Main program # ($infile, $outfile) = @ARGV; $line = 0; -sub process_macro(@) { - $macro = shift(@_); - my $mfunc = $macros{$macro}; - - if (!defined($mfunc)) { - die "$0:$infile:$line: no macro named \$$macro\n"; - } - - return map { split(/\n/, $_) } $mfunc->(@_); -} - ## XXX: fix special case: XCHG ## XXX: check: CMPSS, CMPSD ## XXX: check VEX encoded instructions that do not write @@ -209,14 +298,11 @@ umwait|ver[rw]|vtestp[ps]|xadd|xor|xtest|getsec|rsm|sbb|cmps[bwdq]|hint_.*)$'; my $nozero = '^(jmp|call|bt|test|cmp|ud[012].*|ptwrite|tpause|u?monitor.*|u?mwait.*|incssp.*|\ enqcmds?|senduipi|hint_.*|jmpe|nop|inv.*|push2?p?|vmwrite|clzero|clflush|clwb|lkgs)$'; -my $_last_flag; # Simple uniqueness counter sub add_flag($@) { my $flags = shift(@_); foreach my $fl (@_) { - unless ($fl =~ /^\s*$/) { - $flags->{$fl} = $flags->{$fl} || ++$_last_flag; - } + $flags->{$fl}++ unless ($fl =~ /^\s*$/); } } @@ -302,18 +388,16 @@ open(my $out, '>', $outfile) or die "$0:$outfile: $!\n"; while (defined(my $l = <$in>)) { $line++; chomp $l; - my @insl; + my @insi = ($l); - if ($l =~ /^\s*\$(\w+[^\;]*?)\s*(\;.*)?$/) { - print $out $2, "\n" if ($2 ne ''); # Comment - my @args = ($1 =~ /(?:\[.*?\]|\".*?\"|[^\[\]\"\s]+)+/g); - @insl = process_macro(@args); - } else { - @insl = ($l); - } - - foreach my $ins (@insl) { - process_insn($out, $ins); + while (defined(my $li = shift(@insi))) { + if ($li =~ /^\s*\$(\w+[^\;]*?)\s*(\;.*)?$/) { + print $out $2, "\n" unless ($2 eq ''); # Retain comment + my @args = ($1 =~ /(?:\[[^\]]*\]|\"[^\"]*\"|[^\[\]\"\s])+/g); + push(@insi, process_macro(@args)); + } else { + process_insn($out, $li); + } } } diff --git a/x86/regs.dat b/x86/regs.dat index 12e51942..9bc91841 100644 --- a/x86/regs.dat +++ b/x86/regs.dat @@ -54,11 +54,11 @@ ah REG_HIGH reg8 4 ax REG_AX reg16 0 eax REG_EAX reg32 0 rax REG_RAX reg64 0 -bl REG8NA reg8,reg8_rex 3 +bl REG_BL reg8,reg8_rex 3 bh REG_HIGH reg8 7 -bx REG16NA reg16 3 -ebx REG32NA reg32 3 -rbx REG64NA reg64 3 +bx REG_BX reg16 3 +ebx REG_EBX reg32 3 +rbx REG_RBX reg64 3 cl REG_CL reg8,reg8_rex 1 ch REG_HIGH reg8 5 cx REG_CX reg16 1