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