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

Defined functions

findcalls defined in line 191; used 2 times
operandlength defined in line 129; used 5 times
operandmode defined in line 37; used 5 times
operandname defined in line 77; used 3 times
reladdr defined in line 165; used 2 times

Defined variables

indirectchild defined in line 16; used 2 times
sccsid defined in line 8; never used
Last modified: 1985-06-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1207
Valid CSS Valid XHTML 1.0 Strict