cross.pl
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:6k
源码类别:

数学计算

开发平台:

Unix_Linux

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