[nasm:master] insns: drop special handling of conditional instructions

nasm-bot for H. Peter Anvin hpa at zytor.com
Sat Nov 12 13:03:04 PST 2022


Commit-ID:  a2eabbe1d7e709ad1c96349f9056436bebec53ee
Gitweb:     http://repo.or.cz/w/nasm.git?a=commitdiff;h=a2eabbe1d7e709ad1c96349f9056436bebec53ee
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Sat, 12 Nov 2022 12:26:28 -0800
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Sat, 12 Nov 2022 12:37:37 -0800

insns: drop special handling of conditional instructions

Instead of handling conditional instructions ad hoc, generate
individual instruction patterns as normal. This simplifies the code
and makes CMPccXADD support simpler (otherwise it would be necessary
to hack in the handling of a condition code in the middle of an
instruction.)

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 Makefile.in          |   8 +-
 Mkfiles/msvc.mak     |  10 +--
 Mkfiles/openwcom.mak |  10 +--
 asm/assemble.c       |  10 ---
 asm/parser.c         |   1 -
 asm/tokhash.pl       |  37 +++-----
 disasm/disasm.c      |  27 +-----
 include/nasm.h       |  19 ----
 x86/iflags.ph        |   4 +-
 x86/insns.pl         | 238 +++++++++++++++++++++++++++++++--------------------
 10 files changed, 176 insertions(+), 188 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index ae4fb551..a5c4f7b1 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -304,17 +304,17 @@ doc/warnings.src : doc/warnings.src.time
 	@: Side effect
 
 # Assembler token hash
-asm/tokhash.c: x86/insns.dat x86/regs.dat asm/tokens.dat asm/tokhash.pl \
+asm/tokhash.c: x86/insns.dat x86/insnsn.c asm/tokens.dat asm/tokhash.pl \
 	perllib/phash.ph
 	$(RUNPERL) $(srcdir)/asm/tokhash.pl c \
-		$(srcdir)/x86/insns.dat $(srcdir)/x86/regs.dat \
+		x86/insnsn.c $(srcdir)/x86/regs.dat \
 		$(srcdir)/asm/tokens.dat > asm/tokhash.c
 
 # Assembler token metadata
-asm/tokens.h: x86/insns.dat x86/regs.dat asm/tokens.dat asm/tokhash.pl \
+asm/tokens.h: x86/insns.dat x86/insnsn.c asm/tokens.dat asm/tokhash.pl \
 	perllib/phash.ph
 	$(RUNPERL) $(srcdir)/asm/tokhash.pl h \
-		$(srcdir)/x86/insns.dat $(srcdir)/x86/regs.dat \
+		x86/insnsn.c $(srcdir)/x86/regs.dat \
 		$(srcdir)/asm/tokens.dat > asm/tokens.h
 
 # Preprocessor token hash
diff --git a/Mkfiles/msvc.mak b/Mkfiles/msvc.mak
index 5c62c6e4..25c50df3 100644
--- a/Mkfiles/msvc.mak
+++ b/Mkfiles/msvc.mak
@@ -234,7 +234,7 @@ x86\regs.h: x86\regs.dat x86\regs.pl
 WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src
 
 warnings:
-	$(RM_F) $(WARNFILES)
+	$(RM_F) $(WARNFILES) $(WARNFILES:=.time)
 	$(MAKE) asm\warnings.time
 
 asm\warnings.time: $(ALLOBJ_NW:.$(O)=.c)
@@ -263,17 +263,17 @@ doc\warnings.src : doc\warnings.src.time
 	@: Side effect
 
 # Assembler token hash
-asm\tokhash.c: x86\insns.dat x86\regs.dat asm\tokens.dat asm\tokhash.pl \
+asm\tokhash.c: x86\insns.dat x86\insnsn.c asm\tokens.dat asm\tokhash.pl \
 	perllib\phash.ph
 	$(RUNPERL) $(srcdir)\asm\tokhash.pl c \
-		$(srcdir)\x86\insns.dat $(srcdir)\x86\regs.dat \
+		x86\insnsn.c $(srcdir)\x86\regs.dat \
 		$(srcdir)\asm\tokens.dat > asm\tokhash.c
 
 # Assembler token metadata
-asm\tokens.h: x86\insns.dat x86\regs.dat asm\tokens.dat asm\tokhash.pl \
+asm\tokens.h: x86\insns.dat x86\insnsn.c asm\tokens.dat asm\tokhash.pl \
 	perllib\phash.ph
 	$(RUNPERL) $(srcdir)\asm\tokhash.pl h \
-		$(srcdir)\x86\insns.dat $(srcdir)\x86\regs.dat \
+		x86\insnsn.c $(srcdir)\x86\regs.dat \
 		$(srcdir)\asm\tokens.dat > asm\tokens.h
 
 # Preprocessor token hash
diff --git a/Mkfiles/openwcom.mak b/Mkfiles/openwcom.mak
index 9ffc6b75..589650d7 100644
--- a/Mkfiles/openwcom.mak
+++ b/Mkfiles/openwcom.mak
@@ -247,7 +247,7 @@ x86\regs.h: x86\regs.dat x86\regs.pl
 WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src
 
 warnings:
-	$(RM_F) $(WARNFILES)
+	$(RM_F) $(WARNFILES) $(WARNFILES:=.time)
 	$(MAKE) asm\warnings.time
 
 asm\warnings.time: $(ALLOBJ_NW:.$(O)=.c)
@@ -276,17 +276,17 @@ doc\warnings.src : doc\warnings.src.time
 	@: Side effect
 
 # Assembler token hash
-asm\tokhash.c: x86\insns.dat x86\regs.dat asm\tokens.dat asm\tokhash.pl &
+asm\tokhash.c: x86\insns.dat x86\insnsn.c asm\tokens.dat asm\tokhash.pl &
 	perllib\phash.ph
 	$(RUNPERL) $(srcdir)\asm\tokhash.pl c &
-		$(srcdir)\x86\insns.dat $(srcdir)\x86\regs.dat &
+		x86\insnsn.c $(srcdir)\x86\regs.dat &
 		$(srcdir)\asm\tokens.dat > asm\tokhash.c
 
 # Assembler token metadata
-asm\tokens.h: x86\insns.dat x86\regs.dat asm\tokens.dat asm\tokhash.pl &
+asm\tokens.h: x86\insns.dat x86\insnsn.c asm\tokens.dat asm\tokhash.pl &
 	perllib\phash.ph
 	$(RUNPERL) $(srcdir)\asm\tokhash.pl h &
-		$(srcdir)\x86\insns.dat $(srcdir)\x86\regs.dat &
+		x86\insnsn.c $(srcdir)\x86\regs.dat &
 		$(srcdir)\asm\tokens.dat > asm\tokens.h
 
 # Preprocessor token hash
diff --git a/asm/assemble.c b/asm/assemble.c
index ddee411c..281e02c0 100644
--- a/asm/assemble.c
+++ b/asm/assemble.c
@@ -146,8 +146,6 @@
  * \325             nohi                        instruction which always uses spl/bpl/sil/dil
  * \326             nof3                        instruction not valid with 0xF3 REP prefix.  Hint for
                                                 disassembler only; for SSE instructions.
- * \330                                         a literal byte follows in the code stream, to be added
- *                                              to the condition code value of the instruction.
  * \331             norep                       instruction not valid with REP prefix.  Hint for
  *                                              disassembler only; for SSE instructions.
  * \332             f2i                         REP prefix (0xF2 byte) used as opcode extension.
@@ -1472,10 +1470,6 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
         case 0326:
             break;
 
-        case 0330:
-            codes++, length++;
-            break;
-
         case 0331:
             break;
 
@@ -2188,10 +2182,6 @@ static void gencode(struct out_data *data, insn *ins)
         case 0326:
             break;
 
-        case 0330:
-            out_rawbyte(data, *codes++ ^ get_cond_opcode(ins->condition));
-            break;
-
         case 0331:
             break;
 
diff --git a/asm/parser.c b/asm/parser.c
index d3956572..6b19ffac 100644
--- a/asm/parser.c
+++ b/asm/parser.c
@@ -748,7 +748,6 @@ restart_parse:
     }
 
     result->opcode = tokval.t_integer;
-    result->condition = tokval.t_inttwo;
 
     /*
      * INCBIN cannot be satisfied with incorrectly
diff --git a/asm/tokhash.pl b/asm/tokhash.pl
index 566a3aa3..1f19647a 100755
--- a/asm/tokhash.pl
+++ b/asm/tokhash.pl
@@ -40,7 +40,7 @@
 
 require 'phash.ph';
 
-my($output, $insns_dat, $regs_dat, $tokens_dat) = @ARGV;
+my($output, $insnsn_c, $regs_dat, $tokens_dat) = @ARGV;
 
 %tokens = ();
 @tokendata = ();
@@ -53,33 +53,18 @@ my($output, $insns_dat, $regs_dat, $tokens_dat) = @ARGV;
 	       'nle', 'no', 'np', 'ns', 'nz', 'o', 'p', 'pe', 'po', 's', 'z');
 
 #
-# Read insns.dat
+# Read insnsn.c
 #
-open(ID, '<', $insns_dat) or die "$0: cannot open $insns_dat: $!\n";
+open(ID, '<', $insnsn_c) or die "$0: cannot open $insnsn_c: $!\n";
 while (defined($line = <ID>)) {
-    if ($line =~ /^([\?\@A-Z0-9_]+)(|cc)\s/) {
-	$insn = $1.$2;
-	($token = $1) =~ tr/A-Z/a-z/;
-
-	if ($2 eq '') {
-	    # Single instruction token
-	    if (!defined($tokens{$token})) {
-		$tokens{$token} = scalar @tokendata;
-		push(@tokendata, "\"${token}\", ".length($token).
-		     ", TOKEN_INSN, C_none, 0, I_${insn}");
-	    }
-	} else {
-	    # Conditional instruction
-	    foreach $cc (@conditions) {
-		my $etok = $token.$cc;
-		if (!defined($tokens{$etok})) {
-		    $tokens{$etok} = scalar @tokendata;
-		    push(@tokendata, "\"${etok}\", ".length($etok).
-			 ", TOKEN_INSN, C_\U$cc\E, 0, I_${insn}");
-		}
-	    }
-	}
-    }
+    next unless ($line =~ /^\s*\"([\?\@a-z0-9_]+)\"/);
+
+    my $token = $1;
+    next if (defined($tokens{$token}));	# This should never happen
+
+    $tokens{$token} = scalar @tokendata;
+    push(@tokendata, "\"${token}\", ".length($token).
+	 ", TOKEN_INSN, 0, 0, I_\U${token}");
 }
 close(ID);
 
diff --git a/disasm/disasm.c b/disasm/disasm.c
index 0f3ffc79..ac2dc97f 100644
--- a/disasm/disasm.c
+++ b/disasm/disasm.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2012 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2022 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -506,7 +506,6 @@ static int matches(const struct itemplate *t, uint8_t *data,
         ins->oprs[i].segment = ins->oprs[i].disp_size =
             (segsize == 64 ? SEG_64BIT : segsize == 32 ? SEG_32BIT : 0);
     }
-    ins->condition = -1;
     ins->evex_tuple = 0;
     ins->rex = prefix->rex;
     memset(ins->prefixes, 0, sizeof ins->prefixes);
@@ -957,16 +956,6 @@ static int matches(const struct itemplate *t, uint8_t *data,
             ins->rex |= REX_NH;
             break;
 
-        case 0330:
-        {
-            int t = *r++, d = *data++;
-            if (d < t || d > t + 15)
-                return 0;
-            else
-                ins->condition = d - t;
-            break;
-        }
-
         case 0326:
             if (prefix->rep == 0xF3)
                 return 0;
@@ -1126,12 +1115,6 @@ static int matches(const struct itemplate *t, uint8_t *data,
     return data - origdata;
 }
 
-/* Condition names for disassembly, sorted by x86 code */
-static const char * const condition_name[16] = {
-    "o", "no", "c", "nc", "z", "nz", "na", "a",
-    "s", "ns", "pe", "po", "l", "nl", "ng", "g"
-};
-
 int32_t disasm(uint8_t *data, int32_t data_size, char *output, int outbufsize, int segsize,
                int64_t offset, int autosync, iflag_t *prefer)
 {
@@ -1424,12 +1407,8 @@ int32_t disasm(uint8_t *data, int32_t data_size, char *output, int outbufsize, i
     }
 
     i = (*p)->opcode;
-    if (i >= FIRST_COND_OPCODE)
-        slen += snprintf(output + slen, outbufsize - slen, "%s%s",
-                        nasm_insn_names[i], condition_name[ins.condition]);
-    else
-        slen += snprintf(output + slen, outbufsize - slen, "%s",
-                        nasm_insn_names[i]);
+    slen += snprintf(output + slen, outbufsize - slen, "%s",
+                     nasm_insn_names[i]);
 
     colon = false;
     is_evex = !!(ins.rex & REX_EV);
diff --git a/include/nasm.h b/include/nasm.h
index 1e0b2b91..8b017f3e 100644
--- a/include/nasm.h
+++ b/include/nasm.h
@@ -523,13 +523,6 @@ static inline bool is_register(int reg)
     return reg >= EXPR_REG_START && reg < REG_ENUM_LIMIT;
 }
 
-enum ccode { /* condition code names */
-    C_A, C_AE, C_B, C_BE, C_C, C_E, C_G, C_GE, C_L, C_LE, C_NA, C_NAE,
-    C_NB, C_NBE, C_NC, C_NE, C_NG, C_NGE, C_NL, C_NLE, C_NO, C_NP,
-    C_NS, C_NZ, C_O, C_P, C_PE, C_PO, C_S, C_Z,
-    C_none = -1
-};
-
 /*
  * token flags
  */
@@ -540,17 +533,6 @@ enum ccode { /* condition code names */
 #define TFLAG_WARN	(1 << 3)    /* warning only, treat as ID */
 #define TFLAG_DUP	(1 << 4)    /* valid ID but also has context-specific use */
 
-static inline uint8_t get_cond_opcode(enum ccode c)
-{
-    static const uint8_t ccode_opcodes[] = {
-        0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xf, 0xd, 0xc, 0xe, 0x6, 0x2,
-        0x3, 0x7, 0x3, 0x5, 0xe, 0xc, 0xd, 0xf, 0x1, 0xb, 0x9, 0x5,
-        0x0, 0xa, 0xa, 0xb, 0x8, 0x4
-    };
-
-	return ccode_opcodes[(int)c];
-}
-
 /*
  * REX flags
  */
@@ -766,7 +748,6 @@ typedef struct insn { /* an instruction itself */
     char            *label;                 /* the label defined, or NULL */
     int             prefixes[MAXPREFIX];    /* instruction prefixes, if any */
     enum opcode     opcode;                 /* the opcode - not just the string */
-    enum ccode      condition;              /* the condition code, if Jcc/SETcc */
     int             operands;               /* how many operands? 0-3 (more if db et al) */
     int             addr_size;              /* address size */
     operand         oprs[MAX_OPERANDS];     /* the operands, defined as above */
diff --git a/x86/iflags.ph b/x86/iflags.ph
index 25276bdc..1306ed6b 100644
--- a/x86/iflags.ph
+++ b/x86/iflags.ph
@@ -98,8 +98,10 @@ if_("AMXTILE",           "AMX tile configuration instructions");
 if_("AMXBF16",           "AMX bfloat16 multiplication");
 if_("AMXINT8",           "AMX 8-bit integer multiplication");
 if_("FRED",              "Flexible Return and Exception Delivery (FRED)");
+if_("RAOINT",		 "Remote atomic operations (RAO-INT)");
+if_("UINTR",		 "User interrupts");
 
-# Put these last [hpa: why?]
+# Put these last to minimize their relevance
 if_("OBSOLETE",          "Instruction removed from architecture");
 if_("NEVER",             "Instruction never implemented");
 if_("NOP",               "Instruction is always a (nonintentional) NOP");
diff --git a/x86/insns.pl b/x86/insns.pl
index dbb5a82b..af0ec5d0 100755
--- a/x86/insns.pl
+++ b/x86/insns.pl
@@ -59,10 +59,115 @@ for ($c = 0; $c < $vex_classes; $c++) {
         }
     }
 }
- at disasm_prefixes = (@vexlist, @disasm_prefixes);
+ at disasm_prefixes = (@vexlist, @disasm_prefixes, '');
+%disasm_prefixes = map { $_ => 1 } @disasm_prefixes;
 
 @bytecode_count = (0) x 256;
 
+# Push to an array reference, creating the array if needed
+sub xpush($@) {
+    my $ref = shift @_;
+
+    $$ref = [] unless (defined($$ref));
+    return push(@$$ref, @_);
+}
+
+# Generate relaxed form patterns if applicable
+sub relaxed_forms(@) {
+    my @field_list = @_;
+
+    foreach my $fields (@_) {
+	next unless ($fields->[1] =~ /\*/);
+
+	# This instruction has relaxed form(s)
+	if ($fields->[2] !~ /^\[/) {
+	    warn "$fname:$line: has an * operand but uses raw bytecodes\n";
+	    next;
+	}
+
+	my $opmask = 0;
+	my @ops = split(/,/, $fields->[1]);
+	for (my $oi = 0; $oi < scalar @ops; $oi++) {
+	    if ($ops[$oi] =~ /\*$/) {
+		if ($oi == 0) {
+		    warn "$fname:$line: has a first operand with a *\n";
+		    next;
+		}
+		$opmask |= 1 << $oi;
+	    }
+	}
+
+	for (my $oi = 1; $oi < (1 << scalar @ops); $oi++) {
+	    if (($oi & ~$opmask) == 0) {
+		my @xops = ();
+		my $omask = ~$oi;
+		for ($oj = 0; $oj < scalar(@ops); $oj++) {
+		    if ($omask & 1) {
+			push(@xops, $ops[$oj]);
+		    }
+		    $omask >>= 1;
+		}
+		my @ff = @$fields;
+		$ff[1] = join(',', @xops);
+		$ff[4] = $oi;
+		push(@field_list, [@ff]);
+	    }
+	}
+    }
+
+    return @field_list;
+}
+
+# Condition codes used by the disassembler
+my %condd = ( 'o'   =>  0, 'no'  =>  1, 'c'   =>  2,  'nc'  =>  3,
+	      'z'   =>  4, 'nz'  =>  5, 'na'  =>  6,  'a'   =>  7,
+	      's'   =>  8, 'ns'  =>  9, 'pe'  => 10,  'po'  => 11,
+	      'l'   => 12, 'nl'  => 13, 'ng'  => 14,  'g'   => 15 );
+
+# All condition code aliases
+my %conds = ( %condd,
+	      'ae'  =>  3, 'b'   =>  2, 'be'  =>  6,  'e'   =>  4,
+	      'ge'  => 13, 'le'  => 14, 'nae' =>  2,  'nb'  =>  3,
+	      'nbe' =>  7, 'ne'  =>  5, 'nge' => 12,  'nle' => 15,
+	      'np'  => 11, 'p'   => 10 );
+
+# Generate conditional form patterns if applicable
+sub conditional_forms(@) {
+    my @field_list = ();
+
+    foreach my $fields (@_) {
+	# This is a case sensitive match!
+	if ($fields->[0] !~ /cc/) {
+	    push(@field_list, $fields);
+	    next;
+	}
+
+	if ($fields->[2] !~ /^\[/) {
+	    warn "$fname:$line: conditional instruction using raw bytecodes\n";
+	    next;
+	}
+
+	foreach my $cc (keys(%conds)) {
+	    my @ff = @$fields;
+
+	    $ff[0] =~ s/cc/\U$cc/;
+
+	    unless ($ff[2] =~ /^(\[.*?)\b([0-9a-f]{2})\+c\b(.*\])$/) {
+		warn "$fname:$line: invalid conditional encoding";
+		next;
+	    }
+
+	    $ff[2] = $1.sprintf('%02x', hex($2)^$conds{$cc}).$3;
+	    unless (defined($condd{$cc}) || $ff[3] =~ /\bND\b/) {
+		$ff[3] .= ',ND';
+	    }
+
+	    push(@field_list, [@ff]);
+	}
+    }
+    return @field_list;
+}
+
 print STDERR "Reading insns.dat...\n";
 
 @args   = ();
@@ -86,10 +191,13 @@ open(F, '<', $fname) || die "unable to open $fname";
 
 %dinstables = ();
 @bytecode_list = ();
+%aname = ();
 
 $line = 0;
 $insns = 0;
-$n_opcodes = $n_opcodes_cc = 0;
+$n_opcodes = 0;
+my @allpatterns = ();
+
 while (<F>) {
     $line++;
     chomp;
@@ -99,71 +207,24 @@ while (<F>) {
         warn "line $line does not contain four fields\n";
         next;
     }
-    @fields = ($1, $2, $3, $4);
-    @field_list = ([@fields, 0]);
+    my @field_list = ([$1, $2, $3, $4, 0]);
+    @field_list = relaxed_forms(@field_list);
+    @field_list = conditional_forms(@field_list);
 
-    if ($fields[1] =~ /\*/) {
-        # This instruction has relaxed form(s)
-        if ($fields[2] !~ /^\[/) {
-            warn "line $line has an * operand but uses raw bytecodes\n";
-            next;
-        }
-
-        $opmask = 0;
-        @ops = split(/,/, $fields[1]);
-        for ($oi = 0; $oi < scalar @ops; $oi++) {
-            if ($ops[$oi] =~ /\*$/) {
-                if ($oi == 0) {
-                    warn "line $line has a first operand with a *\n";
-                    next;
-                }
-                $opmask |= 1 << $oi;
-            }
-        }
-
-        for ($oi = 1; $oi < (1 << scalar @ops); $oi++) {
-            if (($oi & ~$opmask) == 0) {
-                my @xops = ();
-                my $omask = ~$oi;
-                for ($oj = 0; $oj < scalar(@ops); $oj++) {
-                    if ($omask & 1) {
-                        push(@xops, $ops[$oj]);
-                    }
-                    $omask >>= 1;
-                }
-                push(@field_list, [$fields[0], join(',', @xops),
-                     $fields[2], $fields[3], $oi]);
-            }
-        }
-    }
-
-    foreach $fptr (@field_list) {
-        @fields = @$fptr;
-        ($formatted, $nd) = format_insn(@fields);
+    foreach my $fields (@field_list) {
+        ($formatted, $nd) = format_insn(@$fields);
         if ($formatted) {
             $insns++;
-            $aname = "aa_$fields[0]";
-            push @$aname, $formatted;
-        }
-        if ( $fields[0] =~ /cc$/ ) {
-            # Conditional instruction
-	    if (!defined($k_opcodes_cc{$fields[0]})) {
-		$k_opcodes_cc{$fields[0]} = $n_opcodes_cc++;
-	    }
-        } else {
-            # Unconditional instruction
-	    if (!defined($k_opcodes{$fields[0]})) {
-		$k_opcodes{$fields[0]} = $n_opcodes++;
-	    }
+	    xpush(\$aname{$fields->[0]}, $formatted);
         }
+	if (!defined($k_opcodes{$fields->[0]})) {
+	    $k_opcodes{$fields->[0]} = $n_opcodes++;
+	}
         if ($formatted && !$nd) {
             push @big, $formatted;
-            my @sseq = startseq($fields[2], $fields[4]);
-            foreach $i (@sseq) {
-                if (!defined($dinstables{$i})) {
-                    $dinstables{$i} = [];
-                }
-                push(@{$dinstables{$i}}, $#big);
+            my @sseq = startseq($fields->[2], $fields->[4]);
+            foreach my $i (@sseq) {
+                xpush(\$dinstables{$i}, $#big);
             }
         }
     }
@@ -194,8 +255,7 @@ foreach $bl (@bytecode_list) {
 }
 undef @bytecode_list;
 
- at opcodes    = sort { $k_opcodes{$a} <=> $k_opcodes{$b} } keys(%k_opcodes);
- at opcodes_cc = sort { $k_opcodes_cc{$a} <=> $k_opcodes_cc{$b} } keys(%k_opcodes_cc);
+ at opcodes = sort { $k_opcodes{$a} <=> $k_opcodes{$b} } keys(%k_opcodes);
 
 if ( $output eq 'b') {
     print STDERR "Writing $oname...\n";
@@ -249,16 +309,15 @@ if ( $output eq 'a' ) {
     print A "#include \"nasm.h\"\n";
     print A "#include \"insns.h\"\n\n";
 
-    foreach $i (@opcodes, @opcodes_cc) {
+    foreach $i (@opcodes) {
         print A "static const struct itemplate instrux_${i}[] = {\n";
-        $aname = "aa_$i";
-        foreach $j (@$aname) {
+        foreach $j (@{$aname{$i}}) {
             print A "    ", codesubst($j), "\n";
         }
         print A "    ITEMPLATE_END\n};\n\n";
     }
     print A "const struct itemplate * const nasm_instructions[] = {\n";
-    foreach $i (@opcodes, @opcodes_cc) {
+    foreach $i (@opcodes) {
         print A "    instrux_${i},\n";
     }
     print A "};\n";
@@ -286,7 +345,7 @@ if ( $output eq 'd' ) {
 
     foreach $h (sort(keys(%dinstables))) {
         next if ($h eq ''); # Skip pseudo-instructions
-            print D "\nstatic const struct itemplate * const itable_${h}[] = {\n";
+	print D "\nstatic const struct itemplate * const itable_${h}[] = {\n";
         foreach $j (@{$dinstables{$h}}) {
             print D "    instrux + $j,\n";
         }
@@ -294,7 +353,7 @@ if ( $output eq 'd' ) {
     }
 
     @prefix_list = ();
-    foreach $h (@disasm_prefixes, '') {
+    foreach $h (@disasm_prefixes) {
         for ($c = 0; $c < 256; $c++) {
             $nn = sprintf("%s%02X", $h, $c);
             if ($is_prefix{$nn} || defined($dinstables{$nn})) {
@@ -315,10 +374,15 @@ if ( $output eq 'd' ) {
         for ($c = 0; $c < 256; $c++) {
             $nn = sprintf("%s%02X", $h, $c);
             if ($is_prefix{$nn}) {
-                die "$fname:$line: ambiguous decoding of $nn\n"
-                    if (defined($dinstables{$nn}));
+		if ($dinstables{$nn}) {
+		    print STDERR "$fname: ambiguous decoding, prefix $nn aliases:\n";
+		    foreach my $dc (@{$dinstables{$nn}}) {
+			print STDERR codesubst($big[$dc]), "\n";
+		    }
+		    exit 1;
+		}
                 printf D "    /* 0x%02x */ { itable_%s, -1 },\n", $c, $nn;
-            } elsif (defined($dinstables{$nn})) {
+            } elsif ($dinstables{$nn}) {
                 printf D "    /* 0x%02x */ { itable_%s, %u },\n", $c,
                        $nn, scalar(@{$dinstables{$nn}});
             } else {
@@ -362,10 +426,9 @@ if ( $output eq 'i' ) {
     print I "#define NASM_INSNSI_H 1\n\n";
     print I "enum opcode {\n";
     $maxlen = 0;
-    foreach $i (@opcodes, @opcodes_cc) {
+    foreach $i (@opcodes) {
         print I "\tI_${i},\n";
         $len = length($i);
-        $len++ if ( $i =~ /cc$/ ); # Condition codes can be 3 characters long
         $maxlen = $len if ( $len > $maxlen );
     }
     print I "\tI_none = -1\n";
@@ -373,7 +436,6 @@ if ( $output eq 'i' ) {
     print I "#define MAX_INSLEN ", $maxlen, "\n";
     print I "#define NASM_VEX_CLASSES ", $vex_classes, "\n";
     print I "#define NO_DECORATOR\t{", join(',',(0) x $MAX_OPERANDS), "}\n";
-    print I "#define FIRST_COND_OPCODE I_", $opcodes_cc[0], "\n\n";
     print I "#endif /* NASM_INSNSI_H */\n";
 
     close I;
@@ -389,14 +451,9 @@ if ( $output eq 'n' ) {
     print N "#include \"tables.h\"\n\n";
 
     print N "const char * const nasm_insn_names[] = {";
-    $first = 1;
-    foreach $i (@opcodes, @opcodes_cc) {
-        print N "," if ( !$first );
-        $first = 0;
-        $ilower = $i;
-        $ilower =~ s/cc$//;             # Remove conditional cc suffix
-        $ilower =~ tr/A-Z/a-z/;         # Change to lower case (Perl 4 compatible)
-        print N "\n\t\"${ilower}\"";
+    foreach $i (@opcodes) {
+        print N "\n\t\"\L$i\"";
+	print N ',' if ($i < $#opcodes);
     }
     print N "\n};\n";
     close N;
@@ -658,7 +715,6 @@ sub hexstr(@) {
 # instruction. We need only consider the codes:
 # \[1234]      mean literal bytes, of course
 # \1[0123]     mean byte plus register value
-# \330         means byte plus condition code
 # \0 or \340   mean give up and return empty set
 # \34[4567]    mean PUSH/POP of segment registers: special case
 # \17[234]     skip is4 control byte
@@ -691,15 +747,16 @@ sub startseq($$) {
             }
 
             foreach $pfx (@disasm_prefixes) {
-                if (substr($fbs, 0, length($pfx)) eq $pfx) {
+		my $len = length($pfx);
+                if (substr($fbs, 0, $len) eq $pfx) {
                     $prefix = $pfx;
-                    $fbs = substr($fbs, length($pfx));
+                    $fbs = substr($fbs, $len, 2);
                     last;
                 }
             }
 
             if ($fbs ne '') {
-                return ($prefix.substr($fbs,0,2));
+                return ($prefix.$fbs);
             }
 
             unshift(@codes, $c0);
@@ -707,8 +764,6 @@ sub startseq($$) {
             return addprefix($prefix, $c1..($c1+7));
         } elsif (($c0 & ~013) == 0144) {
             return addprefix($prefix, $c1, $c1|2);
-        } elsif ($c0 == 0330) {
-            return addprefix($prefix, $c1..($c1+15));
         } elsif ($c0 == 0 || $c0 == 0340) {
             return $prefix;
         } elsif (($c0 & ~3) == 0260 || $c0 == 0270 ||
@@ -729,7 +784,7 @@ sub startseq($$) {
             # and "ignorable" codes here
         }
     }
-    return $prefix;
+    return ();
 }
 
 # EVEX tuple types offset is 0300. e.g. 0301 is for full vector(fv).
@@ -1090,9 +1145,6 @@ sub byte_code_compile($$) {
             }
             push(@codes, 0173, ($oppos{'s'} << 4) + $imm);
             $prefix_ok = 0;
-        } elsif ($op =~ /^([0-9a-f]{2})\+c$/) {
-            push(@codes, 0330, hex $1);
-            $prefix_ok = 0;
         } elsif ($op =~ /^([0-9a-f]{2})\+r$/) {
             if (!defined($oppos{'r'})) {
                 die "$fname:$line: $op without 'r' operand\n";


More information about the Nasm-commits mailing list