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

📄 i960-tdep.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Target-machine dependent code for the Intel 960   Copyright (C) 1991 Free Software Foundation, Inc.   Contributed by Intel Corporation.   examine_prologue and other parts contributed by Wind River Systems.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.  *//* Miscellaneous i80960-dependent routines.   Most are called from macros defined in "tm-i960.h".  */#include "defs.h"#include <signal.h>#include "symtab.h"#include "value.h"#include "frame.h"#include "ieee-float.h"/* Structure of i960 extended floating point format.  */const struct ext_format ext_format_i960 = {/* tot sbyte smask expbyte manbyte */   12, 9,    0x80, 9,8,	   4,0,		/* i960 */};/* gdb960 is always running on a non-960 host.  Check its characteristics.   This routine must be called as part of gdb initialization.  */static voidcheck_host(){	int i;	static struct typestruct {		int hostsize;		/* Size of type on host		*/		int i960size;		/* Size of type on i960		*/		char *typename;		/* Name of type, for error msg	*/	} types[] = {		{ sizeof(short),  2, "short" },		{ sizeof(int),    4, "int" },		{ sizeof(long),   4, "long" },		{ sizeof(float),  4, "float" },		{ sizeof(double), 8, "double" },		{ sizeof(char *), 4, "pointer" },	};#define TYPELEN	(sizeof(types) / sizeof(struct typestruct))	/* Make sure that host type sizes are same as i960	 */	for ( i = 0; i < TYPELEN; i++ ){		if ( types[i].hostsize != types[i].i960size ){			printf("sizeof(%s) != %d:  PROCEED AT YOUR OWN RISK!\n",					types[i].typename, types[i].i960size );		}	}}/* Examine an i960 function prologue, recording the addresses at which   registers are saved explicitly by the prologue code, and returning   the address of the first instruction after the prologue (but not   after the instruction at address LIMIT, as explained below).   LIMIT places an upper bound on addresses of the instructions to be   examined.  If the prologue code scan reaches LIMIT, the scan is   aborted and LIMIT is returned.  This is used, when examining the   prologue for the current frame, to keep examine_prologue () from   claiming that a given register has been saved when in fact the   instruction that saves it has not yet been executed.  LIMIT is used   at other times to stop the scan when we hit code after the true   function prologue (e.g. for the first source line) which might   otherwise be mistaken for function prologue.   The format of the function prologue matched by this routine is   derived from examination of the source to gcc960 1.21, particularly   the routine i960_function_prologue ().  A "regular expression" for   the function prologue is given below:   (lda LRn, g14    mov g14, g[0-7]    (mov 0, g14) | (lda 0, g14))?   (mov[qtl]? g[0-15], r[4-15])*   ((addo [1-31], sp, sp) | (lda n(sp), sp))?   (st[qtl]? g[0-15], n(fp))*   (cmpobne 0, g14, LFn    mov sp, g14    lda 0x30(sp), sp    LFn: stq g0, (g14)    stq g4, 0x10(g14)    stq g8, 0x20(g14))?   (st g14, n(fp))?   (mov g13,r[4-15])?*//* Macros for extracting fields from i960 instructions.  */#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))#define REG_SRC1(insn)    EXTRACT_FIELD (insn, 0, 5)#define REG_SRC2(insn)    EXTRACT_FIELD (insn, 14, 5)#define REG_SRCDST(insn)  EXTRACT_FIELD (insn, 19, 5)#define MEM_SRCDST(insn)  EXTRACT_FIELD (insn, 19, 5)#define MEMA_OFFSET(insn) EXTRACT_FIELD (insn, 0, 12)/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or   is not the address of a valid instruction, the address of the next   instruction beyond ADDR otherwise.  *PWORD1 receives the first word   of the instruction, and (for two-word instructions), *PWORD2 receives   the second.  */#define NEXT_PROLOGUE_INSN(addr, lim, pword1, pword2) \  (((addr) < (lim)) ? next_insn (addr, pword1, pword2) : 0)static CORE_ADDRexamine_prologue (ip, limit, frame_addr, fsr)     register CORE_ADDR ip;     register CORE_ADDR limit;     FRAME_ADDR frame_addr;     struct frame_saved_regs *fsr;{  register CORE_ADDR next_ip;  register int src, dst;  register unsigned int *pcode;  unsigned int insn1, insn2;  int size;  int within_leaf_prologue;  CORE_ADDR save_addr;  static unsigned int varargs_prologue_code [] =    {       0x3507a00c,	/* cmpobne 0x0, g14, LFn */       0x5cf01601,	/* mov sp, g14		 */       0x8c086030,	/* lda 0x30(sp), sp	 */       0xb2879000,	/* LFn: stq  g0, (g14)   */       0xb2a7a010,	/* stq g4, 0x10(g14)	 */       0xb2c7a020	/* stq g8, 0x20(g14)	 */    };  /* Accept a leaf procedure prologue code fragment if present.     Note that ip might point to either the leaf or non-leaf     entry point; we look for the non-leaf entry point first:  */  within_leaf_prologue = 0;  if ((next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2))      && ((insn1 & 0xfffff000) == 0x8cf00000         /* lda LRx, g14 (MEMA) */	  || (insn1 & 0xfffffc60) == 0x8cf03000))    /* lda LRx, g14 (MEMB) */    {      within_leaf_prologue = 1;      next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn1, &insn2);    }  /* Now look for the prologue code at a leaf entry point:  */  if (next_ip      && (insn1 & 0xff87ffff) == 0x5c80161e         /* mov g14, gx */      && REG_SRCDST (insn1) <= G0_REGNUM + 7)    {      within_leaf_prologue = 1;      if ((next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn1, &insn2))	  && (insn1 == 0x8cf00000                   /* lda 0, g14 */	      || insn1 == 0x5cf01e00))              /* mov 0, g14 */	{	  ip = next_ip;	  next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);	  within_leaf_prologue = 0;	}    }  /* If something that looks like the beginning of a leaf prologue     has been seen, but the remainder of the prologue is missing, bail.     We don't know what we've got.  */  if (within_leaf_prologue)    return (ip);	    /* Accept zero or more instances of "mov[qtl]? gx, ry", where y >= 4.     This may cause us to mistake the moving of a register     parameter to a local register for the saving of a callee-saved     register, but that can't be helped, since with the     "-fcall-saved" flag, any register can be made callee-saved.  */  while (next_ip	 && (insn1 & 0xfc802fb0) == 0x5c000610	 && (dst = REG_SRCDST (insn1)) >= (R0_REGNUM + 4))    {      src = REG_SRC1 (insn1);      size = EXTRACT_FIELD (insn1, 24, 2) + 1;      save_addr = frame_addr + ((dst - R0_REGNUM) * 4);      while (size--)	{	  fsr->regs[src++] = save_addr;	  save_addr += 4;	}      ip = next_ip;      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);    }  /* Accept an optional "addo n, sp, sp" or "lda n(sp), sp".  */  if (next_ip &&      ((insn1 & 0xffffffe0) == 0x59084800	/* addo n, sp, sp */       || (insn1 & 0xfffff000) == 0x8c086000	/* lda n(sp), sp (MEMA) */       || (insn1 & 0xfffffc60) == 0x8c087400))	/* lda n(sp), sp (MEMB) */    {      ip = next_ip;      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);    }  /* Accept zero or more instances of "st[qtl]? gx, n(fp)".       This may cause us to mistake the copying of a register     parameter to the frame for the saving of a callee-saved     register, but that can't be helped, since with the     "-fcall-saved" flag, any register can be made callee-saved.     We can, however, refuse to accept a save of register g14,     since that is matched explicitly below.  */  while (next_ip &&	 ((insn1 & 0xf787f000) == 0x9287e000      /* stl? gx, n(fp) (MEMA) */	  || (insn1 & 0xf787fc60) == 0x9287f400   /* stl? gx, n(fp) (MEMB) */	  || (insn1 & 0xef87f000) == 0xa287e000   /* st[tq] gx, n(fp) (MEMA) */	  || (insn1 & 0xef87fc60) == 0xa287f400)  /* st[tq] gx, n(fp) (MEMB) */	 && ((src = MEM_SRCDST (insn1)) != G14_REGNUM))    {      save_addr = frame_addr + ((insn1 & BITMASK (12, 1))				? insn2 : MEMA_OFFSET (insn1));      size = (insn1 & BITMASK (29, 1)) ? ((insn1 & BITMASK (28, 1)) ? 4 : 3)	                               : ((insn1 & BITMASK (27, 1)) ? 2 : 1);      while (size--)	{	  fsr->regs[src++] = save_addr;	  save_addr += 4;	}      ip = next_ip;      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);    }  /* Accept the varargs prologue code if present.  */  size = sizeof (varargs_prologue_code) / sizeof (int);  pcode = varargs_prologue_code;  while (size-- && next_ip && *pcode++ == insn1)    {      ip = next_ip;      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);    }  /* Accept an optional "st g14, n(fp)".  */  if (next_ip &&      ((insn1 & 0xfffff000) == 0x92f7e000	 /* st g14, n(fp) (MEMA) */       || (insn1 & 0xfffffc60) == 0x92f7f400))   /* st g14, n(fp) (MEMB) */    {      fsr->regs[G14_REGNUM] = frame_addr + ((insn1 & BITMASK (12, 1))				            ? insn2 : MEMA_OFFSET (insn1));      ip = next_ip;      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);    }  /* Accept zero or one instance of "mov g13, ry", where y >= 4.     This is saving the address where a struct should be returned.  */  if (next_ip      && (insn1 & 0xff802fbf) == 0x5c00061d      && (dst = REG_SRCDST (insn1)) >= (R0_REGNUM + 4))    {      save_addr = frame_addr + ((dst - R0_REGNUM) * 4);      fsr->regs[G0_REGNUM+13] = save_addr;      ip = next_ip;#if 0  /* We'll need this once there is a subsequent instruction examined. */      next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);#endif    }  return (ip);}/* Given an ip value corresponding to the start of a function,   return the ip of the first instruction after the function    prologue.  */CORE_ADDRskip_prologue (ip)     CORE_ADDR (ip);{  struct frame_saved_regs saved_regs_dummy;  struct symtab_and_line sal;  CORE_ADDR limit;  sal = find_pc_line (ip, 0);  limit = (sal.end) ? sal.end : 0xffffffff;  return (examine_prologue (ip, limit, (FRAME_ADDR) 0, &saved_regs_dummy));}/* Put here the code to store, into a struct frame_saved_regs,   the addresses of the saved registers of frame described by FRAME_INFO.   This includes special registers such as pc and fp saved in special   ways in the stack frame.  sp is even more special:   the address we return for it IS the sp for the next frame.   We cache the result of doing this in the frame_cache_obstack, since   it is fairly expensive.  */voidframe_find_saved_regs (fi, fsr)     struct frame_info *fi;

⌨️ 快捷键说明

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