home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / gprof / tahoe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-12  |  9.0 KB  |  350 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)tahoe.c    1.5 (Berkeley) 6/1/90";
  36. #endif /* not lint */
  37.  
  38. #include    "gprof.h"
  39.  
  40.     /*
  41.      *    a namelist entry to be the child of indirect callf
  42.      */
  43. nltype    indirectchild = {
  44.     "(*)" ,                /* the name */
  45.     (unsigned long) 0 ,        /* the pc entry point */
  46.     (unsigned long) 0 ,        /* entry point aligned to histogram */
  47.     (double) 0.0 ,            /* ticks in this routine */
  48.     (double) 0.0 ,            /* cumulative ticks in children */
  49.     (long) 0 ,            /* how many times called */
  50.     (long) 0 ,            /* how many calls to self */
  51.     (double) 1.0 ,            /* propagation fraction */
  52.     (double) 0.0 ,            /* self propagation time */
  53.     (double) 0.0 ,            /* child propagation time */
  54.     (bool) 0 ,            /* print flag */
  55.     (int) 0 ,            /* index in the graph list */
  56.     (int) 0 ,             /* graph call chain top-sort order */
  57.     (int) 0 ,            /* internal number of cycle on */
  58.     (struct nl *) &indirectchild ,    /* pointer to head of cycle */
  59.     (struct nl *) 0 ,        /* pointer to next member of cycle */
  60.     (arctype *) 0 ,            /* list of caller arcs */
  61.     (arctype *) 0             /* list of callee arcs */
  62.     };
  63.  
  64. operandenum
  65. operandmode( modep )
  66.     unsigned char    *modep;
  67. {
  68.     long    usesreg = ((long)*modep) & 0xf;
  69.     
  70.     switch ( ((long)*modep) >> 4 ) {
  71.     case 0:
  72.     case 1:
  73.     case 2:
  74.     case 3:
  75.         return literal;
  76.     case 4:
  77.         return indexed;
  78.     case 5:
  79.         return reg;
  80.     case 6:
  81.         return regdef;
  82.     case 7:
  83.         return autodec;
  84.     case 8:
  85.         return ( usesreg != 0xe ? autoinc : immediate );
  86.     case 9:
  87.         return ( usesreg != PC ? autoincdef : absolute );
  88.     case 10:
  89.         return ( usesreg != PC ? bytedisp : byterel );
  90.     case 11:
  91.         return ( usesreg != PC ? bytedispdef : bytereldef );
  92.     case 12:
  93.         return ( usesreg != PC ? worddisp : wordrel );
  94.     case 13:
  95.         return ( usesreg != PC ? worddispdef : wordreldef );
  96.     case 14:
  97.         return ( usesreg != PC ? longdisp : longrel );
  98.     case 15:
  99.         return ( usesreg != PC ? longdispdef : longreldef );
  100.     }
  101.     /* NOTREACHED */
  102. }
  103.  
  104. char *
  105. operandname( mode )
  106.     operandenum    mode;
  107. {
  108.     
  109.     switch ( mode ) {
  110.     case literal:
  111.         return "literal";
  112.     case indexed:
  113.         return "indexed";
  114.     case reg:
  115.         return "register";
  116.     case regdef:
  117.         return "register deferred";
  118.     case autodec:
  119.         return "autodecrement";
  120.     case autoinc:
  121.         return "autoincrement";
  122.     case autoincdef:
  123.         return "autoincrement deferred";
  124.     case bytedisp:
  125.         return "byte displacement";
  126.     case bytedispdef:
  127.         return "byte displacement deferred";
  128.     case byterel:
  129.         return "byte relative";
  130.     case bytereldef:
  131.         return "byte relative deferred";
  132.     case worddisp:
  133.         return "word displacement";
  134.     case worddispdef:
  135.         return "word displacement deferred";
  136.     case wordrel:
  137.         return "word relative";
  138.     case wordreldef:
  139.         return "word relative deferred";
  140.     case immediate:
  141.         return "immediate";
  142.     case absolute:
  143.         return "absolute";
  144.     case longdisp:
  145.         return "long displacement";
  146.     case longdispdef:
  147.         return "long displacement deferred";
  148.     case longrel:
  149.         return "long relative";
  150.     case longreldef:
  151.         return "long relative deferred";
  152.     }
  153.     /* NOTREACHED */
  154. }
  155.  
  156. long
  157. operandlength( modep )
  158.     unsigned char    *modep;
  159. {
  160.     
  161.     switch ( operandmode( modep ) ) {
  162.     case literal:
  163.     case reg:
  164.     case regdef:
  165.     case autodec:
  166.     case autoinc:
  167.     case autoincdef:
  168.         return 1;
  169.     case bytedisp:
  170.     case bytedispdef:
  171.     case byterel:
  172.     case bytereldef:
  173.         return 2;
  174.     case worddisp:
  175.     case worddispdef:
  176.     case wordrel:
  177.     case wordreldef:
  178.         return 3;
  179.     case immediate:
  180.     case absolute:
  181.     case longdisp:
  182.     case longdispdef:
  183.     case longrel:
  184.     case longreldef:
  185.         return 5;
  186.     case indexed:
  187.         return 1+operandlength( modep + 1 );
  188.     }
  189.     /* NOTREACHED */
  190. }
  191.  
  192. unsigned long
  193. reladdr( modep )
  194.     char    *modep;
  195. {
  196.     operandenum    mode = operandmode( modep );
  197.     char    *cp;
  198.     short    *sp;
  199.     long    *lp;
  200.     int        i;
  201.     long    value = 0;
  202.  
  203.     cp = modep;
  204.     cp += 1;            /* skip over the mode */
  205.     switch ( mode ) {
  206.     default:
  207.         fprintf( stderr , "[reladdr] not relative address\n" );
  208.         return (unsigned long) modep;
  209.     case byterel:
  210.         return (unsigned long) ( cp + sizeof *cp + *cp );
  211.     case wordrel:
  212.         for (i = 0; i < sizeof *sp; i++)
  213.         value = (value << 8) + (cp[i] & 0xff);
  214.         return (unsigned long) ( cp + sizeof *sp + value );
  215.     case longrel:
  216.         for (i = 0; i < sizeof *lp; i++)
  217.         value = (value << 8) + (cp[i] & 0xff);
  218.         return (unsigned long) ( cp + sizeof *lp + value );
  219.     }
  220. }
  221.  
  222. findcall( parentp , p_lowpc , p_highpc )
  223.     nltype        *parentp;
  224.     unsigned long    p_lowpc;
  225.     unsigned long    p_highpc;
  226. {
  227.     unsigned char    *instructp;
  228.     long        length;
  229.     nltype        *childp;
  230.     operandenum        mode;
  231.     operandenum        firstmode;
  232.     unsigned long    destpc;
  233.  
  234.     if ( textspace == 0 ) {
  235.     return;
  236.     }
  237.     if ( p_lowpc < s_lowpc ) {
  238.     p_lowpc = s_lowpc;
  239.     }
  240.     if ( p_highpc > s_highpc ) {
  241.     p_highpc = s_highpc;
  242.     }
  243. #   ifdef DEBUG
  244.     if ( debug & CALLDEBUG ) {
  245.         printf( "[findcall] %s: 0x%x to 0x%x\n" ,
  246.             parentp -> name , p_lowpc , p_highpc );
  247.     }
  248. #   endif DEBUG
  249.     for (   instructp = textspace + p_lowpc ;
  250.         instructp < textspace + p_highpc ;
  251.         instructp += length ) {
  252.     length = 1;
  253.     if ( *instructp == CALLF ) {
  254.         /*
  255.          *    maybe a callf, better check it out.
  256.          *    skip the count of the number of arguments.
  257.          */
  258. #        ifdef DEBUG
  259.         if ( debug & CALLDEBUG ) {
  260.             printf( "[findcall]\t0x%x:callf" , instructp - textspace );
  261.         }
  262. #        endif DEBUG
  263.         firstmode = operandmode( instructp+length );
  264.         switch ( firstmode ) {
  265.         case literal:
  266.         case immediate:
  267.             break;
  268.         default:
  269.             goto botched;
  270.         }
  271.         length += operandlength( instructp+length );
  272.         mode = operandmode( instructp + length );
  273. #        ifdef DEBUG
  274.         if ( debug & CALLDEBUG ) {
  275.             printf( "\tfirst operand is %s", operandname( firstmode ) );
  276.             printf( "\tsecond operand is %s\n" , operandname( mode ) );
  277.         }
  278. #        endif DEBUG
  279.         switch ( mode ) {
  280.         case regdef:
  281.         case bytedispdef:
  282.         case worddispdef:
  283.         case longdispdef:
  284.         case bytereldef:
  285.         case wordreldef:
  286.         case longreldef:
  287.             /*
  288.              *    indirect call: call through pointer
  289.              *    either    *d(r)    as a parameter or local
  290.              *        (r)    as a return value
  291.              *        *f    as a global pointer
  292.              *    [are there others that we miss?,
  293.              *     e.g. arrays of pointers to functions???]
  294.              */
  295.             addarc( parentp , &indirectchild , (long) 0 );
  296.             length += operandlength( instructp + length );
  297.             continue;
  298.         case byterel:
  299.         case wordrel:
  300.         case longrel:
  301.             /*
  302.              *    regular pc relative addressing
  303.              *    check that this is the address of 
  304.              *    a function.
  305.              */
  306.             destpc = reladdr( instructp+length )
  307.                 - (unsigned long) textspace;
  308.             if ( destpc >= s_lowpc && destpc <= s_highpc ) {
  309.             childp = nllookup( destpc );
  310. #            ifdef DEBUG
  311.                 if ( debug & CALLDEBUG ) {
  312.                 printf( "[findcall]\tdestpc 0x%x" , destpc );
  313.                 printf( " childp->name %s" , childp -> name );
  314.                 printf( " childp->value 0x%x\n" ,
  315.                     childp -> value );
  316.                 }
  317. #            endif DEBUG
  318.             if ( childp -> value == destpc ) {
  319.                 /*
  320.                  *    a hit
  321.                  */
  322.                 addarc( parentp , childp , (long) 0 );
  323.                 length += operandlength( instructp + length );
  324.                 continue;
  325.             }
  326.             goto botched;
  327.             }
  328.             /*
  329.              *    else:
  330.              *    it looked like a callf,
  331.              *    but it wasn't to anywhere.
  332.              */
  333.             goto botched;
  334.         default:
  335.         botched:
  336.             /*
  337.              *    something funny going on.
  338.              */
  339. #            ifdef DEBUG
  340.             if ( debug & CALLDEBUG ) {
  341.                 printf( "[findcall]\tbut it's a botch\n" );
  342.             }
  343. #            endif DEBUG
  344.             length = 1;
  345.             continue;
  346.         }
  347.     }
  348.     }
  349. }
  350.