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