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