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 `callf' 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 tahoe_opermodes tahoe_operandenum;
47 * A symbol to be the child of indirect callf:
49 static Sym indirectchild;
51 static tahoe_operandenum tahoe_operandmode PARAMS ((unsigned char *));
52 static char *tahoe_operandname PARAMS ((tahoe_operandenum));
53 static long tahoe_operandlength PARAMS ((unsigned char *));
54 static bfd_signed_vma tahoe_offset PARAMS ((unsigned char *));
55 void tahoe_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
57 static tahoe_operandenum
58 tahoe_operandmode (modep)
61 long usesreg = *modep & 0xf;
63 switch ((*modep >> 4) & 0xf)
79 return usesreg != 0xe ? autoinc : immediate;
81 return usesreg != PC ? autoincdef : absolute;
83 return usesreg != PC ? bytedisp : byterel;
85 return usesreg != PC ? bytedispdef : bytereldef;
87 return usesreg != PC ? worddisp : wordrel;
89 return usesreg != PC ? worddispdef : wordreldef;
91 return usesreg != PC ? longdisp : longrel;
93 return usesreg != PC ? longdispdef : longreldef;
100 tahoe_operandname (mode)
101 tahoe_operandenum mode;
113 return "register deferred";
115 return "autodecrement";
117 return "autoincrement";
119 return "autoincrement deferred";
121 return "byte displacement";
123 return "byte displacement deferred";
125 return "byte relative";
127 return "byte relative deferred";
129 return "word displacement";
131 return "word displacement deferred";
133 return "word relative";
135 return "word relative deferred";
141 return "long displacement";
143 return "long displacement deferred";
145 return "long relative";
147 return "long relative deferred";
154 tahoe_operandlength (modep)
155 unsigned char *modep;
158 switch (tahoe_operandmode (modep))
185 return 1 + tahoe_operandlength (modep + 1);
191 static bfd_signed_vma
193 unsigned char *modep;
195 tahoe_operandenum mode = tahoe_operandmode (modep);
197 ++modep; /* skip over the mode */
201 fprintf (stderr, "[reladdr] not relative address\n");
204 return 1 + bfd_get_signed_8 (core_bfd, modep);
206 return 2 + bfd_get_signed_16 (core_bfd, modep);
208 return 4 + bfd_get_signed_32 (core_bfd, modep);
213 tahoe_find_call (parent, p_lowpc, p_highpc)
218 unsigned char *instructp;
221 tahoe_operandenum mode;
222 tahoe_operandenum firstmode;
224 static bool inited = FALSE;
229 sym_init (&indirectchild);
230 indirectchild.cg.prop.fract = 1.0;
231 indirectchild.cg.cyc.head = &indirectchild;
234 if (core_text_space == 0)
238 if (p_lowpc < s_lowpc)
242 if (p_highpc > s_highpc)
246 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
247 parent->name, (unsigned long) p_lowpc,
248 (unsigned long) p_highpc));
249 for (pc = p_lowpc; pc < p_highpc; pc += length)
252 instructp = ((unsigned char *) core_text_space
253 + pc - core_text_sect->vma);
254 if ((*instructp & 0xff) == CALLF)
257 * maybe a callf, better check it out.
258 * skip the count of the number of arguments.
260 DBG (CALLDEBUG, printf ("[findcall]\t0x%lx:callf",
261 (unsigned long) pc));
262 firstmode = tahoe_operandmode (instructp + length);
271 length += tahoe_operandlength (instructp + length);
272 mode = tahoe_operandmode (instructp + length);
274 printf ("\tfirst operand is %s", tahoe_operandname (firstmode));
275 printf ("\tsecond operand is %s\n", tahoe_operandname (mode));
287 * indirect call: call through pointer
288 * either *d(r) as a parameter or local
289 * (r) as a return value
290 * *f as a global pointer
291 * [are there others that we miss?,
292 * e.g. arrays of pointers to functions???]
294 arc_add (parent, &indirectchild, (unsigned long) 0);
295 length += tahoe_operandlength (instructp + length);
301 * regular pc relative addressing
302 * check that this is the address of
305 destpc = pc + tahoe_offset (instructp + length);
306 if (destpc >= s_lowpc && destpc <= s_highpc)
308 child = sym_lookup (&symtab, destpc);
310 printf ("[findcall]\tdestpc 0x%lx",
311 (unsigned long) destpc);
312 printf (" child->name %s", child->name);
313 printf (" child->addr 0x%lx\n",
314 (unsigned long) child->addr);
316 if (child->addr == destpc)
321 arc_add (parent, child, (unsigned long) 0);
322 length += tahoe_operandlength (instructp + length);
329 * it looked like a callf,
330 * but it wasn't to anywhere.
336 * something funny going on.
338 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));