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