Make sure x86 ATOMIC_CAS doesn't overwrite its own operands.
[mono-debugger.git] / mono / mini / genmdesc.pl
blob0cd89effeffce07d910abcdc7a03f3e52083ba50
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 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;}
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 = ();
23 sub load_opcodes
25 my ($srcdir, $arch) = @_;
26 my $opcodes_def = "$srcdir/../cil/opcode.def";
27 my $i = 0;
28 my $arch_found = 0;
30 my $cpp = $ENV{"CPP"};
31 $cpp = "cpp" unless defined $cpp;
32 $cpp .= " -undef ";
33 foreach (@defines) {
34 $cpp .= " -U$_";
35 $arch_found = 1 if $arch eq $_;
37 die "$arch arch is not supported.\n" unless $arch_found;
39 $cpp .= " -D$arch $srcdir/mini-ops.h|";
40 #print "Running: $cpp\n";
41 open (OPS, $cpp) || die "Cannot execute cpp: $!";
42 while (<OPS>) {
43 next unless /MINI_OP\s*\(\s*(\S+?)\s*,\s*"(.*?)"/;
44 my ($sym, $name) = ($1, $2);
45 push @opcodes, [$sym, $name];
46 $table{$name} = {num => $i, name => $name};
47 $i++;
49 close (OPS);
52 sub load_file {
53 my ($name) = @_;
54 my $line = 0;
55 my $comment = "";
57 open (DESC, $name) || die "Cannot open $name: $!";
58 while (<DESC>) {
59 $line++;
60 next if /^\s*$/;
61 if (/^\s*(#.*)?$/) {
62 $comment .= "$1\n";
63 next;
65 my @values = split (/\s+/);
66 next unless ($values [0] =~ /(\S+?):/);
67 my $name = $1;
68 my $desc = $table {$name};
69 shift @values;
70 die "Invalid opcode $name at line $line\n" unless defined $desc;
71 die "Duplicated opcode $name at line $line\n" if $desc->{"desc"};
72 $desc->{"desc"} = $_;
73 $desc->{"comment"} = $comment;
74 $desc->{"spec"} = {};
75 $comment = "";
76 #print "values for $name: " . join (' ', @values) . " num: " . int(@values), "\n";
77 for my $val (@values) {
78 if ($val =~ /(\S+):(.*)/) {
79 $desc->{"spec"}->{$1} = $2;
83 close (DESC);
86 sub build_spec {
87 my ($spec) = shift;
88 my %spec = %{$spec};
89 my @vals = ();
90 foreach (@spec_names) {
91 my $val = $spec->{$_};
92 if (defined $val) {
93 push @vals, $val;
94 } else {
95 push @vals, undef;
98 #print "vals: " . join (' ', @vals) . "\n";
99 my $res = "";
100 for (my $i = 0; $i < @vals; ++$i) {
101 if (defined $vals [$i]) {
102 if ($i == INST_LEN) {
103 $res .= sprintf ("\\x%x\" \"", +$vals [$i]);
104 } else {
105 if ($vals [$i] =~ /^[a-zA-Z0-9]$/) {
106 $res .= $vals [$i];
107 } else {
108 $res .= sprintf ("\\x%x\" \"", $vals [$i]);
111 } else {
112 $res .= "\\x0\" \"";
115 return $res;
118 sub build_table {
119 my ($fname, $name) = @_;
120 my $i;
121 my $idx;
122 my $idx_array = "const guint16 ${name}_idx [] = {\n";
124 open (OUT, ">$fname") || die "Cannot open file $fname: $!";
125 print OUT "/* File automatically generated by genmdesc, don't change */\n\n";
126 print OUT "const char $name [] = {\n";
127 print OUT "\t\"" . ("\\x0" x INST_MAX) . "\"\t/* null entry */\n";
128 $idx = 1;
130 for ($i = 0; $i < @opcodes; ++$i) {
131 my $name = $opcodes [$i]->[1];
132 my $desc = $table {$name};
133 my $spec = $desc->{"spec"};
134 if (defined $spec) {
135 print OUT "\t\"";
136 print OUT build_spec ($spec);
137 print OUT "\"\t/* $name */\n";
138 my $pos = $idx * INST_MAX;
139 $idx_array .= "\t$pos,\t/* $name */\n";
140 ++$idx;
141 } else {
142 $idx_array .= "\t0,\t/* $name */\n";
145 print OUT "};\n\n";
146 print OUT "$idx_array};\n\n";
147 close (OUT);
150 sub usage {
151 die "genmdesc.pl arch srcdir desc output name\n";
154 my $arch = shift || usage ();
155 my $srcdir = shift || usage ();
156 my $file = shift || usage ();
157 my $output = shift || usage ();
158 my $name = shift || usage ();
160 load_opcodes ($srcdir, $arch);
161 load_file ($file);
162 build_table ($output, $name);