nasm/regs.pl
H. Peter Anvin 88aa185d36 Use + instead of * for extension; it feels cleaner with the new meaning.
We used to use * to mean substitute in 0-7.  Now it means that it should
be incremented 8 times.  Using a different character feels cleaner.
2007-04-16 01:21:29 +00:00

135 lines
3.3 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*([1-9][0-9]+|0[0-7]+|0x[0-9a-f]+)\s*([0-9]+)$/i ) {
die "regs.dat:$nline: invalid input\n";
}
$reg = $1;
$aclass = $2;
$dclasses = $3;
$regval = toint($4);
$x86regno = toint($5);
if ($reg =~ /[0-9]\+$/) {
$nregs = 8;
$reg =~ s/\+$//;
} else {
$nregs = 1;
}
while ($nregs--) {
$regs{$reg} = $aclass;
$regvals{$reg} = $regval;
foreach $dclass (split(/,/, $dclasses)) {
if ( !defined($disclass{$dclass}) ) {
$disclass{$dclass} = [];
}
$disclass{$dclass}->[$x86regno] = $reg;
}
# Compute the next register, if any
$regval++;
$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)) ) {
print "#define REG_NUM_\U${reg} $regvals{$reg}\n";
}
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 0%03o", $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";
}