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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gprof/] [tahoe.c] - Blame information for rev 868

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

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

powered by: WebSVN 2.1.0

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