* symbols.c (resolve_symbol_value): Don't permit subtraction of
[binutils.git] / gprof / vax.c
blob1a7bd8dc146535fc4ab392866dfd203399e4cfc8
1 /*
2 * Copyright (c) 1983 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 Sym indirectchild;
56 static operandenum
57 vax_operandmode (modep)
58 struct modebyte *modep;
60 long usesreg = modep->regfield;
62 switch (modep->modefield)
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;
94 /* NOTREACHED */
95 abort ();
98 static char *
99 vax_operandname (mode)
100 operandenum mode;
103 switch (mode)
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";
148 /* NOTREACHED */
149 abort ();
152 static long
153 vax_operandlength (modep)
154 struct modebyte *modep;
157 switch (vax_operandmode (modep))
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);
186 /* NOTREACHED */
187 abort ();
190 static bfd_vma
191 vax_reladdr (modep)
192 struct modebyte *modep;
194 operandenum mode = vax_operandmode (modep);
195 char *cp;
196 short *sp;
197 long *lp;
199 cp = (char *) modep;
200 ++cp; /* skip over the mode */
201 switch (mode)
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);
218 void
219 vax_find_call (parent, p_lowpc, p_highpc)
220 Sym *parent;
221 bfd_vma p_lowpc;
222 bfd_vma p_highpc;
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;
232 if (!inited)
234 inited = TRUE;
235 sym_init (&indirectchild);
236 indirectchild.cg.prop.fract = 1.0;
237 indirectchild.cg.cyc.head = &indirectchild;
240 if (core_text_space == 0)
242 return;
244 if (p_lowpc < s_lowpc)
246 p_lowpc = s_lowpc;
248 if (p_highpc > s_highpc)
250 p_highpc = s_highpc;
252 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
253 parent->name, p_lowpc, p_highpc));
254 for (instructp = (unsigned char *) core_text_space + p_lowpc;
255 instructp < (unsigned char *) core_text_space + p_highpc;
256 instructp += length)
258 length = 1;
259 if (*instructp == CALLS)
262 * maybe a calls, better check it out.
263 * skip the count of the number of arguments.
265 DBG (CALLDEBUG,
266 printf ("[findcall]\t0x%x:calls",
267 instructp - (unsigned char *) core_text_space));
268 firstmode = vax_operandmode ((struct modebyte *) (instructp + length));
269 switch (firstmode)
271 case literal:
272 case immediate:
273 break;
274 default:
275 goto botched;
277 length += vax_operandlength ((struct modebyte *) (instructp + length));
278 mode = vax_operandmode ((struct modebyte *) (instructp + length));
279 DBG (CALLDEBUG,
280 printf ("\tfirst operand is %s", vax_operandname (firstmode));
281 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
282 switch (mode)
284 case regdef:
285 case bytedispdef:
286 case worddispdef:
287 case longdispdef:
288 case bytereldef:
289 case wordreldef:
290 case longreldef:
292 * indirect call: call through pointer
293 * either *d(r) as a parameter or local
294 * (r) as a return value
295 * *f as a global pointer
296 * [are there others that we miss?,
297 * e.g. arrays of pointers to functions???]
299 arc_add (parent, &indirectchild, (unsigned long) 0);
300 length += vax_operandlength (
301 (struct modebyte *) (instructp + length));
302 continue;
303 case byterel:
304 case wordrel:
305 case longrel:
307 * regular pc relative addressing
308 * check that this is the address of
309 * a function.
311 destpc = vax_reladdr ((struct modebyte *) (instructp + length))
312 - (bfd_vma) core_text_space;
313 if (destpc >= s_lowpc && destpc <= s_highpc)
315 child = sym_lookup (&symtab, destpc);
316 DBG (CALLDEBUG,
317 printf ("[findcall]\tdestpc 0x%lx", destpc);
318 printf (" child->name %s", child->name);
319 printf (" child->addr 0x%lx\n", child->addr);
321 if (child->addr == destpc)
324 * a hit
326 arc_add (parent, child, (unsigned long) 0);
327 length += vax_operandlength ((struct modebyte *)
328 (instructp + length));
329 continue;
331 goto botched;
334 * else:
335 * it looked like a calls,
336 * but it wasn't to anywhere.
338 goto botched;
339 default:
340 botched:
342 * something funny going on.
344 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
345 length = 1;
346 continue;