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