Prepping for mdoc et. al. move from monodoc/tools to mcs/tools/mdoc...
[mono.git] / mono / mini / genmdesc.pl
1 #!/usr/bin/perl -w
2
3 # perl replacement of genmdesc.c for use when cross-compiling
4
5 use strict;
6 no locale;
7
8 # must keep in sync with mini.h
9 my @spec_names = qw(dest src1 src2 len clob);
10 sub INST_DEST  () {return 0;}
11 sub INST_SRC1  () {return 1;}
12 sub INST_SRC2  () {return 2;}
13 sub INST_LEN   () {return 3;}
14 sub INST_CLOB  () {return 4;}
15 sub INST_MAX   () {return 5;}
16
17 # this must include all the #defines used in mini-ops.h
18 my @defines = qw (__i386__ __x86_64__ __ppc__ __powerpc__ __arm__ 
19         __sparc__ sparc __s390__ s390 __ia64__ __alpha__ __mips__);
20 my %table =();
21 my @opcodes = ();
22
23 sub load_opcodes
24 {
25         my ($srcdir, $arch) = @_;
26         my $opcodes_def = "$srcdir/../cil/opcode.def";
27         my $i = 0;
28         my $arch_found = 0;
29
30         open (OPS, "$opcodes_def") || die "Cannot open $opcodes_def: $!";
31         while (<OPS>) {
32                 next unless /OPDEF\s*\(\s*(\S+?)\s*,\s*"(.*?)"/;
33                 my ($sym, $name) = ($1, $2);
34                 push @opcodes, [$sym, $name];
35                 $table{$name} = {num => $i, name => $name};
36                 $i++;
37         }
38         close (OPS);
39         my $cpp = $ENV{"CPP"};
40         $cpp = "cpp" unless defined $cpp;
41         $cpp .= " -undef ";
42         foreach (@defines) {
43                 $cpp .= " -U$_";
44                 $arch_found = 1 if $arch eq $_;
45         }
46         die "$arch arch is not supported.\n" unless $arch_found;
47
48         $cpp .= " -D$arch $srcdir/mini-ops.h|";
49         #print "Running: $cpp\n";
50         open (OPS, $cpp) || die "Cannot execute cpp: $!";
51         while (<OPS>) {
52                 next unless /MINI_OP\s*\(\s*(\S+?)\s*,\s*"(.*?)"/;
53                 my ($sym, $name) = ($1, $2);
54                 push @opcodes, [$sym, $name];
55                 $table{$name} = {num => $i, name => $name};
56                 $i++;
57         }
58         close (OPS);
59 }
60
61 sub load_file {
62         my ($name) = @_;
63         my $line = 0;
64         my $comment = "";
65
66         open (DESC, $name) || die "Cannot open $name: $!";
67         while (<DESC>) {
68                 $line++;
69                 next if /^\s*$/;
70                 if (/^\s*(#.*)?$/) {
71                         $comment .= "$1\n";
72                         next;
73                 }
74                 my @values = split (/\s+/);
75                 next unless ($values [0] =~ /(\S+?):/);
76                 my $name = $1;
77                 my $desc = $table {$name};
78                 shift @values;
79                 die "Invalid opcode $name at line $line\n" unless defined $desc;
80                 die "Duplicated opcode $name at line $line\n" if $desc->{"desc"};
81                 $desc->{"desc"} = $_;
82                 $desc->{"comment"} = $comment;
83                 $desc->{"spec"} = {};
84                 $comment = "";
85                 #print "values for $name: " . join (' ', @values) . " num: " . int(@values), "\n";
86                 for my $val (@values) {
87                         if ($val =~ /(\S+):(.*)/) {
88                                 $desc->{"spec"}->{$1} = $2;
89                         }
90                 }
91         }
92         close (DESC);
93 }
94
95 sub build_spec {
96         my ($spec) = shift;
97         my %spec = %{$spec};
98         my @vals = ();
99         foreach (@spec_names) {
100                 my $val = $spec->{$_};
101                 if (defined $val) {
102                         push @vals, $val;
103                 } else {
104                         push @vals, undef;
105                 }
106         }
107         #print "vals: " . join (' ', @vals) . "\n";
108         my $res = "";
109         for (my $i = 0; $i < @vals; ++$i) {
110                 if (defined $vals [$i]) {
111                         if ($i == INST_LEN) {
112                                 $res .= sprintf ("\\x%x\" \"", +$vals [$i]);
113                         } else {
114                                 if ($vals [$i] =~ /^[a-zA-Z0-9]$/) {
115                                         $res .= $vals [$i];
116                                 } else {
117                                         $res .= sprintf ("\\x%x\" \"", $vals [$i]);
118                                 }
119                         }
120                 } else {
121                         $res .= "\\x0\" \"";
122                 }
123         }
124         return $res;
125 }
126
127 sub build_table {
128         my ($fname, $name) = @_;
129         my $i;
130         my $idx;
131         my $idx_array = "const guint16 ${name}_idx [] = {\n";
132
133         open (OUT, ">$fname") || die "Cannot open file $fname: $!";
134         print OUT "/* File automatically generated by genmdesc, don't change */\n\n";
135         print OUT "const char $name [] = {\n";
136         print OUT "\t\"" . ("\\x0" x INST_MAX) . "\"\t/* null entry */\n";
137         $idx = 1;
138
139         for ($i = 0; $i < @opcodes; ++$i) {
140                 my $name = $opcodes [$i]->[1];
141                 my $desc = $table {$name};
142                 my $spec = $desc->{"spec"};
143                 if (defined $spec) {
144                         print OUT "\t\"";
145                         print OUT build_spec ($spec);
146                         print OUT "\"\t/* $name */\n";
147                         my $pos = $idx * INST_MAX;
148                         $idx_array .= "\t$pos,\t/* $name */\n";
149                         ++$idx;
150                 } else {
151                         $idx_array .= "\t0,\t/* $name */\n";
152                 }
153         }
154         print OUT "};\n\n";
155         print OUT "$idx_array};\n\n";
156         close (OUT);
157 }
158
159 sub usage {
160         die "genmdesc.pl arch srcdir desc output name\n";
161 }
162
163 my $arch = shift || usage ();
164 my $srcdir = shift || usage ();
165 my $file = shift || usage ();
166 my $output = shift || usage ();
167 my $name = shift || usage ();
168
169 load_opcodes ($srcdir, $arch);
170 load_file ($file);
171 build_table ($output, $name);
172