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 `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:
51 tahoe_operandmode (modep)
54 long usesreg = ((long) *modep) & 0xf;
56 switch (((long) *modep) >> 4)
72 return usesreg != 0xe ? autoinc : immediate;
74 return usesreg != PC ? autoincdef : absolute;
76 return usesreg != PC ? bytedisp : byterel;
78 return usesreg != PC ? bytedispdef : bytereldef;
80 return usesreg != PC ? worddisp : wordrel;
82 return usesreg != PC ? worddispdef : wordreldef;
84 return usesreg != PC ? longdisp : longrel;
86 return usesreg != PC ? longdispdef : longreldef;
93 tahoe_operandname (mode)
94 tahoe_operandenum mode;
106 return "register deferred";
108 return "autodecrement";
110 return "autoincrement";
112 return "autoincrement deferred";
114 return "byte displacement";
116 return "byte displacement deferred";
118 return "byte relative";
120 return "byte relative deferred";
122 return "word displacement";
124 return "word displacement deferred";
126 return "word relative";
128 return "word relative deferred";
134 return "long displacement";
136 return "long displacement deferred";
138 return "long relative";
140 return "long relative deferred";
147 tahoe_operandlength (modep)
148 unsigned char *modep;
151 switch (tahoe_operandmode (modep))
178 return 1 + tahoe_operandlength (modep + 1);
185 tahoe_reladdr (modep)
188 tahoe_operandenum mode = tahoe_operandmode (modep);
196 ++cp; /* skip over the mode */
200 fprintf (stderr, "[reladdr] not relative address\n");
201 return (bfd_vma) modep;
203 return (bfd_vma) (cp + sizeof *cp + *cp);
205 for (i = 0; (size_t) i < sizeof *sp; i++)
206 value = (value << 8) + (cp[i] & 0xff);
207 return (bfd_vma) (cp + sizeof *sp + value);
209 for (i = 0; (size_t) i < sizeof *lp; i++)
210 value = (value << 8) + (cp[i] & 0xff);
211 return (bfd_vma) (cp + sizeof *lp + value);
216 tahoe_find_call (parent, p_lowpc, p_highpc)
221 unsigned char *instructp;
224 tahoe_operandenum mode;
225 tahoe_operandenum firstmode;
227 static bool inited = FALSE;
232 sym_init (&indirectchild);
233 indirectchild.cg.prop.fract = 1.0;
234 indirectchild.cg.cyc.head = &indirectchild;
237 if (core_text_space == 0)
241 if (p_lowpc < s_lowpc)
245 if (p_highpc > s_highpc)
249 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
250 parent->name, (unsigned long) p_lowpc,
251 (unsigned long) p_highpc));
252 for (instructp = (unsigned char *) core_text_space + p_lowpc;
253 instructp < (unsigned char *) core_text_space + p_highpc;
257 if (*instructp == CALLF)
260 * maybe a callf, better check it out.
261 * skip the count of the number of arguments.
263 DBG (CALLDEBUG, printf ("[findcall]\t0x%x:callf",
264 instructp - (unsigned char *) core_text_space));
265 firstmode = tahoe_operandmode (instructp + length);
274 length += tahoe_operandlength (instructp + length);
275 mode = tahoe_operandmode (instructp + length);
277 printf ("\tfirst operand is %s", tahoe_operandname (firstmode));
278 printf ("\tsecond operand is %s\n", tahoe_operandname (mode));
290 * indirect call: call through pointer
291 * either *d(r) as a parameter or local
292 * (r) as a return value
293 * *f as a global pointer
294 * [are there others that we miss?,
295 * e.g. arrays of pointers to functions???]
297 arc_add (parent, &indirectchild, (unsigned long) 0);
298 length += tahoe_operandlength (instructp + length);
304 * regular pc relative addressing
305 * check that this is the address of
308 destpc = tahoe_reladdr (instructp + length)
309 - (bfd_vma) core_text_space;
310 if (destpc >= s_lowpc && destpc <= s_highpc)
312 child = sym_lookup (&symtab, destpc);
314 printf ("[findcall]\tdestpc 0x%lx",
315 (unsigned long) destpc);
316 printf (" child->name %s", child->name);
317 printf (" child->addr 0x%lx\n",
318 (unsigned long) child->addr);
320 if (child->addr == destpc)
325 arc_add (parent, child, (unsigned long) 0);
326 length += tahoe_operandlength (instructp + length);
333 * it looked like a callf,
334 * but it wasn't to anywhere.
340 * something funny going on.
342 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));