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, (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%x:calls",
268 instructp - (unsigned char *) core_text_space));
269 firstmode = vax_operandmode ((struct modebyte *) (instructp + length));
278 length += vax_operandlength ((struct modebyte *) (instructp + length));
279 mode = vax_operandmode ((struct modebyte *) (instructp + length));
281 printf ("\tfirst operand is %s", vax_operandname (firstmode));
282 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
293 * indirect call: call through pointer
294 * either *d(r) as a parameter or local
295 * (r) as a return value
296 * *f as a global pointer
297 * [are there others that we miss?,
298 * e.g. arrays of pointers to functions???]
300 arc_add (parent, &indirectchild, (unsigned long) 0);
301 length += vax_operandlength (
302 (struct modebyte *) (instructp + length));
308 * regular pc relative addressing
309 * check that this is the address of
312 destpc = vax_reladdr ((struct modebyte *) (instructp + length))
313 - (bfd_vma) core_text_space;
314 if (destpc >= s_lowpc && destpc <= s_highpc)
316 child = sym_lookup (&symtab, destpc);
318 printf ("[findcall]\tdestpc 0x%lx",
319 (unsigned long) destpc);
320 printf (" child->name %s", child->name);
321 printf (" child->addr 0x%lx\n",
322 (unsigned long) child->addr);
324 if (child->addr == destpc)
329 arc_add (parent, child, (unsigned long) 0);
330 length += vax_operandlength ((struct modebyte *)
331 (instructp + length));
338 * it looked like a calls,
339 * but it wasn't to anywhere.
345 * something funny going on.
347 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));