2001-10-20 H.J. Lu <hjl@gnu.org>
[binutils.git] / gprof / vax.c
blob9d67430c4ba4364c5d9a54443d7a7a63923a2059
1 /*
2 * Copyright (c) 1983, 2001 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 vax_operandmode PARAMS ((struct modebyte *));
57 static char *vax_operandname PARAMS ((operandenum));
58 static long vax_operandlength PARAMS ((struct modebyte *));
59 static bfd_vma vax_reladdr PARAMS ((struct modebyte *));
60 void vax_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
62 static operandenum
63 vax_operandmode (modep)
64 struct modebyte *modep;
66 long usesreg = modep->regfield;
68 switch (modep->modefield)
70 case 0:
71 case 1:
72 case 2:
73 case 3:
74 return literal;
75 case 4:
76 return indexed;
77 case 5:
78 return reg;
79 case 6:
80 return regdef;
81 case 7:
82 return autodec;
83 case 8:
84 return usesreg != PC ? autoinc : immediate;
85 case 9:
86 return usesreg != PC ? autoincdef : absolute;
87 case 10:
88 return usesreg != PC ? bytedisp : byterel;
89 case 11:
90 return usesreg != PC ? bytedispdef : bytereldef;
91 case 12:
92 return usesreg != PC ? worddisp : wordrel;
93 case 13:
94 return usesreg != PC ? worddispdef : wordreldef;
95 case 14:
96 return usesreg != PC ? longdisp : longrel;
97 case 15:
98 return usesreg != PC ? longdispdef : longreldef;
100 /* NOTREACHED */
101 abort ();
104 static char *
105 vax_operandname (mode)
106 operandenum mode;
109 switch (mode)
111 case literal:
112 return "literal";
113 case indexed:
114 return "indexed";
115 case reg:
116 return "register";
117 case regdef:
118 return "register deferred";
119 case autodec:
120 return "autodecrement";
121 case autoinc:
122 return "autoincrement";
123 case autoincdef:
124 return "autoincrement deferred";
125 case bytedisp:
126 return "byte displacement";
127 case bytedispdef:
128 return "byte displacement deferred";
129 case byterel:
130 return "byte relative";
131 case bytereldef:
132 return "byte relative deferred";
133 case worddisp:
134 return "word displacement";
135 case worddispdef:
136 return "word displacement deferred";
137 case wordrel:
138 return "word relative";
139 case wordreldef:
140 return "word relative deferred";
141 case immediate:
142 return "immediate";
143 case absolute:
144 return "absolute";
145 case longdisp:
146 return "long displacement";
147 case longdispdef:
148 return "long displacement deferred";
149 case longrel:
150 return "long relative";
151 case longreldef:
152 return "long relative deferred";
154 /* NOTREACHED */
155 abort ();
158 static long
159 vax_operandlength (modep)
160 struct modebyte *modep;
163 switch (vax_operandmode (modep))
165 case literal:
166 case reg:
167 case regdef:
168 case autodec:
169 case autoinc:
170 case autoincdef:
171 return 1;
172 case bytedisp:
173 case bytedispdef:
174 case byterel:
175 case bytereldef:
176 return 2;
177 case worddisp:
178 case worddispdef:
179 case wordrel:
180 case wordreldef:
181 return 3;
182 case immediate:
183 case absolute:
184 case longdisp:
185 case longdispdef:
186 case longrel:
187 case longreldef:
188 return 5;
189 case indexed:
190 return 1 + vax_operandlength ((struct modebyte *) ((char *) modep) + 1);
192 /* NOTREACHED */
193 abort ();
196 static bfd_vma
197 vax_reladdr (modep)
198 struct modebyte *modep;
200 operandenum mode = vax_operandmode (modep);
201 char *cp;
202 short *sp;
203 long *lp;
205 cp = (char *) modep;
206 ++cp; /* skip over the mode */
207 switch (mode)
209 default:
210 fprintf (stderr, "[reladdr] not relative address\n");
211 return (bfd_vma) modep;
212 case byterel:
213 return (bfd_vma) (cp + sizeof *cp + *cp);
214 case wordrel:
215 sp = (short *) cp;
216 return (bfd_vma) (cp + sizeof *sp + *sp);
217 case longrel:
218 lp = (long *) cp;
219 return (bfd_vma) (cp + sizeof *lp + *lp);
224 void
225 vax_find_call (parent, p_lowpc, p_highpc)
226 Sym *parent;
227 bfd_vma p_lowpc;
228 bfd_vma p_highpc;
230 unsigned char *instructp;
231 long length;
232 Sym *child;
233 operandenum mode;
234 operandenum firstmode;
235 bfd_vma destpc;
236 static bool inited = FALSE;
238 if (!inited)
240 inited = TRUE;
241 sym_init (&indirectchild);
242 indirectchild.cg.prop.fract = 1.0;
243 indirectchild.cg.cyc.head = &indirectchild;
246 if (core_text_space == 0)
248 return;
250 if (p_lowpc < s_lowpc)
252 p_lowpc = s_lowpc;
254 if (p_highpc > s_highpc)
256 p_highpc = s_highpc;
258 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
259 parent->name, (unsigned long) p_lowpc,
260 (unsigned long) p_highpc));
261 for (instructp = (unsigned char *) core_text_space + p_lowpc;
262 instructp < (unsigned char *) core_text_space + p_highpc;
263 instructp += length)
265 length = 1;
266 if (*instructp == CALLS)
269 * maybe a calls, better check it out.
270 * skip the count of the number of arguments.
272 DBG (CALLDEBUG,
273 printf ("[findcall]\t0x%lx:calls",
274 ((unsigned long)
275 (instructp - (unsigned char *) core_text_space))));
276 firstmode = vax_operandmode ((struct modebyte *) (instructp + length));
277 switch (firstmode)
279 case literal:
280 case immediate:
281 break;
282 default:
283 goto botched;
285 length += vax_operandlength ((struct modebyte *) (instructp + length));
286 mode = vax_operandmode ((struct modebyte *) (instructp + length));
287 DBG (CALLDEBUG,
288 printf ("\tfirst operand is %s", vax_operandname (firstmode));
289 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
290 switch (mode)
292 case regdef:
293 case bytedispdef:
294 case worddispdef:
295 case longdispdef:
296 case bytereldef:
297 case wordreldef:
298 case longreldef:
300 * indirect call: call through pointer
301 * either *d(r) as a parameter or local
302 * (r) as a return value
303 * *f as a global pointer
304 * [are there others that we miss?,
305 * e.g. arrays of pointers to functions???]
307 arc_add (parent, &indirectchild, (unsigned long) 0);
308 length += vax_operandlength (
309 (struct modebyte *) (instructp + length));
310 continue;
311 case byterel:
312 case wordrel:
313 case longrel:
315 * regular pc relative addressing
316 * check that this is the address of
317 * a function.
319 destpc = vax_reladdr ((struct modebyte *) (instructp + length))
320 - (bfd_vma) core_text_space;
321 if (destpc >= s_lowpc && destpc <= s_highpc)
323 child = sym_lookup (&symtab, destpc);
324 DBG (CALLDEBUG,
325 printf ("[findcall]\tdestpc 0x%lx",
326 (unsigned long) destpc);
327 printf (" child->name %s", child->name);
328 printf (" child->addr 0x%lx\n",
329 (unsigned long) child->addr);
331 if (child->addr == destpc)
334 * a hit
336 arc_add (parent, child, (unsigned long) 0);
337 length += vax_operandlength ((struct modebyte *)
338 (instructp + length));
339 continue;
341 goto botched;
344 * else:
345 * it looked like a calls,
346 * but it wasn't to anywhere.
348 goto botched;
349 default:
350 botched:
352 * something funny going on.
354 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
355 length = 1;
356 continue;