Replace 'return false' with a return of a bfd_reloc_ error code.
[deliverable/binutils-gdb.git] / gprof / vax.c
CommitLineData
252b5132 1/*
0eee5820 2 * Copyright (c) 1983, 2001 Regents of the University of California.
252b5132
RH
3 * All rights reserved.
4 *
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.
18 */
19#include "gprof.h"
20#include "cg_arcs.h"
21#include "corefile.h"
22#include "hist.h"
23#include "symtab.h"
24
25 /*
26 * opcode of the `calls' instruction
27 */
28#define CALLS 0xfb
29
30 /*
31 * register for pc relative addressing
32 */
33#define PC 0xf
34
35enum opermodes
36 {
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
41 };
42typedef enum opermodes operandenum;
43
44struct modebyte
45 {
46 unsigned int regfield:4;
47 unsigned int modefield:4;
48 };
49
50/*
51 * A symbol to be the child of indirect calls:
52 */
3b04e729 53static Sym indirectchild;
252b5132 54
5789ecea
AM
55static operandenum vax_operandmode PARAMS ((struct modebyte *));
56static char *vax_operandname PARAMS ((operandenum));
57static long vax_operandlength PARAMS ((struct modebyte *));
58static bfd_vma vax_reladdr PARAMS ((struct modebyte *));
59void vax_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
60
252b5132
RH
61static operandenum
62vax_operandmode (modep)
63 struct modebyte *modep;
64{
65 long usesreg = modep->regfield;
66
67 switch (modep->modefield)
68 {
69 case 0:
70 case 1:
71 case 2:
72 case 3:
73 return literal;
74 case 4:
75 return indexed;
76 case 5:
77 return reg;
78 case 6:
79 return regdef;
80 case 7:
81 return autodec;
82 case 8:
83 return usesreg != PC ? autoinc : immediate;
84 case 9:
85 return usesreg != PC ? autoincdef : absolute;
86 case 10:
87 return usesreg != PC ? bytedisp : byterel;
88 case 11:
89 return usesreg != PC ? bytedispdef : bytereldef;
90 case 12:
91 return usesreg != PC ? worddisp : wordrel;
92 case 13:
93 return usesreg != PC ? worddispdef : wordreldef;
94 case 14:
95 return usesreg != PC ? longdisp : longrel;
96 case 15:
97 return usesreg != PC ? longdispdef : longreldef;
98 }
99 /* NOTREACHED */
100 abort ();
101}
102
103static char *
104vax_operandname (mode)
105 operandenum mode;
106{
107
108 switch (mode)
109 {
110 case literal:
111 return "literal";
112 case indexed:
113 return "indexed";
114 case reg:
115 return "register";
116 case regdef:
117 return "register deferred";
118 case autodec:
119 return "autodecrement";
120 case autoinc:
121 return "autoincrement";
122 case autoincdef:
123 return "autoincrement deferred";
124 case bytedisp:
125 return "byte displacement";
126 case bytedispdef:
127 return "byte displacement deferred";
128 case byterel:
129 return "byte relative";
130 case bytereldef:
131 return "byte relative deferred";
132 case worddisp:
133 return "word displacement";
134 case worddispdef:
135 return "word displacement deferred";
136 case wordrel:
137 return "word relative";
138 case wordreldef:
139 return "word relative deferred";
140 case immediate:
141 return "immediate";
142 case absolute:
143 return "absolute";
144 case longdisp:
145 return "long displacement";
146 case longdispdef:
147 return "long displacement deferred";
148 case longrel:
149 return "long relative";
150 case longreldef:
151 return "long relative deferred";
152 }
153 /* NOTREACHED */
154 abort ();
155}
156
157static long
158vax_operandlength (modep)
159 struct modebyte *modep;
160{
161
162 switch (vax_operandmode (modep))
163 {
164 case literal:
165 case reg:
166 case regdef:
167 case autodec:
168 case autoinc:
169 case autoincdef:
170 return 1;
171 case bytedisp:
172 case bytedispdef:
173 case byterel:
174 case bytereldef:
175 return 2;
176 case worddisp:
177 case worddispdef:
178 case wordrel:
179 case wordreldef:
180 return 3;
181 case immediate:
182 case absolute:
183 case longdisp:
184 case longdispdef:
185 case longrel:
186 case longreldef:
187 return 5;
188 case indexed:
189 return 1 + vax_operandlength ((struct modebyte *) ((char *) modep) + 1);
190 }
191 /* NOTREACHED */
192 abort ();
193}
194
195static bfd_vma
196vax_reladdr (modep)
197 struct modebyte *modep;
198{
199 operandenum mode = vax_operandmode (modep);
200 char *cp;
201 short *sp;
202 long *lp;
203
204 cp = (char *) modep;
205 ++cp; /* skip over the mode */
206 switch (mode)
207 {
208 default:
209 fprintf (stderr, "[reladdr] not relative address\n");
210 return (bfd_vma) modep;
211 case byterel:
212 return (bfd_vma) (cp + sizeof *cp + *cp);
213 case wordrel:
214 sp = (short *) cp;
215 return (bfd_vma) (cp + sizeof *sp + *sp);
216 case longrel:
217 lp = (long *) cp;
218 return (bfd_vma) (cp + sizeof *lp + *lp);
219 }
220}
221
222
223void
224vax_find_call (parent, p_lowpc, p_highpc)
225 Sym *parent;
226 bfd_vma p_lowpc;
227 bfd_vma p_highpc;
228{
229 unsigned char *instructp;
230 long length;
231 Sym *child;
232 operandenum mode;
233 operandenum firstmode;
234 bfd_vma destpc;
235 static bool inited = FALSE;
236
237 if (!inited)
238 {
239 inited = TRUE;
240 sym_init (&indirectchild);
241 indirectchild.cg.prop.fract = 1.0;
242 indirectchild.cg.cyc.head = &indirectchild;
243 }
244
245 if (core_text_space == 0)
246 {
247 return;
248 }
249 if (p_lowpc < s_lowpc)
250 {
251 p_lowpc = s_lowpc;
252 }
253 if (p_highpc > s_highpc)
254 {
255 p_highpc = s_highpc;
256 }
257 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
fdcf7d43
ILT
258 parent->name, (unsigned long) p_lowpc,
259 (unsigned long) p_highpc));
252b5132
RH
260 for (instructp = (unsigned char *) core_text_space + p_lowpc;
261 instructp < (unsigned char *) core_text_space + p_highpc;
262 instructp += length)
263 {
264 length = 1;
265 if (*instructp == CALLS)
266 {
267 /*
268 * maybe a calls, better check it out.
269 * skip the count of the number of arguments.
270 */
271 DBG (CALLDEBUG,
0e69fcbc
ILT
272 printf ("[findcall]\t0x%lx:calls",
273 ((unsigned long)
274 (instructp - (unsigned char *) core_text_space))));
252b5132
RH
275 firstmode = vax_operandmode ((struct modebyte *) (instructp + length));
276 switch (firstmode)
277 {
278 case literal:
279 case immediate:
280 break;
281 default:
282 goto botched;
283 }
284 length += vax_operandlength ((struct modebyte *) (instructp + length));
285 mode = vax_operandmode ((struct modebyte *) (instructp + length));
286 DBG (CALLDEBUG,
287 printf ("\tfirst operand is %s", vax_operandname (firstmode));
288 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
289 switch (mode)
290 {
291 case regdef:
292 case bytedispdef:
293 case worddispdef:
294 case longdispdef:
295 case bytereldef:
296 case wordreldef:
297 case longreldef:
298 /*
299 * indirect call: call through pointer
300 * either *d(r) as a parameter or local
301 * (r) as a return value
302 * *f as a global pointer
303 * [are there others that we miss?,
304 * e.g. arrays of pointers to functions???]
305 */
306 arc_add (parent, &indirectchild, (unsigned long) 0);
307 length += vax_operandlength (
308 (struct modebyte *) (instructp + length));
309 continue;
310 case byterel:
311 case wordrel:
312 case longrel:
313 /*
314 * regular pc relative addressing
0eee5820 315 * check that this is the address of
252b5132
RH
316 * a function.
317 */
318 destpc = vax_reladdr ((struct modebyte *) (instructp + length))
319 - (bfd_vma) core_text_space;
320 if (destpc >= s_lowpc && destpc <= s_highpc)
321 {
322 child = sym_lookup (&symtab, destpc);
323 DBG (CALLDEBUG,
fdcf7d43
ILT
324 printf ("[findcall]\tdestpc 0x%lx",
325 (unsigned long) destpc);
252b5132 326 printf (" child->name %s", child->name);
fdcf7d43
ILT
327 printf (" child->addr 0x%lx\n",
328 (unsigned long) child->addr);
252b5132
RH
329 );
330 if (child->addr == destpc)
331 {
332 /*
333 * a hit
334 */
335 arc_add (parent, child, (unsigned long) 0);
336 length += vax_operandlength ((struct modebyte *)
337 (instructp + length));
338 continue;
339 }
340 goto botched;
341 }
342 /*
343 * else:
344 * it looked like a calls,
345 * but it wasn't to anywhere.
346 */
347 goto botched;
348 default:
349 botched:
350 /*
351 * something funny going on.
352 */
353 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
354 length = 1;
355 continue;
356 }
357 }
358 }
359}
This page took 0.106779 seconds and 4 git commands to generate.