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 `callf' 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 tahoe_opermodes tahoe_operandenum;
45 * A symbol to be the child of indirect callf:
47 static Sym indirectchild;
49 static tahoe_operandenum tahoe_operandmode PARAMS ((unsigned char *));
50 static char *tahoe_operandname PARAMS ((tahoe_operandenum));
51 static long tahoe_operandlength PARAMS ((unsigned char *));
52 static bfd_vma tahoe_reladdr PARAMS ((char *));
53 void tahoe_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
55 static tahoe_operandenum
56 tahoe_operandmode (modep)
59 long usesreg = ((long) *modep) & 0xf;
61 switch (((long) *modep) >> 4)
77 return usesreg != 0xe ? autoinc : immediate;
79 return usesreg != PC ? autoincdef : absolute;
81 return usesreg != PC ? bytedisp : byterel;
83 return usesreg != PC ? bytedispdef : bytereldef;
85 return usesreg != PC ? worddisp : wordrel;
87 return usesreg != PC ? worddispdef : wordreldef;
89 return usesreg != PC ? longdisp : longrel;
91 return usesreg != PC ? longdispdef : longreldef;
98 tahoe_operandname (mode)
99 tahoe_operandenum mode;
111 return "register deferred";
113 return "autodecrement";
115 return "autoincrement";
117 return "autoincrement deferred";
119 return "byte displacement";
121 return "byte displacement deferred";
123 return "byte relative";
125 return "byte relative deferred";
127 return "word displacement";
129 return "word displacement deferred";
131 return "word relative";
133 return "word relative deferred";
139 return "long displacement";
141 return "long displacement deferred";
143 return "long relative";
145 return "long relative deferred";
152 tahoe_operandlength (modep)
153 unsigned char *modep;
156 switch (tahoe_operandmode (modep))
183 return 1 + tahoe_operandlength (modep + 1);
190 tahoe_reladdr (modep)
193 tahoe_operandenum mode = tahoe_operandmode (modep);
201 ++cp; /* skip over the mode */
205 fprintf (stderr, "[reladdr] not relative address\n");
206 return (bfd_vma) modep;
208 return (bfd_vma) (cp + sizeof *cp + *cp);
210 for (i = 0; (size_t) i < sizeof *sp; i++)
211 value = (value << 8) + (cp[i] & 0xff);
212 return (bfd_vma) (cp + sizeof *sp + value);
214 for (i = 0; (size_t) i < sizeof *lp; i++)
215 value = (value << 8) + (cp[i] & 0xff);
216 return (bfd_vma) (cp + sizeof *lp + value);
221 tahoe_find_call (parent, p_lowpc, p_highpc)
226 unsigned char *instructp;
229 tahoe_operandenum mode;
230 tahoe_operandenum firstmode;
232 static bool inited = FALSE;
237 sym_init (&indirectchild);
238 indirectchild.cg.prop.fract = 1.0;
239 indirectchild.cg.cyc.head = &indirectchild;
242 if (core_text_space == 0)
246 if (p_lowpc < s_lowpc)
250 if (p_highpc > s_highpc)
254 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
255 parent->name, (unsigned long) p_lowpc,
256 (unsigned long) p_highpc));
257 for (instructp = (unsigned char *) core_text_space + p_lowpc;
258 instructp < (unsigned char *) core_text_space + p_highpc;
262 if (*instructp == CALLF)
265 * maybe a callf, better check it out.
266 * skip the count of the number of arguments.
268 DBG (CALLDEBUG, printf ("[findcall]\t0x%lx:callf",
271 - (unsigned char *) core_text_space))));
272 firstmode = tahoe_operandmode (instructp + length);
281 length += tahoe_operandlength (instructp + length);
282 mode = tahoe_operandmode (instructp + length);
284 printf ("\tfirst operand is %s", tahoe_operandname (firstmode));
285 printf ("\tsecond operand is %s\n", tahoe_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 += tahoe_operandlength (instructp + length);
311 * regular pc relative addressing
312 * check that this is the address of
315 destpc = tahoe_reladdr (instructp + length)
316 - (bfd_vma) core_text_space;
317 if (destpc >= s_lowpc && destpc <= s_highpc)
319 child = sym_lookup (&symtab, destpc);
321 printf ("[findcall]\tdestpc 0x%lx",
322 (unsigned long) destpc);
323 printf (" child->name %s", child->name);
324 printf (" child->addr 0x%lx\n",
325 (unsigned long) child->addr);
327 if (child->addr == destpc)
332 arc_add (parent, child, (unsigned long) 0);
333 length += tahoe_operandlength (instructp + length);
340 * it looked like a callf,
341 * but it wasn't to anywhere.
347 * something funny going on.
349 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));