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, p_lowpc, p_highpc));
251 for (instructp = (unsigned char *) core_text_space + p_lowpc;
252 instructp < (unsigned char *) core_text_space + p_highpc;
256 if (*instructp == CALLF)
259 * maybe a callf, better check it out.
260 * skip the count of the number of arguments.
262 DBG (CALLDEBUG, printf ("[findcall]\t0x%x:callf",
263 instructp - (unsigned char *) core_text_space));
264 firstmode = tahoe_operandmode (instructp + length);
273 length += tahoe_operandlength (instructp + length);
274 mode = tahoe_operandmode (instructp + length);
276 printf ("\tfirst operand is %s", tahoe_operandname (firstmode));
277 printf ("\tsecond operand is %s\n", tahoe_operandname (mode));
289 * indirect call: call through pointer
290 * either *d(r) as a parameter or local
291 * (r) as a return value
292 * *f as a global pointer
293 * [are there others that we miss?,
294 * e.g. arrays of pointers to functions???]
296 arc_add (parent, &indirectchild, (long) 0);
297 length += tahoe_operandlength (instructp + length);
303 * regular pc relative addressing
304 * check that this is the address of
307 destpc = tahoe_reladdr (instructp + length)
308 - (bfd_vma) core_text_space;
309 if (destpc >= s_lowpc && destpc <= s_highpc)
311 child = sym_lookup (&symtab, destpc);
313 printf ("[findcall]\tdestpc 0x%lx", destpc);
314 printf (" child->name %s", child->name);
315 printf (" child->addr 0x%lx\n", child->addr);
317 if (child->addr == destpc)
322 arc_add (parent, child, (long) 0);
323 length += tahoe_operandlength (instructp + length);
330 * it looked like a callf,
331 * but it wasn't to anywhere.
337 * something funny going on.
339 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));