version 1.1.1.1, 2000/09/09 14:12:42 |
version 1.1.1.2, 2003/08/25 16:06:27 |
|
|
#! /usr/bin/perl |
#! /usr/bin/perl |
|
|
# Copyright (C) 2000 Free Software Foundation, Inc. |
# Copyright 2000, 2001 Free Software Foundation, Inc. |
# |
# |
# This file is part of the GNU MP Library. |
# This file is part of the GNU MP Library. |
# |
# |
|
|
# With no arguments, all .o files corresponding to .asm files are processed. |
# With no arguments, all .o files corresponding to .asm files are processed. |
# This is good in the mpn object directory of a k6*-*-* build. |
# This is good in the mpn object directory of a k6*-*-* build. |
# |
# |
# As far as fixing problems goes, any cache line crossing problems in loops |
# Code alignments of 8 bytes or more are handled. When 32 is used, cache |
# get attention, but as a rule it's too tedious to rearrange code or slip in |
# line boundaries will fall in at offsets 0x20,0x40,etc and problems are |
# nops to fix every problem in setup or finishup code. |
# flagged at those locations. When 16 is used, the line boundaries can also |
|
# fall at offsets 0x10,0x30,0x50,etc, depending where the file is loaded, so |
|
# problems are identified there too. Likewise when 8 byte alignment is used |
|
# problems are flagged additionally at 0x08,0x18,0x28,etc. |
# |
# |
|
# Usually 32 byte alignment is used for k6 routines, but less is certainly |
|
# possible if through good luck, or a little tweaking, cache line crossing |
|
# problems can be avoided at the extra locations. |
|
# |
# Bugs: |
# Bugs: |
# |
# |
# Instructions without mod/rm bytes or which are already vector decoded are |
# Instructions without mod/rm bytes or which are already vector decoded are |
|
|
# though. |
# though. |
# |
# |
# There's no messages for using the vector decoded addressing mode (%esi), |
# There's no messages for using the vector decoded addressing mode (%esi), |
# but that mode is easy to avoid when coding. |
# but that's easy to avoid when coding. |
|
# |
|
# Future: |
|
# |
|
# Warn about jump targets that are poorly aligned (less than 2 instructions |
|
# before a cache line boundary). |
|
|
use strict; |
use strict; |
|
|
sub disassemble { |
sub disassemble { |
my ($file) = @_; |
my ($file) = @_; |
my ($addr,$b1,$b2,$b3, $prefix,$opcode,$modrm); |
my ($addr,$b1,$b2,$b3, $prefix,$opcode,$modrm); |
|
my $align; |
|
|
open (IN, "objdump -Srfh $file |") |
open (IN, "objdump -Srfh $file |") |
|| die "Cannot open pipe from objdump\n"; |
|| die "Cannot open pipe from objdump\n"; |
Line 55 sub disassemble { |
|
Line 68 sub disassemble { |
|
print; |
print; |
|
|
if (/^[ \t]*[0-9]+[ \t]+\.text[ \t]/ && /2\*\*([0-9]+)$/) { |
if (/^[ \t]*[0-9]+[ \t]+\.text[ \t]/ && /2\*\*([0-9]+)$/) { |
if ($1 < 5) { |
$align = 1 << $1; |
print "ZZ need at least 2**5 for predictable cache line crossing\n"; |
if ($align < 8) { |
|
print "ZZ cross.pl cannot handle alignment < 2**3\n"; |
|
$align = 8 |
} |
} |
} |
} |
|
|
Line 88 sub disassemble { |
|
Line 103 sub disassemble { |
|
if ($prefix =~ /0f/ |
if ($prefix =~ /0f/ |
&& $opcode !~ /^8/ # jcond disp32 |
&& $opcode !~ /^8/ # jcond disp32 |
&& $modrm =~ /^[0-3][4c]/) { |
&& $modrm =~ /^[0-3][4c]/) { |
print "ZZ ($file) >3 bytes to determine instruction length\n"; |
print "ZZ ($file) >3 bytes to determine instruction length [K6]\n"; |
} |
} |
|
|
# with just an opcode, starting 1f mod 20h |
# with just an opcode, starting 1f mod 20h |
if ($addr =~ /[13579bdf]f$/ |
if (($align==32 && $addr =~ /[13579bdf]f$/ |
|
|| $align==16 && $addr =~ /f$/ |
|
|| $align==8 && $addr =~ /[7f]$/) |
&& $prefix !~ /0f/ |
&& $prefix !~ /0f/ |
&& $opcode !~ /1[012345]/ # adc |
&& $opcode !~ /1[012345]/ # adc |
&& $opcode !~ /1[89abcd]/ # sbb |
&& $opcode !~ /1[89abcd]/ # sbb |
|
&& $opcode !~ /^4/ # inc/dec reg |
|
&& $opcode !~ /^5/ # push/pop reg |
&& $opcode !~ /68/ # push $imm32 |
&& $opcode !~ /68/ # push $imm32 |
&& $opcode !~ /^7/ # jcond disp8 |
&& $opcode !~ /^7/ # jcond disp8 |
&& $opcode !~ /a[89]/ # test+imm |
&& $opcode !~ /a[89]/ # test+imm |
&& $opcode !~ /a[a-f]/ # stos/lods/scas |
&& $opcode !~ /a[a-f]/ # stos/lods/scas |
&& $opcode !~ /b8/ # movl $imm32,%eax |
&& $opcode !~ /b8/ # movl $imm32,%eax |
|
&& $opcode !~ /d[0123]/ # rcl |
&& $opcode !~ /e[0123]/ # loop/loopz/loopnz/jcxz |
&& $opcode !~ /e[0123]/ # loop/loopz/loopnz/jcxz |
&& $opcode !~ /e[b9]/ # jmp disp8/disp32 |
&& $opcode !~ /e8/ # call disp32 |
|
&& $opcode !~ /e[9b]/ # jmp disp32/disp8 |
&& $opcode !~ /f[89abcd]/ # clc,stc,cli,sti,cld,std |
&& $opcode !~ /f[89abcd]/ # clc,stc,cli,sti,cld,std |
&& !($opcode =~ /f[67]/ # grp 1 |
&& !($opcode =~ /f[67]/ # grp 1 |
&& $modrm =~ /^[2367abef]/) # mul, imul, div, idiv |
&& $modrm =~ /^[2367abef]/) # mul, imul, div, idiv |
Line 111 sub disassemble { |
|
Line 132 sub disassemble { |
|
} |
} |
|
|
# with an 0F prefix, anything starting at 1f mod 20h |
# with an 0F prefix, anything starting at 1f mod 20h |
if ($addr =~ /[13579bdf][f]$/ |
if (($align==32 && $addr =~ /[13579bdf][f]$/ |
&& $prefix =~ /0f/) { |
|| $align==16 && $addr =~ /f$/ |
|
|| $align==8 && $addr =~ /[7f]$/) |
|
&& $prefix =~ /0f/ |
|
&& $opcode !~ /af/ # imul |
|
&& $opcode !~ /a[45]/ # shldl |
|
&& $opcode !~ /a[cd]/ # shrdl |
|
) { |
print "ZZ ($file) prefix/opcode cross 32-byte boundary\n"; |
print "ZZ ($file) prefix/opcode cross 32-byte boundary\n"; |
} |
} |
|
|
# with an 0F prefix, anything with mod/rm starting at 1e mod 20h |
# with an 0F prefix, anything with mod/rm starting at 1e mod 20h |
if ($addr =~ /[13579bdf][e]$/ |
if (($align==32 && $addr =~ /[13579bdf][e]$/ |
|
|| $align==16 && $addr =~ /[e]$/ |
|
|| $align==8 && $addr =~ /[6e]$/) |
&& $prefix =~ /0f/ |
&& $prefix =~ /0f/ |
&& $opcode !~ /^8/ # jcond disp32 |
&& $opcode !~ /^8/ # jcond disp32 |
|
&& $opcode !~ /af/ # imull reg,reg |
|
&& $opcode !~ /a[45]/ # shldl |
|
&& $opcode !~ /a[cd]/ # shrdl |
&& $modrm !~ /^$/) { |
&& $modrm !~ /^$/) { |
print "ZZ ($file) prefix/opcode/modrm cross 32-byte boundary\n"; |
print "ZZ ($file) prefix/opcode/modrm cross 32-byte boundary\n"; |
} |
} |