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