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