Path from Roland McGrath <roland@baalperazim.frob.com>
[binutils.git] / gprof / vax.c
blob33fdf43d460f4efe54cef73f1d06bc289b49d971
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 `calls' instruction
28 #define CALLS 0xfb
31 * register for pc relative addressing
33 #define PC 0xf
35 enum 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 opermodes operandenum;
44 struct modebyte
46 unsigned int regfield:4;
47 unsigned int modefield:4;
51 * A symbol to be the child of indirect calls:
53 Sym indirectchild;
56 static operandenum
57 vax_operandmode (modep)
58 struct modebyte *modep;
60 long usesreg = modep->regfield;
62 switch (modep->modefield)
64 case 0:
65 case 1:
66 case 2:
67 case 3:
68 return literal;
69 case 4:
70 return indexed;
71 case 5:
72 return reg;
73 case 6:
74 return regdef;
75 case 7:
76 return autodec;
77 case 8:
78 return usesreg != PC ? autoinc : immediate;
79 case 9:
80 return usesreg != PC ? autoincdef : absolute;
81 case 10:
82 return usesreg != PC ? bytedisp : byterel;
83 case 11:
84 return usesreg != PC ? bytedispdef : bytereldef;
85 case 12:
86 return usesreg != PC ? worddisp : wordrel;
87 case 13:
88 return usesreg != PC ? worddispdef : wordreldef;
89 case 14:
90 return usesreg != PC ? longdisp : longrel;
91 case 15:
92 return usesreg != PC ? longdispdef : longreldef;
94 /* NOTREACHED */
95 abort ();
98 static char *
99 vax_operandname (mode)
100 operandenum mode;
103 switch (mode)
105 case literal:
106 return "literal";
107 case indexed:
108 return "indexed";
109 case reg:
110 return "register";
111 case regdef:
112 return "register deferred";
113 case autodec:
114 return "autodecrement";
115 case autoinc:
116 return "autoincrement";
117 case autoincdef:
118 return "autoincrement deferred";
119 case bytedisp:
120 return "byte displacement";
121 case bytedispdef:
122 return "byte displacement deferred";
123 case byterel:
124 return "byte relative";
125 case bytereldef:
126 return "byte relative deferred";
127 case worddisp:
128 return "word displacement";
129 case worddispdef:
130 return "word displacement deferred";
131 case wordrel:
132 return "word relative";
133 case wordreldef:
134 return "word relative deferred";
135 case immediate:
136 return "immediate";
137 case absolute:
138 return "absolute";
139 case longdisp:
140 return "long displacement";
141 case longdispdef:
142 return "long displacement deferred";
143 case longrel:
144 return "long relative";
145 case longreldef:
146 return "long relative deferred";
148 /* NOTREACHED */
149 abort ();
152 static long
153 vax_operandlength (modep)
154 struct modebyte *modep;
157 switch (vax_operandmode (modep))
159 case literal:
160 case reg:
161 case regdef:
162 case autodec:
163 case autoinc:
164 case autoincdef:
165 return 1;
166 case bytedisp:
167 case bytedispdef:
168 case byterel:
169 case bytereldef:
170 return 2;
171 case worddisp:
172 case worddispdef:
173 case wordrel:
174 case wordreldef:
175 return 3;
176 case immediate:
177 case absolute:
178 case longdisp:
179 case longdispdef:
180 case longrel:
181 case longreldef:
182 return 5;
183 case indexed:
184 return 1 + vax_operandlength ((struct modebyte *) ((char *) modep) + 1);
186 /* NOTREACHED */
187 abort ();
190 static bfd_vma
191 vax_reladdr (modep)
192 struct modebyte *modep;
194 operandenum mode = vax_operandmode (modep);
195 char *cp;
196 short *sp;
197 long *lp;
199 cp = (char *) modep;
200 ++cp; /* skip over the mode */
201 switch (mode)
203 default:
204 fprintf (stderr, "[reladdr] not relative address\n");
205 return (bfd_vma) modep;
206 case byterel:
207 return (bfd_vma) (cp + sizeof *cp + *cp);
208 case wordrel:
209 sp = (short *) cp;
210 return (bfd_vma) (cp + sizeof *sp + *sp);
211 case longrel:
212 lp = (long *) cp;
213 return (bfd_vma) (cp + sizeof *lp + *lp);
218 void
219 vax_find_call (parent, p_lowpc, p_highpc)
220 Sym *parent;
221 bfd_vma p_lowpc;
222 bfd_vma p_highpc;
224 unsigned char *instructp;
225 long length;
226 Sym *child;
227 operandenum mode;
228 operandenum firstmode;
229 bfd_vma destpc;
230 static bool inited = FALSE;
232 if (!inited)
234 inited = TRUE;
235 sym_init (&indirectchild);
236 indirectchild.cg.prop.fract = 1.0;
237 indirectchild.cg.cyc.head = &indirectchild;
240 if (core_text_space == 0)
242 return;
244 if (p_lowpc < s_lowpc)
246 p_lowpc = s_lowpc;
248 if (p_highpc > s_highpc)
250 p_highpc = s_highpc;
252 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
253 parent->name, (unsigned long) p_lowpc,
254 (unsigned long) p_highpc));
255 for (instructp = (unsigned char *) core_text_space + p_lowpc;
256 instructp < (unsigned char *) core_text_space + p_highpc;
257 instructp += length)
259 length = 1;
260 if (*instructp == CALLS)
263 * maybe a calls, better check it out.
264 * skip the count of the number of arguments.
266 DBG (CALLDEBUG,
267 printf ("[findcall]\t0x%x:calls",
268 instructp - (unsigned char *) core_text_space));
269 firstmode = vax_operandmode ((struct modebyte *) (instructp + length));
270 switch (firstmode)
272 case literal:
273 case immediate:
274 break;
275 default:
276 goto botched;
278 length += vax_operandlength ((struct modebyte *) (instructp + length));
279 mode = vax_operandmode ((struct modebyte *) (instructp + length));
280 DBG (CALLDEBUG,
281 printf ("\tfirst operand is %s", vax_operandname (firstmode));
282 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
283 switch (mode)
285 case regdef:
286 case bytedispdef:
287 case worddispdef:
288 case longdispdef:
289 case bytereldef:
290 case wordreldef:
291 case longreldef:
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???]
300 arc_add (parent, &indirectchild, (unsigned long) 0);
301 length += vax_operandlength (
302 (struct modebyte *) (instructp + length));
303 continue;
304 case byterel:
305 case wordrel:
306 case longrel:
308 * regular pc relative addressing
309 * check that this is the address of
310 * a function.
312 destpc = vax_reladdr ((struct modebyte *) (instructp + length))
313 - (bfd_vma) core_text_space;
314 if (destpc >= s_lowpc && destpc <= s_highpc)
316 child = sym_lookup (&symtab, destpc);
317 DBG (CALLDEBUG,
318 printf ("[findcall]\tdestpc 0x%lx",
319 (unsigned long) destpc);
320 printf (" child->name %s", child->name);
321 printf (" child->addr 0x%lx\n",
322 (unsigned long) child->addr);
324 if (child->addr == destpc)
327 * a hit
329 arc_add (parent, child, (unsigned long) 0);
330 length += vax_operandlength ((struct modebyte *)
331 (instructp + length));
332 continue;
334 goto botched;
337 * else:
338 * it looked like a calls,
339 * but it wasn't to anywhere.
341 goto botched;
342 default:
343 botched:
345 * something funny going on.
347 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
348 length = 1;
349 continue;