regs.pl: add include guards to generated header files
[platform/upstream/nasm.git] / regs.pl
1 #!/usr/bin/perl
2 #
3 # Read regs.dat and output regs.h and regs.c (included in names.c)
4 #
5
6 $nline = 0;
7
8 sub toint($) {
9     my($v) = @_;
10
11     return ($v =~ /^0/) ? oct $v : $v+0;
12 }
13
14 sub process_line($) {
15     my($line) = @_;
16     my @v;
17
18     if ( $line !~ /^\s*(\S+)\s*(\S+)\s*(\S+)\s*([0-9]+)$/i ) {
19         die "regs.dat:$nline: invalid input\n";
20     }
21     $reg      = $1;
22     $aclass   = $2;
23     $dclasses = $3;
24     $x86regno = toint($4);
25
26     if ($reg =~ /^(.*[^0-9])([0-9]+)\-([0-9]+)(|[^0-9].*)$/) {
27         $nregs = $3-$2+1;
28         $reg = $1.$2.$4;
29         $reg_nr = $2;
30         $reg_prefix = $1;
31         $reg_suffix = $4;
32     } else {
33         $nregs = 1;
34         undef $reg_prefix, $reg_suffix;
35     }
36
37     while ($nregs--) {
38         $regs{$reg} = $aclass;
39         $regvals{$reg} = $x86regno;
40
41         foreach $dclass (split(/,/, $dclasses)) {
42             if ( !defined($disclass{$dclass}) ) {
43                 $disclass{$dclass} = [];
44             }
45
46             $disclass{$dclass}->[$x86regno] = $reg;
47         }
48
49         # Compute the next register, if any
50         if (defined($reg_prefix)) {
51             $x86regno++;
52             $reg_nr++;
53             $reg = sprintf("%s%u%s", $reg_prefix, $reg_nr, $reg_suffix);
54         } else {
55             # Not a dashed sequence
56             die if ($nregs);
57         }
58     }
59 }
60
61 ($fmt, $file) = @ARGV;
62
63 %regs = ();
64 %regvals = ();
65 %disclass = ();
66 open(REGS, "< ${file}") or die "$0: Cannot open $file\n";
67 while ( defined($line = <REGS>) ) {
68     $nline++;
69
70     chomp $line;
71     $line =~ s/\s*(\#.*|)$//;
72
73     next if ( $line eq '' );
74
75     process_line($line);
76 }
77 close(REGS);
78
79 if ( $fmt eq 'h' ) {
80     # Output regs.h
81     print "/* automatically generated from $file - do not edit */\n\n";
82     print "#ifndef NASM_REGS_H\n";
83     print "#define NASM_REGS_H\n\n";
84
85     $expr_regs = 1;
86     printf "#define EXPR_REG_START %d\n\n", $expr_regs;
87     print "enum reg_enum {\n";
88     # Unfortunately the code uses both 0 and -1 as "no register" in
89     # different places...
90     print "    R_zero = 0,\n";
91     print "    R_none = -1,\n";
92     $attach = ' = EXPR_REG_START'; # EXPR_REG_START == 1
93     foreach $reg ( sort(keys(%regs)) ) {
94         print "    R_\U${reg}\E${attach},\n";
95         $attach = '';
96         $expr_regs++;
97     }
98     print "    REG_ENUM_LIMIT\n";
99     print "};\n\n";
100     printf "#define EXPR_REG_END %d\n\n", $expr_regs-1;
101     foreach $reg ( sort(keys(%regs)) ) {
102         printf "#define %-15s %2d\n", "REG_NUM_\U${reg}", $regvals{$reg};
103     }
104     print "\n\n#endif /* NASM_REGS_H */\n";
105 } elsif ( $fmt eq 'c' ) {
106     # Output regs.c
107     print "/* automatically generated from $file - do not edit */\n\n";
108     print "#include \"tables.h\"\n\n";
109     print "const char * const nasm_reg_names[] = "; $ch = '{';
110     # This one has no dummy entry for 0
111     foreach $reg ( sort(keys(%regs)) ) {
112         print "$ch\n    \"${reg}\"";
113         $ch = ',';
114     }
115     print "\n};\n";
116 } elsif ( $fmt eq 'fc' ) {
117     # Output regflags.c
118     print "/* automatically generated from $file - do not edit */\n\n";
119     print "#include \"tables.h\"\n";
120     print "#include \"nasm.h\"\n\n";
121     print "const int32_t nasm_reg_flags[] = {\n";
122     printf "    0,\n";          # Dummy entry for 0
123     foreach $reg ( sort(keys(%regs)) ) {
124         # Print the class of the register
125         printf "    %-15s /* %-5s */\n",
126                 $regs{$reg}.',', $reg;
127     }
128     print "};\n";
129 } elsif ( $fmt eq 'vc' ) {
130     # Output regvals.c
131     print "/* automatically generated from $file - do not edit */\n\n";
132     print "#include \"tables.h\"\n\n";
133     print "const int nasm_regvals[] = {\n";
134     print "    -1,\n";          # Dummy entry for 0
135     foreach $reg ( sort(keys(%regs)) ) {
136         # Print the x86 value of the register
137         printf "    %2d,  /* %-5s */\n", $regvals{$reg}, $reg;
138     }
139     print "};\n";
140 } elsif ( $fmt eq 'dc' ) {
141     # Output regdis.c
142     print "/* automatically generated from $file - do not edit */\n\n";
143     print "#include \"regdis.h\"\n\n";
144     foreach $class ( sort(keys(%disclass)) ) {
145         printf "const enum reg_enum nasm_rd_%-8s[%2d] = {",
146                 $class, scalar @{$disclass{$class}};
147         @foo = @{$disclass{$class}};
148         @bar = ();
149         for ( $i = 0 ; $i < scalar(@foo) ; $i++ ) {
150             if (defined($foo[$i])) {
151                 push(@bar, "R_\U$foo[$i]\E");
152             } else {
153                 die "$0: No register name for class $class, value $i\n";
154             }
155         }
156         print join(',', @bar), "};\n";
157     }
158 } elsif ( $fmt eq 'dh' ) {
159     # Output regdis.h
160     print "/* automatically generated from $file - do not edit */\n\n";
161     print "#ifndef NASM_REGDIS_H\n";
162     print "#define NASM_REGDIS_H\n\n";
163     print "#include \"regs.h\"\n\n";
164     foreach $class ( sort(keys(%disclass)) ) {
165         printf "extern const enum reg_enum nasm_rd_%-8s[%2d];\n",
166                 $class, scalar @{$disclass{$class}};
167     }
168     print "\n#endif /* NASM_REGDIS_H */\n";
169 } else {
170     die "$0: Unknown output format\n";
171 }