2 * Copyright (c) 1983, 2001 Regents of the University of California.
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.
26 * opcode of the `calls' instruction
31 * register for pc relative addressing
37 literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
38 bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
39 immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
42 typedef enum opermodes operandenum;
46 unsigned int regfield:4;
47 unsigned int modefield:4;
51 * A symbol to be the child of indirect calls:
57 vax_operandmode (modep)
58 struct modebyte *modep;
60 long usesreg = modep->regfield;
62 switch (modep->modefield)
78 return usesreg != PC ? autoinc : immediate;
80 return usesreg != PC ? autoincdef : absolute;
82 return usesreg != PC ? bytedisp : byterel;
84 return usesreg != PC ? bytedispdef : bytereldef;
86 return usesreg != PC ? worddisp : wordrel;
88 return usesreg != PC ? worddispdef : wordreldef;
90 return usesreg != PC ? longdisp : longrel;
92 return usesreg != PC ? longdispdef : longreldef;
99 vax_operandname (mode)
112 return "register deferred";
114 return "autodecrement";
116 return "autoincrement";
118 return "autoincrement deferred";
120 return "byte displacement";
122 return "byte displacement deferred";
124 return "byte relative";
126 return "byte relative deferred";
128 return "word displacement";
130 return "word displacement deferred";
132 return "word relative";
134 return "word relative deferred";
140 return "long displacement";
142 return "long displacement deferred";
144 return "long relative";
146 return "long relative deferred";
153 vax_operandlength (modep)
154 struct modebyte *modep;
157 switch (vax_operandmode (modep))
184 return 1 + vax_operandlength ((struct modebyte *) ((char *) modep) + 1);
192 struct modebyte *modep;
194 operandenum mode = vax_operandmode (modep);
200 ++cp; /* skip over the mode */
204 fprintf (stderr, "[reladdr] not relative address\n");
205 return (bfd_vma) modep;
207 return (bfd_vma) (cp + sizeof *cp + *cp);
210 return (bfd_vma) (cp + sizeof *sp + *sp);
213 return (bfd_vma) (cp + sizeof *lp + *lp);
219 vax_find_call (parent, p_lowpc, p_highpc)
224 unsigned char *instructp;
228 operandenum firstmode;
230 static bool inited = FALSE;
235 sym_init (&indirectchild);
236 indirectchild.cg.prop.fract = 1.0;
237 indirectchild.cg.cyc.head = &indirectchild;
240 if (core_text_space == 0)
244 if (p_lowpc < s_lowpc)
248 if (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;
260 if (*instructp == CALLS)
263 * maybe a calls, better check it out.
264 * skip the count of the number of arguments.
267 printf ("[findcall]\t0x%lx:calls",
269 (instructp - (unsigned char *) core_text_space))));
270 firstmode = vax_operandmode ((struct modebyte *) (instructp + length));
279 length += vax_operandlength ((struct modebyte *) (instructp + length));
280 mode = vax_operandmode ((struct modebyte *) (instructp + length));
282 printf ("\tfirst operand is %s", vax_operandname (firstmode));
283 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
294 * indirect call: call through pointer
295 * either *d(r) as a parameter or local
296 * (r) as a return value
297 * *f as a global pointer
298 * [are there others that we miss?,
299 * e.g. arrays of pointers to functions???]
301 arc_add (parent, &indirectchild, (unsigned long) 0);
302 length += vax_operandlength (
303 (struct modebyte *) (instructp + length));
309 * regular pc relative addressing
310 * check that this is the address of
313 destpc = vax_reladdr ((struct modebyte *) (instructp + length))
314 - (bfd_vma) core_text_space;
315 if (destpc >= s_lowpc && destpc <= s_highpc)
317 child = sym_lookup (&symtab, destpc);
319 printf ("[findcall]\tdestpc 0x%lx",
320 (unsigned long) destpc);
321 printf (" child->name %s", child->name);
322 printf (" child->addr 0x%lx\n",
323 (unsigned long) child->addr);
325 if (child->addr == destpc)
330 arc_add (parent, child, (unsigned long) 0);
331 length += vax_operandlength ((struct modebyte *)
332 (instructp + length));
339 * it looked like a calls,
340 * but it wasn't to anywhere.
346 * something funny going on.
348 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));