2002-06-06 10:41:20 +08:00
|
|
|
#!/usr/bin/perl
|
|
|
|
#
|
|
|
|
# Read regs.dat and output regs.h and regs.c (included in names.c)
|
|
|
|
#
|
|
|
|
|
|
|
|
$nline = 0;
|
|
|
|
|
2007-04-16 07:12:17 +08:00
|
|
|
sub toint($) {
|
|
|
|
my($v) = @_;
|
|
|
|
|
|
|
|
return ($v =~ /^0/) ? oct $v : $v+0;
|
|
|
|
}
|
|
|
|
|
2002-06-06 10:41:20 +08:00
|
|
|
sub process_line($) {
|
|
|
|
my($line) = @_;
|
|
|
|
my @v;
|
|
|
|
|
2007-05-30 11:25:21 +08:00
|
|
|
if ( $line !~ /^\s*(\S+)\s*(\S+)\s*(\S+)\s*([0-9]+)$/i ) {
|
2002-06-06 10:41:20 +08:00
|
|
|
die "regs.dat:$nline: invalid input\n";
|
|
|
|
}
|
2007-04-16 07:12:17 +08:00
|
|
|
$reg = $1;
|
|
|
|
$aclass = $2;
|
|
|
|
$dclasses = $3;
|
2007-05-30 11:25:21 +08:00
|
|
|
$x86regno = toint($4);
|
2002-06-06 10:41:20 +08:00
|
|
|
|
2007-08-21 05:03:14 +08:00
|
|
|
if ($reg =~ /^(.*[^0-9])([0-9]+)\-([0-9]+)(|[^0-9].*)$/) {
|
2007-05-30 11:25:21 +08:00
|
|
|
$nregs = $3-$2+1;
|
2007-08-31 05:40:08 +08:00
|
|
|
$reg = $1.$2.$4;
|
2007-08-21 05:03:14 +08:00
|
|
|
$reg_nr = $2;
|
|
|
|
$reg_prefix = $1;
|
|
|
|
$reg_suffix = $4;
|
2007-04-16 07:12:17 +08:00
|
|
|
} else {
|
|
|
|
$nregs = 1;
|
2007-08-21 05:03:14 +08:00
|
|
|
undef $reg_prefix, $reg_suffix;
|
2002-06-06 10:41:20 +08:00
|
|
|
}
|
|
|
|
|
2007-04-16 07:12:17 +08:00
|
|
|
while ($nregs--) {
|
|
|
|
$regs{$reg} = $aclass;
|
2007-05-30 11:25:21 +08:00
|
|
|
$regvals{$reg} = $x86regno;
|
2007-04-16 07:12:17 +08:00
|
|
|
|
|
|
|
foreach $dclass (split(/,/, $dclasses)) {
|
|
|
|
if ( !defined($disclass{$dclass}) ) {
|
|
|
|
$disclass{$dclass} = [];
|
|
|
|
}
|
2007-10-20 05:42:29 +08:00
|
|
|
|
2007-04-16 07:12:17 +08:00
|
|
|
$disclass{$dclass}->[$x86regno] = $reg;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Compute the next register, if any
|
2007-08-21 05:03:14 +08:00
|
|
|
if (defined($reg_prefix)) {
|
|
|
|
$x86regno++;
|
|
|
|
$reg_nr++;
|
|
|
|
$reg = sprintf("%s%u%s", $reg_prefix, $reg_nr, $reg_suffix);
|
|
|
|
} else {
|
|
|
|
# Not a dashed sequence
|
|
|
|
die if ($nregs);
|
2007-04-16 07:12:17 +08:00
|
|
|
}
|
|
|
|
}
|
2002-06-06 10:41:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
($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*(\#.*|)$//;
|
2007-10-20 05:42:29 +08:00
|
|
|
|
2002-06-06 10:41:20 +08:00
|
|
|
next if ( $line eq '' );
|
|
|
|
|
2007-04-16 07:12:17 +08:00
|
|
|
process_line($line);
|
2002-06-06 10:41:20 +08:00
|
|
|
}
|
|
|
|
close(REGS);
|
|
|
|
|
|
|
|
if ( $fmt eq 'h' ) {
|
|
|
|
# Output regs.h
|
2007-10-03 12:53:51 +08:00
|
|
|
print "/* automatically generated from $file - do not edit */\n\n";
|
2008-05-28 05:43:14 +08:00
|
|
|
print "#ifndef NASM_REGS_H\n";
|
|
|
|
print "#define NASM_REGS_H\n\n";
|
|
|
|
|
2007-05-30 12:28:50 +08:00
|
|
|
$expr_regs = 1;
|
2008-05-28 05:32:55 +08:00
|
|
|
printf "#define EXPR_REG_START %d\n\n", $expr_regs;
|
2002-06-06 10:41:20 +08:00
|
|
|
print "enum reg_enum {\n";
|
2008-05-28 05:32:55 +08:00
|
|
|
# Unfortunately the code uses both 0 and -1 as "no register" in
|
|
|
|
# different places...
|
|
|
|
print " R_zero = 0,\n";
|
|
|
|
print " R_none = -1,\n";
|
2002-06-06 10:41:20 +08:00
|
|
|
$attach = ' = EXPR_REG_START'; # EXPR_REG_START == 1
|
|
|
|
foreach $reg ( sort(keys(%regs)) ) {
|
|
|
|
print " R_\U${reg}\E${attach},\n";
|
2007-09-13 11:27:41 +08:00
|
|
|
$attach = '';
|
2007-05-30 12:28:50 +08:00
|
|
|
$expr_regs++;
|
2002-06-06 10:41:20 +08:00
|
|
|
}
|
2008-05-28 05:32:55 +08:00
|
|
|
print " REG_ENUM_LIMIT\n";
|
2007-04-12 10:40:54 +08:00
|
|
|
print "};\n\n";
|
2008-05-28 05:32:55 +08:00
|
|
|
printf "#define EXPR_REG_END %d\n\n", $expr_regs-1;
|
2007-04-12 10:40:54 +08:00
|
|
|
foreach $reg ( sort(keys(%regs)) ) {
|
2007-05-30 11:25:21 +08:00
|
|
|
printf "#define %-15s %2d\n", "REG_NUM_\U${reg}", $regvals{$reg};
|
2007-04-12 10:40:54 +08:00
|
|
|
}
|
2008-05-28 05:43:14 +08:00
|
|
|
print "\n\n#endif /* NASM_REGS_H */\n";
|
2002-06-06 10:41:20 +08:00
|
|
|
} elsif ( $fmt eq 'c' ) {
|
|
|
|
# Output regs.c
|
2007-10-03 12:53:51 +08:00
|
|
|
print "/* automatically generated from $file - do not edit */\n\n";
|
2008-05-21 05:21:29 +08:00
|
|
|
print "#include \"tables.h\"\n\n";
|
|
|
|
print "const char * const nasm_reg_names[] = "; $ch = '{';
|
2002-06-06 10:41:20 +08:00
|
|
|
# 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
|
2008-05-21 05:21:29 +08:00
|
|
|
print "/* automatically generated from $file - do not edit */\n\n";
|
|
|
|
print "#include \"tables.h\"\n";
|
|
|
|
print "#include \"nasm.h\"\n\n";
|
|
|
|
print "const int32_t nasm_reg_flags[] = {\n";
|
2008-05-27 10:32:52 +08:00
|
|
|
printf " 0,\n"; # Dummy entry for 0
|
2002-06-06 10:41:20 +08:00
|
|
|
foreach $reg ( sort(keys(%regs)) ) {
|
2008-05-27 10:32:52 +08:00
|
|
|
# Print the class of the register
|
|
|
|
printf " %-15s /* %-5s */\n",
|
|
|
|
$regs{$reg}.',', $reg;
|
2002-06-06 10:41:20 +08:00
|
|
|
}
|
2008-05-27 10:32:52 +08:00
|
|
|
print "};\n";
|
2002-06-06 10:41:20 +08:00
|
|
|
} elsif ( $fmt eq 'vc' ) {
|
|
|
|
# Output regvals.c
|
2008-05-21 05:21:29 +08:00
|
|
|
print "/* automatically generated from $file - do not edit */\n\n";
|
|
|
|
print "#include \"tables.h\"\n\n";
|
|
|
|
print "const int nasm_regvals[] = {\n";
|
2008-05-27 10:32:52 +08:00
|
|
|
print " -1,\n"; # Dummy entry for 0
|
2002-06-06 10:41:20 +08:00
|
|
|
foreach $reg ( sort(keys(%regs)) ) {
|
2008-05-27 10:32:52 +08:00
|
|
|
# Print the x86 value of the register
|
|
|
|
printf " %2d, /* %-5s */\n", $regvals{$reg}, $reg;
|
2002-06-06 10:41:20 +08:00
|
|
|
}
|
2008-05-27 10:32:52 +08:00
|
|
|
print "};\n";
|
2002-06-06 10:41:20 +08:00
|
|
|
} elsif ( $fmt eq 'dc' ) {
|
|
|
|
# Output regdis.c
|
2008-05-21 05:21:29 +08:00
|
|
|
print "/* automatically generated from $file - do not edit */\n\n";
|
2008-05-28 05:32:55 +08:00
|
|
|
print "#include \"regdis.h\"\n\n";
|
2002-06-06 10:41:20 +08:00
|
|
|
foreach $class ( sort(keys(%disclass)) ) {
|
2008-05-21 05:38:21 +08:00
|
|
|
printf "const enum reg_enum nasm_rd_%-8s[%2d] = {",
|
2008-05-21 05:21:29 +08:00
|
|
|
$class, scalar @{$disclass{$class}};
|
2002-06-06 10:41:20 +08:00
|
|
|
@foo = @{$disclass{$class}};
|
2007-04-15 13:32:18 +08:00
|
|
|
@bar = ();
|
2002-06-06 10:41:20 +08:00
|
|
|
for ( $i = 0 ; $i < scalar(@foo) ; $i++ ) {
|
2007-04-15 09:37:13 +08:00
|
|
|
if (defined($foo[$i])) {
|
2007-04-15 13:32:18 +08:00
|
|
|
push(@bar, "R_\U$foo[$i]\E");
|
2007-04-16 07:12:17 +08:00
|
|
|
} else {
|
|
|
|
die "$0: No register name for class $class, value $i\n";
|
2007-04-15 09:37:13 +08:00
|
|
|
}
|
2002-06-06 10:41:20 +08:00
|
|
|
}
|
2007-04-15 09:37:13 +08:00
|
|
|
print join(',', @bar), "};\n";
|
2002-06-06 10:41:20 +08:00
|
|
|
}
|
2008-05-21 05:21:29 +08:00
|
|
|
} elsif ( $fmt eq 'dh' ) {
|
|
|
|
# Output regdis.h
|
2008-05-28 05:43:14 +08:00
|
|
|
print "/* automatically generated from $file - do not edit */\n\n";
|
|
|
|
print "#ifndef NASM_REGDIS_H\n";
|
|
|
|
print "#define NASM_REGDIS_H\n\n";
|
|
|
|
print "#include \"regs.h\"\n\n";
|
2008-05-21 05:21:29 +08:00
|
|
|
foreach $class ( sort(keys(%disclass)) ) {
|
2008-05-28 05:32:55 +08:00
|
|
|
printf "extern const enum reg_enum nasm_rd_%-8s[%2d];\n",
|
2008-05-21 05:21:29 +08:00
|
|
|
$class, scalar @{$disclass{$class}};
|
|
|
|
}
|
2008-05-28 05:43:14 +08:00
|
|
|
print "\n#endif /* NASM_REGDIS_H */\n";
|
2002-06-06 10:41:20 +08:00
|
|
|
} else {
|
|
|
|
die "$0: Unknown output format\n";
|
|
|
|
}
|