* i386.c (i386_iscall): Static.
[binutils.git] / gprof / vax.c
blobbce1e7218b99871ea131e02e36317ffa849c2871
1 /*
2 * Copyright (c) 1983, 2001 Regents of the University of California.
3 * All rights reserved.
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.
19 #include "gprof.h"
20 #include "cg_arcs.h"
21 #include "corefile.h"
22 #include "hist.h"
23 #include "symtab.h"
26 * opcode of the `calls' instruction
28 #define CALLS 0xfb
31 * register for pc relative addressing
33 #define PC 0xf
35 enum opermodes
37 literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
38 bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
39 immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
40 longrel, longreldef
42 typedef enum opermodes operandenum;
44 struct modebyte
46 unsigned int regfield:4;
47 unsigned int modefield:4;
51 * A symbol to be the child of indirect calls:
53 static Sym indirectchild;
55 static operandenum vax_operandmode PARAMS ((struct modebyte *));
56 static char *vax_operandname PARAMS ((operandenum));
57 static long vax_operandlength PARAMS ((struct modebyte *));
58 static bfd_vma vax_reladdr PARAMS ((struct modebyte *));
59 void vax_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
61 static operandenum
62 vax_operandmode (modep)
63 struct modebyte *modep;
65 long usesreg = modep->regfield;
67 switch (modep->modefield)
69 case 0:
70 case 1:
71 case 2:
72 case 3:
73 return literal;
74 case 4:
75 return indexed;
76 case 5:
77 return reg;
78 case 6:
79 return regdef;
80 case 7:
81 return autodec;
82 case 8:
83 return usesreg != PC ? autoinc : immediate;
84 case 9:
85 return usesreg != PC ? autoincdef : absolute;
86 case 10:
87 return usesreg != PC ? bytedisp : byterel;
88 case 11:
89 return usesreg != PC ? bytedispdef : bytereldef;
90 case 12:
91 return usesreg != PC ? worddisp : wordrel;
92 case 13:
93 return usesreg != PC ? worddispdef : wordreldef;
94 case 14:
95 return usesreg != PC ? longdisp : longrel;
96 case 15:
97 return usesreg != PC ? longdispdef : longreldef;
99 /* NOTREACHED */
100 abort ();
103 static char *
104 vax_operandname (mode)
105 operandenum mode;
108 switch (mode)
110 case literal:
111 return "literal";
112 case indexed:
113 return "indexed";
114 case reg:
115 return "register";
116 case regdef:
117 return "register deferred";
118 case autodec:
119 return "autodecrement";
120 case autoinc:
121 return "autoincrement";
122 case autoincdef:
123 return "autoincrement deferred";
124 case bytedisp:
125 return "byte displacement";
126 case bytedispdef:
127 return "byte displacement deferred";
128 case byterel:
129 return "byte relative";
130 case bytereldef:
131 return "byte relative deferred";
132 case worddisp:
133 return "word displacement";
134 case worddispdef:
135 return "word displacement deferred";
136 case wordrel:
137 return "word relative";
138 case wordreldef:
139 return "word relative deferred";
140 case immediate:
141 return "immediate";
142 case absolute:
143 return "absolute";
144 case longdisp:
145 return "long displacement";
146 case longdispdef:
147 return "long displacement deferred";
148 case longrel:
149 return "long relative";
150 case longreldef:
151 return "long relative deferred";
153 /* NOTREACHED */
154 abort ();
157 static long
158 vax_operandlength (modep)
159 struct modebyte *modep;
162 switch (vax_operandmode (modep))
164 case literal:
165 case reg:
166 case regdef:
167 case autodec:
168 case autoinc:
169 case autoincdef:
170 return 1;
171 case bytedisp:
172 case bytedispdef:
173 case byterel:
174 case bytereldef:
175 return 2;
176 case worddisp:
177 case worddispdef:
178 case wordrel:
179 case wordreldef:
180 return 3;
181 case immediate:
182 case absolute:
183 case longdisp:
184 case longdispdef:
185 case longrel:
186 case longreldef:
187 return 5;
188 case indexed:
189 return 1 + vax_operandlength ((struct modebyte *) ((char *) modep) + 1);
191 /* NOTREACHED */
192 abort ();
195 static bfd_vma
196 vax_reladdr (modep)
197 struct modebyte *modep;
199 operandenum mode = vax_operandmode (modep);
200 char *cp;
201 short *sp;
202 long *lp;
204 cp = (char *) modep;
205 ++cp; /* skip over the mode */
206 switch (mode)
208 default:
209 fprintf (stderr, "[reladdr] not relative address\n");
210 return (bfd_vma) modep;
211 case byterel:
212 return (bfd_vma) (cp + sizeof *cp + *cp);
213 case wordrel:
214 sp = (short *) cp;
215 return (bfd_vma) (cp + sizeof *sp + *sp);
216 case longrel:
217 lp = (long *) cp;
218 return (bfd_vma) (cp + sizeof *lp + *lp);
223 void
224 vax_find_call (parent, p_lowpc, p_highpc)
225 Sym *parent;
226 bfd_vma p_lowpc;
227 bfd_vma p_highpc;
229 unsigned char *instructp;
230 long length;
231 Sym *child;
232 operandenum mode;
233 operandenum firstmode;
234 bfd_vma destpc;
235 static bool inited = FALSE;
237 if (!inited)
239 inited = TRUE;
240 sym_init (&indirectchild);
241 indirectchild.cg.prop.fract = 1.0;
242 indirectchild.cg.cyc.head = &indirectchild;
245 if (core_text_space == 0)
247 return;
249 if (p_lowpc < s_lowpc)
251 p_lowpc = s_lowpc;
253 if (p_highpc > s_highpc)
255 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 (instructp = (unsigned char *) core_text_space + p_lowpc;
261 instructp < (unsigned char *) core_text_space + p_highpc;
262 instructp += length)
264 length = 1;
265 if (*instructp == CALLS)
268 * maybe a calls, better check it out.
269 * skip the count of the number of arguments.
271 DBG (CALLDEBUG,
272 printf ("[findcall]\t0x%lx:calls",
273 ((unsigned long)
274 (instructp - (unsigned char *) core_text_space))));
275 firstmode = vax_operandmode ((struct modebyte *) (instructp + length));
276 switch (firstmode)
278 case literal:
279 case immediate:
280 break;
281 default:
282 goto botched;
284 length += vax_operandlength ((struct modebyte *) (instructp + length));
285 mode = vax_operandmode ((struct modebyte *) (instructp + length));
286 DBG (CALLDEBUG,
287 printf ("\tfirst operand is %s", vax_operandname (firstmode));
288 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
289 switch (mode)
291 case regdef:
292 case bytedispdef:
293 case worddispdef:
294 case longdispdef:
295 case bytereldef:
296 case wordreldef:
297 case longreldef:
299 * indirect call: call through pointer
300 * either *d(r) as a parameter or local
301 * (r) as a return value
302 * *f as a global pointer
303 * [are there others that we miss?,
304 * e.g. arrays of pointers to functions???]
306 arc_add (parent, &indirectchild, (unsigned long) 0);
307 length += vax_operandlength (
308 (struct modebyte *) (instructp + length));
309 continue;
310 case byterel:
311 case wordrel:
312 case longrel:
314 * regular pc relative addressing
315 * check that this is the address of
316 * a function.
318 destpc = vax_reladdr ((struct modebyte *) (instructp + length))
319 - (bfd_vma) core_text_space;
320 if (destpc >= s_lowpc && destpc <= s_highpc)
322 child = sym_lookup (&symtab, destpc);
323 DBG (CALLDEBUG,
324 printf ("[findcall]\tdestpc 0x%lx",
325 (unsigned long) destpc);
326 printf (" child->name %s", child->name);
327 printf (" child->addr 0x%lx\n",
328 (unsigned long) child->addr);
330 if (child->addr == destpc)
333 * a hit
335 arc_add (parent, child, (unsigned long) 0);
336 length += vax_operandlength ((struct modebyte *)
337 (instructp + length));
338 continue;
340 goto botched;
343 * else:
344 * it looked like a calls,
345 * but it wasn't to anywhere.
347 goto botched;
348 default:
349 botched:
351 * something funny going on.
353 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
354 length = 1;
355 continue;