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