Initial revision
[binutils.git] / gprof / tahoe.c
blobd133c1779506445915442022c9ec0d03a375c764
1 /*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.
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.
19 #include "gprof.h"
20 #include "cg_arcs.h"
21 #include "corefile.h"
22 #include "hist.h"
23 #include "symtab.h"
26 * opcode of the `callf' instruction
28 #define CALLF 0xfe
31 * register for pc relative addressing
33 #define PC 0xf
35 enum tahoe_opermodes
37 literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
38 bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
39 immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
40 longrel, longreldef
42 typedef enum tahoe_opermodes tahoe_operandenum;
45 * A symbol to be the child of indirect callf:
47 Sym indirectchild;
50 tahoe_operandenum
51 tahoe_operandmode (modep)
52 unsigned char *modep;
54 long usesreg = ((long) *modep) & 0xf;
56 switch (((long) *modep) >> 4)
58 case 0:
59 case 1:
60 case 2:
61 case 3:
62 return literal;
63 case 4:
64 return indexed;
65 case 5:
66 return reg;
67 case 6:
68 return regdef;
69 case 7:
70 return autodec;
71 case 8:
72 return usesreg != 0xe ? autoinc : immediate;
73 case 9:
74 return usesreg != PC ? autoincdef : absolute;
75 case 10:
76 return usesreg != PC ? bytedisp : byterel;
77 case 11:
78 return usesreg != PC ? bytedispdef : bytereldef;
79 case 12:
80 return usesreg != PC ? worddisp : wordrel;
81 case 13:
82 return usesreg != PC ? worddispdef : wordreldef;
83 case 14:
84 return usesreg != PC ? longdisp : longrel;
85 case 15:
86 return usesreg != PC ? longdispdef : longreldef;
88 /* NOTREACHED */
89 abort ();
92 char *
93 tahoe_operandname (mode)
94 tahoe_operandenum mode;
97 switch (mode)
99 case literal:
100 return "literal";
101 case indexed:
102 return "indexed";
103 case reg:
104 return "register";
105 case regdef:
106 return "register deferred";
107 case autodec:
108 return "autodecrement";
109 case autoinc:
110 return "autoincrement";
111 case autoincdef:
112 return "autoincrement deferred";
113 case bytedisp:
114 return "byte displacement";
115 case bytedispdef:
116 return "byte displacement deferred";
117 case byterel:
118 return "byte relative";
119 case bytereldef:
120 return "byte relative deferred";
121 case worddisp:
122 return "word displacement";
123 case worddispdef:
124 return "word displacement deferred";
125 case wordrel:
126 return "word relative";
127 case wordreldef:
128 return "word relative deferred";
129 case immediate:
130 return "immediate";
131 case absolute:
132 return "absolute";
133 case longdisp:
134 return "long displacement";
135 case longdispdef:
136 return "long displacement deferred";
137 case longrel:
138 return "long relative";
139 case longreldef:
140 return "long relative deferred";
142 /* NOTREACHED */
143 abort ();
146 long
147 tahoe_operandlength (modep)
148 unsigned char *modep;
151 switch (tahoe_operandmode (modep))
153 case literal:
154 case reg:
155 case regdef:
156 case autodec:
157 case autoinc:
158 case autoincdef:
159 return 1;
160 case bytedisp:
161 case bytedispdef:
162 case byterel:
163 case bytereldef:
164 return 2;
165 case worddisp:
166 case worddispdef:
167 case wordrel:
168 case wordreldef:
169 return 3;
170 case immediate:
171 case absolute:
172 case longdisp:
173 case longdispdef:
174 case longrel:
175 case longreldef:
176 return 5;
177 case indexed:
178 return 1 + tahoe_operandlength (modep + 1);
180 /* NOTREACHED */
181 abort ();
184 bfd_vma
185 tahoe_reladdr (modep)
186 char *modep;
188 tahoe_operandenum mode = tahoe_operandmode (modep);
189 char *cp;
190 short *sp;
191 long *lp;
192 int i;
193 long value = 0;
195 cp = modep;
196 ++cp; /* skip over the mode */
197 switch (mode)
199 default:
200 fprintf (stderr, "[reladdr] not relative address\n");
201 return (bfd_vma) modep;
202 case byterel:
203 return (bfd_vma) (cp + sizeof *cp + *cp);
204 case wordrel:
205 for (i = 0; (size_t) i < sizeof *sp; i++)
206 value = (value << 8) + (cp[i] & 0xff);
207 return (bfd_vma) (cp + sizeof *sp + value);
208 case longrel:
209 for (i = 0; (size_t) i < sizeof *lp; i++)
210 value = (value << 8) + (cp[i] & 0xff);
211 return (bfd_vma) (cp + sizeof *lp + value);
215 void
216 tahoe_find_call (parent, p_lowpc, p_highpc)
217 Sym *parent;
218 bfd_vma p_lowpc;
219 bfd_vma p_highpc;
221 unsigned char *instructp;
222 long length;
223 Sym *child;
224 tahoe_operandenum mode;
225 tahoe_operandenum firstmode;
226 bfd_vma destpc;
227 static bool inited = FALSE;
229 if (!inited)
231 inited = TRUE;
232 sym_init (&indirectchild);
233 indirectchild.cg.prop.fract = 1.0;
234 indirectchild.cg.cyc.head = &indirectchild;
237 if (core_text_space == 0)
239 return;
241 if (p_lowpc < s_lowpc)
243 p_lowpc = s_lowpc;
245 if (p_highpc > s_highpc)
247 p_highpc = s_highpc;
249 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
250 parent->name, p_lowpc, p_highpc));
251 for (instructp = (unsigned char *) core_text_space + p_lowpc;
252 instructp < (unsigned char *) core_text_space + p_highpc;
253 instructp += length)
255 length = 1;
256 if (*instructp == CALLF)
259 * maybe a callf, better check it out.
260 * skip the count of the number of arguments.
262 DBG (CALLDEBUG, printf ("[findcall]\t0x%x:callf",
263 instructp - (unsigned char *) core_text_space));
264 firstmode = tahoe_operandmode (instructp + length);
265 switch (firstmode)
267 case literal:
268 case immediate:
269 break;
270 default:
271 goto botched;
273 length += tahoe_operandlength (instructp + length);
274 mode = tahoe_operandmode (instructp + length);
275 DBG (CALLDEBUG,
276 printf ("\tfirst operand is %s", tahoe_operandname (firstmode));
277 printf ("\tsecond operand is %s\n", tahoe_operandname (mode));
279 switch (mode)
281 case regdef:
282 case bytedispdef:
283 case worddispdef:
284 case longdispdef:
285 case bytereldef:
286 case wordreldef:
287 case longreldef:
289 * indirect call: call through pointer
290 * either *d(r) as a parameter or local
291 * (r) as a return value
292 * *f as a global pointer
293 * [are there others that we miss?,
294 * e.g. arrays of pointers to functions???]
296 arc_add (parent, &indirectchild, (unsigned long) 0);
297 length += tahoe_operandlength (instructp + length);
298 continue;
299 case byterel:
300 case wordrel:
301 case longrel:
303 * regular pc relative addressing
304 * check that this is the address of
305 * a function.
307 destpc = tahoe_reladdr (instructp + length)
308 - (bfd_vma) core_text_space;
309 if (destpc >= s_lowpc && destpc <= s_highpc)
311 child = sym_lookup (&symtab, destpc);
312 DBG (CALLDEBUG,
313 printf ("[findcall]\tdestpc 0x%lx", destpc);
314 printf (" child->name %s", child->name);
315 printf (" child->addr 0x%lx\n", child->addr);
317 if (child->addr == destpc)
320 * a hit
322 arc_add (parent, child, (unsigned long) 0);
323 length += tahoe_operandlength (instructp + length);
324 continue;
326 goto botched;
329 * else:
330 * it looked like a callf,
331 * but it wasn't to anywhere.
333 goto botched;
334 default:
335 botched:
337 * something funny going on.
339 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
340 length = 1;
341 continue;