alpha.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 172 行

C
172
字号
/* * Copyright (c) 1983, 1998 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that: (1) source distributions retain this entire copyright * notice and comment, and (2) distributions including binaries display * the following acknowledgement:  ``This product includes software * developed by the University of California, Berkeley and its contributors'' * in the documentation or other materials provided with the distribution * and in all advertising materials mentioning features or use of this * software. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#include "gprof.h"#include "cg_arcs.h"#include "corefile.h"#include "hist.h"#include "symtab.h"/* * Opcodes of the call instructions: */#define OP_Jxx	0x1a#define	OP_BSR	0x34#define Jxx_FUNC_JMP		0#define Jxx_FUNC_JSR		1#define Jxx_FUNC_RET		2#define Jxx_FUNC_JSR_COROUTINE	3typedef union  {    struct      {	unsigned other:26;	unsigned op_code:6;      }    a;				/* any format */    struct      {	int disp:21;	unsigned ra:5;	unsigned op_code:6;      }    b;				/* branch format */    struct      {	int hint:14;	unsigned func:2;	unsigned rb:5;	unsigned ra:5;	unsigned op_code:6;      }    j;				/* jump format */  }alpha_Instruction;static Sym indirect_child;/* * On the Alpha we can only detect PC relative calls, which are * usually generated for calls to functions within the same * object file only.  This is still better than nothing, however. * (In particular it should be possible to find functions that *  potentially call integer division routines, for example.) */voidalpha_find_call (parent, p_lowpc, p_highpc)     Sym *parent;     bfd_vma p_lowpc;     bfd_vma p_highpc;{  static bfd_vma delta = 0;  bfd_vma dest_pc;  alpha_Instruction *pc;  Sym *child;  if (!delta)    {      delta = (bfd_vma) core_text_space - core_text_sect->vma;      sym_init (&indirect_child);      indirect_child.name = _("<indirect child>");      indirect_child.cg.prop.fract = 1.0;      indirect_child.cg.cyc.head = &indirect_child;    }  if (!core_text_space)    {      return;    }  if (p_lowpc < s_lowpc)    {      p_lowpc = s_lowpc;    }  if (p_highpc > s_highpc)    {      p_highpc = s_highpc;    }  DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),			  parent->name, (unsigned long) p_lowpc,			  (unsigned long) p_highpc));  for (pc = (alpha_Instruction *) (p_lowpc + delta);       pc < (alpha_Instruction *) (p_highpc + delta);       ++pc)    {      switch (pc->a.op_code)	{	case OP_Jxx:	  /*	   * There is no simple and reliable way to determine the	   * target of a jsr (the hint bits help, but there aren't	   * enough bits to get a satisfactory hit rate).  Instead,	   * for any indirect jump we simply add an arc from PARENT	   * to INDIRECT_CHILD---that way the user it at least able	   * to see that there are other calls as well.	   */	  if (pc->j.func == Jxx_FUNC_JSR	      || pc->j.func == Jxx_FUNC_JSR_COROUTINE)	    {	      DBG (CALLDEBUG,		   printf (_("[find_call] 0x%lx: jsr%s <indirect_child>\n"),			   (unsigned long) pc - delta,			   pc->j.func == Jxx_FUNC_JSR ? "" : "_coroutine"));	      arc_add (parent, &indirect_child, (unsigned long) 0);	    }	  break;	case OP_BSR:	  DBG (CALLDEBUG,	       printf (_("[find_call] 0x%lx: bsr"),		       (unsigned long) pc - delta));	  /*	   * Regular PC relative addressing.  Check that this is the	   * address of a function.  The linker sometimes redirects	   * the entry point by 8 bytes to skip loading the global	   * pointer, so we all for either address:	   */	  dest_pc = ((bfd_vma) (pc + 1 + pc->b.disp)) - delta;	  if (dest_pc >= s_lowpc && dest_pc <= s_highpc)	    {	      child = sym_lookup (&symtab, dest_pc);	      DBG (CALLDEBUG,		   printf (" 0x%lx\t; name=%s, addr=0x%lx",			   (unsigned long) dest_pc, child->name,			   (unsigned long) child->addr));	      if (child->addr == dest_pc || child->addr == dest_pc - 8)		{		  DBG (CALLDEBUG, printf ("\n"));		  /* a hit:  */		  arc_add (parent, child, (unsigned long) 0);		  continue;		}	    }	  /*	   * Something funny going on.	   */	  DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));	  break;	default:	  break;	}    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?