Upload Tizen:Base source
[external/gmp.git] / mpn / x86 / k6 / cross.pl
1 #! /usr/bin/perl
2
3 # Copyright 2000, 2001 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 3 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.  If not, see http://www.gnu.org/licenses/.
19
20
21 # Usage: cross.pl [filename.o]...
22 #
23 # Produce an annotated disassembly of the given object files, indicating
24 # certain code alignment and addressing mode problems afflicting K6 chips.
25 # "ZZ" is used on all annotations, so this can be searched for.
26 #
27 # With no arguments, all .o files corresponding to .asm files are processed.
28 # This is good in the mpn object directory of a k6*-*-* build.
29 #
30 # Code alignments of 8 bytes or more are handled.  When 32 is used, cache
31 # line boundaries will fall in at offsets 0x20,0x40,etc and problems are
32 # flagged at those locations.  When 16 is used, the line boundaries can also
33 # fall at offsets 0x10,0x30,0x50,etc, depending where the file is loaded, so
34 # problems are identified there too.  Likewise when 8 byte alignment is used
35 # problems are flagged additionally at 0x08,0x18,0x28,etc.
36 #
37 # Usually 32 byte alignment is used for k6 routines, but less is certainly
38 # possible if through good luck, or a little tweaking, cache line crossing
39 # problems can be avoided at the extra locations.
40 #
41 # Bugs:
42 #
43 # Instructions without mod/rm bytes or which are already vector decoded are
44 # unaffected by cache line boundary crossing, but not all of these have yet
45 # been put in as exceptions.  All that occur in practice in GMP are present
46 # though.
47 #
48 # There's no messages for using the vector decoded addressing mode (%esi),
49 # but that's easy to avoid when coding.
50 #
51 # Future:
52 #
53 # Warn about jump targets that are poorly aligned (less than 2 instructions
54 # before a cache line boundary).
55
56 use strict;
57
58 sub disassemble {
59     my ($file) = @_;
60     my ($addr,$b1,$b2,$b3, $prefix,$opcode,$modrm);
61     my $align;
62
63     open (IN, "objdump -Srfh $file |")
64         || die "Cannot open pipe from objdump\n";
65     while (<IN>) {
66         print;
67
68         if (/^[ \t]*[0-9]+[ \t]+\.text[ \t]/ && /2\*\*([0-9]+)$/) {
69             $align = 1 << $1;
70             if ($align < 8) {
71                 print "ZZ cross.pl cannot handle alignment < 2**3\n";
72                 $align = 8
73             }
74         }
75
76         if (/^[ \t]*([0-9a-f]*):[ \t]*([0-9a-f]+)[ \t]+([0-9a-f]+)[ \t]+([0-9a-f]+)/) {
77             ($addr,$b1,$b2,$b3) = ($1,$2,$3,$4);
78
79         } elsif (/^[ \t]*([0-9a-f]*):[ \t]*([0-9a-f]+)[ \t]+([0-9a-f]+)/) {
80             ($addr,$b1,$b2,$b3) = ($1,$2,$3,'');
81
82         } elsif (/^[ \t]*([0-9a-f]*):[ \t]*([0-9a-f]+)/) {
83             ($addr,$b1,$b2,$b3) = ($1,$2,'','');
84
85         } else {
86             next;
87         }
88
89         if ($b1 =~ /0f/) {
90             $prefix = $b1;
91             $opcode = $b2;
92             $modrm = $b3;
93         } else {
94             $prefix = '';
95             $opcode = $b1;
96             $modrm = $b2;
97         }
98
99         # modrm of the form 00-xxx-100 with an 0F prefix is the problem case
100         # for K6 and pre-CXT K6-2
101         if ($prefix =~ /0f/
102             && $opcode !~ /^8/         # jcond disp32
103             && $modrm =~ /^[0-3][4c]/) {
104             print "ZZ ($file) >3 bytes to determine instruction length [K6]\n";
105         }
106
107         # with just an opcode, starting 1f mod 20h
108         if (($align==32 && $addr =~ /[13579bdf]f$/
109              || $align==16 && $addr =~ /f$/
110              || $align==8 && $addr =~ /[7f]$/)
111             && $prefix !~ /0f/
112             && $opcode !~ /1[012345]/ # adc
113             && $opcode !~ /1[89abcd]/ # sbb
114             && $opcode !~ /^4/        # inc/dec reg
115             && $opcode !~ /^5/        # push/pop reg
116             && $opcode !~ /68/        # push $imm32
117             && $opcode !~ /^7/        # jcond disp8
118             && $opcode !~ /a[89]/     # test+imm
119             && $opcode !~ /a[a-f]/    # stos/lods/scas
120             && $opcode !~ /b8/        # movl $imm32,%eax
121             && $opcode !~ /d[0123]/   # rcl
122             && $opcode !~ /e[0123]/   # loop/loopz/loopnz/jcxz
123             && $opcode !~ /e8/        # call disp32
124             && $opcode !~ /e[9b]/     # jmp disp32/disp8
125             && $opcode !~ /f[89abcd]/ # clc,stc,cli,sti,cld,std
126             && !($opcode =~ /f[67]/          # grp 1
127                  && $modrm =~ /^[2367abef]/) # mul, imul, div, idiv
128             && $modrm !~ /^$/) {
129             print "ZZ ($file) opcode/modrm cross 32-byte boundary\n";
130         }
131
132         # with an 0F prefix, anything starting at 1f mod 20h
133         if (($align==32 && $addr =~ /[13579bdf][f]$/
134              || $align==16 && $addr =~ /f$/
135              || $align==8 && $addr =~ /[7f]$/)
136             && $prefix =~ /0f/
137             && $opcode !~ /af/        # imul
138             && $opcode !~ /a[45]/     # shldl
139             && $opcode !~ /a[cd]/     # shrdl
140             ) {
141             print "ZZ ($file) prefix/opcode cross 32-byte boundary\n";
142         }
143
144         # with an 0F prefix, anything with mod/rm starting at 1e mod 20h
145         if (($align==32 && $addr =~ /[13579bdf][e]$/
146              || $align==16 && $addr =~ /[e]$/
147              || $align==8 && $addr =~ /[6e]$/)
148             && $prefix =~ /0f/
149              && $opcode !~ /^8/        # jcond disp32
150              && $opcode !~ /af/        # imull reg,reg
151              && $opcode !~ /a[45]/     # shldl
152              && $opcode !~ /a[cd]/     # shrdl
153             && $modrm !~ /^$/) {
154             print "ZZ ($file) prefix/opcode/modrm cross 32-byte boundary\n";
155         }
156     }
157     close IN || die "Error from objdump (or objdump not available)\n";
158 }
159
160
161 my @files;
162 if ($#ARGV >= 0) {
163     @files = @ARGV;
164 } else {
165     @files = glob "*.asm";
166     map {s/.asm/.o/} @files;
167 }
168
169 foreach (@files)  {
170     disassemble($_);
171 }