121958Sdist /* 221958Sdist * Copyright (c) 1983 Regents of the University of California. 334199Sbostic * All rights reserved. 434199Sbostic * 5*42683Sbostic * %sccs.include.redist.c% 621958Sdist */ 721958Sdist 84858Speter #ifndef lint 9*42683Sbostic static char sccsid[] = "@(#)vax.c 5.6 (Berkeley) 06/01/90"; 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 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 * 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 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 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 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