OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gprof/] [vax.c] - Blame information for rev 228

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 25 khays
/*
2
 * Copyright (c) 1983, 1993, 2001
3
 *      The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the University nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
#include "gprof.h"
30
#include "search_list.h"
31
#include "source.h"
32
#include "symtab.h"
33
#include "cg_arcs.h"
34
#include "corefile.h"
35
#include "hist.h"
36
 
37
    /*
38
     *        opcode of the `calls' instruction
39
     */
40
#define CALLS   0xfb
41
 
42
    /*
43
     *        register for pc relative addressing
44
     */
45
#define PC      0xf
46
 
47
enum opermodes
48
  {
49
    literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
50
    bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
51
    immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
52
    longrel, longreldef
53
  };
54
typedef enum opermodes operandenum;
55
 
56
/* *INDENT-OFF* */
57
/* Here to document only.  We can't use this when cross compiling as
58
   the bitfield layout might not be the same as native.
59
 
60
   struct modebyte
61
     {
62
       unsigned int regfield:4;
63
       unsigned int modefield:4;
64
     };
65
*/
66
/* *INDENT-ON* */
67
 
68
/*
69
 * A symbol to be the child of indirect calls:
70
 */
71
static Sym indirectchild;
72
 
73
static operandenum vax_operandmode (unsigned char *);
74
static char *vax_operandname (operandenum);
75
static long vax_operandlength (unsigned char *);
76
static bfd_signed_vma vax_offset (unsigned char *);
77
void vax_find_call (Sym *, bfd_vma, bfd_vma);
78
 
79
static operandenum
80
vax_operandmode (unsigned char *modep)
81
{
82
  int usesreg = *modep & 0xf;
83
 
84
  switch ((*modep >> 4) & 0xf)
85
    {
86
    case 0:
87
    case 1:
88
    case 2:
89
    case 3:
90
      return literal;
91
    case 4:
92
      return indexed;
93
    case 5:
94
      return reg;
95
    case 6:
96
      return regdef;
97
    case 7:
98
      return autodec;
99
    case 8:
100
      return usesreg != PC ? autoinc : immediate;
101
    case 9:
102
      return usesreg != PC ? autoincdef : absolute;
103
    case 10:
104
      return usesreg != PC ? bytedisp : byterel;
105
    case 11:
106
      return usesreg != PC ? bytedispdef : bytereldef;
107
    case 12:
108
      return usesreg != PC ? worddisp : wordrel;
109
    case 13:
110
      return usesreg != PC ? worddispdef : wordreldef;
111
    case 14:
112
      return usesreg != PC ? longdisp : longrel;
113
    case 15:
114
      return usesreg != PC ? longdispdef : longreldef;
115
    }
116
  /* NOTREACHED */
117
  abort ();
118
}
119
 
120
static char *
121
vax_operandname (operandenum mode)
122
{
123
 
124
  switch (mode)
125
    {
126
    case literal:
127
      return "literal";
128
    case indexed:
129
      return "indexed";
130
    case reg:
131
      return "register";
132
    case regdef:
133
      return "register deferred";
134
    case autodec:
135
      return "autodecrement";
136
    case autoinc:
137
      return "autoincrement";
138
    case autoincdef:
139
      return "autoincrement deferred";
140
    case bytedisp:
141
      return "byte displacement";
142
    case bytedispdef:
143
      return "byte displacement deferred";
144
    case byterel:
145
      return "byte relative";
146
    case bytereldef:
147
      return "byte relative deferred";
148
    case worddisp:
149
      return "word displacement";
150
    case worddispdef:
151
      return "word displacement deferred";
152
    case wordrel:
153
      return "word relative";
154
    case wordreldef:
155
      return "word relative deferred";
156
    case immediate:
157
      return "immediate";
158
    case absolute:
159
      return "absolute";
160
    case longdisp:
161
      return "long displacement";
162
    case longdispdef:
163
      return "long displacement deferred";
164
    case longrel:
165
      return "long relative";
166
    case longreldef:
167
      return "long relative deferred";
168
    }
169
  /* NOTREACHED */
170
  abort ();
171
}
172
 
173
static long
174
vax_operandlength (unsigned char *modep)
175
{
176
 
177
  switch (vax_operandmode (modep))
178
    {
179
    case literal:
180
    case reg:
181
    case regdef:
182
    case autodec:
183
    case autoinc:
184
    case autoincdef:
185
      return 1;
186
    case bytedisp:
187
    case bytedispdef:
188
    case byterel:
189
    case bytereldef:
190
      return 2;
191
    case worddisp:
192
    case worddispdef:
193
    case wordrel:
194
    case wordreldef:
195
      return 3;
196
    case immediate:
197
    case absolute:
198
    case longdisp:
199
    case longdispdef:
200
    case longrel:
201
    case longreldef:
202
      return 5;
203
    case indexed:
204
      return 1 + vax_operandlength (modep + 1);
205
    }
206
  /* NOTREACHED */
207
  abort ();
208
}
209
 
210
static bfd_signed_vma
211
vax_offset (unsigned char *modep)
212
{
213
  operandenum mode = vax_operandmode (modep);
214
 
215
  ++modep;                              /* skip over the mode */
216
  switch (mode)
217
    {
218
    default:
219
      fprintf (stderr, "[reladdr] not relative address\n");
220
      return 0;
221
    case byterel:
222
      return 1 + bfd_get_signed_8 (core_bfd, modep);
223
    case wordrel:
224
      return 2 + bfd_get_signed_16 (core_bfd, modep);
225
    case longrel:
226
      return 4 + bfd_get_signed_32 (core_bfd, modep);
227
    }
228
}
229
 
230
 
231
void
232
vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
233
{
234
  unsigned char *instructp;
235
  long length;
236
  Sym *child;
237
  operandenum mode;
238
  operandenum firstmode;
239
  bfd_vma pc, destpc;
240
  static bfd_boolean inited = FALSE;
241
 
242
  if (!inited)
243
    {
244
      inited = TRUE;
245
      sym_init (&indirectchild);
246
      indirectchild.cg.prop.fract = 1.0;
247
      indirectchild.cg.cyc.head = &indirectchild;
248
    }
249
 
250
  DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
251
                          parent->name, (unsigned long) p_lowpc,
252
                          (unsigned long) p_highpc));
253
  for (pc = p_lowpc; pc < p_highpc; pc += length)
254
    {
255
      length = 1;
256
      instructp = ((unsigned char *) core_text_space
257
                   + pc - core_text_sect->vma);
258
      if ((*instructp & 0xff) == CALLS)
259
        {
260
          /*
261
           *    maybe a calls, better check it out.
262
           *      skip the count of the number of arguments.
263
           */
264
          DBG (CALLDEBUG,
265
               printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
266
          firstmode = vax_operandmode (instructp + length);
267
          switch (firstmode)
268
            {
269
            case literal:
270
            case immediate:
271
              break;
272
            default:
273
              goto botched;
274
            }
275
          length += vax_operandlength (instructp + length);
276
          mode = vax_operandmode (instructp + length);
277
          DBG (CALLDEBUG,
278
               printf ("\tfirst operand is %s", vax_operandname (firstmode));
279
               printf ("\tsecond operand is %s\n", vax_operandname (mode)));
280
          switch (mode)
281
            {
282
            case regdef:
283
            case bytedispdef:
284
            case worddispdef:
285
            case longdispdef:
286
            case bytereldef:
287
            case wordreldef:
288
            case longreldef:
289
              /*
290
               *    indirect call: call through pointer
291
               *      either  *d(r)   as a parameter or local
292
               *              (r)     as a return value
293
               *              *f      as a global pointer
294
               *      [are there others that we miss?,
295
               *       e.g. arrays of pointers to functions???]
296
               */
297
              arc_add (parent, &indirectchild, (unsigned long) 0);
298
              length += vax_operandlength (instructp + length);
299
              continue;
300
            case byterel:
301
            case wordrel:
302
            case longrel:
303
              /*
304
               *    regular pc relative addressing
305
               *      check that this is the address of
306
               *      a function.
307
               */
308
              destpc = pc + vax_offset (instructp + length);
309
              if (hist_check_address (destpc))
310
                {
311
                  child = sym_lookup (&symtab, destpc);
312
                  if (child)
313
                    {
314
                      DBG (CALLDEBUG,
315
                           printf ("[findcall]\tdestpc 0x%lx",
316
                                   (unsigned long) destpc);
317
                           printf (" child->name %s", child->name);
318
                           printf (" child->addr 0x%lx\n",
319
                                   (unsigned long) child->addr);
320
                        );
321
                      if (child->addr == destpc)
322
                        {
323
                          /*
324
                           *    a hit
325
                           */
326
                          arc_add (parent, child, (unsigned long) 0);
327
                          length += vax_operandlength (instructp + length);
328
                          continue;
329
                        }
330
                    }
331
                  goto botched;
332
                }
333
              /*
334
               *    else:
335
               *      it looked like a calls,
336
               *      but it wasn't to anywhere.
337
               */
338
              goto botched;
339
            default:
340
            botched:
341
              /*
342
               *    something funny going on.
343
               */
344
              DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
345
              length = 1;
346
              continue;
347
            }
348
        }
349
    }
350
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.