diff options
author | H. Peter Anvin (Intel) <hpa@zytor.com> | 2019-08-09 14:52:16 -0700 |
---|---|---|
committer | H. Peter Anvin (Intel) <hpa@zytor.com> | 2019-08-09 14:52:16 -0700 |
commit | 5b394611781dfa20b87253dcd81b7e398f6478bb (patch) | |
tree | fdb18329b9c3cdef3c578514c012e2a0edba2a1c | |
parent | fb118890402f44a816c7e345b80e2b2dd54c73b7 (diff) | |
download | nasm-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.c | 31 | ||||
-rw-r--r-- | test/obsolete.asm | 3 | ||||
-rw-r--r-- | x86/iflags.ph | 4 | ||||
-rw-r--r-- | x86/insns.dat | 2 | ||||
-rwxr-xr-x | x86/insns.pl | 21 |
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); |