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