date and time created 81/11/11 11:16:40 by peter
authorPeter B. Kessler <peter@ucbvax.Berkeley.EDU>
Thu, 12 Nov 1981 03:16:40 +0000 (19:16 -0800)
committerPeter B. Kessler <peter@ucbvax.Berkeley.EDU>
Thu, 12 Nov 1981 03:16:40 +0000 (19:16 -0800)
SCCS-vsn: usr.bin/gprof/vax.c 1.1

usr/src/usr.bin/gprof/vax.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/gprof/vax.c b/usr/src/usr.bin/gprof/vax.c
new file mode 100644 (file)
index 0000000..1c20abe
--- /dev/null
@@ -0,0 +1,309 @@
+#ifndef lint
+    static     char *sccsid = "@(#)vax.c       1.1 (Berkeley) %G%";
+#endif not lint
+
+#include       "gprof.h"
+
+    /*
+     * a namelist entry to be the child of indirect calls
+     */
+nltype indirectchild = {
+       "(*)" ,                         /* the name */
+       (unsigned long) 0 ,             /* the pc entry point */
+       (double) 0.0 ,                  /* ticks in this routine */
+       (double) 0.0 ,                  /* cumulative ticks in children */
+       (long) 0 ,                      /* how many times called */
+       (long) 0 ,                      /* how many calls to self */
+       (int) 0 ,                       /* index in the graph list */
+       (int) 0 ,                       /* graph call chain top-sort order */
+       (int) 0 ,                       /* internal number of cycle on */
+       (struct nl *) &indirectchild ,  /* pointer to head of cycle */
+       (struct nl *) 0 ,               /* pointer to next member of cycle */
+       (arctype *) 0 ,                 /* list of caller arcs */
+       (arctype *) 0                   /* list of callee arcs */
+    };
+
+operandenum
+operandmode( modep )
+    struct modebyte    *modep;
+{
+    long       usesreg = modep -> regfield;
+    
+    switch ( modep -> modefield ) {
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+           return literal;
+       case 4:
+           return indexed;
+       case 5:
+           return reg;
+       case 6:
+           return regdef;
+       case 7:
+           return autodec;
+       case 8:
+           return ( usesreg != PC ? autoinc : immediate );
+       case 9:
+           return ( usesreg != PC ? autoincdef : absolute );
+       case 10:
+           return ( usesreg != PC ? bytedisp : byterel );
+       case 11:
+           return ( usesreg != PC ? bytedispdef : bytereldef );
+       case 12:
+           return ( usesreg != PC ? worddisp : wordrel );
+       case 13:
+           return ( usesreg != PC ? worddispdef : wordreldef );
+       case 14:
+           return ( usesreg != PC ? longdisp : longrel );
+       case 15:
+           return ( usesreg != PC ? longdispdef : longreldef );
+    }
+    /* NOTREACHED */
+}
+
+char *
+operandname( mode )
+    operandenum        mode;
+{
+    
+    switch ( mode ) {
+       case literal:
+           return "literal";
+       case indexed:
+           return "indexed";
+       case reg:
+           return "register";
+       case regdef:
+           return "register deferred";
+       case autodec:
+           return "autodecrement";
+       case autoinc:
+           return "autoincrement";
+       case autoincdef:
+           return "autoincrement deferred";
+       case bytedisp:
+           return "byte displacement";
+       case bytedispdef:
+           return "byte displacement deferred";
+       case byterel:
+           return "byte relative";
+       case bytereldef:
+           return "byte relative deferred";
+       case worddisp:
+           return "word displacement";
+       case worddispdef:
+           return "word displacement deferred";
+       case wordrel:
+           return "word relative";
+       case wordreldef:
+           return "word relative deferred";
+       case immediate:
+           return "immediate";
+       case absolute:
+           return "absolute";
+       case longdisp:
+           return "long displacement";
+       case longdispdef:
+           return "long displacement deferred";
+       case longrel:
+           return "long relative";
+       case longreldef:
+           return "long relative deferred";
+    }
+    /* NOTREACHED */
+}
+
+long
+operandlength( modep )
+    struct modebyte    *modep;
+{
+    
+    switch ( operandmode( modep ) ) {
+       case literal:
+       case reg:
+       case regdef:
+       case autodec:
+       case autoinc:
+       case autoincdef:
+           return 1;
+       case bytedisp:
+       case bytedispdef:
+       case byterel:
+       case bytereldef:
+           return 2;
+       case worddisp:
+       case worddispdef:
+       case wordrel:
+       case wordreldef:
+           return 3;
+       case immediate:
+       case absolute:
+       case longdisp:
+       case longdispdef:
+       case longrel:
+       case longreldef:
+           return 5;
+       case indexed:
+           return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 );
+    }
+    /* NOTREACHED */
+}
+
+unsigned long
+reladdr( modep )
+    struct modebyte    *modep;
+{
+    operandenum        mode = operandmode( modep );
+    char       *cp;
+    short      *sp;
+    long       *lp;
+
+    cp = (char *) modep;
+    cp += 1;                   /* skip over the mode */
+    switch ( mode ) {
+       default:
+           fprintf( stderr , "[reladdr] not relative address\n" );
+           return (unsigned long) modep;
+       case byterel:
+           return (unsigned long) ( cp + sizeof *cp + *cp );
+       case wordrel:
+           sp = (short *) cp;
+           return (unsigned long) ( cp + sizeof *sp + *sp );
+       case longrel:
+           lp = (long *) cp;
+           return (unsigned long) ( cp + sizeof *lp + *lp );
+    }
+}
+
+findcalls( parentp , p_lowpc , p_highpc )
+    nltype             *parentp;
+    unsigned long      p_lowpc;
+    unsigned long      p_highpc;
+{
+    unsigned char      *instructp;
+    long               length;
+    nltype             *childp;
+    operandenum                mode;
+    operandenum                firstmode;
+    unsigned long      destpc;
+
+    if ( textspace == 0 ) {
+       return;
+    }
+    if ( p_lowpc < s_lowpc ) {
+       p_lowpc = s_lowpc;
+    }
+    if ( p_highpc > s_highpc ) {
+       p_highpc = s_highpc;
+    }
+#   ifdef DEBUG
+       if ( debug & CALLSDEBUG ) {
+           printf( "[findcalls] %s: 0x%x to 0x%x\n" ,
+                   parentp -> name , p_lowpc , p_highpc );
+       }
+#   endif DEBUG
+    for (   instructp = textspace + p_lowpc ;
+           instructp < textspace + p_highpc ;
+           instructp += length ) {
+       length = 1;
+       if ( *instructp == CALLS ) {
+               /*
+                *      maybe a calls, better check it out.
+                *      skip the count of the number of arguments.
+                */
+#          ifdef DEBUG
+               if ( debug & CALLSDEBUG ) {
+                   printf( "[findcalls]\t0x%x:calls" , instructp - textspace );
+               }
+#          endif DEBUG
+           firstmode = operandmode( (struct modebyte *) (instructp+length) );
+           switch ( firstmode ) {
+               case literal:
+               case immediate:
+                   break;
+               default:
+                   goto botched;
+           }
+           length += operandlength( (struct modebyte *) (instructp+length) );
+           mode = operandmode( (struct modebyte *) ( instructp + length ) );
+#          ifdef DEBUG
+               if ( debug & CALLSDEBUG ) {
+                   printf( "\tfirst operand is %s", operandname( firstmode ) );
+                   printf( "\tsecond operand is %s\n" , operandname( mode ) );
+               }
+#          endif DEBUG
+           switch ( mode ) {
+               case regdef:
+               case bytedispdef:
+               case worddispdef:
+               case longdispdef:
+               case bytereldef:
+               case wordreldef:
+               case longreldef:
+                       /*
+                        *      indirect call: call through pointer
+                        *      either  *d(r)   as a parameter or local
+                        *              (r)     as a return value
+                        *              *f      as a global pointer
+                        *      [are there others that we miss?,
+                        *       e.g. arrays of pointers to functions???]
+                        */
+                   addarc( parentp , &indirectchild , (long) 0 );
+                   length += operandlength(
+                               (struct modebyte *) ( instructp + length ) );
+                   continue;
+               case byterel:
+               case wordrel:
+               case longrel:
+                       /*
+                        *      regular pc relative addressing
+                        *      check that this is the address of 
+                        *      a function.
+                        */
+                   destpc = reladdr( (struct modebyte *) (instructp+length) )
+                               - (unsigned long) textspace;
+                   if ( destpc >= s_lowpc && destpc <= s_highpc ) {
+                       childp = nllookup( destpc );
+#                      ifdef DEBUG
+                           if ( debug & CALLSDEBUG ) {
+                               printf( "[findcalls]\tdestpc 0x%x" , destpc );
+                               printf( " childp->name %s" , childp -> name );
+                               printf( " childp->value 0x%x\n" ,
+                                       childp -> value );
+                           }
+#                      endif DEBUG
+                       if ( childp -> value == destpc ) {
+                               /*
+                                *      a hit
+                                */
+                           addarc( parentp , childp , (long) 0 );
+                           length += operandlength( (struct modebyte *)
+                                           ( instructp + length ) );
+                           continue;
+                       }
+                       goto botched;
+                   }
+                       /*
+                        *      else:
+                        *      it looked like a calls,
+                        *      but it wasn't to anywhere.
+                        */
+                   goto botched;
+               default:
+               botched:
+                       /*
+                        *      something funny going on.
+                        */
+#                  ifdef DEBUG
+                       if ( debug & CALLSDEBUG ) {
+                           printf( "[findcalls]\tbut it's a botch\n" );
+                       }
+#                  endif DEBUG
+                   length = 1;
+                   continue;
+           }
+       }
+    }
+}