Annotation of src/usr.bin/gprof/vax.c, Revision 1.7
1.7 ! espie 1: /* $OpenBSD: vax.c,v 1.6 2003/06/03 02:56:08 millert Exp $ */
1.2 deraadt 2: /* $NetBSD: vax.c,v 1.6 1996/04/20 14:56:37 ragge Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1983, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.6 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: #if 0
35: static char sccsid[] = "@(#)vax.c 8.1 (Berkeley) 6/6/93";
36: #else
1.7 ! espie 37: static char rcsid[] = "$OpenBSD: vax.c,v 1.6 2003/06/03 02:56:08 millert Exp $";
1.1 deraadt 38: #endif
39: #endif /* not lint */
40:
41: #include "gprof.h"
42:
43: /*
44: * a namelist entry to be the child of indirect calls
45: */
46: nltype indirectchild = {
47: "(*)" , /* the name */
48: (unsigned long) 0 , /* the pc entry point */
49: (unsigned long) 0 , /* entry point aligned to histogram */
50: (double) 0.0 , /* ticks in this routine */
51: (double) 0.0 , /* cumulative ticks in children */
52: (long) 0 , /* how many times called */
1.2 deraadt 53: (long) 0 , /* times called by live arcs */
1.1 deraadt 54: (long) 0 , /* how many calls to self */
55: (double) 1.0 , /* propagation fraction */
56: (double) 0.0 , /* self propagation time */
57: (double) 0.0 , /* child propagation time */
1.2 deraadt 58: (short) 0 , /* print flag */
59: (short) 0 , /* see below */
1.1 deraadt 60: (int) 0 , /* index in the graph list */
61: (int) 0 , /* graph call chain top-sort order */
62: (int) 0 , /* internal number of cycle on */
1.2 deraadt 63: (int) 0 , /* number of live parent arcs */
1.1 deraadt 64: (struct nl *) &indirectchild , /* pointer to head of cycle */
65: (struct nl *) 0 , /* pointer to next member of cycle */
66: (arctype *) 0 , /* list of caller arcs */
67: (arctype *) 0 /* list of callee arcs */
68: };
69:
70: operandenum
1.7 ! espie 71: operandmode(struct modebyte *modep)
1.1 deraadt 72: {
73: long usesreg = modep -> regfield;
74:
75: switch ( modep -> modefield ) {
76: case 0:
77: case 1:
78: case 2:
79: case 3:
80: return literal;
81: case 4:
82: return indexed;
83: case 5:
84: return reg;
85: case 6:
86: return regdef;
87: case 7:
88: return autodec;
89: case 8:
90: return ( usesreg != PC ? autoinc : immediate );
91: case 9:
92: return ( usesreg != PC ? autoincdef : absolute );
93: case 10:
94: return ( usesreg != PC ? bytedisp : byterel );
95: case 11:
96: return ( usesreg != PC ? bytedispdef : bytereldef );
97: case 12:
98: return ( usesreg != PC ? worddisp : wordrel );
99: case 13:
100: return ( usesreg != PC ? worddispdef : wordreldef );
101: case 14:
102: return ( usesreg != PC ? longdisp : longrel );
103: case 15:
104: return ( usesreg != PC ? longdispdef : longreldef );
105: }
106: /* NOTREACHED */
107: }
108:
109: char *
1.7 ! espie 110: operandname(operandenum mode)
1.1 deraadt 111: {
112:
113: switch ( mode ) {
114: case literal:
115: return "literal";
116: case indexed:
117: return "indexed";
118: case reg:
119: return "register";
120: case regdef:
121: return "register deferred";
122: case autodec:
123: return "autodecrement";
124: case autoinc:
125: return "autoincrement";
126: case autoincdef:
127: return "autoincrement deferred";
128: case bytedisp:
129: return "byte displacement";
130: case bytedispdef:
131: return "byte displacement deferred";
132: case byterel:
133: return "byte relative";
134: case bytereldef:
135: return "byte relative deferred";
136: case worddisp:
137: return "word displacement";
138: case worddispdef:
139: return "word displacement deferred";
140: case wordrel:
141: return "word relative";
142: case wordreldef:
143: return "word relative deferred";
144: case immediate:
145: return "immediate";
146: case absolute:
147: return "absolute";
148: case longdisp:
149: return "long displacement";
150: case longdispdef:
151: return "long displacement deferred";
152: case longrel:
153: return "long relative";
154: case longreldef:
155: return "long relative deferred";
156: }
157: /* NOTREACHED */
158: }
159:
160: long
1.7 ! espie 161: operandlength(struct modebyte *modep)
1.1 deraadt 162: {
163:
164: switch ( operandmode( modep ) ) {
165: case literal:
166: case reg:
167: case regdef:
168: case autodec:
169: case autoinc:
170: case autoincdef:
171: return 1;
172: case bytedisp:
173: case bytedispdef:
174: case byterel:
175: case bytereldef:
176: return 2;
177: case worddisp:
178: case worddispdef:
179: case wordrel:
180: case wordreldef:
181: return 3;
182: case immediate:
183: case absolute:
184: case longdisp:
185: case longdispdef:
186: case longrel:
187: case longreldef:
188: return 5;
189: case indexed:
190: return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 );
191: }
192: /* NOTREACHED */
193: }
194:
195: unsigned long
1.7 ! espie 196: reladdr(struct modebyte *modep)
1.1 deraadt 197: {
198: operandenum mode = operandmode( modep );
199: char *cp;
200: short *sp;
201: long *lp;
202:
203: cp = (char *) modep;
204: cp += 1; /* skip over the mode */
205: switch ( mode ) {
206: default:
1.4 mickey 207: warnx("[reladdr] not relative address");
1.1 deraadt 208: return (unsigned long) modep;
209: case byterel:
210: return (unsigned long) ( cp + sizeof *cp + *cp );
211: case wordrel:
212: sp = (short *) cp;
213: return (unsigned long) ( cp + sizeof *sp + *sp );
214: case longrel:
215: lp = (long *) cp;
216: return (unsigned long) ( cp + sizeof *lp + *lp );
217: }
218: }
219:
1.4 mickey 220: void
1.7 ! espie 221: findcall(nltype *parentp, unsigned long p_lowpc, unsigned long p_highpc)
1.1 deraadt 222: {
223: unsigned char *instructp;
224: long length;
225: nltype *childp;
226: operandenum mode;
227: operandenum firstmode;
228: unsigned long destpc;
229:
230: if ( textspace == 0 ) {
231: return;
232: }
233: if ( p_lowpc < s_lowpc ) {
234: p_lowpc = s_lowpc;
235: }
236: if ( p_highpc > s_highpc ) {
237: p_highpc = s_highpc;
238: }
239: # ifdef DEBUG
240: if ( debug & CALLDEBUG ) {
241: printf( "[findcall] %s: 0x%x to 0x%x\n" ,
242: parentp -> name , p_lowpc , p_highpc );
243: }
1.5 danh 244: # endif /* DEBUG */
1.1 deraadt 245: for ( instructp = textspace + p_lowpc ;
246: instructp < textspace + p_highpc ;
247: instructp += length ) {
248: length = 1;
249: if ( *instructp == CALLS ) {
250: /*
251: * maybe a calls, better check it out.
252: * skip the count of the number of arguments.
253: */
254: # ifdef DEBUG
255: if ( debug & CALLDEBUG ) {
256: printf( "[findcall]\t0x%x:calls" , instructp - textspace );
257: }
1.5 danh 258: # endif /* DEBUG */
1.1 deraadt 259: firstmode = operandmode( (struct modebyte *) (instructp+length) );
260: switch ( firstmode ) {
261: case literal:
262: case immediate:
263: break;
264: default:
265: goto botched;
266: }
267: length += operandlength( (struct modebyte *) (instructp+length) );
268: mode = operandmode( (struct modebyte *) ( instructp + length ) );
269: # ifdef DEBUG
270: if ( debug & CALLDEBUG ) {
271: printf( "\tfirst operand is %s", operandname( firstmode ) );
272: printf( "\tsecond operand is %s\n" , operandname( mode ) );
273: }
1.5 danh 274: # endif /* DEBUG */
1.1 deraadt 275: switch ( mode ) {
276: case regdef:
277: case bytedispdef:
278: case worddispdef:
279: case longdispdef:
280: case bytereldef:
281: case wordreldef:
282: case longreldef:
283: /*
284: * indirect call: call through pointer
285: * either *d(r) as a parameter or local
286: * (r) as a return value
287: * *f as a global pointer
288: * [are there others that we miss?,
289: * e.g. arrays of pointers to functions???]
290: */
291: addarc( parentp , &indirectchild , (long) 0 );
292: length += operandlength(
293: (struct modebyte *) ( instructp + length ) );
294: continue;
295: case byterel:
296: case wordrel:
297: case longrel:
298: /*
299: * regular pc relative addressing
300: * check that this is the address of
301: * a function.
302: */
303: destpc = reladdr( (struct modebyte *) (instructp+length) )
304: - (unsigned long) textspace;
305: if ( destpc >= s_lowpc && destpc <= s_highpc ) {
306: childp = nllookup( destpc );
307: # ifdef DEBUG
308: if ( debug & CALLDEBUG ) {
309: printf( "[findcall]\tdestpc 0x%x" , destpc );
310: printf( " childp->name %s" , childp -> name );
311: printf( " childp->value 0x%x\n" ,
312: childp -> value );
313: }
1.5 danh 314: # endif /* DEBUG */
1.1 deraadt 315: if ( childp -> value == destpc ) {
316: /*
317: * a hit
318: */
319: addarc( parentp , childp , (long) 0 );
320: length += operandlength( (struct modebyte *)
321: ( instructp + length ) );
322: continue;
323: }
324: goto botched;
325: }
326: /*
327: * else:
328: * it looked like a calls,
329: * but it wasn't to anywhere.
330: */
331: goto botched;
332: default:
333: botched:
334: /*
335: * something funny going on.
336: */
337: # ifdef DEBUG
338: if ( debug & CALLDEBUG ) {
339: printf( "[findcall]\tbut it's a botch\n" );
340: }
1.5 danh 341: # endif /* DEBUG */
1.1 deraadt 342: length = 1;
343: continue;
344: }
345: }
346: }
347: }