aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin (Intel) <hpa@zytor.com>2020-07-30 15:13:13 -0700
committerH. Peter Anvin (Intel) <hpa@zytor.com>2020-07-30 15:16:11 -0700
commite56c2dc5b7223f231d4d080690cb32a301ba8766 (patch)
tree4c3af5bd4c16d0ce6e04329d6a1d31819242acd3
parent5b89628e44fe97771662163067588d255f5c86a6 (diff)
downloadnasm-e56c2dc5b7223f231d4d080690cb32a301ba8766.tar.gz
nasm-e56c2dc5b7223f231d4d080690cb32a301ba8766.tar.xz
nasm-e56c2dc5b7223f231d4d080690cb32a301ba8766.zip
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>
-rw-r--r--test/immsize.asm36
-rw-r--r--test/insertps.asm10
-rw-r--r--test/movhpd.asm15
-rw-r--r--test/ssesize.asm14
-rw-r--r--x86/insns.dat34
-rwxr-xr-xx86/insns.pl53
6 files changed, 141 insertions, 21 deletions
diff --git a/test/immsize.asm b/test/immsize.asm
new file mode 100644
index 00000000..742e3ae0
--- /dev/null
+++ b/test/immsize.asm
@@ -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
diff --git a/test/insertps.asm b/test/insertps.asm
new file mode 100644
index 00000000..d66240d8
--- /dev/null
+++ b/test/insertps.asm
@@ -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
diff --git a/test/movhpd.asm b/test/movhpd.asm
new file mode 100644
index 00000000..af1e5740
--- /dev/null
+++ b/test/movhpd.asm
@@ -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
diff --git a/test/ssesize.asm b/test/ssesize.asm
new file mode 100644
index 00000000..a812cdee
--- /dev/null
+++ b/test/ssesize.asm
@@ -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
diff --git a/x86/insns.dat b/x86/insns.dat
index bc0916a3..e24c2479 100644
--- a/x86/insns.dat
+++ b/x86/insns.dat
@@ -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
diff --git a/x86/insns.pl b/x86/insns.pl
index b13569b5..aed8c679 100755
--- a/x86/insns.pl
+++ b/x86/insns.pl
@@ -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]);