1*4858Speter #ifndef lint 2*4858Speter static char *sccsid = "@(#)vax.c 1.1 (Berkeley) 11/11/81"; 3*4858Speter #endif not lint 4*4858Speter 5*4858Speter #include "gprof.h" 6*4858Speter 7*4858Speter /* 8*4858Speter * a namelist entry to be the child of indirect calls 9*4858Speter */ 10*4858Speter nltype indirectchild = { 11*4858Speter "(*)" , /* the name */ 12*4858Speter (unsigned long) 0 , /* the pc entry point */ 13*4858Speter (double) 0.0 , /* ticks in this routine */ 14*4858Speter (double) 0.0 , /* cumulative ticks in children */ 15*4858Speter (long) 0 , /* how many times called */ 16*4858Speter (long) 0 , /* how many calls to self */ 17*4858Speter (int) 0 , /* index in the graph list */ 18*4858Speter (int) 0 , /* graph call chain top-sort order */ 19*4858Speter (int) 0 , /* internal number of cycle on */ 20*4858Speter (struct nl *) &indirectchild , /* pointer to head of cycle */ 21*4858Speter (struct nl *) 0 , /* pointer to next member of cycle */ 22*4858Speter (arctype *) 0 , /* list of caller arcs */ 23*4858Speter (arctype *) 0 /* list of callee arcs */ 24*4858Speter }; 25*4858Speter 26*4858Speter operandenum 27*4858Speter operandmode( modep ) 28*4858Speter struct modebyte *modep; 29*4858Speter { 30*4858Speter long usesreg = modep -> regfield; 31*4858Speter 32*4858Speter switch ( modep -> modefield ) { 33*4858Speter case 0: 34*4858Speter case 1: 35*4858Speter case 2: 36*4858Speter case 3: 37*4858Speter return literal; 38*4858Speter case 4: 39*4858Speter return indexed; 40*4858Speter case 5: 41*4858Speter return reg; 42*4858Speter case 6: 43*4858Speter return regdef; 44*4858Speter case 7: 45*4858Speter return autodec; 46*4858Speter case 8: 47*4858Speter return ( usesreg != PC ? autoinc : immediate ); 48*4858Speter case 9: 49*4858Speter return ( usesreg != PC ? autoincdef : absolute ); 50*4858Speter case 10: 51*4858Speter return ( usesreg != PC ? bytedisp : byterel ); 52*4858Speter case 11: 53*4858Speter return ( usesreg != PC ? bytedispdef : bytereldef ); 54*4858Speter case 12: 55*4858Speter return ( usesreg != PC ? worddisp : wordrel ); 56*4858Speter case 13: 57*4858Speter return ( usesreg != PC ? worddispdef : wordreldef ); 58*4858Speter case 14: 59*4858Speter return ( usesreg != PC ? longdisp : longrel ); 60*4858Speter case 15: 61*4858Speter return ( usesreg != PC ? longdispdef : longreldef ); 62*4858Speter } 63*4858Speter /* NOTREACHED */ 64*4858Speter } 65*4858Speter 66*4858Speter char * 67*4858Speter operandname( mode ) 68*4858Speter operandenum mode; 69*4858Speter { 70*4858Speter 71*4858Speter switch ( mode ) { 72*4858Speter case literal: 73*4858Speter return "literal"; 74*4858Speter case indexed: 75*4858Speter return "indexed"; 76*4858Speter case reg: 77*4858Speter return "register"; 78*4858Speter case regdef: 79*4858Speter return "register deferred"; 80*4858Speter case autodec: 81*4858Speter return "autodecrement"; 82*4858Speter case autoinc: 83*4858Speter return "autoincrement"; 84*4858Speter case autoincdef: 85*4858Speter return "autoincrement deferred"; 86*4858Speter case bytedisp: 87*4858Speter return "byte displacement"; 88*4858Speter case bytedispdef: 89*4858Speter return "byte displacement deferred"; 90*4858Speter case byterel: 91*4858Speter return "byte relative"; 92*4858Speter case bytereldef: 93*4858Speter return "byte relative deferred"; 94*4858Speter case worddisp: 95*4858Speter return "word displacement"; 96*4858Speter case worddispdef: 97*4858Speter return "word displacement deferred"; 98*4858Speter case wordrel: 99*4858Speter return "word relative"; 100*4858Speter case wordreldef: 101*4858Speter return "word relative deferred"; 102*4858Speter case immediate: 103*4858Speter return "immediate"; 104*4858Speter case absolute: 105*4858Speter return "absolute"; 106*4858Speter case longdisp: 107*4858Speter return "long displacement"; 108*4858Speter case longdispdef: 109*4858Speter return "long displacement deferred"; 110*4858Speter case longrel: 111*4858Speter return "long relative"; 112*4858Speter case longreldef: 113*4858Speter return "long relative deferred"; 114*4858Speter } 115*4858Speter /* NOTREACHED */ 116*4858Speter } 117*4858Speter 118*4858Speter long 119*4858Speter operandlength( modep ) 120*4858Speter struct modebyte *modep; 121*4858Speter { 122*4858Speter 123*4858Speter switch ( operandmode( modep ) ) { 124*4858Speter case literal: 125*4858Speter case reg: 126*4858Speter case regdef: 127*4858Speter case autodec: 128*4858Speter case autoinc: 129*4858Speter case autoincdef: 130*4858Speter return 1; 131*4858Speter case bytedisp: 132*4858Speter case bytedispdef: 133*4858Speter case byterel: 134*4858Speter case bytereldef: 135*4858Speter return 2; 136*4858Speter case worddisp: 137*4858Speter case worddispdef: 138*4858Speter case wordrel: 139*4858Speter case wordreldef: 140*4858Speter return 3; 141*4858Speter case immediate: 142*4858Speter case absolute: 143*4858Speter case longdisp: 144*4858Speter case longdispdef: 145*4858Speter case longrel: 146*4858Speter case longreldef: 147*4858Speter return 5; 148*4858Speter case indexed: 149*4858Speter return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 ); 150*4858Speter } 151*4858Speter /* NOTREACHED */ 152*4858Speter } 153*4858Speter 154*4858Speter unsigned long 155*4858Speter reladdr( modep ) 156*4858Speter struct modebyte *modep; 157*4858Speter { 158*4858Speter operandenum mode = operandmode( modep ); 159*4858Speter char *cp; 160*4858Speter short *sp; 161*4858Speter long *lp; 162*4858Speter 163*4858Speter cp = (char *) modep; 164*4858Speter cp += 1; /* skip over the mode */ 165*4858Speter switch ( mode ) { 166*4858Speter default: 167*4858Speter fprintf( stderr , "[reladdr] not relative address\n" ); 168*4858Speter return (unsigned long) modep; 169*4858Speter case byterel: 170*4858Speter return (unsigned long) ( cp + sizeof *cp + *cp ); 171*4858Speter case wordrel: 172*4858Speter sp = (short *) cp; 173*4858Speter return (unsigned long) ( cp + sizeof *sp + *sp ); 174*4858Speter case longrel: 175*4858Speter lp = (long *) cp; 176*4858Speter return (unsigned long) ( cp + sizeof *lp + *lp ); 177*4858Speter } 178*4858Speter } 179*4858Speter 180*4858Speter findcalls( parentp , p_lowpc , p_highpc ) 181*4858Speter nltype *parentp; 182*4858Speter unsigned long p_lowpc; 183*4858Speter unsigned long p_highpc; 184*4858Speter { 185*4858Speter unsigned char *instructp; 186*4858Speter long length; 187*4858Speter nltype *childp; 188*4858Speter operandenum mode; 189*4858Speter operandenum firstmode; 190*4858Speter unsigned long destpc; 191*4858Speter 192*4858Speter if ( textspace == 0 ) { 193*4858Speter return; 194*4858Speter } 195*4858Speter if ( p_lowpc < s_lowpc ) { 196*4858Speter p_lowpc = s_lowpc; 197*4858Speter } 198*4858Speter if ( p_highpc > s_highpc ) { 199*4858Speter p_highpc = s_highpc; 200*4858Speter } 201*4858Speter # ifdef DEBUG 202*4858Speter if ( debug & CALLSDEBUG ) { 203*4858Speter printf( "[findcalls] %s: 0x%x to 0x%x\n" , 204*4858Speter parentp -> name , p_lowpc , p_highpc ); 205*4858Speter } 206*4858Speter # endif DEBUG 207*4858Speter for ( instructp = textspace + p_lowpc ; 208*4858Speter instructp < textspace + p_highpc ; 209*4858Speter instructp += length ) { 210*4858Speter length = 1; 211*4858Speter if ( *instructp == CALLS ) { 212*4858Speter /* 213*4858Speter * maybe a calls, better check it out. 214*4858Speter * skip the count of the number of arguments. 215*4858Speter */ 216*4858Speter # ifdef DEBUG 217*4858Speter if ( debug & CALLSDEBUG ) { 218*4858Speter printf( "[findcalls]\t0x%x:calls" , instructp - textspace ); 219*4858Speter } 220*4858Speter # endif DEBUG 221*4858Speter firstmode = operandmode( (struct modebyte *) (instructp+length) ); 222*4858Speter switch ( firstmode ) { 223*4858Speter case literal: 224*4858Speter case immediate: 225*4858Speter break; 226*4858Speter default: 227*4858Speter goto botched; 228*4858Speter } 229*4858Speter length += operandlength( (struct modebyte *) (instructp+length) ); 230*4858Speter mode = operandmode( (struct modebyte *) ( instructp + length ) ); 231*4858Speter # ifdef DEBUG 232*4858Speter if ( debug & CALLSDEBUG ) { 233*4858Speter printf( "\tfirst operand is %s", operandname( firstmode ) ); 234*4858Speter printf( "\tsecond operand is %s\n" , operandname( mode ) ); 235*4858Speter } 236*4858Speter # endif DEBUG 237*4858Speter switch ( mode ) { 238*4858Speter case regdef: 239*4858Speter case bytedispdef: 240*4858Speter case worddispdef: 241*4858Speter case longdispdef: 242*4858Speter case bytereldef: 243*4858Speter case wordreldef: 244*4858Speter case longreldef: 245*4858Speter /* 246*4858Speter * indirect call: call through pointer 247*4858Speter * either *d(r) as a parameter or local 248*4858Speter * (r) as a return value 249*4858Speter * *f as a global pointer 250*4858Speter * [are there others that we miss?, 251*4858Speter * e.g. arrays of pointers to functions???] 252*4858Speter */ 253*4858Speter addarc( parentp , &indirectchild , (long) 0 ); 254*4858Speter length += operandlength( 255*4858Speter (struct modebyte *) ( instructp + length ) ); 256*4858Speter continue; 257*4858Speter case byterel: 258*4858Speter case wordrel: 259*4858Speter case longrel: 260*4858Speter /* 261*4858Speter * regular pc relative addressing 262*4858Speter * check that this is the address of 263*4858Speter * a function. 264*4858Speter */ 265*4858Speter destpc = reladdr( (struct modebyte *) (instructp+length) ) 266*4858Speter - (unsigned long) textspace; 267*4858Speter if ( destpc >= s_lowpc && destpc <= s_highpc ) { 268*4858Speter childp = nllookup( destpc ); 269*4858Speter # ifdef DEBUG 270*4858Speter if ( debug & CALLSDEBUG ) { 271*4858Speter printf( "[findcalls]\tdestpc 0x%x" , destpc ); 272*4858Speter printf( " childp->name %s" , childp -> name ); 273*4858Speter printf( " childp->value 0x%x\n" , 274*4858Speter childp -> value ); 275*4858Speter } 276*4858Speter # endif DEBUG 277*4858Speter if ( childp -> value == destpc ) { 278*4858Speter /* 279*4858Speter * a hit 280*4858Speter */ 281*4858Speter addarc( parentp , childp , (long) 0 ); 282*4858Speter length += operandlength( (struct modebyte *) 283*4858Speter ( instructp + length ) ); 284*4858Speter continue; 285*4858Speter } 286*4858Speter goto botched; 287*4858Speter } 288*4858Speter /* 289*4858Speter * else: 290*4858Speter * it looked like a calls, 291*4858Speter * but it wasn't to anywhere. 292*4858Speter */ 293*4858Speter goto botched; 294*4858Speter default: 295*4858Speter botched: 296*4858Speter /* 297*4858Speter * something funny going on. 298*4858Speter */ 299*4858Speter # ifdef DEBUG 300*4858Speter if ( debug & CALLSDEBUG ) { 301*4858Speter printf( "[findcalls]\tbut it's a botch\n" ); 302*4858Speter } 303*4858Speter # endif DEBUG 304*4858Speter length = 1; 305*4858Speter continue; 306*4858Speter } 307*4858Speter } 308*4858Speter } 309*4858Speter } 310