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