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

📄 i960-tdep.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
     struct frame_saved_regs *fsr;{  register CORE_ADDR next_addr;  register CORE_ADDR *saved_regs;  register int regnum;  register struct frame_saved_regs *cache_fsr;  extern struct obstack frame_cache_obstack;  CORE_ADDR ip;  struct symtab_and_line sal;  CORE_ADDR limit;  if (!fi->fsr)    {      cache_fsr = (struct frame_saved_regs *)		  obstack_alloc (&frame_cache_obstack,				 sizeof (struct frame_saved_regs));      bzero (cache_fsr, sizeof (struct frame_saved_regs));      fi->fsr = cache_fsr;      /* Find the start and end of the function prologue.  If the PC	 is in the function prologue, we only consider the part that	 has executed already.  */               ip = get_pc_function_start (fi->pc);      sal = find_pc_line (ip, 0);      limit = (sal.end && sal.end < fi->pc) ? sal.end: fi->pc;      examine_prologue (ip, limit, fi->frame, cache_fsr);      /* Record the addresses at which the local registers are saved.	 Strictly speaking, we should only do this for non-leaf procedures,	 but no one will ever look at these values if it is a leaf procedure,	 since local registers are always caller-saved.  */      next_addr = (CORE_ADDR) fi->frame;      saved_regs = cache_fsr->regs;      for (regnum = R0_REGNUM; regnum <= R15_REGNUM; regnum++)	{	  *saved_regs++ = next_addr;	  next_addr += 4;	}      cache_fsr->regs[FP_REGNUM] = cache_fsr->regs[PFP_REGNUM];    }  *fsr = *fi->fsr;  /* Fetch the value of the sp from memory every time, since it     is conceivable that it has changed since the cache was flushed.       This unfortunately undoes much of the savings from caching the      saved register values.  I suggest adding an argument to      get_frame_saved_regs () specifying the register number we're     interested in (or -1 for all registers).  This would be passed     through to FRAME_FIND_SAVED_REGS (), permitting more efficient     computation of saved register addresses (e.g., on the i960,     we don't have to examine the prologue to find local registers). 	-- markf@wrs.com      FIXME, we don't need to refetch this, since the cache is cleared     every time the child process is restarted.  If GDB itself     modifies SP, it has to clear the cache by hand (does it?).  -gnu */  fsr->regs[SP_REGNUM] = read_memory_integer (fsr->regs[SP_REGNUM], 4);}/* Return the address of the argument block for the frame   described by FI.  Returns 0 if the address is unknown.  */CORE_ADDRframe_args_address (fi, must_be_correct)     struct frame_info *fi;{  register FRAME frame;  struct frame_saved_regs fsr;  CORE_ADDR ap;  /* If g14 was saved in the frame by the function prologue code, return     the saved value.  If the frame is current and we are being sloppy,     return the value of g14.  Otherwise, return zero.  */  frame = FRAME_INFO_ID (fi);  get_frame_saved_regs (fi, &fsr);  if (fsr.regs[G14_REGNUM])    ap = read_memory_integer (fsr.regs[G14_REGNUM],4);  else {    if (must_be_correct)      return 0;			/* Don't cache this result */    if (get_next_frame (frame))      ap = 0;    else      ap = read_register (G14_REGNUM);    if (ap == 0)      ap = fi->frame;  }  fi->arg_pointer = ap;		/* Cache it for next time */  return ap;}/* Return the address of the return struct for the frame   described by FI.  Returns 0 if the address is unknown.  */CORE_ADDRframe_struct_result_address (fi)     struct frame_info *fi;{  register FRAME frame;  struct frame_saved_regs fsr;  CORE_ADDR ap;  /* If the frame is non-current, check to see if g14 was saved in the     frame by the function prologue code; return the saved value if so,     zero otherwise.  If the frame is current, return the value of g14.     FIXME, shouldn't this use the saved value as long as we are past     the function prologue, and only use the current value if we have     no saved value and are at TOS?   -- gnu@cygnus.com */  frame = FRAME_INFO_ID (fi);  if (get_next_frame (frame)) {    get_frame_saved_regs (fi, &fsr);    if (fsr.regs[G13_REGNUM])      ap = read_memory_integer (fsr.regs[G13_REGNUM],4);    else      ap = 0;  } else {    ap = read_register (G13_REGNUM);  }  return ap;}/* Return address to which the currently executing leafproc will return,   or 0 if ip is not in a leafproc (or if we can't tell if it is).     Do this by finding the starting address of the routine in which ip lies.   If the instruction there is "mov g14, gx" (where x is in [0,7]), this   is a leafproc and the return address is in register gx.  Well, this is   true unless the return address points at a RET instruction in the current   procedure, which indicates that we have a 'dual entry' routine that   has been entered through the CALL entry point.  */CORE_ADDRleafproc_return (ip)     CORE_ADDR ip;	/* ip from currently executing function	*/{  register struct minimal_symbol *msymbol;  char *p;  int dst;  unsigned int insn1, insn2;  CORE_ADDR return_addr;  char *index ();  if ((msymbol = lookup_minimal_symbol_by_pc (ip)) != NULL)    {      if ((p = index (msymbol -> name, '.')) && !strcmp (p, ".lf"))	{	  if (next_insn (msymbol -> address, &insn1, &insn2)	      && (insn1 & 0xff87ffff) == 0x5c80161e       /* mov g14, gx */	      && (dst = REG_SRCDST (insn1)) <= G0_REGNUM + 7)	    {	      /* Get the return address.  If the "mov g14, gx" 		 instruction hasn't been executed yet, read		 the return address from g14; otherwise, read it		 from the register into which g14 was moved.  */	      return_addr = read_register ((ip == msymbol->address)				           ? G14_REGNUM : dst);	      /* We know we are in a leaf procedure, but we don't know		 whether the caller actually did a "bal" to the ".lf"		 entry point, or a normal "call" to the non-leaf entry		 point one instruction before.  In the latter case, the		 return address will be the address of a "ret"		 instruction within the procedure itself.  We test for		 this below.  */	      if (!next_insn (return_addr, &insn1, &insn2)		  || (insn1 & 0xff000000) != 0xa000000   /* ret */	          || lookup_minimal_symbol_by_pc (return_addr) != msymbol)		return (return_addr);	    }	}    }    return (0);}/* Immediately after a function call, return the saved pc.   Can't go through the frames for this because on some machines   the new frame is not set up until the new function executes   some instructions.    On the i960, the frame *is* set up immediately after the call,   unless the function is a leaf procedure.  */CORE_ADDRsaved_pc_after_call (frame)     FRAME frame;{  CORE_ADDR saved_pc;  CORE_ADDR get_frame_pc ();  saved_pc = leafproc_return (get_frame_pc (frame));  if (!saved_pc)    saved_pc = FRAME_SAVED_PC (frame);  return (saved_pc);}/* Discard from the stack the innermost frame,   restoring all saved registers.  */pop_frame (){  register struct frame_info *current_fi, *prev_fi;  register int i;  CORE_ADDR save_addr;  CORE_ADDR leaf_return_addr;  struct frame_saved_regs fsr;  char local_regs_buf[16 * 4];  current_fi = get_frame_info (get_current_frame ());  /* First, undo what the hardware does when we return.     If this is a non-leaf procedure, restore local registers from     the save area in the calling frame.  Otherwise, load the return     address obtained from leafproc_return () into the rip.  */  leaf_return_addr = leafproc_return (current_fi->pc);  if (!leaf_return_addr)    {      /* Non-leaf procedure.  Restore local registers, incl IP.  */      prev_fi = get_frame_info (get_prev_frame (FRAME_INFO_ID (current_fi)));      read_memory (prev_fi->frame, local_regs_buf, sizeof (local_regs_buf));      write_register_bytes (REGISTER_BYTE (R0_REGNUM), local_regs_buf, 		            sizeof (local_regs_buf));      /* Restore frame pointer.  */      write_register (FP_REGNUM, prev_fi->frame);    }  else    {      /* Leaf procedure.  Just restore the return address into the IP.  */      write_register (RIP_REGNUM, leaf_return_addr);    }  /* Now restore any global regs that the current function had saved. */  get_frame_saved_regs (current_fi, &fsr);  for (i = G0_REGNUM; i < G14_REGNUM; i++)    {      if (save_addr = fsr.regs[i])	write_register (i, read_memory_integer (save_addr, 4));    }  /* Flush the frame cache, create a frame for the new innermost frame,     and make it the current frame.  */  flush_cached_frames ();  set_current_frame (create_new_frame (read_register (FP_REGNUM), read_pc ()));}/* Print out text describing a "signal number" with which the i80960 halted.     See the file "fault.c" in the nindy monitor source code for a list   of stop codes.  */voidprint_fault( siggnal )    int siggnal;	/* Signal number, as returned by target_wait() */{	static char unknown[] = "Unknown fault or trace";	static char *sigmsgs[] = {		/* FAULTS */		"parallel fault",	/* 0x00 */		unknown,		/* 0x01 */		"operation fault",	/* 0x02 */		"arithmetic fault",	/* 0x03 */		"floating point fault",	/* 0x04 */		"constraint fault",	/* 0x05 */		"virtual memory fault",	/* 0x06 */		"protection fault",	/* 0x07 */		"machine fault",	/* 0x08 */		"structural fault",	/* 0x09 */		"type fault",		/* 0x0a */		"reserved (0xb) fault",	/* 0x0b */		"process fault",	/* 0x0c */		"descriptor fault",	/* 0x0d */		"event fault",		/* 0x0e */		"reserved (0xf) fault",	/* 0x0f */		/* TRACES */		"single-step trace",	/* 0x10 */		"branch trace",		/* 0x11 */		"call trace",		/* 0x12 */		"return trace",		/* 0x13 */		"pre-return trace",	/* 0x14 */		"supervisor call trace",/* 0x15 */		"breakpoint trace",	/* 0x16 */	};#	define NUMMSGS ((int)( sizeof(sigmsgs) / sizeof(sigmsgs[0]) ))	if (siggnal < NSIG) {	      printf ("\nProgram received signal %d, %s\n",		      siggnal, safe_strsignal (siggnal));	} else {		/* The various target_wait()s bias the 80960 "signal number"		   by adding NSIG to it, so it won't get confused with any		   of the Unix signals elsewhere in GDB.  We need to		   "unbias" it before using it.  */		siggnal -= NSIG;		printf("Program stopped for reason #%d: %s.\n", siggnal,				(siggnal < NUMMSGS && siggnal >= 0)?				sigmsgs[siggnal] : unknown );	}}/* Initialization stub */_initialize_i960_tdep (){  check_host ();}

⌨️ 快捷键说明

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