nasm/regs.pl
H. Peter Anvin 3df97a7270 Get rid of magic open-coded "register numbers"
Get rid of magic open-coded register numbers.  We now keep track of
a total of three different kinds of register numbers: the register
enumeration (regs.h), the x86 register value, and the register flags.
That has all the information we need.

Additionally, do massive revamping of the EA generation code and the
REX generation logic.
2007-05-30 03:25:21 +00:00

134 lines
3.2 KiB
Perl
Executable File

#!/usr/bin/perl
# $Id$
#
# Read regs.dat and output regs.h and regs.c (included in names.c)
#
$nline = 0;
sub toint($) {
my($v) = @_;
return ($v =~ /^0/) ? oct $v : $v+0;
}
sub process_line($) {
my($line) = @_;
my @v;
if ( $line !~ /^\s*(\S+)\s*(\S+)\s*(\S+)\s*([0-9]+)$/i ) {
die "regs.dat:$nline: invalid input\n";
}
$reg = $1;
$aclass = $2;
$dclasses = $3;
$x86regno = toint($4);
if ($reg =~ /^(.*[^0-9])([0-9]+)\-([0-9]+)$/) {
$nregs = $3-$2+1;
$reg = $1.$2;
} else {
$nregs = 1;
}
while ($nregs--) {
$regs{$reg} = $aclass;
$regvals{$reg} = $x86regno;
foreach $dclass (split(/,/, $dclasses)) {
if ( !defined($disclass{$dclass}) ) {
$disclass{$dclass} = [];
}
$disclass{$dclass}->[$x86regno] = $reg;
}
# Compute the next register, if any
$x86regno++;
if ($reg =~ /^(.*[^0-9])([0-9]+)$/) {
$reg = sprintf("%s%u", $1, $2+1);
}
}
}
($fmt, $file) = @ARGV;
%regs = ();
%regvals = ();
%disclass = ();
open(REGS, "< ${file}") or die "$0: Cannot open $file\n";
while ( defined($line = <REGS>) ) {
$nline++;
chomp $line;
$line =~ s/\s*(\#.*|)$//;
next if ( $line eq '' );
process_line($line);
}
close(REGS);
if ( $fmt eq 'h' ) {
# Output regs.h
print "/* automatically generated from $file - do not edit */\n";
print "enum reg_enum {\n";
$attach = ' = EXPR_REG_START'; # EXPR_REG_START == 1
foreach $reg ( sort(keys(%regs)) ) {
print " R_\U${reg}\E${attach},\n";
$attach = ''; $ch = ',';
}
print " REG_ENUM_LIMIT\n";
print "};\n\n";
foreach $reg ( sort(keys(%regs)) ) {
printf "#define %-15s %2d\n", "REG_NUM_\U${reg}", $regvals{$reg};
}
print "\n";
} elsif ( $fmt eq 'c' ) {
# Output regs.c
print "/* automatically generated from $file - do not edit */\n";
print "static const char *reg_names[] = "; $ch = '{';
# This one has no dummy entry for 0
foreach $reg ( sort(keys(%regs)) ) {
print "$ch\n \"${reg}\"";
$ch = ',';
}
print "\n};\n";
} elsif ( $fmt eq 'fc' ) {
# Output regflags.c
print "/* automatically generated from $file - do not edit */\n";
print "static const int32_t reg_flags[] = {\n";
print " 0"; # Dummy entry for 0
foreach $reg ( sort(keys(%regs)) ) {
print ",\n ", $regs{$reg}; # Print the class of the register
}
print "\n};\n";
} elsif ( $fmt eq 'vc' ) {
# Output regvals.c
print "/* automatically generated from $file - do not edit */\n";
print "static const int regvals[] = {\n";
print " -1"; # Dummy entry for 0
foreach $reg ( sort(keys(%regs)) ) {
printf ",\n %2d", $regvals{$reg}; # Print the regval of the register
}
print "\n};\n";
} elsif ( $fmt eq 'dc' ) {
# Output regdis.c
print "/* automatically generated from $file - do not edit */\n";
foreach $class ( sort(keys(%disclass)) ) {
printf "static const int rd_%-8s[] = {", $class;
@foo = @{$disclass{$class}};
@bar = ();
for ( $i = 0 ; $i < scalar(@foo) ; $i++ ) {
if (defined($foo[$i])) {
push(@bar, "R_\U$foo[$i]\E");
} else {
die "$0: No register name for class $class, value $i\n";
}
}
print join(',', @bar), "};\n";
}
} else {
die "$0: Unknown output format\n";
}