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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gprof/] [vax.c] - Diff between revs 156 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/*
/*
 * Copyright (c) 1983, 1993, 2001
 * Copyright (c) 1983, 1993, 2001
 *      The Regents of the University of California.  All rights reserved.
 *      The Regents of the University of California.  All rights reserved.
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * modification, are permitted provided that the following conditions
 * are met:
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *    without specific prior written permission.
 *
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * SUCH DAMAGE.
 */
 */
#include "gprof.h"
#include "gprof.h"
#include "search_list.h"
#include "search_list.h"
#include "source.h"
#include "source.h"
#include "symtab.h"
#include "symtab.h"
#include "cg_arcs.h"
#include "cg_arcs.h"
#include "corefile.h"
#include "corefile.h"
#include "hist.h"
#include "hist.h"
 
 
    /*
    /*
     *        opcode of the `calls' instruction
     *        opcode of the `calls' instruction
     */
     */
#define CALLS   0xfb
#define CALLS   0xfb
 
 
    /*
    /*
     *        register for pc relative addressing
     *        register for pc relative addressing
     */
     */
#define PC      0xf
#define PC      0xf
 
 
enum opermodes
enum opermodes
  {
  {
    literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
    literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
    bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
    bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
    immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
    immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
    longrel, longreldef
    longrel, longreldef
  };
  };
typedef enum opermodes operandenum;
typedef enum opermodes operandenum;
 
 
/* *INDENT-OFF* */
/* *INDENT-OFF* */
/* Here to document only.  We can't use this when cross compiling as
/* Here to document only.  We can't use this when cross compiling as
   the bitfield layout might not be the same as native.
   the bitfield layout might not be the same as native.
 
 
   struct modebyte
   struct modebyte
     {
     {
       unsigned int regfield:4;
       unsigned int regfield:4;
       unsigned int modefield:4;
       unsigned int modefield:4;
     };
     };
*/
*/
/* *INDENT-ON* */
/* *INDENT-ON* */
 
 
/*
/*
 * A symbol to be the child of indirect calls:
 * A symbol to be the child of indirect calls:
 */
 */
static Sym indirectchild;
static Sym indirectchild;
 
 
static operandenum vax_operandmode (unsigned char *);
static operandenum vax_operandmode (unsigned char *);
static char *vax_operandname (operandenum);
static char *vax_operandname (operandenum);
static long vax_operandlength (unsigned char *);
static long vax_operandlength (unsigned char *);
static bfd_signed_vma vax_offset (unsigned char *);
static bfd_signed_vma vax_offset (unsigned char *);
void vax_find_call (Sym *, bfd_vma, bfd_vma);
void vax_find_call (Sym *, bfd_vma, bfd_vma);
 
 
static operandenum
static operandenum
vax_operandmode (unsigned char *modep)
vax_operandmode (unsigned char *modep)
{
{
  int usesreg = *modep & 0xf;
  int usesreg = *modep & 0xf;
 
 
  switch ((*modep >> 4) & 0xf)
  switch ((*modep >> 4) & 0xf)
    {
    {
    case 0:
    case 0:
    case 1:
    case 1:
    case 2:
    case 2:
    case 3:
    case 3:
      return literal;
      return literal;
    case 4:
    case 4:
      return indexed;
      return indexed;
    case 5:
    case 5:
      return reg;
      return reg;
    case 6:
    case 6:
      return regdef;
      return regdef;
    case 7:
    case 7:
      return autodec;
      return autodec;
    case 8:
    case 8:
      return usesreg != PC ? autoinc : immediate;
      return usesreg != PC ? autoinc : immediate;
    case 9:
    case 9:
      return usesreg != PC ? autoincdef : absolute;
      return usesreg != PC ? autoincdef : absolute;
    case 10:
    case 10:
      return usesreg != PC ? bytedisp : byterel;
      return usesreg != PC ? bytedisp : byterel;
    case 11:
    case 11:
      return usesreg != PC ? bytedispdef : bytereldef;
      return usesreg != PC ? bytedispdef : bytereldef;
    case 12:
    case 12:
      return usesreg != PC ? worddisp : wordrel;
      return usesreg != PC ? worddisp : wordrel;
    case 13:
    case 13:
      return usesreg != PC ? worddispdef : wordreldef;
      return usesreg != PC ? worddispdef : wordreldef;
    case 14:
    case 14:
      return usesreg != PC ? longdisp : longrel;
      return usesreg != PC ? longdisp : longrel;
    case 15:
    case 15:
      return usesreg != PC ? longdispdef : longreldef;
      return usesreg != PC ? longdispdef : longreldef;
    }
    }
  /* NOTREACHED */
  /* NOTREACHED */
  abort ();
  abort ();
}
}
 
 
static char *
static char *
vax_operandname (operandenum mode)
vax_operandname (operandenum mode)
{
{
 
 
  switch (mode)
  switch (mode)
    {
    {
    case literal:
    case literal:
      return "literal";
      return "literal";
    case indexed:
    case indexed:
      return "indexed";
      return "indexed";
    case reg:
    case reg:
      return "register";
      return "register";
    case regdef:
    case regdef:
      return "register deferred";
      return "register deferred";
    case autodec:
    case autodec:
      return "autodecrement";
      return "autodecrement";
    case autoinc:
    case autoinc:
      return "autoincrement";
      return "autoincrement";
    case autoincdef:
    case autoincdef:
      return "autoincrement deferred";
      return "autoincrement deferred";
    case bytedisp:
    case bytedisp:
      return "byte displacement";
      return "byte displacement";
    case bytedispdef:
    case bytedispdef:
      return "byte displacement deferred";
      return "byte displacement deferred";
    case byterel:
    case byterel:
      return "byte relative";
      return "byte relative";
    case bytereldef:
    case bytereldef:
      return "byte relative deferred";
      return "byte relative deferred";
    case worddisp:
    case worddisp:
      return "word displacement";
      return "word displacement";
    case worddispdef:
    case worddispdef:
      return "word displacement deferred";
      return "word displacement deferred";
    case wordrel:
    case wordrel:
      return "word relative";
      return "word relative";
    case wordreldef:
    case wordreldef:
      return "word relative deferred";
      return "word relative deferred";
    case immediate:
    case immediate:
      return "immediate";
      return "immediate";
    case absolute:
    case absolute:
      return "absolute";
      return "absolute";
    case longdisp:
    case longdisp:
      return "long displacement";
      return "long displacement";
    case longdispdef:
    case longdispdef:
      return "long displacement deferred";
      return "long displacement deferred";
    case longrel:
    case longrel:
      return "long relative";
      return "long relative";
    case longreldef:
    case longreldef:
      return "long relative deferred";
      return "long relative deferred";
    }
    }
  /* NOTREACHED */
  /* NOTREACHED */
  abort ();
  abort ();
}
}
 
 
static long
static long
vax_operandlength (unsigned char *modep)
vax_operandlength (unsigned char *modep)
{
{
 
 
  switch (vax_operandmode (modep))
  switch (vax_operandmode (modep))
    {
    {
    case literal:
    case literal:
    case reg:
    case reg:
    case regdef:
    case regdef:
    case autodec:
    case autodec:
    case autoinc:
    case autoinc:
    case autoincdef:
    case autoincdef:
      return 1;
      return 1;
    case bytedisp:
    case bytedisp:
    case bytedispdef:
    case bytedispdef:
    case byterel:
    case byterel:
    case bytereldef:
    case bytereldef:
      return 2;
      return 2;
    case worddisp:
    case worddisp:
    case worddispdef:
    case worddispdef:
    case wordrel:
    case wordrel:
    case wordreldef:
    case wordreldef:
      return 3;
      return 3;
    case immediate:
    case immediate:
    case absolute:
    case absolute:
    case longdisp:
    case longdisp:
    case longdispdef:
    case longdispdef:
    case longrel:
    case longrel:
    case longreldef:
    case longreldef:
      return 5;
      return 5;
    case indexed:
    case indexed:
      return 1 + vax_operandlength (modep + 1);
      return 1 + vax_operandlength (modep + 1);
    }
    }
  /* NOTREACHED */
  /* NOTREACHED */
  abort ();
  abort ();
}
}
 
 
static bfd_signed_vma
static bfd_signed_vma
vax_offset (unsigned char *modep)
vax_offset (unsigned char *modep)
{
{
  operandenum mode = vax_operandmode (modep);
  operandenum mode = vax_operandmode (modep);
 
 
  ++modep;                              /* skip over the mode */
  ++modep;                              /* skip over the mode */
  switch (mode)
  switch (mode)
    {
    {
    default:
    default:
      fprintf (stderr, "[reladdr] not relative address\n");
      fprintf (stderr, "[reladdr] not relative address\n");
      return 0;
      return 0;
    case byterel:
    case byterel:
      return 1 + bfd_get_signed_8 (core_bfd, modep);
      return 1 + bfd_get_signed_8 (core_bfd, modep);
    case wordrel:
    case wordrel:
      return 2 + bfd_get_signed_16 (core_bfd, modep);
      return 2 + bfd_get_signed_16 (core_bfd, modep);
    case longrel:
    case longrel:
      return 4 + bfd_get_signed_32 (core_bfd, modep);
      return 4 + bfd_get_signed_32 (core_bfd, modep);
    }
    }
}
}
 
 
 
 
void
void
vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
{
{
  unsigned char *instructp;
  unsigned char *instructp;
  long length;
  long length;
  Sym *child;
  Sym *child;
  operandenum mode;
  operandenum mode;
  operandenum firstmode;
  operandenum firstmode;
  bfd_vma pc, destpc;
  bfd_vma pc, destpc;
  static bfd_boolean inited = FALSE;
  static bfd_boolean inited = FALSE;
 
 
  if (!inited)
  if (!inited)
    {
    {
      inited = TRUE;
      inited = TRUE;
      sym_init (&indirectchild);
      sym_init (&indirectchild);
      indirectchild.cg.prop.fract = 1.0;
      indirectchild.cg.prop.fract = 1.0;
      indirectchild.cg.cyc.head = &indirectchild;
      indirectchild.cg.cyc.head = &indirectchild;
    }
    }
 
 
  DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
  DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
                          parent->name, (unsigned long) p_lowpc,
                          parent->name, (unsigned long) p_lowpc,
                          (unsigned long) p_highpc));
                          (unsigned long) p_highpc));
  for (pc = p_lowpc; pc < p_highpc; pc += length)
  for (pc = p_lowpc; pc < p_highpc; pc += length)
    {
    {
      length = 1;
      length = 1;
      instructp = ((unsigned char *) core_text_space
      instructp = ((unsigned char *) core_text_space
                   + pc - core_text_sect->vma);
                   + pc - core_text_sect->vma);
      if ((*instructp & 0xff) == CALLS)
      if ((*instructp & 0xff) == CALLS)
        {
        {
          /*
          /*
           *    maybe a calls, better check it out.
           *    maybe a calls, better check it out.
           *      skip the count of the number of arguments.
           *      skip the count of the number of arguments.
           */
           */
          DBG (CALLDEBUG,
          DBG (CALLDEBUG,
               printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
               printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
          firstmode = vax_operandmode (instructp + length);
          firstmode = vax_operandmode (instructp + length);
          switch (firstmode)
          switch (firstmode)
            {
            {
            case literal:
            case literal:
            case immediate:
            case immediate:
              break;
              break;
            default:
            default:
              goto botched;
              goto botched;
            }
            }
          length += vax_operandlength (instructp + length);
          length += vax_operandlength (instructp + length);
          mode = vax_operandmode (instructp + length);
          mode = vax_operandmode (instructp + length);
          DBG (CALLDEBUG,
          DBG (CALLDEBUG,
               printf ("\tfirst operand is %s", vax_operandname (firstmode));
               printf ("\tfirst operand is %s", vax_operandname (firstmode));
               printf ("\tsecond operand is %s\n", vax_operandname (mode)));
               printf ("\tsecond operand is %s\n", vax_operandname (mode)));
          switch (mode)
          switch (mode)
            {
            {
            case regdef:
            case regdef:
            case bytedispdef:
            case bytedispdef:
            case worddispdef:
            case worddispdef:
            case longdispdef:
            case longdispdef:
            case bytereldef:
            case bytereldef:
            case wordreldef:
            case wordreldef:
            case longreldef:
            case longreldef:
              /*
              /*
               *    indirect call: call through pointer
               *    indirect call: call through pointer
               *      either  *d(r)   as a parameter or local
               *      either  *d(r)   as a parameter or local
               *              (r)     as a return value
               *              (r)     as a return value
               *              *f      as a global pointer
               *              *f      as a global pointer
               *      [are there others that we miss?,
               *      [are there others that we miss?,
               *       e.g. arrays of pointers to functions???]
               *       e.g. arrays of pointers to functions???]
               */
               */
              arc_add (parent, &indirectchild, (unsigned long) 0);
              arc_add (parent, &indirectchild, (unsigned long) 0);
              length += vax_operandlength (instructp + length);
              length += vax_operandlength (instructp + length);
              continue;
              continue;
            case byterel:
            case byterel:
            case wordrel:
            case wordrel:
            case longrel:
            case longrel:
              /*
              /*
               *    regular pc relative addressing
               *    regular pc relative addressing
               *      check that this is the address of
               *      check that this is the address of
               *      a function.
               *      a function.
               */
               */
              destpc = pc + vax_offset (instructp + length);
              destpc = pc + vax_offset (instructp + length);
              if (hist_check_address (destpc))
              if (hist_check_address (destpc))
                {
                {
                  child = sym_lookup (&symtab, destpc);
                  child = sym_lookup (&symtab, destpc);
                  DBG (CALLDEBUG,
                  DBG (CALLDEBUG,
                       printf ("[findcall]\tdestpc 0x%lx",
                       printf ("[findcall]\tdestpc 0x%lx",
                               (unsigned long) destpc);
                               (unsigned long) destpc);
                       printf (" child->name %s", child->name);
                       printf (" child->name %s", child->name);
                       printf (" child->addr 0x%lx\n",
                       printf (" child->addr 0x%lx\n",
                               (unsigned long) child->addr);
                               (unsigned long) child->addr);
                    );
                    );
                  if (child->addr == destpc)
                  if (child->addr == destpc)
                    {
                    {
                      /*
                      /*
                       *    a hit
                       *    a hit
                       */
                       */
                      arc_add (parent, child, (unsigned long) 0);
                      arc_add (parent, child, (unsigned long) 0);
                      length += vax_operandlength (instructp + length);
                      length += vax_operandlength (instructp + length);
                      continue;
                      continue;
                    }
                    }
                  goto botched;
                  goto botched;
                }
                }
              /*
              /*
               *    else:
               *    else:
               *      it looked like a calls,
               *      it looked like a calls,
               *      but it wasn't to anywhere.
               *      but it wasn't to anywhere.
               */
               */
              goto botched;
              goto botched;
            default:
            default:
            botched:
            botched:
              /*
              /*
               *    something funny going on.
               *    something funny going on.
               */
               */
              DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
              DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
              length = 1;
              length = 1;
              continue;
              continue;
            }
            }
        }
        }
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

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