Automatic date update in version.in
[binutils-gdb.git] / gprof / vax.c
blobfafe2b17b53e6c2def76149b428ae1eb1b74b850
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 /* *INDENT-OFF* */
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.
60 struct modebyte
62 unsigned int regfield:4;
63 unsigned int modefield:4;
66 /* *INDENT-ON* */
69 * A symbol to be the child of indirect calls:
71 static Sym indirectchild;
73 static operandenum vax_operandmode (unsigned char *);
74 static char *vax_operandname (operandenum);
75 static long vax_operandlength (unsigned char *);
76 static bfd_signed_vma vax_offset (unsigned char *);
77 void vax_find_call (Sym *, bfd_vma, bfd_vma);
79 static operandenum
80 vax_operandmode (unsigned char *modep)
82 int usesreg = *modep & 0xf;
84 switch ((*modep >> 4) & 0xf)
86 case 0:
87 case 1:
88 case 2:
89 case 3:
90 return literal;
91 case 4:
92 return indexed;
93 case 5:
94 return reg;
95 case 6:
96 return regdef;
97 case 7:
98 return autodec;
99 case 8:
100 return usesreg != PC ? autoinc : immediate;
101 case 9:
102 return usesreg != PC ? autoincdef : absolute;
103 case 10:
104 return usesreg != PC ? bytedisp : byterel;
105 case 11:
106 return usesreg != PC ? bytedispdef : bytereldef;
107 case 12:
108 return usesreg != PC ? worddisp : wordrel;
109 case 13:
110 return usesreg != PC ? worddispdef : wordreldef;
111 case 14:
112 return usesreg != PC ? longdisp : longrel;
113 case 15:
114 return usesreg != PC ? longdispdef : longreldef;
116 /* NOTREACHED */
117 abort ();
120 static char *
121 vax_operandname (operandenum mode)
124 switch (mode)
126 case literal:
127 return "literal";
128 case indexed:
129 return "indexed";
130 case reg:
131 return "register";
132 case regdef:
133 return "register deferred";
134 case autodec:
135 return "autodecrement";
136 case autoinc:
137 return "autoincrement";
138 case autoincdef:
139 return "autoincrement deferred";
140 case bytedisp:
141 return "byte displacement";
142 case bytedispdef:
143 return "byte displacement deferred";
144 case byterel:
145 return "byte relative";
146 case bytereldef:
147 return "byte relative deferred";
148 case worddisp:
149 return "word displacement";
150 case worddispdef:
151 return "word displacement deferred";
152 case wordrel:
153 return "word relative";
154 case wordreldef:
155 return "word relative deferred";
156 case immediate:
157 return "immediate";
158 case absolute:
159 return "absolute";
160 case longdisp:
161 return "long displacement";
162 case longdispdef:
163 return "long displacement deferred";
164 case longrel:
165 return "long relative";
166 case longreldef:
167 return "long relative deferred";
169 /* NOTREACHED */
170 abort ();
173 static long
174 vax_operandlength (unsigned char *modep)
177 switch (vax_operandmode (modep))
179 case literal:
180 case reg:
181 case regdef:
182 case autodec:
183 case autoinc:
184 case autoincdef:
185 return 1;
186 case bytedisp:
187 case bytedispdef:
188 case byterel:
189 case bytereldef:
190 return 2;
191 case worddisp:
192 case worddispdef:
193 case wordrel:
194 case wordreldef:
195 return 3;
196 case immediate:
197 case absolute:
198 case longdisp:
199 case longdispdef:
200 case longrel:
201 case longreldef:
202 return 5;
203 case indexed:
204 return 1 + vax_operandlength (modep + 1);
206 /* NOTREACHED */
207 abort ();
210 static bfd_signed_vma
211 vax_offset (unsigned char *modep)
213 operandenum mode = vax_operandmode (modep);
215 ++modep; /* skip over the mode */
216 switch (mode)
218 default:
219 fprintf (stderr, "[reladdr] not relative address\n");
220 return 0;
221 case byterel:
222 return 1 + bfd_get_signed_8 (core_bfd, modep);
223 case wordrel:
224 return 2 + bfd_get_signed_16 (core_bfd, modep);
225 case longrel:
226 return 4 + bfd_get_signed_32 (core_bfd, modep);
231 void
232 vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
234 unsigned char *instructp;
235 long length;
236 Sym *child;
237 operandenum mode;
238 operandenum firstmode;
239 bfd_vma pc, destpc;
240 static bool inited = false;
242 if (!inited)
244 inited = true;
245 sym_init (&indirectchild);
246 indirectchild.cg.prop.fract = 1.0;
247 indirectchild.cg.cyc.head = &indirectchild;
250 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
251 parent->name, (unsigned long) p_lowpc,
252 (unsigned long) p_highpc));
253 for (pc = p_lowpc; pc < p_highpc; pc += length)
255 unsigned char *operand;
257 length = 1;
258 instructp = ((unsigned char *) core_text_space
259 + pc - core_text_sect->vma);
260 if ((*instructp & 0xff) == 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%lx:calls", (unsigned long) pc));
268 if (pc - core_text_sect->vma + length >= core_text_sect->size)
269 goto botched;
270 operand = instructp + length;
271 firstmode = vax_operandmode (operand);
272 switch (firstmode)
274 case literal:
275 case immediate:
276 break;
277 default:
278 goto botched;
280 length += vax_operandlength (operand);
281 if (pc - core_text_sect->vma + length >= core_text_sect->size)
282 goto botched;
283 operand = instructp + length;
284 mode = vax_operandmode (operand);
285 DBG (CALLDEBUG,
286 printf ("\tfirst operand is %s", vax_operandname (firstmode));
287 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
288 switch (mode)
290 case regdef:
291 case bytedispdef:
292 case worddispdef:
293 case longdispdef:
294 case bytereldef:
295 case wordreldef:
296 case longreldef:
298 * indirect call: call through pointer
299 * either *d(r) as a parameter or local
300 * (r) as a return value
301 * *f as a global pointer
302 * [are there others that we miss?,
303 * e.g. arrays of pointers to functions???]
305 length += vax_operandlength (operand);
306 if (pc - core_text_sect->vma + length > core_text_sect->size)
307 goto botched;
308 arc_add (parent, &indirectchild, (unsigned long) 0);
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 length += vax_operandlength (operand);
319 if (pc - core_text_sect->vma + length > core_text_sect->size)
320 goto botched;
321 destpc = pc + vax_offset (operand);
322 if (hist_check_address (destpc))
324 child = sym_lookup (&symtab, destpc);
325 if (child)
327 DBG (CALLDEBUG,
328 printf ("[findcall]\tdestpc 0x%lx",
329 (unsigned long) destpc);
330 printf (" child->name %s", child->name);
331 printf (" child->addr 0x%lx\n",
332 (unsigned long) child->addr);
334 if (child->addr == destpc)
337 * a hit
339 arc_add (parent, child, (unsigned long) 0);
340 continue;
343 goto botched;
346 * else:
347 * it looked like a calls,
348 * but it wasn't to anywhere.
350 goto botched;
351 default:
352 botched:
354 * something funny going on.
356 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
357 length = 1;
358 continue;