* symbols.c (colon) [!WORKING_DOT_WORD]: Don't declare
[binutils.git] / gprof / vax.c
blob9c0665010ec9f848ab097b5ddb9f16654597951f
1 /*
2 * Copyright (c) 1983, 1993, 2001
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 #include "gprof.h"
30 #include "search_list.h"
31 #include "source.h"
32 #include "symtab.h"
33 #include "cg_arcs.h"
34 #include "corefile.h"
35 #include "hist.h"
38 * opcode of the `calls' instruction
40 #define CALLS 0xfb
43 * register for pc relative addressing
45 #define PC 0xf
47 enum opermodes
49 literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
50 bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
51 immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
52 longrel, longreldef
54 typedef enum opermodes operandenum;
56 #if 0
57 /* Here to document only. We can't use this when cross compiling as
58 the bitfield layout might not be the same as native. */
59 struct modebyte
61 unsigned int regfield:4;
62 unsigned int modefield:4;
64 #endif
67 * A symbol to be the child of indirect calls:
69 static Sym indirectchild;
71 static operandenum vax_operandmode (unsigned char *);
72 static char *vax_operandname (operandenum);
73 static long vax_operandlength (unsigned char *);
74 static bfd_signed_vma vax_offset (unsigned char *);
75 void vax_find_call (Sym *, bfd_vma, bfd_vma);
77 static operandenum
78 vax_operandmode (unsigned char *modep)
80 int usesreg = *modep & 0xf;
82 switch ((*modep >> 4) & 0xf)
84 case 0:
85 case 1:
86 case 2:
87 case 3:
88 return literal;
89 case 4:
90 return indexed;
91 case 5:
92 return reg;
93 case 6:
94 return regdef;
95 case 7:
96 return autodec;
97 case 8:
98 return usesreg != PC ? autoinc : immediate;
99 case 9:
100 return usesreg != PC ? autoincdef : absolute;
101 case 10:
102 return usesreg != PC ? bytedisp : byterel;
103 case 11:
104 return usesreg != PC ? bytedispdef : bytereldef;
105 case 12:
106 return usesreg != PC ? worddisp : wordrel;
107 case 13:
108 return usesreg != PC ? worddispdef : wordreldef;
109 case 14:
110 return usesreg != PC ? longdisp : longrel;
111 case 15:
112 return usesreg != PC ? longdispdef : longreldef;
114 /* NOTREACHED */
115 abort ();
118 static char *
119 vax_operandname (operandenum mode)
122 switch (mode)
124 case literal:
125 return "literal";
126 case indexed:
127 return "indexed";
128 case reg:
129 return "register";
130 case regdef:
131 return "register deferred";
132 case autodec:
133 return "autodecrement";
134 case autoinc:
135 return "autoincrement";
136 case autoincdef:
137 return "autoincrement deferred";
138 case bytedisp:
139 return "byte displacement";
140 case bytedispdef:
141 return "byte displacement deferred";
142 case byterel:
143 return "byte relative";
144 case bytereldef:
145 return "byte relative deferred";
146 case worddisp:
147 return "word displacement";
148 case worddispdef:
149 return "word displacement deferred";
150 case wordrel:
151 return "word relative";
152 case wordreldef:
153 return "word relative deferred";
154 case immediate:
155 return "immediate";
156 case absolute:
157 return "absolute";
158 case longdisp:
159 return "long displacement";
160 case longdispdef:
161 return "long displacement deferred";
162 case longrel:
163 return "long relative";
164 case longreldef:
165 return "long relative deferred";
167 /* NOTREACHED */
168 abort ();
171 static long
172 vax_operandlength (unsigned char *modep)
175 switch (vax_operandmode (modep))
177 case literal:
178 case reg:
179 case regdef:
180 case autodec:
181 case autoinc:
182 case autoincdef:
183 return 1;
184 case bytedisp:
185 case bytedispdef:
186 case byterel:
187 case bytereldef:
188 return 2;
189 case worddisp:
190 case worddispdef:
191 case wordrel:
192 case wordreldef:
193 return 3;
194 case immediate:
195 case absolute:
196 case longdisp:
197 case longdispdef:
198 case longrel:
199 case longreldef:
200 return 5;
201 case indexed:
202 return 1 + vax_operandlength (modep + 1);
204 /* NOTREACHED */
205 abort ();
208 static bfd_signed_vma
209 vax_offset (unsigned char *modep)
211 operandenum mode = vax_operandmode (modep);
213 ++modep; /* skip over the mode */
214 switch (mode)
216 default:
217 fprintf (stderr, "[reladdr] not relative address\n");
218 return 0;
219 case byterel:
220 return 1 + bfd_get_signed_8 (core_bfd, modep);
221 case wordrel:
222 return 2 + bfd_get_signed_16 (core_bfd, modep);
223 case longrel:
224 return 4 + bfd_get_signed_32 (core_bfd, modep);
229 void
230 vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
232 unsigned char *instructp;
233 long length;
234 Sym *child;
235 operandenum mode;
236 operandenum firstmode;
237 bfd_vma pc, destpc;
238 static bfd_boolean inited = FALSE;
240 if (!inited)
242 inited = TRUE;
243 sym_init (&indirectchild);
244 indirectchild.cg.prop.fract = 1.0;
245 indirectchild.cg.cyc.head = &indirectchild;
248 if (core_text_space == 0)
250 return;
252 if (p_lowpc < s_lowpc)
254 p_lowpc = s_lowpc;
256 if (p_highpc > s_highpc)
258 p_highpc = s_highpc;
260 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
261 parent->name, (unsigned long) p_lowpc,
262 (unsigned long) p_highpc));
263 for (pc = p_lowpc; pc < p_highpc; pc += length)
265 length = 1;
266 instructp = ((unsigned char *) core_text_space
267 + pc - core_text_sect->vma);
268 if ((*instructp & 0xff) == CALLS)
271 * maybe a calls, better check it out.
272 * skip the count of the number of arguments.
274 DBG (CALLDEBUG,
275 printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
276 firstmode = vax_operandmode (instructp + length);
277 switch (firstmode)
279 case literal:
280 case immediate:
281 break;
282 default:
283 goto botched;
285 length += vax_operandlength (instructp + length);
286 mode = vax_operandmode (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 (instructp + length);
309 continue;
310 case byterel:
311 case wordrel:
312 case longrel:
314 * regular pc relative addressing
315 * check that this is the address of
316 * a function.
318 destpc = pc + vax_offset (instructp + length);
319 if (destpc >= s_lowpc && destpc <= s_highpc)
321 child = sym_lookup (&symtab, destpc);
322 DBG (CALLDEBUG,
323 printf ("[findcall]\tdestpc 0x%lx",
324 (unsigned long) destpc);
325 printf (" child->name %s", child->name);
326 printf (" child->addr 0x%lx\n",
327 (unsigned long) child->addr);
329 if (child->addr == destpc)
332 * a hit
334 arc_add (parent, child, (unsigned long) 0);
335 length += vax_operandlength (instructp + length);
336 continue;
338 goto botched;
341 * else:
342 * it looked like a calls,
343 * but it wasn't to anywhere.
345 goto botched;
346 default:
347 botched:
349 * something funny going on.
351 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
352 length = 1;
353 continue;