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.
20 #include "search_list.h"
28 * opcode of the `calls' instruction
33 * register for pc relative addressing
39 literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
40 bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
41 immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
44 typedef enum opermodes operandenum;
47 /* Here to document only. We can't use this when cross compiling as
48 the bitfield layout might not be the same as native. */
51 unsigned int regfield:4;
52 unsigned int modefield:4;
57 * A symbol to be the child of indirect calls:
59 static Sym indirectchild;
61 static operandenum vax_operandmode PARAMS ((unsigned char *));
62 static char *vax_operandname PARAMS ((operandenum));
63 static long vax_operandlength PARAMS ((unsigned char *));
64 static bfd_signed_vma vax_offset PARAMS ((unsigned char *));
65 void vax_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
68 vax_operandmode (modep)
71 int usesreg = *modep & 0xf;
73 switch ((*modep >> 4) & 0xf)
89 return usesreg != PC ? autoinc : immediate;
91 return usesreg != PC ? autoincdef : absolute;
93 return usesreg != PC ? bytedisp : byterel;
95 return usesreg != PC ? bytedispdef : bytereldef;
97 return usesreg != PC ? worddisp : wordrel;
99 return usesreg != PC ? worddispdef : wordreldef;
101 return usesreg != PC ? longdisp : longrel;
103 return usesreg != PC ? longdispdef : longreldef;
110 vax_operandname (mode)
123 return "register deferred";
125 return "autodecrement";
127 return "autoincrement";
129 return "autoincrement deferred";
131 return "byte displacement";
133 return "byte displacement deferred";
135 return "byte relative";
137 return "byte relative deferred";
139 return "word displacement";
141 return "word displacement deferred";
143 return "word relative";
145 return "word relative deferred";
151 return "long displacement";
153 return "long displacement deferred";
155 return "long relative";
157 return "long relative deferred";
164 vax_operandlength (modep)
165 unsigned char *modep;
168 switch (vax_operandmode (modep))
195 return 1 + vax_operandlength (modep + 1);
201 static bfd_signed_vma
203 unsigned char *modep;
205 operandenum mode = vax_operandmode (modep);
207 ++modep; /* skip over the mode */
211 fprintf (stderr, "[reladdr] not relative address\n");
214 return 1 + bfd_get_signed_8 (core_bfd, modep);
216 return 2 + bfd_get_signed_16 (core_bfd, modep);
218 return 4 + bfd_get_signed_32 (core_bfd, modep);
224 vax_find_call (parent, p_lowpc, p_highpc)
229 unsigned char *instructp;
233 operandenum firstmode;
235 static boolean inited = false;
240 sym_init (&indirectchild);
241 indirectchild.cg.prop.fract = 1.0;
242 indirectchild.cg.cyc.head = &indirectchild;
245 if (core_text_space == 0)
249 if (p_lowpc < s_lowpc)
253 if (p_highpc > s_highpc)
257 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
258 parent->name, (unsigned long) p_lowpc,
259 (unsigned long) p_highpc));
260 for (pc = p_lowpc; pc < p_highpc; pc += length)
263 instructp = ((unsigned char *) core_text_space
264 + pc - core_text_sect->vma);
265 if ((*instructp & 0xff) == CALLS)
268 * maybe a calls, better check it out.
269 * skip the count of the number of arguments.
272 printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
273 firstmode = vax_operandmode (instructp + length);
282 length += vax_operandlength (instructp + length);
283 mode = vax_operandmode (instructp + length);
285 printf ("\tfirst operand is %s", vax_operandname (firstmode));
286 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
297 * indirect call: call through pointer
298 * either *d(r) as a parameter or local
299 * (r) as a return value
300 * *f as a global pointer
301 * [are there others that we miss?,
302 * e.g. arrays of pointers to functions???]
304 arc_add (parent, &indirectchild, (unsigned long) 0);
305 length += vax_operandlength (instructp + length);
311 * regular pc relative addressing
312 * check that this is the address of
315 destpc = pc + vax_offset (instructp + length);
316 if (destpc >= s_lowpc && destpc <= s_highpc)
318 child = sym_lookup (&symtab, destpc);
320 printf ("[findcall]\tdestpc 0x%lx",
321 (unsigned long) destpc);
322 printf (" child->name %s", child->name);
323 printf (" child->addr 0x%lx\n",
324 (unsigned long) child->addr);
326 if (child->addr == destpc)
331 arc_add (parent, child, (unsigned long) 0);
332 length += vax_operandlength (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"));