drd: Add a consistency check
[valgrind.git] / auxprogs / s390-check-opcodes.pl
blob180a3bca6b438743bc4bb0bb97aea621268c01ad
1 #!/usr/bin/env perl
3 use strict;
4 use warnings;
6 #------------------------------------------------------------------
7 # This script assists in updating s390-opcodes.csv
8 # It utilizes <binutils>/opcodes/s390-opc.txt and
9 # <valgrind>/VEX/priv/guest_s390_toIR.c and will
10 # - identify new opcodes that are present in s390-opc.txt
11 # (s390-opc.txt is the golden list)
12 # - identify opcodes that are implemented in guest_s390_toIR.c
13 # but have an out-of-date status in the CSV file.
14 #------------------------------------------------------------------
15 my $num_arg = $#ARGV + 1;
17 if ($num_arg != 3) {
18 die "usage: s390-check-opcodes s390-opcodes.csv s390-opc.txt guest_s390_toIR.c\n";
21 my $csv_file = $ARGV[0];
22 my $opc_file = $ARGV[1];
23 my $toir_file = $ARGV[2];
25 my %opc_desc = ();
26 my %csv_desc = ();
27 my %csv_implemented = ();
28 my %toir_implemented = ();
29 my %toir_decoded = ();
32 #----------------------------------------------------
33 # Read s390-opc.txt (binutils)
34 #----------------------------------------------------
35 open(OPC, "$opc_file") || die "cannot open $opc_file\n";
36 while (my $line = <OPC>) {
37 chomp $line;
38 next if ($line =~ "^[ ]*#"); # comments
39 next if ($line =~ /^\s*$/); # blank line
40 my $description = (split /"/,$line)[1];
41 my ($encoding,$mnemonic,$format) = split /\s+/,$line;
43 # Ignore opcodes that have wildcards in them ('$', '*')
44 # Those provide alternate mnemonics for specific instances of this opcode
45 next if ($mnemonic =~ /\$/);
46 next if ($mnemonic =~ /\*/);
48 # Ignore certain opcodes which are special cases of other opcodes
49 next if ($mnemonic eq "br"); # special case of bcr
50 next if ($mnemonic eq "nopr"); # special case of bcr
51 next if ($mnemonic eq "b"); # special case of bc
52 next if ($mnemonic eq "nop"); # special case of bc
53 next if ($mnemonic eq "j"); # special case of brc
54 next if ($mnemonic eq "jg"); # special case of brcl
55 next if ($mnemonic eq "tmh"); # alternate mnemonic for tmlh
56 next if ($mnemonic eq "tml"); # alternate mnemonic for tmll
57 next if ($mnemonic eq "lrdr"); # alternate mnemonic for ldxr
58 next if ($mnemonic eq "lrer"); # alternate mnemonic for ledr
59 next if ($mnemonic eq "me"); # alternate mnemonic for mde
60 next if ($mnemonic eq "mer"); # alternate mnemonic for mder
61 next if ($mnemonic eq "cuutf"); # alternate mnemonic for cu21
62 next if ($mnemonic eq "cutfu"); # alternate mnemonic for cu12
64 next if ($mnemonic eq "cfdbra"); # indistinguishable from cfdbr
65 next if ($mnemonic eq "cfebra"); # indistinguishable from cfebr
66 next if ($mnemonic eq "cfxbra"); # indistinguishable from cfxbr
67 next if ($mnemonic eq "cgdbra"); # indistinguishable from cgdbr
68 next if ($mnemonic eq "cgebra"); # indistinguishable from cgebr
69 next if ($mnemonic eq "cgxbra"); # indistinguishable from cgxbr
70 next if ($mnemonic eq "cdfbra"); # indistinguishable from cdfbr
71 next if ($mnemonic eq "cefbra"); # indistinguishable from cefbr
72 next if ($mnemonic eq "cxfbra"); # indistinguishable from cxfbr
73 next if ($mnemonic eq "cdgbra"); # indistinguishable from cdgbr
74 next if ($mnemonic eq "cegbra"); # indistinguishable from cegbr
75 next if ($mnemonic eq "cxgbra"); # indistinguishable from cxgbr
76 next if ($mnemonic eq "ldxbra"); # indistinguishable from ldxbr
77 next if ($mnemonic eq "lexbra"); # indistinguishable from lexbr
78 next if ($mnemonic eq "ledbra"); # indistinguishable from ledbr
79 next if ($mnemonic eq "cdgtra"); # indistinguishable from cdgtr
80 next if ($mnemonic eq "cxgtra"); # indistinguishable from cxgtr
81 next if ($mnemonic eq "cgdtra"); # indistinguishable from cgdtr
82 next if ($mnemonic eq "cgxtra"); # indistinguishable from cgxtr
83 next if ($mnemonic eq "fidbra"); # indistinguishable from fidbr
84 next if ($mnemonic eq "fiebra"); # indistinguishable from fiebr
85 next if ($mnemonic eq "fixbra"); # indistinguishable from fixbr
86 next if ($mnemonic eq "adtr"); # indistinguishable from adtra
87 next if ($mnemonic eq "axtr"); # indistinguishable from axtra
88 next if ($mnemonic eq "sdtr"); # indistinguishable from sdtra
89 next if ($mnemonic eq "sxtr"); # indistinguishable from sxtra
90 next if ($mnemonic eq "ddtr"); # indistinguishable from ddtra
91 next if ($mnemonic eq "dxtr"); # indistinguishable from dxtra
92 next if ($mnemonic eq "mdtr"); # indistinguishable from mdtra
93 next if ($mnemonic eq "mxtr"); # indistinguishable from mxtra
95 $description =~ s/^[\s]+//g; # remove leading blanks
96 $description =~ s/[\s]+$//g; # remove trailing blanks
97 $description =~ s/[ ][ ]+/ /g; # replace multiple blanks with a single one
100 # Certain opcodes are listed more than once. Let the first description win
101 if ($opc_desc{$mnemonic}) {
102 # already there
103 # if ($opc_desc{$mnemonic} ne $description) {
104 # print "multiple description for opcode $mnemonic\n";
105 # print " old: |" . $opc_desc{$mnemonic} . "|\n";
106 # print " new: |" . $description . "|\n";
108 } else {
109 $opc_desc{$mnemonic} = $description;
112 if ($description =~ /,/) {
113 print "warning: description of $mnemonic contains comma\n";
116 close(OPC);
118 #----------------------------------------------------
119 # Read CSV file (valgrind)
120 #----------------------------------------------------
121 open(CSV, "$csv_file") || die "cannot open $csv_file\n";
122 while (my $line = <CSV>) {
123 chomp $line;
124 next if ($line =~ "^[ ]*#"); # comments
125 my ($mnemonic,$description,$status) = split /,/,$line;
127 $mnemonic =~ s/"//g;
128 $description =~ s/"//g;
130 next if ($mnemonic eq "cfdbra"); # indistinguishable from cfdbr
131 next if ($mnemonic eq "cfebra"); # indistinguishable from cfebr
132 next if ($mnemonic eq "cfxbra"); # indistinguishable from cfxbr
133 next if ($mnemonic eq "cgdbra"); # indistinguishable from cgdbr
134 next if ($mnemonic eq "cgebra"); # indistinguishable from cgebr
135 next if ($mnemonic eq "cgxbra"); # indistinguishable from cgxbr
136 next if ($mnemonic eq "cdfbra"); # indistinguishable from cdfbr
137 next if ($mnemonic eq "cefbra"); # indistinguishable from cefbr
138 next if ($mnemonic eq "cxfbra"); # indistinguishable from cxfbr
139 next if ($mnemonic eq "cegbra"); # indistinguishable from cegbr
140 next if ($mnemonic eq "cdgbra"); # indistinguishable from cdgbr
141 next if ($mnemonic eq "cegbra"); # indistinguishable from cegbr
142 next if ($mnemonic eq "cxgbra"); # indistinguishable from cxgbr
143 next if ($mnemonic eq "ldxbra"); # indistinguishable from ldxbr
144 next if ($mnemonic eq "lexbra"); # indistinguishable from lexbr
145 next if ($mnemonic eq "ledbra"); # indistinguishable from ledbr
146 next if ($mnemonic eq "cdgtra"); # indistinguishable from cdgtr
147 next if ($mnemonic eq "cxgtra"); # indistinguishable from cxgtr
148 next if ($mnemonic eq "cgdtra"); # indistinguishable from cgdtr
149 next if ($mnemonic eq "cgxtra"); # indistinguishable from cgxtr
150 next if ($mnemonic eq "fidbra"); # indistinguishable from fidbr
151 next if ($mnemonic eq "fiebra"); # indistinguishable from fiebr
152 next if ($mnemonic eq "fixbra"); # indistinguishable from fixbr
153 next if ($mnemonic eq "adtr"); # indistinguishable from adtra
154 next if ($mnemonic eq "sdtr"); # indistinguishable from sdtra
155 next if ($mnemonic eq "ddtr"); # indistinguishable from ddtra
156 next if ($mnemonic eq "mdtr"); # indistinguishable from mdtra
158 # Complain about duplicate entries. We don't want them.
159 if ($csv_desc{$mnemonic}) {
160 print "$mnemonic: duplicate entry\n";
161 } else {
162 $csv_desc{$mnemonic} = $description;
164 # Remember whether it is implemented or not
165 next if ($line =~ /not\s+implemented/);
166 next if ($line =~ /N\/A/);
167 next if ($line =~ /won't do/);
168 if ($line =~ /implemented/) {
169 $csv_implemented{$mnemonic} = 1;
170 } else {
171 print "*** unknown implementation status of $mnemonic\n";
174 close(CSV);
176 #----------------------------------------------------
177 # Read s390_guest_toIR.c file. Compile list of implemented opcodes
178 #----------------------------------------------------
179 open(TOIR, "$toir_file") || die "cannot open $toir_file\n";
180 while (my $line = <TOIR>) {
181 chomp $line;
182 if ($line =~ /goto\s+unimplemented/) {
183 # Assume this is in the decoder
184 if ($line =~ /\/\*\s([A-Z][A-Z0-9]+)\s\*\//) {
185 my $mnemonic = $1;
186 $mnemonic =~ tr/A-Z/a-z/;
187 $toir_decoded{$mnemonic} = 1;
188 # print "DECODED: $mnemonic\n";
191 next if (! ($line =~ /^s390_irgen_[A-Z]/));
192 $line =~ /^s390_irgen_([A-Z][A-Z0-9]*)/;
193 my $op = $1;
194 $op =~ tr/A-Z/a-z/;
195 $toir_implemented{$op} = 1;
197 close(TOIR);
199 #----------------------------------------------------
200 # 1) Make sure there are no missing/extra opcodes
201 #----------------------------------------------------
202 foreach my $opc (keys %opc_desc) {
203 if (! $csv_desc{$opc}) {
204 print "*** opcode $opc not listed in $csv_file\n";
207 foreach my $opc (keys %csv_desc) {
208 if (! $opc_desc{$opc}) {
209 print "*** opcode $opc not listed in $opc_file\n";
213 #----------------------------------------------------
214 # 2) Make sure opcode descriptions are the same
215 #----------------------------------------------------
216 foreach my $opc (keys %opc_desc) {
217 if (defined $csv_desc{$opc}) {
218 if ($opc_desc{$opc} ne $csv_desc{$opc}) {
219 print "*** opcode $opc differs:\n";
220 print " binutils: $opc_desc{$opc}\n";
221 print " opcodes.csv: $csv_desc{$opc}\n";
226 #----------------------------------------------------
227 # 3) Make sure implemented'ness is correct
228 #----------------------------------------------------
229 foreach my $opc (keys %toir_implemented) {
230 if (! $csv_implemented{$opc}) {
231 print "*** opcode $opc is implemented but CSV file does not say so\n";
235 foreach my $opc (keys %csv_implemented) {
236 if (! $toir_implemented{$opc}) {
237 print "*** opcode $opc is not implemented but CSV file says so\n";
241 #----------------------------------------------------
242 # 4) Make sure all opcodes are handled by the decoder
243 #----------------------------------------------------
245 # We only have to check those for which we don't generate IR.
247 foreach my $opc (keys %opc_desc) {
248 if (! $toir_implemented{$opc} && ! $toir_decoded{$opc}) {
249 print "*** opcode $opc is not handled by the decoder\n";
253 print "there are " . int(keys %toir_implemented) . " implemented opcodes\n";
254 exit 0