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