2 * Copyright (c) 1983 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, p_lowpc, p_highpc));
254 for (instructp = (unsigned char *) core_text_space + p_lowpc;
255 instructp < (unsigned char *) core_text_space + p_highpc;
259 if (*instructp == CALLS)
262 * maybe a calls, better check it out.
263 * skip the count of the number of arguments.
266 printf ("[findcall]\t0x%x:calls",
267 instructp - (unsigned char *) core_text_space));
268 firstmode = vax_operandmode ((struct modebyte *) (instructp + length));
277 length += vax_operandlength ((struct modebyte *) (instructp + length));
278 mode = vax_operandmode ((struct modebyte *) (instructp + length));
280 printf ("\tfirst operand is %s", vax_operandname (firstmode));
281 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
292 * indirect call: call through pointer
293 * either *d(r) as a parameter or local
294 * (r) as a return value
295 * *f as a global pointer
296 * [are there others that we miss?,
297 * e.g. arrays of pointers to functions???]
299 arc_add (parent, &indirectchild, (unsigned long) 0);
300 length += vax_operandlength (
301 (struct modebyte *) (instructp + length));
307 * regular pc relative addressing
308 * check that this is the address of
311 destpc = vax_reladdr ((struct modebyte *) (instructp + length))
312 - (bfd_vma) core_text_space;
313 if (destpc >= s_lowpc && destpc <= s_highpc)
315 child = sym_lookup (&symtab, destpc);
317 printf ("[findcall]\tdestpc 0x%lx", destpc);
318 printf (" child->name %s", child->name);
319 printf (" child->addr 0x%lx\n", child->addr);
321 if (child->addr == destpc)
326 arc_add (parent, child, (unsigned long) 0);
327 length += vax_operandlength ((struct modebyte *)
328 (instructp + length));
335 * it looked like a calls,
336 * but it wasn't to anywhere.
342 * something funny going on.
344 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));