* __bb_exit_func.c: New file, from David Mosberger-Tang.
[deliverable/binutils-gdb.git] / gprof / tahoe.c
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: (1) source distributions retain this entire copyright
7 * notice and comment, and (2) distributions including binaries display
8 * the following acknowledgement: ``This product includes software
9 * developed by the University of California, Berkeley and its contributors''
10 * in the documentation or other materials provided with the distribution
11 * and in all advertising materials mentioning features or use of this
12 * software. Neither the name of the University nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 */
19 #include "gprof.h"
20 #include "time_host.h"
21
22 /*
23 * A symbol to be the child of indirect callf:
24 */
25 Sym indirectchild;
26
27
28 operandenum
29 operandmode (modep)
30 unsigned char *modep;
31 {
32 long usesreg = ((long) *modep) & 0xf;
33
34 switch (((long) *modep) >> 4)
35 {
36 case 0:
37 case 1:
38 case 2:
39 case 3:
40 return literal;
41 case 4:
42 return indexed;
43 case 5:
44 return reg;
45 case 6:
46 return regdef;
47 case 7:
48 return autodec;
49 case 8:
50 return usesreg != 0xe ? autoinc : immediate;
51 case 9:
52 return usesreg != PC ? autoincdef : absolute;
53 case 10:
54 return usesreg != PC ? bytedisp : byterel;
55 case 11:
56 return usesreg != PC ? bytedispdef : bytereldef;
57 case 12:
58 return usesreg != PC ? worddisp : wordrel;
59 case 13:
60 return usesreg != PC ? worddispdef : wordreldef;
61 case 14:
62 return usesreg != PC ? longdisp : longrel;
63 case 15:
64 return usesreg != PC ? longdispdef : longreldef;
65 }
66 /* NOTREACHED */
67 }
68
69 char *
70 operandname (mode)
71 operandenum mode;
72 {
73
74 switch (mode)
75 {
76 case literal:
77 return "literal";
78 case indexed:
79 return "indexed";
80 case reg:
81 return "register";
82 case regdef:
83 return "register deferred";
84 case autodec:
85 return "autodecrement";
86 case autoinc:
87 return "autoincrement";
88 case autoincdef:
89 return "autoincrement deferred";
90 case bytedisp:
91 return "byte displacement";
92 case bytedispdef:
93 return "byte displacement deferred";
94 case byterel:
95 return "byte relative";
96 case bytereldef:
97 return "byte relative deferred";
98 case worddisp:
99 return "word displacement";
100 case worddispdef:
101 return "word displacement deferred";
102 case wordrel:
103 return "word relative";
104 case wordreldef:
105 return "word relative deferred";
106 case immediate:
107 return "immediate";
108 case absolute:
109 return "absolute";
110 case longdisp:
111 return "long displacement";
112 case longdispdef:
113 return "long displacement deferred";
114 case longrel:
115 return "long relative";
116 case longreldef:
117 return "long relative deferred";
118 }
119 /* NOTREACHED */
120 }
121
122 long
123 operandlength (modep)
124 unsigned char *modep;
125 {
126
127 switch (operandmode (modep))
128 {
129 case literal:
130 case reg:
131 case regdef:
132 case autodec:
133 case autoinc:
134 case autoincdef:
135 return 1;
136 case bytedisp:
137 case bytedispdef:
138 case byterel:
139 case bytereldef:
140 return 2;
141 case worddisp:
142 case worddispdef:
143 case wordrel:
144 case wordreldef:
145 return 3;
146 case immediate:
147 case absolute:
148 case longdisp:
149 case longdispdef:
150 case longrel:
151 case longreldef:
152 return 5;
153 case indexed:
154 return 1 + operandlength (modep + 1);
155 }
156 /* NOTREACHED */
157 }
158
159 bfd_vma
160 reladdr (modep)
161 char *modep;
162 {
163 operandenum mode = operandmode (modep);
164 char *cp;
165 short *sp;
166 long *lp;
167 int i;
168 long value = 0;
169
170 cp = modep;
171 ++cp; /* skip over the mode */
172 switch (mode)
173 {
174 default:
175 fprintf (stderr, "[reladdr] not relative address\n");
176 return (bfd_vma) modep;
177 case byterel:
178 return (bfd_vma) (cp + sizeof *cp + *cp);
179 case wordrel:
180 for (i = 0; i < sizeof *sp; i++)
181 value = (value << 8) + (cp[i] & 0xff);
182 return (bfd_vma) (cp + sizeof *sp + value);
183 case longrel:
184 for (i = 0; i < sizeof *lp; i++)
185 value = (value << 8) + (cp[i] & 0xff);
186 return (bfd_vma) (cp + sizeof *lp + value);
187 }
188 }
189
190 find_call (parent, p_lowpc, p_highpc)
191 Sym *parent;
192 bfd_vma p_lowpc;
193 bfd_vma p_highpc;
194 {
195 unsigned char *instructp;
196 long length;
197 Sym *child;
198 operandenum mode;
199 operandenum firstmode;
200 bfd_vma destpc;
201 static bool inited = FALSE;
202
203 if (!inited)
204 {
205 inited = TRUE;
206 sym_init (&indirectchild);
207 indirectchild.cg.prop.fract = 1.0;
208 indirectchild.cg.cyc.head = &indirectchild;
209 }
210
211 if (textspace == 0)
212 {
213 return;
214 }
215 if (p_lowpc < s_lowpc)
216 {
217 p_lowpc = s_lowpc;
218 }
219 if (p_highpc > s_highpc)
220 {
221 p_highpc = s_highpc;
222 }
223 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%x to 0x%x\n",
224 parent->name, p_lowpc, p_highpc));
225 for (instructp = textspace + p_lowpc;
226 instructp < textspace + p_highpc;
227 instructp += length)
228 {
229 length = 1;
230 if (*instructp == CALLF)
231 {
232 /*
233 * maybe a callf, better check it out.
234 * skip the count of the number of arguments.
235 */
236 DBG (CALLDEBUG, printf ("[findcall]\t0x%x:callf",
237 instructp - textspace));
238 firstmode = operandmode (instructp + length);
239 switch (firstmode)
240 {
241 case literal:
242 case immediate:
243 break;
244 default:
245 goto botched;
246 }
247 length += operandlength (instructp + length);
248 mode = operandmode (instructp + length);
249 DBG (CALLDEBUG,
250 printf ("\tfirst operand is %s", operandname (firstmode));
251 printf ("\tsecond operand is %s\n", operandname (mode));
252 );
253 switch (mode)
254 {
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 arc_add (parent, &indirectchild, (long) 0);
271 length += operandlength (instructp + length);
272 continue;
273 case byterel:
274 case wordrel:
275 case longrel:
276 /*
277 * regular pc relative addressing
278 * check that this is the address of
279 * a function.
280 */
281 destpc = reladdr (instructp + length)
282 - (bfd_vma) textspace;
283 if (destpc >= s_lowpc && destpc <= s_highpc)
284 {
285 child = sym_lookup (destpc);
286 DBG (CALLDEBUG,
287 printf ("[findcall]\tdestpc 0x%x", destpc);
288 printf (" child->name %s", child->name);
289 printf (" child->addr 0x%x\n", child->addr);
290 );
291 if (child->addr == destpc)
292 {
293 /*
294 * a hit
295 */
296 arc_add (parent, child, (long) 0);
297 length += operandlength (instructp + length);
298 continue;
299 }
300 goto botched;
301 }
302 /*
303 * else:
304 * it looked like a callf,
305 * but it wasn't to anywhere.
306 */
307 goto botched;
308 default:
309 botched:
310 /*
311 * something funny going on.
312 */
313 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
314 length = 1;
315 continue;
316 }
317 }
318 }
319 }
This page took 0.036044 seconds and 5 git commands to generate.