insns.pl: use less cantankerous string expansion; better error info

The flags massaging in insns.pl could end up with things like double
commas in some pathological cases, which would make insns_flag_index()
very unhappy due to the appearance of an empty argument. Fix this by
processing the flags as a list already in insns.pl.

Be more explicit and consistent in error messages.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2019-08-09 02:41:37 -07:00
parent 1c21a53e4e
commit 602e67f932
2 changed files with 54 additions and 45 deletions

View file

@ -80,10 +80,11 @@ my $iflag_words;
sub if_($$) {
my($name, $def) = @_;
my $v = [$n_iflags++, $name, $def];
my $num = $n_iflags++;
my $v = [$num, $name, $def];
$flag_byname{$name} = $v;
$flag_bynum[$v->[0]] = $v;
$flag_bynum[$num] = $v;
return 1;
}
@ -122,24 +123,25 @@ sub insns_flag_index(@) {
my @prekey = sort(@_);
my $key = join(',', @prekey);
my $flag_index = $insns_flag_hash{$key};
if (not defined($insns_flag_hash{$key})) {
unless (defined($flag_index)) {
my @newkey = (0) x $iflag_words;
for my $i (@prekey) {
die "No key for $i\n" if not defined($flag_byname{$i});
$newkey[$flag_byname{$i}->[0] >> 5] |=
(1 << ($flag_byname{$i}->[0] & 31));
foreach my $i (@prekey) {
my $flag = $flag_byname{$i};
die "No key for $i (in $key)\n" if not defined($flag);
$newkey[$flag->[0] >> 5] |= (1 << ($flag->[0] & 31));
}
my $str = join(',', map { sprintf("UINT32_C(0x%08x)",$_) } @newkey);
push @insns_flag_values, $str;
push @insns_flag_lists, $key;
$insns_flag_hash{$key} = $#insns_flag_values;
$insns_flag_hash{$key} = $flag_index = $#insns_flag_values;
}
return $insns_flag_hash{$key};
return $flag_index;
}
sub write_iflaggen_h() {

View file

@ -315,7 +315,7 @@ if ( $output eq 'd' ) {
for ($c = 0; $c < 256; $c++) {
$nn = sprintf("%s%02X", $h, $c);
if ($is_prefix{$nn}) {
die "$fname: ambiguous decoding of $nn\n"
die "$fname:$line: ambiguous decoding of $nn\n"
if (defined($dinstables{$nn}));
printf D " /* 0x%02x */ { itable_%s, -1 },\n", $c, $nn;
} elsif (defined($dinstables{$nn})) {
@ -498,19 +498,26 @@ sub format_insn($$$$$) {
}
$decorators =~ tr/a-z/A-Z/;
# format the flags
$nd = 1 if $flags =~ /(^|\,)ND($|\,)/;
$flags =~ s/(^|\,)ND($|\,)/\1/g;
$flags =~ s/(^|\,)X64($|\,)/\1LONG,X86_64\2/g;
if ($codes =~ /evex\./) {
$flags .= ",EVEX";
} elsif ($codes =~ /(vex|xop)\./) {
$flags .= ",VEX";
# expand the flags
my @flags;
foreach my $flag (split(',', $flags)) {
if ($flag eq 'ND') {
$nd = 1;
} elsif ($flag eq 'X64') {
push(@flags, 'LONG', 'X86_64');
} elsif ($flag ne '') {
push(@flags, $flag);
}
}
$rawflags = $flags;
$flagsindex = insns_flag_index(split(',',$flags));
die "Error in flags $rawflags" if not defined($flagsindex);
if ($codes =~ /evex\./) {
push(@flags, 'EVEX');
} elsif ($codes =~ /(vex|xop)\./) {
push(@flags, 'VEX');
}
$flagsindex = insns_flag_index(@flags);
die "$fname:$line: error in flags $flags" unless (defined($flagsindex));
@bytecode = (decodify($codes, $relax), 0);
push(@bytecode_list, [@bytecode]);
@ -531,7 +538,7 @@ sub codesubst($) {
while ($s =~ /\@\@CODES-([0-9A-F]+)\@\@/) {
my $pos = $bytecode_pos{$1};
if (!defined($pos)) {
die "$fname: no position assigned to byte code $1\n";
die "$fname:$line: no position assigned to byte code $1\n";
}
$s = $` . "nasm_bytecodes+${pos}" . "$'";
}
@ -577,7 +584,7 @@ sub decodify($$) {
$c = $2;
next;
} else {
die "$fname: unknown code format in \"$codestr\"\n";
die "$fname:$line: unknown code format in \"$codestr\"\n";
}
}
}
@ -700,7 +707,7 @@ sub tupletype($) {
if (defined $tuple_codes{$tuplestr}) {
return 0300 + $tuple_codes{$tuplestr};
} else {
die "Undefined tuple type : $tuplestr\n";
die "$fname:$line: undefined tuple type : $tuplestr\n";
}
}