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