0
0
mirror of https://github.com/netwide-assembler/nasm.git synced 2025-11-08 23:27:15 -05:00

Fix matching of branch instructions with prefixes and sizes

Matching of branch instructions with prefixes and sizes is, to say the
least, tricky. Work through it, and add a new macro to help.

Fixes: https://github.com/netwide-assembler/nasm/issues/144
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel)
2025-10-10 13:03:33 -07:00
parent 2c71e67762
commit a7457e66cf
22 changed files with 6875 additions and 100 deletions

3297
test/jmpxx.asm Normal file

File diff suppressed because it is too large Load Diff

97
test/jmpxx.pl Normal file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/perl
use strict;
use integer;
my $bw = 1;
my @errs = ();
foreach my $errf (@ARGV) {
if (open(my $e, '<', $errf)) {
while (defined(my $l = <$e>)) {
if ($l =~ /^.*?\:([0-9]+)\:/) {
$errs[$1] |= $bw;
}
}
close($e);
}
$bw <<= 1;
}
my $ln = 0;
$ln++; print "%pragma list options -befms\n";
$ln++; print "%ifndef ERR\n";
$ln++; print " %define ERR 0\n";
$ln++; print "%endif\n";
my @nots = ('');
for (my $cc = 1; $cc < 7; $cc++) {
my $ss = 'no';
$ss .= 'w' if ($cc & 1);
$ss .= 'd' if ($cc & 2);
$ss .= 'q' if ($cc & 4);
$ln++; print "%macro $ss 1+.nolist\n";
$ln++; printf " %%if ERR || !(__BITS__ & 0x%02x)\n", $cc << 4;
$ln++; print "\t%1\n";
$ln++; print " %endif\n";
$ln++; print "%endmacro\n";
push(@nots, "$ss");
}
$ln++; print "%macro bogus 1+.nolist\n";
$ln++; printf " %%if ERR\n";
$ln++; print "\t%1\n";
$ln++; print " %endif\n";
$ln++; print "%endmacro\n";
push(@nots, 'bogus');
$ln++; print "\n";
$ln++; print "\tsection text1\n";
$ln++; print "top:\n";
$ln++; print "\ttimes 128 nop\n";
$ln++; print "\n";
foreach my $insn ('jmp', 'call', 'jz', 'jcxz', 'jecxz', 'jrcxz',
'loop', 'loope', 'loopne') {
$ln++; print "here_$insn:\n";
foreach my $tgt ('$', 'top', 'there') {
foreach my $str ('', 'strict') {
foreach my $sz ('', 'byte', 'word', 'dword', 'qword') {
foreach my $o ('', 'o16', 'o32', 'o64') {
foreach my $sn ('', 'short', 'near') {
my $is_short =
($sn eq 'short' || $insn =~ /^(j\w?cxz|loop\w*)$/);
$ln++;
$errs[$ln] |= 3 if ($sz eq 'qword' || $o eq 'o64'
|| $insn eq 'jrcxz');
$errs[$ln] |= 4 if ($sz =~ /^d?word$'/ || $o =~ /^o(16|32)$/ ||
$insn eq 'jcxz');
if (($sz eq 'word' && $o =~ /^o(32|64)$/) ||
($sz eq 'dword' && $o =~ /^o(16|64)$/) ||
($sz eq 'qword' && $o =~ /^o(16|32)$/) ||
($sz eq 'byte') ||
($is_short &&
($sn eq 'near' || $tgt ne '$' || $insn eq 'call'))) {
$errs[$ln] |= 7;
}
my $is_short =
printf " %-5s %s\n",
$nots[$errs[$ln]],
join(' ', grep { $_ ne '' }
($o,$insn,$str,$sz,$sn,$tgt));
}
}
}
}
}
}
$ln++; print "\n";
$ln++; print "\tsection text2\n";
$ln++; print "there:\n";
$ln++; print "\tret\n";