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