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;
23 my ($basedir) = $cwd =~ m
|(.*)/valgrind/|;
24 $csv_file = "$basedir/valgrind/docs/internals/s390-opcodes.csv";
25 $opc_file = "$basedir/binutils-gdb/opcodes/s390-opc.txt";
26 $toir_file = "$basedir/valgrind/VEX/priv/guest_s390_toIR.c";
27 } elsif ($num_arg == 3) {
30 $toir_file = $ARGV[2];
32 die "usage: s390-check-opcodes s390-opcodes.csv s390-opc.txt guest_s390_toIR.c\n";
37 my %csv_implemented = ();
38 my %toir_implemented = ();
39 my %toir_decoded = ();
40 my %known_arch = map {($_ => 1)}
41 qw(g5 z900 z990 z9-109 z9-ec z10 z196 zEC12 z13 arch12 arch13 arch14);
43 # Patterns for identifying certain extended mnemonics that shall be
44 # skipped in "s390-opc.txt" and "s390-opcodes.csv".
46 my @extended_mnemonics = (
47 "bi", # extended mnemonic for bic
57 'llg[fh]i', # llilf, llill
58 'notg?r', # nork, nogrk
140 "vsch[sdx]p", # vschp (short/long/extended)
146 "vsum(b|gh|gf|h|qf|qg)",
167 "prno" # alternate mnemonic for ppno
170 # Compile excluded mnemonics into one regular expression to optimize
171 # speed. Also it simplifies the code.
173 my $extended_mnemonics_pattern = '^(' .
174 join('|', map "$_", @extended_mnemonics) . ')$';
176 #----------------------------------------------------
177 # Read s390-opc.txt (binutils)
178 #----------------------------------------------------
179 open(OPC
, "$opc_file") || die "cannot open $opc_file\n";
180 while (my $line = <OPC
>) {
182 next if ($line =~ "^[ ]*#"); # comments
183 next if ($line =~ /^\s*$/); # blank line
184 my ($encoding,$mnemonic,$format) = $line =~ /^(\S+) (\S+) (\S+)/gc;
186 # Ignore opcodes that have wildcards in them ('$', '*')
187 # Those provide alternate mnemonics for specific instances of this opcode
188 next if ($mnemonic =~ /\$/);
189 next if ($mnemonic =~ /\*/);
191 # Ignore certain opcodes which are special cases of other opcodes
192 next if ($mnemonic eq "br"); # special case of bcr
193 next if ($mnemonic eq "nopr"); # special case of bcr
194 next if ($mnemonic eq "b"); # special case of bc
195 next if ($mnemonic eq "nop"); # special case of bc
196 next if ($mnemonic eq "j"); # special case of brc
197 next if ($mnemonic eq "jg"); # special case of brcl
198 next if ($mnemonic eq "tmh"); # alternate mnemonic for tmlh
199 next if ($mnemonic eq "tml"); # alternate mnemonic for tmll
200 next if ($mnemonic eq "lrdr"); # alternate mnemonic for ldxr
201 next if ($mnemonic eq "lrer"); # alternate mnemonic for ledr
202 next if ($mnemonic eq "me"); # alternate mnemonic for mde
203 next if ($mnemonic eq "mer"); # alternate mnemonic for mder
204 next if ($mnemonic eq "cuutf"); # alternate mnemonic for cu21
205 next if ($mnemonic eq "cutfu"); # alternate mnemonic for cu12
207 next if ($mnemonic eq "cfdbra"); # indistinguishable from cfdbr
208 next if ($mnemonic eq "cfebra"); # indistinguishable from cfebr
209 next if ($mnemonic eq "cfxbra"); # indistinguishable from cfxbr
210 next if ($mnemonic eq "cgdbra"); # indistinguishable from cgdbr
211 next if ($mnemonic eq "cgebra"); # indistinguishable from cgebr
212 next if ($mnemonic eq "cgxbra"); # indistinguishable from cgxbr
213 next if ($mnemonic eq "cdfbra"); # indistinguishable from cdfbr
214 next if ($mnemonic eq "cefbra"); # indistinguishable from cefbr
215 next if ($mnemonic eq "cxfbra"); # indistinguishable from cxfbr
216 next if ($mnemonic eq "cdgbra"); # indistinguishable from cdgbr
217 next if ($mnemonic eq "cegbra"); # indistinguishable from cegbr
218 next if ($mnemonic eq "cxgbra"); # indistinguishable from cxgbr
219 next if ($mnemonic eq "ldxbra"); # indistinguishable from ldxbr
220 next if ($mnemonic eq "lexbra"); # indistinguishable from lexbr
221 next if ($mnemonic eq "ledbra"); # indistinguishable from ledbr
222 next if ($mnemonic eq "cdgtr"); # indistinguishable from cdgtra
223 next if ($mnemonic eq "cxgtra"); # indistinguishable from cxgtr
224 next if ($mnemonic eq "cgdtra"); # indistinguishable from cgdtr
225 next if ($mnemonic eq "cgxtra"); # indistinguishable from cgxtr
226 next if ($mnemonic eq "fidbr"); # indistinguishable from fidbra
227 next if ($mnemonic eq "fiebr"); # indistinguishable from fiebra
228 next if ($mnemonic eq "fixbr"); # indistinguishable from fixbra
229 next if ($mnemonic eq "adtr"); # indistinguishable from adtra
230 next if ($mnemonic eq "axtr"); # indistinguishable from axtra
231 next if ($mnemonic eq "sdtr"); # indistinguishable from sdtra
232 next if ($mnemonic eq "sxtr"); # indistinguishable from sxtra
233 next if ($mnemonic eq "ddtr"); # indistinguishable from ddtra
234 next if ($mnemonic eq "dxtr"); # indistinguishable from dxtra
235 next if ($mnemonic eq "mdtr"); # indistinguishable from mdtra
236 next if ($mnemonic eq "mxtr"); # indistinguishable from mxtra
237 next if ($mnemonic =~ /$extended_mnemonics_pattern/);
239 my ($description) = $line =~ /\G\s+"\s*(.*?)\s*"/gc;
240 my ($arch) = $line =~ /\G\s+(\S+)/gc;
241 unless ($known_arch{$arch}) {
242 unless (exists $known_arch{$arch}) {
243 print "warning: unsupported arch \"$arch\" in s390-opc.txt\n";
244 $known_arch{$arch} = 0;
249 $description =~ s/\s\s+/ /g; # replace multiple blanks with a single one
251 # Certain opcodes are listed more than once. Let the first description
253 if (exists $opc_desc{$mnemonic}) {
255 # if ($opc_desc{$mnemonic} ne $description) {
256 # print "multiple description for opcode $mnemonic\n";
257 # print " old: |" . $opc_desc{$mnemonic} . "|\n";
258 # print " new: |" . $description . "|\n";
261 $opc_desc{$mnemonic} = $description;
264 if ($description =~ /,/) {
265 print "warning: description of $mnemonic contains comma\n";
270 #----------------------------------------------------
271 # Read CSV file (valgrind)
272 #----------------------------------------------------
273 open(CSV
, "$csv_file") || die "cannot open $csv_file\n";
274 while (my $line = <CSV
>) {
276 next if ($line =~ "^[ ]*#"); # comments
277 my ($mnemonic,$description,$status) = split /,/,$line;
280 $description =~ s/"//g;
282 next if ($mnemonic eq "cfdbra"); # indistinguishable from cfdbr
283 next if ($mnemonic eq "cfebra"); # indistinguishable from cfebr
284 next if ($mnemonic eq "cfxbra"); # indistinguishable from cfxbr
285 next if ($mnemonic eq "cgdbra"); # indistinguishable from cgdbr
286 next if ($mnemonic eq "cgebra"); # indistinguishable from cgebr
287 next if ($mnemonic eq "cgxbra"); # indistinguishable from cgxbr
288 next if ($mnemonic eq "cdfbra"); # indistinguishable from cdfbr
289 next if ($mnemonic eq "cefbra"); # indistinguishable from cefbr
290 next if ($mnemonic eq "cxfbra"); # indistinguishable from cxfbr
291 next if ($mnemonic eq "cegbra"); # indistinguishable from cegbr
292 next if ($mnemonic eq "cdgbra"); # indistinguishable from cdgbr
293 next if ($mnemonic eq "cegbra"); # indistinguishable from cegbr
294 next if ($mnemonic eq "cxgbra"); # indistinguishable from cxgbr
295 next if ($mnemonic eq "ldxbra"); # indistinguishable from ldxbr
296 next if ($mnemonic eq "lexbra"); # indistinguishable from lexbr
297 next if ($mnemonic eq "ledbra"); # indistinguishable from ledbr
298 next if ($mnemonic eq "cdgtr"); # indistinguishable from cdgtra
299 next if ($mnemonic eq "cxgtra"); # indistinguishable from cxgtr
300 next if ($mnemonic eq "cgdtra"); # indistinguishable from cgdtr
301 next if ($mnemonic eq "cgxtra"); # indistinguishable from cgxtr
302 next if ($mnemonic eq "fidbr"); # indistinguishable from fidbra
303 next if ($mnemonic eq "fiebr"); # indistinguishable from fiebra
304 next if ($mnemonic eq "fixbr"); # indistinguishable from fixbra
305 next if ($mnemonic eq "adtr"); # indistinguishable from adtra
306 next if ($mnemonic eq "sdtr"); # indistinguishable from sdtra
307 next if ($mnemonic eq "ddtr"); # indistinguishable from ddtra
308 next if ($mnemonic eq "mdtr"); # indistinguishable from mdtra
309 next if ($mnemonic =~ /$extended_mnemonics_pattern/);
311 # Complain about duplicate entries. We don't want them.
312 if ($csv_desc{$mnemonic}) {
313 print "$mnemonic: duplicate entry\n";
315 $csv_desc{$mnemonic} = $description;
317 # Remember whether it is implemented or not
318 next if ($line =~ /not\s+implemented/);
319 next if ($line =~ /N\/A
/);
320 next if ($line =~ /won't do/);
321 if ($line =~ /implemented/) {
322 $csv_implemented{$mnemonic} = 1;
324 print "*** unknown implementation status of $mnemonic\n";
329 #----------------------------------------------------
330 # Read s390_guest_toIR.c file. Compile list of implemented opcodes
331 #----------------------------------------------------
332 open(TOIR
, "$toir_file") || die "cannot open $toir_file\n";
333 while (my $line = <TOIR
>) {
335 if ($line =~ /goto\s+unimplemented/) {
336 # Assume this is in the decoder
337 if ($line =~ /\/\
*\s
([A
-Z
][A
-Z0
-9]*)\s\
*\
//) {
338 my $mnemonic = lc $1;
339 $toir_decoded{$mnemonic} = 1;
341 } elsif ($line =~ /^s390_irgen_([A-Z][A-Z0-9]*)\b/) {
342 my $mnemonic = lc $1;
343 $toir_implemented{$mnemonic} = 1;
348 #----------------------------------------------------
349 # 1) Make sure there are no missing/extra opcodes
350 #----------------------------------------------------
351 foreach my $opc (keys %opc_desc) {
352 if (! $csv_desc{$opc}) {
353 print "*** opcode $opc not listed in $csv_file\n";
356 foreach my $opc (keys %csv_desc) {
357 if (! $opc_desc{$opc}) {
358 print "*** opcode $opc not listed in $opc_file\n";
362 #----------------------------------------------------
363 # 2) Make sure opcode descriptions are the same
364 #----------------------------------------------------
365 foreach my $opc (keys %opc_desc) {
366 if (defined $csv_desc{$opc}) {
367 if (lc($opc_desc{$opc}) ne lc($csv_desc{$opc})) {
368 print "*** opcode $opc differs:\n";
369 print " binutils: $opc_desc{$opc}\n";
370 print " opcodes.csv: $csv_desc{$opc}\n";
375 #----------------------------------------------------
376 # 3) Make sure implemented'ness is correct
377 #----------------------------------------------------
378 foreach my $opc (keys %toir_implemented) {
379 if (! $csv_implemented{$opc}) {
380 print "*** opcode $opc is implemented but CSV file does not say so\n";
384 foreach my $opc (keys %csv_implemented) {
385 if (! $toir_implemented{$opc}) {
386 print "*** opcode $opc is not implemented but CSV file says so\n";
390 #----------------------------------------------------
391 # 4) Make sure all opcodes are handled by the decoder
392 #----------------------------------------------------
394 # We only have to check those for which we don't generate IR.
396 foreach my $opc (keys %opc_desc) {
397 if (! $toir_implemented{$opc} && ! $toir_decoded{$opc}) {
398 print "*** opcode $opc is not handled by the decoder\n";
402 print "there are " . int(keys %toir_implemented) . " implemented opcodes\n";