Annotation of src/usr.bin/gprof/vax.c, Revision 1.1.1.1
1.1 deraadt 1: /* $NetBSD: vax.c,v 1.5 1995/04/19 07:16:30 cgd Exp $ */
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
40: static char rcsid[] = "$NetBSD: vax.c,v 1.5 1995/04/19 07:16:30 cgd Exp $";
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 */
56: (long) 0 , /* how many calls to self */
57: (double) 1.0 , /* propagation fraction */
58: (double) 0.0 , /* self propagation time */
59: (double) 0.0 , /* child propagation time */
60: (bool) 0 , /* print flag */
61: (int) 0 , /* index in the graph list */
62: (int) 0 , /* graph call chain top-sort order */
63: (int) 0 , /* internal number of cycle on */
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
71: operandmode( modep )
72: struct modebyte *modep;
73: {
74: long usesreg = modep -> regfield;
75:
76: switch ( modep -> modefield ) {
77: case 0:
78: case 1:
79: case 2:
80: case 3:
81: return literal;
82: case 4:
83: return indexed;
84: case 5:
85: return reg;
86: case 6:
87: return regdef;
88: case 7:
89: return autodec;
90: case 8:
91: return ( usesreg != PC ? autoinc : immediate );
92: case 9:
93: return ( usesreg != PC ? autoincdef : absolute );
94: case 10:
95: return ( usesreg != PC ? bytedisp : byterel );
96: case 11:
97: return ( usesreg != PC ? bytedispdef : bytereldef );
98: case 12:
99: return ( usesreg != PC ? worddisp : wordrel );
100: case 13:
101: return ( usesreg != PC ? worddispdef : wordreldef );
102: case 14:
103: return ( usesreg != PC ? longdisp : longrel );
104: case 15:
105: return ( usesreg != PC ? longdispdef : longreldef );
106: }
107: /* NOTREACHED */
108: }
109:
110: char *
111: operandname( mode )
112: operandenum mode;
113: {
114:
115: switch ( mode ) {
116: case literal:
117: return "literal";
118: case indexed:
119: return "indexed";
120: case reg:
121: return "register";
122: case regdef:
123: return "register deferred";
124: case autodec:
125: return "autodecrement";
126: case autoinc:
127: return "autoincrement";
128: case autoincdef:
129: return "autoincrement deferred";
130: case bytedisp:
131: return "byte displacement";
132: case bytedispdef:
133: return "byte displacement deferred";
134: case byterel:
135: return "byte relative";
136: case bytereldef:
137: return "byte relative deferred";
138: case worddisp:
139: return "word displacement";
140: case worddispdef:
141: return "word displacement deferred";
142: case wordrel:
143: return "word relative";
144: case wordreldef:
145: return "word relative deferred";
146: case immediate:
147: return "immediate";
148: case absolute:
149: return "absolute";
150: case longdisp:
151: return "long displacement";
152: case longdispdef:
153: return "long displacement deferred";
154: case longrel:
155: return "long relative";
156: case longreldef:
157: return "long relative deferred";
158: }
159: /* NOTREACHED */
160: }
161:
162: long
163: operandlength( modep )
164: struct modebyte *modep;
165: {
166:
167: switch ( operandmode( modep ) ) {
168: case literal:
169: case reg:
170: case regdef:
171: case autodec:
172: case autoinc:
173: case autoincdef:
174: return 1;
175: case bytedisp:
176: case bytedispdef:
177: case byterel:
178: case bytereldef:
179: return 2;
180: case worddisp:
181: case worddispdef:
182: case wordrel:
183: case wordreldef:
184: return 3;
185: case immediate:
186: case absolute:
187: case longdisp:
188: case longdispdef:
189: case longrel:
190: case longreldef:
191: return 5;
192: case indexed:
193: return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 );
194: }
195: /* NOTREACHED */
196: }
197:
198: unsigned long
199: reladdr( modep )
200: struct modebyte *modep;
201: {
202: operandenum mode = operandmode( modep );
203: char *cp;
204: short *sp;
205: long *lp;
206:
207: cp = (char *) modep;
208: cp += 1; /* skip over the mode */
209: switch ( mode ) {
210: default:
211: fprintf( stderr , "[reladdr] not relative address\n" );
212: return (unsigned long) modep;
213: case byterel:
214: return (unsigned long) ( cp + sizeof *cp + *cp );
215: case wordrel:
216: sp = (short *) cp;
217: return (unsigned long) ( cp + sizeof *sp + *sp );
218: case longrel:
219: lp = (long *) cp;
220: return (unsigned long) ( cp + sizeof *lp + *lp );
221: }
222: }
223:
224: findcall( parentp , p_lowpc , p_highpc )
225: nltype *parentp;
226: unsigned long p_lowpc;
227: unsigned long p_highpc;
228: {
229: unsigned char *instructp;
230: long length;
231: nltype *childp;
232: operandenum mode;
233: operandenum firstmode;
234: unsigned long destpc;
235:
236: if ( textspace == 0 ) {
237: return;
238: }
239: if ( p_lowpc < s_lowpc ) {
240: p_lowpc = s_lowpc;
241: }
242: if ( p_highpc > s_highpc ) {
243: p_highpc = s_highpc;
244: }
245: # ifdef DEBUG
246: if ( debug & CALLDEBUG ) {
247: printf( "[findcall] %s: 0x%x to 0x%x\n" ,
248: parentp -> name , p_lowpc , p_highpc );
249: }
250: # endif DEBUG
251: for ( instructp = textspace + p_lowpc ;
252: instructp < textspace + p_highpc ;
253: instructp += length ) {
254: length = 1;
255: if ( *instructp == CALLS ) {
256: /*
257: * maybe a calls, better check it out.
258: * skip the count of the number of arguments.
259: */
260: # ifdef DEBUG
261: if ( debug & CALLDEBUG ) {
262: printf( "[findcall]\t0x%x:calls" , instructp - textspace );
263: }
264: # endif DEBUG
265: firstmode = operandmode( (struct modebyte *) (instructp+length) );
266: switch ( firstmode ) {
267: case literal:
268: case immediate:
269: break;
270: default:
271: goto botched;
272: }
273: length += operandlength( (struct modebyte *) (instructp+length) );
274: mode = operandmode( (struct modebyte *) ( instructp + length ) );
275: # ifdef DEBUG
276: if ( debug & CALLDEBUG ) {
277: printf( "\tfirst operand is %s", operandname( firstmode ) );
278: printf( "\tsecond operand is %s\n" , operandname( mode ) );
279: }
280: # endif DEBUG
281: switch ( mode ) {
282: case regdef:
283: case bytedispdef:
284: case worddispdef:
285: case longdispdef:
286: case bytereldef:
287: case wordreldef:
288: case longreldef:
289: /*
290: * indirect call: call through pointer
291: * either *d(r) as a parameter or local
292: * (r) as a return value
293: * *f as a global pointer
294: * [are there others that we miss?,
295: * e.g. arrays of pointers to functions???]
296: */
297: addarc( parentp , &indirectchild , (long) 0 );
298: length += operandlength(
299: (struct modebyte *) ( instructp + length ) );
300: continue;
301: case byterel:
302: case wordrel:
303: case longrel:
304: /*
305: * regular pc relative addressing
306: * check that this is the address of
307: * a function.
308: */
309: destpc = reladdr( (struct modebyte *) (instructp+length) )
310: - (unsigned long) textspace;
311: if ( destpc >= s_lowpc && destpc <= s_highpc ) {
312: childp = nllookup( destpc );
313: # ifdef DEBUG
314: if ( debug & CALLDEBUG ) {
315: printf( "[findcall]\tdestpc 0x%x" , destpc );
316: printf( " childp->name %s" , childp -> name );
317: printf( " childp->value 0x%x\n" ,
318: childp -> value );
319: }
320: # endif DEBUG
321: if ( childp -> value == destpc ) {
322: /*
323: * a hit
324: */
325: addarc( parentp , childp , (long) 0 );
326: length += operandlength( (struct modebyte *)
327: ( instructp + length ) );
328: continue;
329: }
330: goto botched;
331: }
332: /*
333: * else:
334: * it looked like a calls,
335: * but it wasn't to anywhere.
336: */
337: goto botched;
338: default:
339: botched:
340: /*
341: * something funny going on.
342: */
343: # ifdef DEBUG
344: if ( debug & CALLDEBUG ) {
345: printf( "[findcall]\tbut it's a botch\n" );
346: }
347: # endif DEBUG
348: length = 1;
349: continue;
350: }
351: }
352: }
353: }