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