summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin (Intel) <hpa@zytor.com>2019-08-09 14:52:16 -0700
committerH. Peter Anvin (Intel) <hpa@zytor.com>2019-08-09 14:52:16 -0700
commit5b394611781dfa20b87253dcd81b7e398f6478bb (patch)
treefdb18329b9c3cdef3c578514c012e2a0edba2a1c
parentfb118890402f44a816c7e345b80e2b2dd54c73b7 (diff)
downloadnasm-5b394611781dfa20b87253dcd81b7e398f6478bb.tar.gz
obsolete handing: handle a few more subcases in a useful way
Distinguish instructions which have once been valid (OBSOLETE) from those that never saw the light of day (NEVER). Futhermore, flag instructions which devolve to an architectural noop from those with undefined behavior and possibly recycled opcodes. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
-rw-r--r--asm/assemble.c31
-rw-r--r--test/obsolete.asm3
-rw-r--r--x86/iflags.ph4
-rw-r--r--x86/insns.dat2
-rwxr-xr-xx86/insns.pl21
5 files changed, 46 insertions, 15 deletions
diff --git a/asm/assemble.c b/asm/assemble.c
index ad6d5ea6..de1abc26 100644
--- a/asm/assemble.c
+++ b/asm/assemble.c
@@ -781,6 +781,11 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
if (m == MOK_GOOD) {
/* Matches! */
if (unlikely(itemp_has(temp, IF_OBSOLETE))) {
+ errflags warning;
+ const char *whathappened;
+ const char *validity;
+ bool never = itemp_has(temp, IF_NEVER);
+
/*
* If IF_OBSOLETE is set, warn the user. Different
* warning classes for "obsolete but valid for this
@@ -794,20 +799,34 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
*! which, \c{0Fh}, instead is an opcode prefix on
*! CPUs newer than the first generation 8086.
*
+ *!obsolete-nop [on] instruction obsolete and is a noop on the target CPU
+ *! warns for an instruction which has been removed
+ *! from the architecture, but has been architecturally
+ *! defined to be a noop for future CPUs.
+ *
*!obsolete-valid [on] instruction obsolete but valid on the target CPU
*! warns for an instruction which has been removed
*! from the architecture, but is still valid on the
*! specific CPU given in the \c{CPU} directive. Code
- *! using these instructions is not forward compatible.
+ *! using these instructions is most likely not
+ *! forward compatible.
*/
- if (iflag_cmp_cpu_level(&insns_flags[temp->iflag_idx], &cpu)) {
- nasm_warn(WARN_OBSOLETE_REMOVED,
- "instruction obsolete and removed on the target CPU");
+ whathappened = never ? "never implemented" : "obsolete";
+
+ if (!never && !iflag_cmp_cpu_level(&insns_flags[temp->iflag_idx], &cpu)) {
+ warning = WARN_OBSOLETE_VALID;
+ validity = "but valid on";
+ } else if (itemp_has(temp, IF_NOP)) {
+ warning = WARN_OBSOLETE_NOP;
+ validity = "and is a noop on";
} else {
- nasm_warn(WARN_OBSOLETE_VALID,
- "instruction obsolete but valid on the target CPU");
+ warning = WARN_OBSOLETE_REMOVED;
+ validity = "and removed from";
}
+
+ nasm_warn(warning, "instruction %s %s the target CPU",
+ whathappened, validity);
}
data.itemp = temp;
diff --git a/test/obsolete.asm b/test/obsolete.asm
index 49dd772f..6174fc4c 100644
--- a/test/obsolete.asm
+++ b/test/obsolete.asm
@@ -7,3 +7,6 @@
cpu 386
pop cs
mov cs,ax
+
+ cpu any
+ pcommit
diff --git a/x86/iflags.ph b/x86/iflags.ph
index d6f11623..723855c0 100644
--- a/x86/iflags.ph
+++ b/x86/iflags.ph
@@ -83,8 +83,10 @@ if_("AVX5124FMAPS", "AVX-512 4-iteration multiply-add");
if_("AVX5124VNNIW", "AVX-512 4-iteration dot product");
if_("SGX", "Intel Software Guard Extensions (SGX)");
-# Put these last
+# Put these last [hpa: why?]
if_("OBSOLETE", "Instruction removed from architecture");
+if_("NEVER", "Instruction never implemented");
+if_("NOP", "Instruction is always a (nonintentional) NOP");
if_("VEX", "VEX or XOP encoded instruction");
if_("EVEX", "EVEX encoded instruction");
diff --git a/x86/insns.dat b/x86/insns.dat
index 85261224..a35c807b 100644
--- a/x86/insns.dat
+++ b/x86/insns.dat
@@ -5262,7 +5262,7 @@ RDPID reg32 [m: f3 0f c7 /7] X64,UNDOC,FUTURE
CLFLUSHOPT mem [m: 66 0f ae /7] FUTURE
CLWB mem [m: 66 0f ae /6] FUTURE
; This one was killed before it saw the light of day
-PCOMMIT void [ 66 0f ae f8] FUTURE,UNDOC,OBSOLETE
+PCOMMIT void [ 66 0f ae f8] FUTURE,NEVER,NOP
; AMD Zen v1
CLZERO void [ 0f 01 fc] FUTURE,AMD
diff --git a/x86/insns.pl b/x86/insns.pl
index 5716d540..cd9aaf4f 100755
--- a/x86/insns.pl
+++ b/x86/insns.pl
@@ -499,25 +499,32 @@ sub format_insn($$$$$) {
}
$decorators =~ tr/a-z/A-Z/;
- # expand the flags
- my @flags;
+ # expand and uniqify the flags
+ my %flags;
foreach my $flag (split(',', $flags)) {
if ($flag eq 'ND') {
$nd = 1;
} elsif ($flag eq 'X64') {
- push(@flags, 'LONG', 'X86_64');
+ # X64 is shorthand for "LONG,X86_64"
+ $flags{'LONG'}++;
+ $flags{'X86_64'}++;
} elsif ($flag ne '') {
- push(@flags, $flag);
+ $flags{$flag}++;
+ }
+
+ if ($flag eq 'NEVER' || $flag eq 'NOP') {
+ # These flags imply OBSOLETE
+ $flags{'OBSOLETE'}++;
}
}
if ($codes =~ /evex\./) {
- push(@flags, 'EVEX');
+ $flags{'EVEX'}++;
} elsif ($codes =~ /(vex|xop)\./) {
- push(@flags, 'VEX');
+ $flags{'VEX'}++;
}
- $flagsindex = insns_flag_index(@flags);
+ $flagsindex = insns_flag_index(keys %flags);
die "$fname:$line: error in flags $flags" unless (defined($flagsindex));
@bytecode = (decodify($codes, $relax), 0);