0
0
mirror of https://github.com/netwide-assembler/nasm.git synced 2025-10-10 00:25:06 -04:00

insns: more macro goodness

Even better macro support, add match for the BX register.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin
2024-08-14 20:48:18 -07:00
parent 1b136eb543
commit 557d99d796
5 changed files with 214 additions and 261 deletions

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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