remove empty dir
[ghc-hetmet.git] / ghc / rts / gmp / mpn / x86 / k6 / cross.pl
1 #! /usr/bin/perl
2
3 # Copyright (C) 2000 Free Software Foundation, Inc.
4 #
5 # This file is part of the GNU MP Library.
6 #
7 # The GNU MP Library is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU Lesser General Public License as published
9 # by the Free Software Foundation; either version 2.1 of the License, or (at
10 # your option) any later version.
11 #
12 # The GNU MP Library is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 # License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public License
18 # along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
19 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 # MA 02111-1307, USA.
21
22
23 # Usage: cross.pl [filename.o]...
24 #
25 # Produce an annotated disassembly of the given object files, indicating
26 # certain code alignment and addressing mode problems afflicting K6 chips.
27 # "ZZ" is used on all annotations, so this can be searched for.
28 #
29 # With no arguments, all .o files corresponding to .asm files are processed.
30 # This is good in the mpn object directory of a k6*-*-* build.
31 #
32 # As far as fixing problems goes, any cache line crossing problems in loops
33 # get attention, but as a rule it's too tedious to rearrange code or slip in
34 # nops to fix every problem in setup or finishup code.
35 #
36 # Bugs:
37 #
38 # Instructions without mod/rm bytes or which are already vector decoded are
39 # unaffected by cache line boundary crossing, but not all of these have yet
40 # been put in as exceptions.  All that occur in practice in GMP are present
41 # though.
42 #
43 # There's no messages for using the vector decoded addressing mode (%esi),
44 # but that mode is easy to avoid when coding.
45
46 use strict;
47
48 sub disassemble {
49     my ($file) = @_;
50     my ($addr,$b1,$b2,$b3, $prefix,$opcode,$modrm);
51
52     open (IN, "objdump -Srfh $file |")
53         || die "Cannot open pipe from objdump\n";
54     while (<IN>) {
55         print;
56
57         if (/^[ \t]*[0-9]+[ \t]+\.text[ \t]/ && /2\*\*([0-9]+)$/) {
58             if ($1 < 5) {
59                 print "ZZ need at least 2**5 for predictable cache line crossing\n";
60             }
61         }
62         
63         if (/^[ \t]*([0-9a-f]*):[ \t]*([0-9a-f]+)[ \t]+([0-9a-f]+)[ \t]+([0-9a-f]+)/) {
64             ($addr,$b1,$b2,$b3) = ($1,$2,$3,$4);
65
66         } elsif (/^[ \t]*([0-9a-f]*):[ \t]*([0-9a-f]+)[ \t]+([0-9a-f]+)/) {
67             ($addr,$b1,$b2,$b3) = ($1,$2,$3,'');
68
69         } elsif (/^[ \t]*([0-9a-f]*):[ \t]*([0-9a-f]+)/) {
70             ($addr,$b1,$b2,$b3) = ($1,$2,'','');
71
72         } else {
73             next;
74         }
75
76         if ($b1 =~ /0f/) {
77             $prefix = $b1;
78             $opcode = $b2;
79             $modrm = $b3;
80         } else {
81             $prefix = '';
82             $opcode = $b1;
83             $modrm = $b2;
84         }
85
86         # modrm of the form 00-xxx-100 with an 0F prefix is the problem case
87         # for K6 and pre-CXT K6-2
88         if ($prefix =~ /0f/
89             && $opcode !~ /^8/         # jcond disp32
90             && $modrm =~ /^[0-3][4c]/) {
91             print "ZZ ($file) >3 bytes to determine instruction length\n";
92         }
93
94         # with just an opcode, starting 1f mod 20h
95         if ($addr =~ /[13579bdf]f$/
96             && $prefix !~ /0f/
97             && $opcode !~ /1[012345]/ # adc
98             && $opcode !~ /1[89abcd]/ # sbb
99             && $opcode !~ /68/        # push $imm32
100             && $opcode !~ /^7/        # jcond disp8
101             && $opcode !~ /a[89]/     # test+imm
102             && $opcode !~ /a[a-f]/    # stos/lods/scas
103             && $opcode !~ /b8/        # movl $imm32,%eax
104             && $opcode !~ /e[0123]/   # loop/loopz/loopnz/jcxz
105             && $opcode !~ /e[b9]/     # jmp disp8/disp32
106             && $opcode !~ /f[89abcd]/ # clc,stc,cli,sti,cld,std
107             && !($opcode =~ /f[67]/          # grp 1
108                  && $modrm =~ /^[2367abef]/) # mul, imul, div, idiv
109             && $modrm !~ /^$/) {
110             print "ZZ ($file) opcode/modrm cross 32-byte boundary\n";
111         }
112
113         # with an 0F prefix, anything starting at 1f mod 20h
114         if ($addr =~ /[13579bdf][f]$/
115             && $prefix =~ /0f/) {
116             print "ZZ ($file) prefix/opcode cross 32-byte boundary\n";
117         }
118
119         # with an 0F prefix, anything with mod/rm starting at 1e mod 20h
120         if ($addr =~ /[13579bdf][e]$/
121             && $prefix =~ /0f/
122              && $opcode !~ /^8/        # jcond disp32
123             && $modrm !~ /^$/) {
124             print "ZZ ($file) prefix/opcode/modrm cross 32-byte boundary\n";
125         }
126     }
127     close IN || die "Error from objdump (or objdump not available)\n";
128 }
129
130
131 my @files;
132 if ($#ARGV >= 0) {
133     @files = @ARGV;
134 } else {
135     @files = glob "*.asm";
136     map {s/.asm/.o/} @files;
137 }
138
139 foreach (@files)  {
140     disassemble($_);
141 }