xref: /csrg-svn/usr.bin/gprof/vax.c (revision 34199)
121958Sdist /*
221958Sdist  * Copyright (c) 1983 Regents of the University of California.
3*34199Sbostic  * All rights reserved.
4*34199Sbostic  *
5*34199Sbostic  * Redistribution and use in source and binary forms are permitted
6*34199Sbostic  * provided that this notice is preserved and that due credit is given
7*34199Sbostic  * to the University of California at Berkeley. The name of the University
8*34199Sbostic  * may not be used to endorse or promote products derived from this
9*34199Sbostic  * software without specific prior written permission. This software
10*34199Sbostic  * is provided ``as is'' without express or implied warranty.
1121958Sdist  */
1221958Sdist 
134858Speter #ifndef lint
14*34199Sbostic static char sccsid[] = "@(#)vax.c	5.4 (Berkeley) 05/05/88";
15*34199Sbostic #endif /* not lint */
164858Speter 
174858Speter #include	"gprof.h"
184858Speter 
194858Speter     /*
204858Speter      *	a namelist entry to be the child of indirect calls
214858Speter      */
224858Speter nltype	indirectchild = {
234858Speter 	"(*)" ,				/* the name */
244858Speter 	(unsigned long) 0 ,		/* the pc entry point */
2511800Speter 	(unsigned long) 0 ,		/* entry point aligned to histogram */
264858Speter 	(double) 0.0 ,			/* ticks in this routine */
274858Speter 	(double) 0.0 ,			/* cumulative ticks in children */
284858Speter 	(long) 0 ,			/* how many times called */
294858Speter 	(long) 0 ,			/* how many calls to self */
307222Speter 	(double) 1.0 ,			/* propagation fraction */
317222Speter 	(double) 0.0 ,			/* self propagation time */
327222Speter 	(double) 0.0 ,			/* child propagation time */
337172Speter 	(bool) 0 ,			/* print flag */
344858Speter 	(int) 0 ,			/* index in the graph list */
354858Speter 	(int) 0 , 			/* graph call chain top-sort order */
364858Speter 	(int) 0 ,			/* internal number of cycle on */
374858Speter 	(struct nl *) &indirectchild ,	/* pointer to head of cycle */
384858Speter 	(struct nl *) 0 ,		/* pointer to next member of cycle */
394858Speter 	(arctype *) 0 ,			/* list of caller arcs */
404858Speter 	(arctype *) 0 			/* list of callee arcs */
414858Speter     };
424858Speter 
434858Speter operandenum
444858Speter operandmode( modep )
454858Speter     struct modebyte	*modep;
464858Speter {
474858Speter     long	usesreg = modep -> regfield;
484858Speter 
494858Speter     switch ( modep -> modefield ) {
504858Speter 	case 0:
514858Speter 	case 1:
524858Speter 	case 2:
534858Speter 	case 3:
544858Speter 	    return literal;
554858Speter 	case 4:
564858Speter 	    return indexed;
574858Speter 	case 5:
584858Speter 	    return reg;
594858Speter 	case 6:
604858Speter 	    return regdef;
614858Speter 	case 7:
624858Speter 	    return autodec;
634858Speter 	case 8:
644858Speter 	    return ( usesreg != PC ? autoinc : immediate );
654858Speter 	case 9:
664858Speter 	    return ( usesreg != PC ? autoincdef : absolute );
674858Speter 	case 10:
684858Speter 	    return ( usesreg != PC ? bytedisp : byterel );
694858Speter 	case 11:
704858Speter 	    return ( usesreg != PC ? bytedispdef : bytereldef );
714858Speter 	case 12:
724858Speter 	    return ( usesreg != PC ? worddisp : wordrel );
734858Speter 	case 13:
744858Speter 	    return ( usesreg != PC ? worddispdef : wordreldef );
754858Speter 	case 14:
764858Speter 	    return ( usesreg != PC ? longdisp : longrel );
774858Speter 	case 15:
784858Speter 	    return ( usesreg != PC ? longdispdef : longreldef );
794858Speter     }
804858Speter     /* NOTREACHED */
814858Speter }
824858Speter 
834858Speter char *
844858Speter operandname( mode )
854858Speter     operandenum	mode;
864858Speter {
874858Speter 
884858Speter     switch ( mode ) {
894858Speter 	case literal:
904858Speter 	    return "literal";
914858Speter 	case indexed:
924858Speter 	    return "indexed";
934858Speter 	case reg:
944858Speter 	    return "register";
954858Speter 	case regdef:
964858Speter 	    return "register deferred";
974858Speter 	case autodec:
984858Speter 	    return "autodecrement";
994858Speter 	case autoinc:
1004858Speter 	    return "autoincrement";
1014858Speter 	case autoincdef:
1024858Speter 	    return "autoincrement deferred";
1034858Speter 	case bytedisp:
1044858Speter 	    return "byte displacement";
1054858Speter 	case bytedispdef:
1064858Speter 	    return "byte displacement deferred";
1074858Speter 	case byterel:
1084858Speter 	    return "byte relative";
1094858Speter 	case bytereldef:
1104858Speter 	    return "byte relative deferred";
1114858Speter 	case worddisp:
1124858Speter 	    return "word displacement";
1134858Speter 	case worddispdef:
1144858Speter 	    return "word displacement deferred";
1154858Speter 	case wordrel:
1164858Speter 	    return "word relative";
1174858Speter 	case wordreldef:
1184858Speter 	    return "word relative deferred";
1194858Speter 	case immediate:
1204858Speter 	    return "immediate";
1214858Speter 	case absolute:
1224858Speter 	    return "absolute";
1234858Speter 	case longdisp:
1244858Speter 	    return "long displacement";
1254858Speter 	case longdispdef:
1264858Speter 	    return "long displacement deferred";
1274858Speter 	case longrel:
1284858Speter 	    return "long relative";
1294858Speter 	case longreldef:
1304858Speter 	    return "long relative deferred";
1314858Speter     }
1324858Speter     /* NOTREACHED */
1334858Speter }
1344858Speter 
1354858Speter long
1364858Speter operandlength( modep )
1374858Speter     struct modebyte	*modep;
1384858Speter {
1394858Speter 
1404858Speter     switch ( operandmode( modep ) ) {
1414858Speter 	case literal:
1424858Speter 	case reg:
1434858Speter 	case regdef:
1444858Speter 	case autodec:
1454858Speter 	case autoinc:
1464858Speter 	case autoincdef:
1474858Speter 	    return 1;
1484858Speter 	case bytedisp:
1494858Speter 	case bytedispdef:
1504858Speter 	case byterel:
1514858Speter 	case bytereldef:
1524858Speter 	    return 2;
1534858Speter 	case worddisp:
1544858Speter 	case worddispdef:
1554858Speter 	case wordrel:
1564858Speter 	case wordreldef:
1574858Speter 	    return 3;
1584858Speter 	case immediate:
1594858Speter 	case absolute:
1604858Speter 	case longdisp:
1614858Speter 	case longdispdef:
1624858Speter 	case longrel:
1634858Speter 	case longreldef:
1644858Speter 	    return 5;
1654858Speter 	case indexed:
1664858Speter 	    return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 );
1674858Speter     }
1684858Speter     /* NOTREACHED */
1694858Speter }
1704858Speter 
1714858Speter unsigned long
1724858Speter reladdr( modep )
1734858Speter     struct modebyte	*modep;
1744858Speter {
1754858Speter     operandenum	mode = operandmode( modep );
1764858Speter     char	*cp;
1774858Speter     short	*sp;
1784858Speter     long	*lp;
1794858Speter 
1804858Speter     cp = (char *) modep;
1814858Speter     cp += 1;			/* skip over the mode */
1824858Speter     switch ( mode ) {
1834858Speter 	default:
1844858Speter 	    fprintf( stderr , "[reladdr] not relative address\n" );
1854858Speter 	    return (unsigned long) modep;
1864858Speter 	case byterel:
1874858Speter 	    return (unsigned long) ( cp + sizeof *cp + *cp );
1884858Speter 	case wordrel:
1894858Speter 	    sp = (short *) cp;
1904858Speter 	    return (unsigned long) ( cp + sizeof *sp + *sp );
1914858Speter 	case longrel:
1924858Speter 	    lp = (long *) cp;
1934858Speter 	    return (unsigned long) ( cp + sizeof *lp + *lp );
1944858Speter     }
1954858Speter }
1964858Speter 
19725713Ssam findcall( parentp , p_lowpc , p_highpc )
1984858Speter     nltype		*parentp;
1994858Speter     unsigned long	p_lowpc;
2004858Speter     unsigned long	p_highpc;
2014858Speter {
2024858Speter     unsigned char	*instructp;
2034858Speter     long		length;
2044858Speter     nltype		*childp;
2054858Speter     operandenum		mode;
2064858Speter     operandenum		firstmode;
2074858Speter     unsigned long	destpc;
2084858Speter 
2094858Speter     if ( textspace == 0 ) {
2104858Speter 	return;
2114858Speter     }
2124858Speter     if ( p_lowpc < s_lowpc ) {
2134858Speter 	p_lowpc = s_lowpc;
2144858Speter     }
2154858Speter     if ( p_highpc > s_highpc ) {
2164858Speter 	p_highpc = s_highpc;
2174858Speter     }
2184858Speter #   ifdef DEBUG
21925710Ssam 	if ( debug & CALLDEBUG ) {
22025713Ssam 	    printf( "[findcall] %s: 0x%x to 0x%x\n" ,
2214858Speter 		    parentp -> name , p_lowpc , p_highpc );
2224858Speter 	}
2234858Speter #   endif DEBUG
2244858Speter     for (   instructp = textspace + p_lowpc ;
2254858Speter 	    instructp < textspace + p_highpc ;
2264858Speter 	    instructp += length ) {
2274858Speter 	length = 1;
2284858Speter 	if ( *instructp == CALLS ) {
2294858Speter 		/*
2304858Speter 		 *	maybe a calls, better check it out.
2314858Speter 		 *	skip the count of the number of arguments.
2324858Speter 		 */
2334858Speter #	    ifdef DEBUG
23425710Ssam 		if ( debug & CALLDEBUG ) {
23525713Ssam 		    printf( "[findcall]\t0x%x:calls" , instructp - textspace );
2364858Speter 		}
2374858Speter #	    endif DEBUG
2384858Speter 	    firstmode = operandmode( (struct modebyte *) (instructp+length) );
2394858Speter 	    switch ( firstmode ) {
2404858Speter 		case literal:
2414858Speter 		case immediate:
2424858Speter 		    break;
2434858Speter 		default:
2444858Speter 		    goto botched;
2454858Speter 	    }
2464858Speter 	    length += operandlength( (struct modebyte *) (instructp+length) );
2474858Speter 	    mode = operandmode( (struct modebyte *) ( instructp + length ) );
2484858Speter #	    ifdef DEBUG
24925710Ssam 		if ( debug & CALLDEBUG ) {
2504858Speter 		    printf( "\tfirst operand is %s", operandname( firstmode ) );
2514858Speter 		    printf( "\tsecond operand is %s\n" , operandname( mode ) );
2524858Speter 		}
2534858Speter #	    endif DEBUG
2544858Speter 	    switch ( mode ) {
2554858Speter 		case regdef:
2564858Speter 		case bytedispdef:
2574858Speter 		case worddispdef:
2584858Speter 		case longdispdef:
2594858Speter 		case bytereldef:
2604858Speter 		case wordreldef:
2614858Speter 		case longreldef:
2624858Speter 			/*
2634858Speter 			 *	indirect call: call through pointer
2644858Speter 			 *	either	*d(r)	as a parameter or local
2654858Speter 			 *		(r)	as a return value
2664858Speter 			 *		*f	as a global pointer
2674858Speter 			 *	[are there others that we miss?,
2684858Speter 			 *	 e.g. arrays of pointers to functions???]
2694858Speter 			 */
2704858Speter 		    addarc( parentp , &indirectchild , (long) 0 );
2714858Speter 		    length += operandlength(
2724858Speter 				(struct modebyte *) ( instructp + length ) );
2734858Speter 		    continue;
2744858Speter 		case byterel:
2754858Speter 		case wordrel:
2764858Speter 		case longrel:
2774858Speter 			/*
2784858Speter 			 *	regular pc relative addressing
2794858Speter 			 *	check that this is the address of
2804858Speter 			 *	a function.
2814858Speter 			 */
2824858Speter 		    destpc = reladdr( (struct modebyte *) (instructp+length) )
2834858Speter 				- (unsigned long) textspace;
2844858Speter 		    if ( destpc >= s_lowpc && destpc <= s_highpc ) {
2854858Speter 			childp = nllookup( destpc );
2864858Speter #			ifdef DEBUG
28725710Ssam 			    if ( debug & CALLDEBUG ) {
28825713Ssam 				printf( "[findcall]\tdestpc 0x%x" , destpc );
2894858Speter 				printf( " childp->name %s" , childp -> name );
2904858Speter 				printf( " childp->value 0x%x\n" ,
2914858Speter 					childp -> value );
2924858Speter 			    }
2934858Speter #			endif DEBUG
2944858Speter 			if ( childp -> value == destpc ) {
2954858Speter 				/*
2964858Speter 				 *	a hit
2974858Speter 				 */
2984858Speter 			    addarc( parentp , childp , (long) 0 );
2994858Speter 			    length += operandlength( (struct modebyte *)
3004858Speter 					    ( instructp + length ) );
3014858Speter 			    continue;
3024858Speter 			}
3034858Speter 			goto botched;
3044858Speter 		    }
3054858Speter 			/*
3064858Speter 			 *	else:
3074858Speter 			 *	it looked like a calls,
3084858Speter 			 *	but it wasn't to anywhere.
3094858Speter 			 */
3104858Speter 		    goto botched;
3114858Speter 		default:
3124858Speter 		botched:
3134858Speter 			/*
3144858Speter 			 *	something funny going on.
3154858Speter 			 */
3164858Speter #		    ifdef DEBUG
31725710Ssam 			if ( debug & CALLDEBUG ) {
31825713Ssam 			    printf( "[findcall]\tbut it's a botch\n" );
3194858Speter 			}
3204858Speter #		    endif DEBUG
3214858Speter 		    length = 1;
3224858Speter 		    continue;
3234858Speter 	    }
3244858Speter 	}
3254858Speter     }
3264858Speter }
327