home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / binutils-2.7-src.tgz / tar.out / fsf / binutils / gprof / tahoe.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  8KB  |  320 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 are permitted
  6.  * provided that: (1) source distributions retain this entire copyright
  7.  * notice and comment, and (2) distributions including binaries display
  8.  * the following acknowledgement:  ``This product includes software
  9.  * developed by the University of California, Berkeley and its contributors''
  10.  * in the documentation or other materials provided with the distribution
  11.  * and in all advertising materials mentioning features or use of this
  12.  * software. Neither the name of the University nor the names of its
  13.  * contributors may be used to endorse or promote products derived
  14.  * from this software without specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19. #include "gprof.h"
  20. #include "time_host.h"
  21.  
  22. /*
  23.  * A symbol to be the child of indirect callf:
  24.  */
  25. Sym indirectchild;
  26.  
  27.  
  28. operandenum
  29. operandmode (modep)
  30.      unsigned char *modep;
  31. {
  32.   long usesreg = ((long) *modep) & 0xf;
  33.  
  34.   switch (((long) *modep) >> 4)
  35.     {
  36.     case 0:
  37.     case 1:
  38.     case 2:
  39.     case 3:
  40.       return literal;
  41.     case 4:
  42.       return indexed;
  43.     case 5:
  44.       return reg;
  45.     case 6:
  46.       return regdef;
  47.     case 7:
  48.       return autodec;
  49.     case 8:
  50.       return usesreg != 0xe ? autoinc : immediate;
  51.     case 9:
  52.       return usesreg != PC ? autoincdef : absolute;
  53.     case 10:
  54.       return usesreg != PC ? bytedisp : byterel;
  55.     case 11:
  56.       return usesreg != PC ? bytedispdef : bytereldef;
  57.     case 12:
  58.       return usesreg != PC ? worddisp : wordrel;
  59.     case 13:
  60.       return usesreg != PC ? worddispdef : wordreldef;
  61.     case 14:
  62.       return usesreg != PC ? longdisp : longrel;
  63.     case 15:
  64.       return usesreg != PC ? longdispdef : longreldef;
  65.     }
  66.   /* NOTREACHED */
  67. }
  68.  
  69. char *
  70. operandname (mode)
  71.      operandenum mode;
  72. {
  73.  
  74.   switch (mode)
  75.     {
  76.     case literal:
  77.       return "literal";
  78.     case indexed:
  79.       return "indexed";
  80.     case reg:
  81.       return "register";
  82.     case regdef:
  83.       return "register deferred";
  84.     case autodec:
  85.       return "autodecrement";
  86.     case autoinc:
  87.       return "autoincrement";
  88.     case autoincdef:
  89.       return "autoincrement deferred";
  90.     case bytedisp:
  91.       return "byte displacement";
  92.     case bytedispdef:
  93.       return "byte displacement deferred";
  94.     case byterel:
  95.       return "byte relative";
  96.     case bytereldef:
  97.       return "byte relative deferred";
  98.     case worddisp:
  99.       return "word displacement";
  100.     case worddispdef:
  101.       return "word displacement deferred";
  102.     case wordrel:
  103.       return "word relative";
  104.     case wordreldef:
  105.       return "word relative deferred";
  106.     case immediate:
  107.       return "immediate";
  108.     case absolute:
  109.       return "absolute";
  110.     case longdisp:
  111.       return "long displacement";
  112.     case longdispdef:
  113.       return "long displacement deferred";
  114.     case longrel:
  115.       return "long relative";
  116.     case longreldef:
  117.       return "long relative deferred";
  118.     }
  119.   /* NOTREACHED */
  120. }
  121.  
  122. long
  123. operandlength (modep)
  124.      unsigned char *modep;
  125. {
  126.  
  127.   switch (operandmode (modep))
  128.     {
  129.     case literal:
  130.     case reg:
  131.     case regdef:
  132.     case autodec:
  133.     case autoinc:
  134.     case autoincdef:
  135.       return 1;
  136.     case bytedisp:
  137.     case bytedispdef:
  138.     case byterel:
  139.     case bytereldef:
  140.       return 2;
  141.     case worddisp:
  142.     case worddispdef:
  143.     case wordrel:
  144.     case wordreldef:
  145.       return 3;
  146.     case immediate:
  147.     case absolute:
  148.     case longdisp:
  149.     case longdispdef:
  150.     case longrel:
  151.     case longreldef:
  152.       return 5;
  153.     case indexed:
  154.       return 1 + operandlength (modep + 1);
  155.     }
  156.   /* NOTREACHED */
  157. }
  158.  
  159. bfd_vma
  160. reladdr (modep)
  161.      char *modep;
  162. {
  163.   operandenum mode = operandmode (modep);
  164.   char *cp;
  165.   short *sp;
  166.   long *lp;
  167.   int i;
  168.   long value = 0;
  169.  
  170.   cp = modep;
  171.   ++cp;                /* skip over the mode */
  172.   switch (mode)
  173.     {
  174.     default:
  175.       fprintf (stderr, "[reladdr] not relative address\n");
  176.       return (bfd_vma) modep;
  177.     case byterel:
  178.       return (bfd_vma) (cp + sizeof *cp + *cp);
  179.     case wordrel:
  180.       for (i = 0; i < sizeof *sp; i++)
  181.     value = (value << 8) + (cp[i] & 0xff);
  182.       return (bfd_vma) (cp + sizeof *sp + value);
  183.     case longrel:
  184.       for (i = 0; i < sizeof *lp; i++)
  185.     value = (value << 8) + (cp[i] & 0xff);
  186.       return (bfd_vma) (cp + sizeof *lp + value);
  187.     }
  188. }
  189.  
  190. find_call (parent, p_lowpc, p_highpc)
  191.      Sym *parent;
  192.      bfd_vma p_lowpc;
  193.      bfd_vma p_highpc;
  194. {
  195.   unsigned char *instructp;
  196.   long length;
  197.   Sym *child;
  198.   operandenum mode;
  199.   operandenum firstmode;
  200.   bfd_vma destpc;
  201.   static bool inited = FALSE;
  202.  
  203.   if (!inited)
  204.     {
  205.       inited = TRUE;
  206.       sym_init (&indirectchild);
  207.       indirectchild.cg.prop.fract = 1.0;
  208.       indirectchild.cg.cyc.head = &indirectchild;
  209.     }
  210.  
  211.   if (textspace == 0)
  212.     {
  213.       return;
  214.     }
  215.   if (p_lowpc < s_lowpc)
  216.     {
  217.       p_lowpc = s_lowpc;
  218.     }
  219.   if (p_highpc > s_highpc)
  220.     {
  221.       p_highpc = s_highpc;
  222.     }
  223.   DBG (CALLDEBUG, printf ("[findcall] %s: 0x%x to 0x%x\n",
  224.               parent->name, p_lowpc, p_highpc));
  225.   for (instructp = textspace + p_lowpc;
  226.        instructp < textspace + p_highpc;
  227.        instructp += length)
  228.     {
  229.       length = 1;
  230.       if (*instructp == CALLF)
  231.     {
  232.       /*
  233.        *    maybe a callf, better check it out.
  234.        *      skip the count of the number of arguments.
  235.        */
  236.       DBG (CALLDEBUG, printf ("[findcall]\t0x%x:callf",
  237.                   instructp - textspace));
  238.       firstmode = operandmode (instructp + length);
  239.       switch (firstmode)
  240.         {
  241.         case literal:
  242.         case immediate:
  243.           break;
  244.         default:
  245.           goto botched;
  246.         }
  247.       length += operandlength (instructp + length);
  248.       mode = operandmode (instructp + length);
  249.       DBG (CALLDEBUG,
  250.            printf ("\tfirst operand is %s", operandname (firstmode));
  251.            printf ("\tsecond operand is %s\n", operandname (mode));
  252.         );
  253.       switch (mode)
  254.         {
  255.         case regdef:
  256.         case bytedispdef:
  257.         case worddispdef:
  258.         case longdispdef:
  259.         case bytereldef:
  260.         case wordreldef:
  261.         case longreldef:
  262.           /*
  263.            *    indirect call: call through pointer
  264.            *      either  *d(r)   as a parameter or local
  265.            *              (r)     as a return value
  266.            *              *f      as a global pointer
  267.            *      [are there others that we miss?,
  268.            *       e.g. arrays of pointers to functions???]
  269.            */
  270.           arc_add (parent, &indirectchild, (long) 0);
  271.           length += operandlength (instructp + length);
  272.           continue;
  273.         case byterel:
  274.         case wordrel:
  275.         case longrel:
  276.           /*
  277.            *    regular pc relative addressing
  278.            *      check that this is the address of 
  279.            *      a function.
  280.            */
  281.           destpc = reladdr (instructp + length)
  282.         - (bfd_vma) textspace;
  283.           if (destpc >= s_lowpc && destpc <= s_highpc)
  284.         {
  285.           child = sym_lookup (destpc);
  286.           DBG (CALLDEBUG,
  287.                printf ("[findcall]\tdestpc 0x%x", destpc);
  288.                printf (" child->name %s", child->name);
  289.                printf (" child->addr 0x%x\n", child->addr);
  290.             );
  291.           if (child->addr == destpc)
  292.             {
  293.               /*
  294.                *    a hit
  295.                */
  296.               arc_add (parent, child, (long) 0);
  297.               length += operandlength (instructp + length);
  298.               continue;
  299.             }
  300.           goto botched;
  301.         }
  302.           /*
  303.            *    else:
  304.            *      it looked like a callf,
  305.            *      but it wasn't to anywhere.
  306.            */
  307.           goto botched;
  308.         default:
  309.         botched:
  310.           /*
  311.            *    something funny going on.
  312.            */
  313.           DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
  314.           length = 1;
  315.           continue;
  316.         }
  317.     }
  318.     }
  319. }
  320.