⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 am29k-tdep.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Target-machine dependent code for the AMD 29000   Copyright 1990, 1991 Free Software Foundation, Inc.   Contributed by Cygnus Support.  Written by Jim Kingdon.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */#include "defs.h"#include "gdbcore.h"#include "frame.h"#include "value.h"/*#include <sys/param.h> */#include "symtab.h"#include "inferior.h"#include "gdbcmd.h"extern CORE_ADDR text_start;	/* FIXME, kludge... *//* The user-settable top of the register stack in virtual memory.  We   won't attempt to access any stored registers above this address, if set   nonzero.  */static CORE_ADDR rstack_high_address = UINT_MAX;/* Structure to hold cached info about function prologues.  */struct prologue_info{  CORE_ADDR pc;			/* First addr after fn prologue */  unsigned rsize, msize;	/* register stack frame size, mem stack ditto */  unsigned mfp_used : 1;	/* memory frame pointer used */  unsigned rsize_valid : 1;	/* Validity bits for the above */  unsigned msize_valid : 1;  unsigned mfp_valid : 1;};/* Examine the prologue of a function which starts at PC.  Return   the first addess past the prologue.  If MSIZE is non-NULL, then   set *MSIZE to the memory stack frame size.  If RSIZE is non-NULL,   then set *RSIZE to the register stack frame size (not including   incoming arguments and the return address & frame pointer stored   with them).  If no prologue is found, *RSIZE is set to zero.   If no prologue is found, or a prologue which doesn't involve   allocating a memory stack frame, then set *MSIZE to zero.   Note that both msize and rsize are in bytes.  This is not consistent   with the _User's Manual_ with respect to rsize, but it is much more   convenient.   If MFP_USED is non-NULL, *MFP_USED is set to nonzero if a memory   frame pointer is being used.  */CORE_ADDRexamine_prologue (pc, rsize, msize, mfp_used)     CORE_ADDR pc;     unsigned *msize;     unsigned *rsize;     int *mfp_used;{  long insn;  CORE_ADDR p = pc;  struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);  struct prologue_info *mi = 0;  if (msymbol != NULL)    mi = (struct prologue_info *) msymbol -> info;  if (mi != 0)    {      int valid = 1;      if (rsize != NULL)	{	  *rsize = mi->rsize;	  valid &= mi->rsize_valid;	}      if (msize != NULL)	{	  *msize = mi->msize;	  valid &= mi->msize_valid;	}      if (mfp_used != NULL)	{	  *mfp_used = mi->mfp_used;	  valid &= mi->mfp_valid;	}      if (valid)	return mi->pc;    }  if (rsize != NULL)    *rsize = 0;  if (msize != NULL)    *msize = 0;  if (mfp_used != NULL)    *mfp_used = 0;    /* Prologue must start with subtracting a constant from gr1.     Normally this is sub gr1,gr1,<rsize * 4>.  */  insn = read_memory_integer (p, 4);  if ((insn & 0xffffff00) != 0x25010100)    {      /* If the frame is large, instead of a single instruction it	 might be a pair of instructions:	 const <reg>, <rsize * 4>	 sub gr1,gr1,<reg>	 */      int reg;      /* Possible value for rsize.  */      unsigned int rsize0;            if ((insn & 0xff000000) != 0x03000000)	{	  p = pc;	  goto done;	}      reg = (insn >> 8) & 0xff;      rsize0 = (((insn >> 8) & 0xff00) | (insn & 0xff));      p += 4;      insn = read_memory_integer (p, 4);      if ((insn & 0xffffff00) != 0x24010100	  || (insn & 0xff) != reg)	{	  p = pc;	  goto done;	}      if (rsize != NULL)	*rsize = rsize0;    }  else    {      if (rsize != NULL)	*rsize = (insn & 0xff);    }  p += 4;  /* Next instruction must be asgeu V_SPILL,gr1,rab.     * We don't check the vector number to allow for kernel debugging.  The    * kernel will use a different trap number.    */  insn = read_memory_integer (p, 4);  if ((insn & 0xff00ffff) != (0x5e000100|RAB_HW_REGNUM))    {      p = pc;      goto done;    }  p += 4;  /* Next instruction usually sets the frame pointer (lr1) by adding     <size * 4> from gr1.  However, this can (and high C does) be     deferred until anytime before the first function call.  So it is     OK if we don't see anything which sets lr1.       To allow for alternate register sets (gcc -mkernel-registers)  the msp     register number is a compile time constant. */  /* Normally this is just add lr1,gr1,<size * 4>.  */  insn = read_memory_integer (p, 4);  if ((insn & 0xffffff00) == 0x15810100)    p += 4;  else    {      /* However, for large frames it can be	 const <reg>, <size *4>	 add lr1,gr1,<reg>	 */      int reg;      CORE_ADDR q;      if ((insn & 0xff000000) == 0x03000000)	{	  reg = (insn >> 8) & 0xff;	  q = p + 4;	  insn = read_memory_integer (q, 4);	  if ((insn & 0xffffff00) == 0x14810100	      && (insn & 0xff) == reg)	    p = q;	}    }  /* Next comes "add lr{<rsize-1>},msp,0", but only if a memory     frame pointer is in use.  We just check for add lr<anything>,msp,0;     we don't check this rsize against the first instruction, and     we don't check that the trace-back tag indicates a memory frame pointer     is in use.       To allow for alternate register sets (gcc -mkernel-registers)  the msp     register number is a compile time constant.     The recommended instruction is actually "sll lr<whatever>,msp,0".      We check for that, too.  Originally Jim Kingdon's code seemed     to be looking for a "sub" instruction here, but the mask was set     up to lose all the time. */  insn = read_memory_integer (p, 4);  if (((insn & 0xff80ffff) == (0x15800000|(MSP_HW_REGNUM<<8)))     /* add */   || ((insn & 0xff80ffff) == (0x81800000|(MSP_HW_REGNUM<<8))))    /* sll */    {      p += 4;      if (mfp_used != NULL)	*mfp_used = 1;    }  /* Next comes a subtraction from msp to allocate a memory frame,     but only if a memory frame is     being used.  We don't check msize against the trace-back tag.     To allow for alternate register sets (gcc -mkernel-registers) the msp     register number is a compile time constant.     Normally this is just     sub msp,msp,<msize>     */  insn = read_memory_integer (p, 4);  if ((insn & 0xffffff00) == 		(0x25000000|(MSP_HW_REGNUM<<16)|(MSP_HW_REGNUM<<8)))    {      p += 4;      if (msize != NULL) 	*msize = insn & 0xff;    }  else    {      /* For large frames, instead of a single instruction it might	 be	 const <reg>, <msize>	 consth <reg>, <msize>     ; optional	 sub msp,msp,<reg>	 */      int reg;      unsigned msize0;      CORE_ADDR q = p;      if ((insn & 0xff000000) == 0x03000000)	{	  reg = (insn >> 8) & 0xff;	  msize0 = ((insn >> 8) & 0xff00) | (insn & 0xff);	  q += 4;	  insn = read_memory_integer (q, 4);	  /* Check for consth.  */	  if ((insn & 0xff000000) == 0x02000000	      && (insn & 0x0000ff00) == reg)	    {	      msize0 |= (insn << 8) & 0xff000000;	      msize0 |= (insn << 16) & 0x00ff0000;	      q += 4;	      insn = read_memory_integer (q, 4);	    }	  /* Check for sub msp,msp,<reg>.  */          if ((insn & 0xffffff00) == 		(0x24000000|(MSP_HW_REGNUM<<16)|(MSP_HW_REGNUM<<8))	      && (insn & 0xff) == reg)	    {	      p = q + 4;	      if (msize != NULL)		*msize = msize0;	    }	}    } done:  if (msymbol != NULL)    {      if (mi == 0)	{	  /* Add a new cache entry.  */	  mi = (struct prologue_info *)xmalloc (sizeof (struct prologue_info));	  msymbol -> info = (char *)mi;	  mi->rsize_valid = 0;	  mi->msize_valid = 0;	  mi->mfp_valid = 0;	}      /* else, cache entry exists, but info is incomplete.  */      mi->pc = p;      if (rsize != NULL)	{	  mi->rsize = *rsize;	  mi->rsize_valid = 1;	}      if (msize != NULL)	{	  mi->msize = *msize;	  mi->msize_valid = 1;	}      if (mfp_used != NULL)	{	  mi->mfp_used = *mfp_used;	  mi->mfp_valid = 1;	}    }  return p;}/* Advance PC across any function entry prologue instructions   to reach some "real" code.  */CORE_ADDRskip_prologue (pc)     CORE_ADDR pc;{  return examine_prologue (pc, (unsigned *)NULL, (unsigned *)NULL,			   (int *)NULL);}/* * Examine the one or two word tag at the beginning of a function. * The tag word is expect to be at 'p', if it is not there, we fail * by returning 0.  The documentation for the tag word was taken from * page 7-15 of the 29050 User's Manual.  We are assuming that the * m bit is in bit 22 of the tag word, which seems to be the agreed upon * convention today (1/15/92). * msize is return in bytes. */static int	/* 0/1 - failure/success of finding the tag word  */examine_tag(p, is_trans, argcount, msize, mfp_used)     CORE_ADDR p;     int *is_trans;     int   *argcount;     unsigned *msize;     int *mfp_used;{  unsigned int tag1, tag2;  tag1 = read_memory_integer (p, 4);  if ((tag1 & 0xff000000) != 0)		/* Not a tag word */    return 0;  if (tag1 & (1<<23)) 			/* A two word tag */    {       tag2 = read_memory_integer (p+4, 4);       if (msize)	 *msize = tag2;    }  else					/* A one word tag */    {       if (msize)	 *msize = tag1 & 0x7ff;    }  if (is_trans)    *is_trans = ((tag1 & (1<<21)) ? 1 : 0);   if (argcount)    *argcount = (tag1 >> 16) & 0x1f;  if (mfp_used)    *mfp_used = ((tag1 & (1<<22)) ? 1 : 0);   return(1);}/* Initialize the frame.  In addition to setting "extra" frame info,   we also set ->frame because we use it in a nonstandard way, and ->pc   because we need to know it to get the other stuff.  See the diagram   of stacks and the frame cache in tm-29k.h for more detail.  */static voidinit_frame_info (innermost_frame, fci)     int innermost_frame;     struct frame_info *fci;{  CORE_ADDR p;  long insn;  unsigned rsize;  unsigned msize;  int mfp_used, trans;  struct symbol *func;  p = fci->pc;  if (innermost_frame)    fci->frame = read_register (GR1_REGNUM);  else    fci->frame = fci->next_frame + fci->next->rsize;  #if CALL_DUMMY_LOCATION == ON_STACK  This wont work;#else  if (PC_IN_CALL_DUMMY (p, 0, 0))#endif    {      fci->rsize = DUMMY_FRAME_RSIZE;      /* This doesn't matter since we never try to get locals or args	 from a dummy frame.  */      fci->msize = 0;      /* Dummy frames always use a memory frame pointer.  */      fci->saved_msp = 	read_register_stack_integer (fci->frame + DUMMY_FRAME_RSIZE - 4, 4);      fci->flags |= (TRANSPARENT|MFP_USED);      return;    }      func = find_pc_function (p);  if (func != NULL)    p = BLOCK_START (SYMBOL_BLOCK_VALUE (func));  else    {      /* Search backward to find the trace-back tag.  However,	 do not trace back beyond the start of the text segment	 (just as a sanity check to avoid going into never-never land).  */      while (p >= text_start	     && ((insn = read_memory_integer (p, 4)) & 0xff000000) != 0)	p -= 4;            if (p < text_start)	{	  /* Couldn't find the trace-back tag.	     Something strange is going on.  */	  fci->saved_msp = 0;	  fci->rsize = 0;	  fci->msize = 0;	  fci->flags = TRANSPARENT;	  return;	}      else	/* Advance to the first word of the function, i.e. the word	   after the trace-back tag.  */

⌨️ 快捷键说明

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