insns.pl: audit for impossible Sx patterns; fix a few

Break the instruction processing if there are impossible combinations
of Sx flags and operand sizes. If the intent is to always require
explicit sizes, use the SX flag.

The INSERTPS instruction pattern was explicitly wrong, the rest of
these are nuisance fixes.

TODO: fix the disassembler to be able to exclude patterns where these
bits don't matter.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2020-07-30 15:13:13 -07:00
parent 5b89628e44
commit e56c2dc5b7
6 changed files with 141 additions and 21 deletions

36
test/immsize.asm Normal file
View File

@ -0,0 +1,36 @@
bits 64
%macro b 1
%1 ax,16
%1 eax,16
%1 rax,16
%1 word [rdi],16
%1 dword [rdi],16
%1 qword [rdi],16
%1 ax,byte 16
%1 eax,byte 16
%1 rax,byte 16
%1 word [rdi],byte 16
%1 dword [rdi],byte 16
%1 qword [rdi],byte 16
%endmacro
b bt
b btc
b btr
b bts
imul ax,[rdi],16
imul ax,word [rdi],16
imul ax,[rdi],byte 16
imul ax,word [rdi],byte 16
imul eax,[rdi],16
imul eax,dword [rdi],16
imul eax,[rdi],byte 16
imul eax,dword [rdi],byte 16
imul rax,[rdi],16
imul rax,qword [rdi],16
imul rax,[rdi],byte 16
imul rax,qword [rdi],byte 16

10
test/insertps.asm Normal file
View File

@ -0,0 +1,10 @@
bits 64
insertps xmm0,xmm1,16
insertps xmm0,dword xmm1,16
insertps xmm0,xmm1,byte 16
insertps xmm0,dword xmm1,byte 16
insertps xmm0,[rax],16
insertps xmm0,dword [rax],16
insertps xmm0,[rax],byte 16
insertps xmm0,dword [rax],byte 16

15
test/movhpd.asm Normal file
View File

@ -0,0 +1,15 @@
bits 64
movhpd xmm0,[rdi+2]
movhpd xmm0,qword [rdi+2]
movhpd [rsi+3],xmm1
movhpd qword [rsi+3],xmm1
vmovhpd xmm2,xmm1,[rax+4]
vmovhpd xmm2,xmm1,qword [rax+4]
vmovhpd xmm3,[rax+4]
vmovhpd xmm3,qword [rax+4]
vmovhpd [rcx+5],xmm4
vmovhpd qword [rcx+5],xmm4

14
test/ssesize.asm Normal file
View File

@ -0,0 +1,14 @@
_start:
movd ecx,xmm0
movd [foo],xmm0
movd dword [foo],xmm0
movdqa xmm1,xmm0
movdqa [foo],xmm0
movdqa oword [foo],xmm0
cmppd xmm2,xmm3,8
cmppd xmm2,xmm3,byte 8
section .bss
foo: reso 1

View File

@ -218,36 +218,36 @@ BT mem,reg32 [mr: o32 0f a3 /r] 386,SM
BT reg32,reg32 [mr: o32 0f a3 /r] 386
BT mem,reg64 [mr: o64 0f a3 /r] X86_64,LONG,SM
BT reg64,reg64 [mr: o64 0f a3 /r] X86_64,LONG
BT rm16,imm [mi: o16 0f ba /4 ib,u] 386,SB
BT rm32,imm [mi: o32 0f ba /4 ib,u] 386,SB
BT rm64,imm [mi: o64 0f ba /4 ib,u] X86_64,LONG,SB
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 mem,reg16 [mr: hle o16 0f bb /r] 386,SM,LOCK
BTC reg16,reg16 [mr: o16 0f bb /r] 386
BTC mem,reg32 [mr: hle o32 0f bb /r] 386,SM,LOCK
BTC reg32,reg32 [mr: o32 0f bb /r] 386
BTC mem,reg64 [mr: hle o64 0f bb /r] X86_64,LONG,SM,LOCK
BTC reg64,reg64 [mr: o64 0f bb /r] X86_64,LONG
BTC rm16,imm [mi: hle o16 0f ba /7 ib,u] 386,SB,LOCK
BTC rm32,imm [mi: hle o32 0f ba /7 ib,u] 386,SB,LOCK
BTC rm64,imm [mi: hle o64 0f ba /7 ib,u] X86_64,LONG,SB,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 mem,reg16 [mr: hle o16 0f b3 /r] 386,SM,LOCK
BTR reg16,reg16 [mr: o16 0f b3 /r] 386
BTR mem,reg32 [mr: hle o32 0f b3 /r] 386,SM,LOCK
BTR reg32,reg32 [mr: o32 0f b3 /r] 386
BTR mem,reg64 [mr: hle o64 0f b3 /r] X86_64,LONG,SM,LOCK
BTR reg64,reg64 [mr: o64 0f b3 /r] X86_64,LONG
BTR rm16,imm [mi: hle o16 0f ba /6 ib,u] 386,SB,LOCK
BTR rm32,imm [mi: hle o32 0f ba /6 ib,u] 386,SB,LOCK
BTR rm64,imm [mi: hle o64 0f ba /6 ib,u] X86_64,LONG,SB,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 mem,reg16 [mr: hle o16 0f ab /r] 386,SM,LOCK
BTS reg16,reg16 [mr: o16 0f ab /r] 386
BTS mem,reg32 [mr: hle o32 0f ab /r] 386,SM,LOCK
BTS reg32,reg32 [mr: o32 0f ab /r] 386
BTS mem,reg64 [mr: hle o64 0f ab /r] X86_64,LONG,SM,LOCK
BTS reg64,reg64 [mr: o64 0f ab /r] X86_64,LONG
BTS rm16,imm [mi: hle o16 0f ba /5 ib,u] 386,SB,LOCK
BTS rm32,imm [mi: hle o32 0f ba /5 ib,u] 386,SB,LOCK
BTS rm64,imm [mi: hle o64 0f ba /5 ib,u] X86_64,LONG,SB,LOCK
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
CALL imm [i: odf e8 rel] 8086,BND
CALL imm|near [i: odf e8 rel] 8086,ND,BND
CALL imm|far [i: odf 9a iwd seg] 8086,ND,NOLONG
@ -607,7 +607,7 @@ IMUL reg32,mem [rm: o32 0f af /r] 386,SM
IMUL reg32,reg32 [rm: o32 0f af /r] 386
IMUL reg64,mem [rm: o64 0f af /r] X86_64,LONG,SM
IMUL reg64,reg64 [rm: o64 0f af /r] X86_64,LONG
IMUL reg16,mem,imm8 [rmi: o16 6b /r ib,s] 186,SM
IMUL reg16,mem,imm8 [rmi: o16 6b /r ib,s] 186,SM2
IMUL reg16,mem,sbyteword [rmi: o16 6b /r ib,s] 186,SM,ND
IMUL reg16,mem,imm16 [rmi: o16 69 /r iw] 186,SM
IMUL reg16,mem,imm [rmi: o16 69 /r iw] 186,SM,ND
@ -615,7 +615,7 @@ IMUL reg16,reg16,imm8 [rmi: o16 6b /r ib,s] 186
IMUL reg16,reg16,sbyteword [rmi: o16 6b /r ib,s] 186,SM,ND
IMUL reg16,reg16,imm16 [rmi: o16 69 /r iw] 186
IMUL reg16,reg16,imm [rmi: o16 69 /r iw] 186,SM,ND
IMUL reg32,mem,imm8 [rmi: o32 6b /r ib,s] 386,SM
IMUL reg32,mem,imm8 [rmi: o32 6b /r ib,s] 386,SM2
IMUL reg32,mem,sbytedword [rmi: o32 6b /r ib,s] 386,SM,ND
IMUL reg32,mem,imm32 [rmi: o32 69 /r id] 386,SM
IMUL reg32,mem,imm [rmi: o32 69 /r id] 386,SM,ND
@ -623,9 +623,9 @@ IMUL reg32,reg32,imm8 [rmi: o32 6b /r ib,s] 386
IMUL reg32,reg32,sbytedword [rmi: o32 6b /r ib,s] 386,SM,ND
IMUL reg32,reg32,imm32 [rmi: o32 69 /r id] 386
IMUL reg32,reg32,imm [rmi: o32 69 /r id] 386,SM,ND
IMUL reg64,mem,imm8 [rmi: o64 6b /r ib,s] X86_64,LONG,SM
IMUL reg64,mem,imm8 [rmi: o64 6b /r ib,s] X86_64,LONG,SM2
IMUL reg64,mem,sbytedword [rmi: o64 6b /r ib,s] X86_64,LONG,SM,ND
IMUL reg64,mem,imm32 [rmi: o64 69 /r id] X86_64,LONG,SM
IMUL reg64,mem,imm32 [rmi: o64 69 /r id] X86_64,LONG,SM2
IMUL reg64,mem,imm [rmi: o64 69 /r id,s] X86_64,LONG,SM,ND
IMUL reg64,reg64,imm8 [rmi: o64 6b /r ib,s] X86_64,LONG
IMUL reg64,reg64,sbytedword [rmi: o64 6b /r ib,s] X86_64,LONG,SM,ND
@ -1959,7 +1959,7 @@ DPPD xmmreg,xmmrm128,imm8 [rmi: 66 0f 3a 41 /r ib,u] SSE41
DPPS xmmreg,xmmrm128,imm8 [rmi: 66 0f 3a 40 /r ib,u] SSE41
EXTRACTPS rm32,xmmreg,imm8 [mri: 66 0f 3a 17 /r ib,u] SSE41
EXTRACTPS reg64,xmmreg,imm8 [mri: o64 66 0f 3a 17 /r ib,u] SSE41,X86_64,LONG
INSERTPS xmmreg,xmmrm32,imm8 [rmi: 66 0f 3a 21 /r ib,u] SSE41,SD
INSERTPS xmmreg,xmmrm32,imm8 [rmi: 66 0f 3a 21 /r ib,u] SSE41
MOVNTDQA xmmreg,mem128 [rm: 66 0f 38 2a /r] SSE41
MPSADBW xmmreg,xmmrm128,imm8 [rmi: 66 0f 3a 42 /r ib,u] SSE41
PACKUSDW xmmreg,xmmrm128 [rm: 66 0f 38 2b /r] SSE41

View File

@ -1,7 +1,7 @@
#!/usr/bin/perl
## --------------------------------------------------------------------------
##
## Copyright 1996-2017 The NASM Authors - All Rights Reserved
## Copyright 1996-2020 The NASM Authors - All Rights Reserved
## See the file AUTHORS included with the NASM distribution for
## the specific copyright holders.
##
@ -444,7 +444,7 @@ sub format_insn($$$$$) {
my $nd = 0;
my ($num, $flagsindex);
my @bytecode;
my ($op, @ops, $opp, @opx, @oppx, @decos, @opevex);
my ($op, @ops, @opsize, $opp, @opx, @oppx, @decos, @opevex);
return (undef, undef) if $operands eq "ignore";
@ -452,9 +452,11 @@ sub format_insn($$$$$) {
$operands =~ s/\*//g;
$operands =~ s/:/|colon,/g;
@ops = ();
@opsize = ();
@decos = ();
if ($operands ne 'void') {
foreach $op (split(/,/, $operands)) {
my $opsz = 0;
@opx = ();
@opevex = ();
foreach $opp (split(/\|/, $op)) {
@ -465,6 +467,7 @@ sub format_insn($$$$$) {
if ($opp =~ s/(?<!\d)(8|16|32|64|80|128|256|512)$//) {
push(@oppx, "bits$1");
$opsz = $1 + 0;
}
$opp =~ s/^mem$/memory/;
$opp =~ s/^memory_offs$/mem_offs/;
@ -481,6 +484,7 @@ sub format_insn($$$$$) {
}
$op = join('|', @opx);
push(@ops, $op);
push(@opsize, $opsz);
push(@decos, (@opevex ? join('|', @opevex) : '0'));
}
}
@ -488,6 +492,7 @@ sub format_insn($$$$$) {
$num = scalar(@ops);
while (scalar(@ops) < $MAX_OPERANDS) {
push(@ops, '0');
push(@opsize, 0);
push(@decos, '0');
}
$operands = join(',', @ops);
@ -499,11 +504,14 @@ sub format_insn($$$$$) {
}
$decorators =~ tr/a-z/A-Z/;
# Remember if we have an ARx flag
my $arx = undef;
# expand and uniqify the flags
my %flags;
foreach my $flag (split(',', $flags)) {
next if ($flag eq '');
if ($flag eq 'ND') {
$nd = 1;
} else {
@ -514,6 +522,10 @@ sub format_insn($$$$$) {
# These flags imply OBSOLETE
$flags{'OBSOLETE'}++;
}
if ($flag =~ /^AR([0-9]+)$/) {
$arx = $1+0;
}
}
if ($codes =~ /evex\./) {
@ -522,8 +534,41 @@ sub format_insn($$$$$) {
$flags{'VEX'}++;
}
# Look for SM flags clearly inconsistent with operand bitsizes
if ($flags{'SM'} || $flags{'SM2'}) {
my $ssize = 0;
my $e = $flags{'SM2'} ? 2 : $MAX_OPERANDS;
for (my $i = 0; $i < $e; $i++) {
next if (!$opsize[$i]);
if (!$ssize) {
$ssize = $opsize[$i];
} elsif ($opsize[$i] != $ssize) {
die "$fname:$line: inconsistent SM flag for argument $i\n";
}
}
}
# Look for Sx flags that can never match operand bitsizes. If the
# intent is to never match (require explicit sizes), use the SX flag.
# This doesn't apply to registers that pre-define specific sizes;
# this should really be derived from include/opflags.h...
my %sflags = ( 'SB' => 8, 'SW' => 16, 'SD' => 32, 'SQ' => 64,
'SO' => 128, 'SY' => 256, 'SZ' => 512 );
my $s = defined($arx) ? $arx : 0;
my $e = defined($arx) ? $arx : $MAX_OPERANDS - 1;
foreach my $sf (keys(%sflags)) {
next if (!$flags{$sf});
for (my $i = $s; $i <= $e; $i++) {
if ($opsize[$i] && $ops[$i] !~ /\breg_(gpr|[cdts]reg)\b/) {
die "$fname:$line: inconsistent $sf flag for argument $i ($ops[$i])\n"
if ($opsize[$i] != $sflags{$sf});
}
}
}
$flagsindex = insns_flag_index(keys %flags);
die "$fname:$line: error in flags $flags" unless (defined($flagsindex));
die "$fname:$line: error in flags $flags\n" unless (defined($flagsindex));
@bytecode = (decodify($codes, $relax), 0);
push(@bytecode_list, [@bytecode]);