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