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:
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));
63 vax_operandmode (modep)
64 struct modebyte *modep;
66 long usesreg = modep->regfield;
68 switch (modep->modefield)
84 return usesreg != PC ? autoinc : immediate;
86 return usesreg != PC ? autoincdef : absolute;
88 return usesreg != PC ? bytedisp : byterel;
90 return usesreg != PC ? bytedispdef : bytereldef;
92 return usesreg != PC ? worddisp : wordrel;
94 return usesreg != PC ? worddispdef : wordreldef;
96 return usesreg != PC ? longdisp : longrel;
98 return usesreg != PC ? longdispdef : longreldef;
105 vax_operandname (mode)
118 return "register deferred";
120 return "autodecrement";
122 return "autoincrement";
124 return "autoincrement deferred";
126 return "byte displacement";
128 return "byte displacement deferred";
130 return "byte relative";
132 return "byte relative deferred";
134 return "word displacement";
136 return "word displacement deferred";
138 return "word relative";
140 return "word relative deferred";
146 return "long displacement";
148 return "long displacement deferred";
150 return "long relative";
152 return "long relative deferred";
159 vax_operandlength (modep)
160 struct modebyte *modep;
163 switch (vax_operandmode (modep))
190 return 1 + vax_operandlength ((struct modebyte *) ((char *) modep) + 1);
198 struct modebyte *modep;
200 operandenum mode = vax_operandmode (modep);
206 ++cp; /* skip over the mode */
210 fprintf (stderr, "[reladdr] not relative address\n");
211 return (bfd_vma) modep;
213 return (bfd_vma) (cp + sizeof *cp + *cp);
216 return (bfd_vma) (cp + sizeof *sp + *sp);
219 return (bfd_vma) (cp + sizeof *lp + *lp);
225 vax_find_call (parent, p_lowpc, p_highpc)
230 unsigned char *instructp;
234 operandenum firstmode;
236 static bool inited = FALSE;
241 sym_init (&indirectchild);
242 indirectchild.cg.prop.fract = 1.0;
243 indirectchild.cg.cyc.head = &indirectchild;
246 if (core_text_space == 0)
250 if (p_lowpc < s_lowpc)
254 if (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;
266 if (*instructp == CALLS)
269 * maybe a calls, better check it out.
270 * skip the count of the number of arguments.
273 printf ("[findcall]\t0x%lx:calls",
275 (instructp - (unsigned char *) core_text_space))));
276 firstmode = vax_operandmode ((struct modebyte *) (instructp + length));
285 length += vax_operandlength ((struct modebyte *) (instructp + length));
286 mode = vax_operandmode ((struct modebyte *) (instructp + length));
288 printf ("\tfirst operand is %s", vax_operandname (firstmode));
289 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
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));
315 * regular pc relative addressing
316 * check that this is the address of
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);
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)
336 arc_add (parent, child, (unsigned long) 0);
337 length += vax_operandlength ((struct modebyte *)
338 (instructp + length));
345 * it looked like a calls,
346 * but it wasn't to anywhere.
352 * something funny going on.
354 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));