static int
mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno)
{
  return (regno == MIPS_ZERO_REGNUM
	  || regno == mips_regnum (gdbarch)->fp_implementation_revision);
}
static bool
getregs_supplies (struct gdbarch *gdbarch, int regnum)
{
  return (regnum >= MIPS_ZERO_REGNUM
	  && regnum <= mips_regnum (gdbarch)->pc);
}
static bool
getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
{
  return (regnum >= mips_regnum (gdbarch)->fp0
	  && regnum <= mips_regnum (gdbarch)->fp_implementation_revision);
}
Beispiel #4
0
static void
mips_linux_o32_sigframe_init (const struct tramp_frame *self,
			      struct frame_info *next_frame,
			      struct trad_frame_cache *this_cache,
			      CORE_ADDR func)
{
  int ireg, reg_position;
  CORE_ADDR sigcontext_base = func - SIGFRAME_CODE_OFFSET;
  const struct mips_regnum *regs = mips_regnum (current_gdbarch);
  CORE_ADDR regs_base;

  if (self == &mips_linux_o32_sigframe)
    sigcontext_base += SIGFRAME_SIGCONTEXT_OFFSET;
  else
    sigcontext_base += RTSIGFRAME_SIGCONTEXT_OFFSET;

  /* I'm not proud of this hack.  Eventually we will have the
     infrastructure to indicate the size of saved registers on a
     per-frame basis, but right now we don't; the kernel saves eight
     bytes but we only want four.  Use regs_base to access any
     64-bit fields.  */
  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
    regs_base = sigcontext_base + 4;
  else
    regs_base = sigcontext_base;

  if (mips_linux_restart_reg_p (current_gdbarch))
    trad_frame_set_reg_addr (this_cache,
			     (MIPS_RESTART_REGNUM
			      + gdbarch_num_regs (current_gdbarch)),
			     regs_base + SIGCONTEXT_REGS);

  for (ireg = 1; ireg < 32; ireg++)
    trad_frame_set_reg_addr (this_cache,
			     ireg + MIPS_ZERO_REGNUM
			       + gdbarch_num_regs (current_gdbarch),
			     regs_base + SIGCONTEXT_REGS
			     + ireg * SIGCONTEXT_REG_SIZE);

  /* The way that floating point registers are saved, unfortunately,
     depends on the architecture the kernel is built for.  For the r3000 and
     tx39, four bytes of each register are at the beginning of each of the
     32 eight byte slots.  For everything else, the registers are saved
     using double precision; only the even-numbered slots are initialized,
     and the high bits are the odd-numbered register.  Assume the latter
     layout, since we can't tell, and it's much more common.  Which bits are
     the "high" bits depends on endianness.  */
  for (ireg = 0; ireg < 32; ireg++)
    if ((gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) != (ireg & 1))
      trad_frame_set_reg_addr (this_cache,
			       ireg + regs->fp0 +
				 gdbarch_num_regs (current_gdbarch),
			       sigcontext_base + SIGCONTEXT_FPREGS + 4
			       + (ireg & ~1) * SIGCONTEXT_REG_SIZE);
    else
      trad_frame_set_reg_addr (this_cache,
			       ireg + regs->fp0
				 + gdbarch_num_regs (current_gdbarch),
			       sigcontext_base + SIGCONTEXT_FPREGS
			       + (ireg & ~1) * SIGCONTEXT_REG_SIZE);

  trad_frame_set_reg_addr (this_cache,
			   regs->pc + gdbarch_num_regs (current_gdbarch),
			   regs_base + SIGCONTEXT_PC);

  trad_frame_set_reg_addr (this_cache,
			   regs->fp_control_status
			   + gdbarch_num_regs (current_gdbarch),
			   sigcontext_base + SIGCONTEXT_FPCSR);
  trad_frame_set_reg_addr (this_cache,
			   regs->hi + gdbarch_num_regs (current_gdbarch),
			   regs_base + SIGCONTEXT_HI);
  trad_frame_set_reg_addr (this_cache,
			   regs->lo + gdbarch_num_regs (current_gdbarch),
			   regs_base + SIGCONTEXT_LO);
  trad_frame_set_reg_addr (this_cache,
			   regs->cause + gdbarch_num_regs (current_gdbarch),
			   sigcontext_base + SIGCONTEXT_CAUSE);
  trad_frame_set_reg_addr (this_cache,
			   regs->badvaddr + gdbarch_num_regs (current_gdbarch),
			   sigcontext_base + SIGCONTEXT_BADVADDR);

  /* Choice of the bottom of the sigframe is somewhat arbitrary.  */
  trad_frame_set_id (this_cache,
		     frame_id_build (func - SIGFRAME_CODE_OFFSET,
				     func));
}
Beispiel #5
0
void
mips64_fill_fpregset (const struct regcache *regcache,
		      mips64_elf_fpregset_t *fpregsetp, int regno)
{
  gdb_byte *to;

  if ((regno >= gdbarch_fp0_regnum (current_gdbarch))
      && (regno < gdbarch_fp0_regnum (current_gdbarch) + 32))
    {
      /* See mips_linux_o32_sigframe_init for a description of the
	 peculiar FP register layout.  */
      if (register_size (current_gdbarch, regno) == 4)
	{
	  int regi = regno - gdbarch_fp0_regnum (current_gdbarch);

	  to = (gdb_byte *) (*fpregsetp + (regi & ~1));
	  if ((gdbarch_byte_order (current_gdbarch)
	      == BFD_ENDIAN_BIG) != (regi & 1))
	    to += 4;
	  regcache_raw_collect (regcache, regno, to);
	}
      else
	{
	  to = (gdb_byte *) (*fpregsetp + regno
			     - gdbarch_fp0_regnum (current_gdbarch));
	  regcache_raw_collect (regcache, regno, to);
	}
    }
  else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
    {
      gdb_byte buf[MAX_REGISTER_SIZE];
      LONGEST val;

      regcache_raw_collect (regcache, regno, buf);
      val = extract_signed_integer (buf,
				    register_size (current_gdbarch, regno));
      to = (gdb_byte *) (*fpregsetp + 32);
      store_signed_integer (to, 4, val);
    }
  else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
    {
      gdb_byte buf[MAX_REGISTER_SIZE];
      LONGEST val;

      regcache_raw_collect (regcache, regno, buf);
      val = extract_signed_integer (buf,
				    register_size (current_gdbarch, regno));
      to = (gdb_byte *) (*fpregsetp + 32) + 4;
      store_signed_integer (to, 4, val);
    }
  else if (regno == -1)
    {
      int regi;

      for (regi = 0; regi < 32; regi++)
	mips64_fill_fpregset (regcache, fpregsetp,
			      gdbarch_fp0_regnum (current_gdbarch) + regi);
      mips64_fill_fpregset (regcache, fpregsetp,
			    mips_regnum (current_gdbarch)->fp_control_status);
      mips64_fill_fpregset (regcache, fpregsetp,
			    (mips_regnum (current_gdbarch)
			     ->fp_implementation_revision));
    }
}
Beispiel #6
0
static void
mips_linux_n32n64_sigframe_init (const struct tramp_frame *self,
				 struct frame_info *next_frame,
				 struct trad_frame_cache *this_cache,
				 CORE_ADDR func)
{
  int ireg, reg_position;
  CORE_ADDR sigcontext_base = func - SIGFRAME_CODE_OFFSET;
  const struct mips_regnum *regs = mips_regnum (current_gdbarch);

  if (self == &mips_linux_n32_rt_sigframe)
    sigcontext_base += N32_SIGFRAME_SIGCONTEXT_OFFSET;
  else
    sigcontext_base += N64_SIGFRAME_SIGCONTEXT_OFFSET;

  if (mips_linux_restart_reg_p (current_gdbarch))
    trad_frame_set_reg_addr (this_cache,
			     (MIPS_RESTART_REGNUM
			      + gdbarch_num_regs (current_gdbarch)),
			     sigcontext_base + N64_SIGCONTEXT_REGS);

  for (ireg = 1; ireg < 32; ireg++)
    trad_frame_set_reg_addr (this_cache,
			     ireg + MIPS_ZERO_REGNUM
			     + gdbarch_num_regs (current_gdbarch),
			     sigcontext_base + N64_SIGCONTEXT_REGS
			     + ireg * N64_SIGCONTEXT_REG_SIZE);

  for (ireg = 0; ireg < 32; ireg++)
    trad_frame_set_reg_addr (this_cache,
			     ireg + regs->fp0
			     + gdbarch_num_regs (current_gdbarch),
			     sigcontext_base + N64_SIGCONTEXT_FPREGS
			     + ireg * N64_SIGCONTEXT_REG_SIZE);

  trad_frame_set_reg_addr (this_cache,
			   regs->pc + gdbarch_num_regs (current_gdbarch),
			   sigcontext_base + N64_SIGCONTEXT_PC);

  trad_frame_set_reg_addr (this_cache,
			   regs->fp_control_status
			   + gdbarch_num_regs (current_gdbarch),
			   sigcontext_base + N64_SIGCONTEXT_FPCSR);
  trad_frame_set_reg_addr (this_cache,
			   regs->hi + gdbarch_num_regs (current_gdbarch),
			   sigcontext_base + N64_SIGCONTEXT_HI);
  trad_frame_set_reg_addr (this_cache,
			   regs->lo + gdbarch_num_regs (current_gdbarch),
			   sigcontext_base + N64_SIGCONTEXT_LO);
  trad_frame_set_reg_addr (this_cache,
			   regs->cause + gdbarch_num_regs (current_gdbarch),
			   sigcontext_base + N64_SIGCONTEXT_CAUSE);
  trad_frame_set_reg_addr (this_cache,
			   regs->badvaddr + gdbarch_num_regs (current_gdbarch),
			   sigcontext_base + N64_SIGCONTEXT_BADVADDR);

  /* Choice of the bottom of the sigframe is somewhat arbitrary.  */
  trad_frame_set_id (this_cache,
		     frame_id_build (func - SIGFRAME_CODE_OFFSET,
				     func));
}
Beispiel #7
0
static void
mips_linux_n32n64_sigframe_init (const struct tramp_frame *self,
				 struct frame_info *this_frame,
				 struct trad_frame_cache *this_cache,
				 CORE_ADDR func)
{
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  int ireg;
  CORE_ADDR frame_sp = get_frame_sp (this_frame);
  CORE_ADDR sigcontext_base;
  const struct mips_regnum *regs = mips_regnum (gdbarch);

  if (self == &mips_linux_n32_rt_sigframe)
    sigcontext_base = frame_sp + N32_SIGFRAME_SIGCONTEXT_OFFSET;
  else
    sigcontext_base = frame_sp + N64_SIGFRAME_SIGCONTEXT_OFFSET;

  if (mips_linux_restart_reg_p (gdbarch))
    trad_frame_set_reg_addr (this_cache,
			     (MIPS_RESTART_REGNUM
			      + gdbarch_num_regs (gdbarch)),
			     sigcontext_base + N64_SIGCONTEXT_REGS);

  for (ireg = 1; ireg < 32; ireg++)
    trad_frame_set_reg_addr (this_cache,
			     ireg + MIPS_ZERO_REGNUM
			     + gdbarch_num_regs (gdbarch),
			     sigcontext_base + N64_SIGCONTEXT_REGS
			     + ireg * N64_SIGCONTEXT_REG_SIZE);

  for (ireg = 0; ireg < 32; ireg++)
    trad_frame_set_reg_addr (this_cache,
			     ireg + regs->fp0
			     + gdbarch_num_regs (gdbarch),
			     sigcontext_base + N64_SIGCONTEXT_FPREGS
			     + ireg * N64_SIGCONTEXT_REG_SIZE);

  trad_frame_set_reg_addr (this_cache,
			   regs->pc + gdbarch_num_regs (gdbarch),
			   sigcontext_base + N64_SIGCONTEXT_PC);

  trad_frame_set_reg_addr (this_cache,
			   regs->fp_control_status
			   + gdbarch_num_regs (gdbarch),
			   sigcontext_base + N64_SIGCONTEXT_FPCSR);

  trad_frame_set_reg_addr (this_cache,
			   regs->hi + gdbarch_num_regs (gdbarch),
			   sigcontext_base + N64_SIGCONTEXT_HI);
  trad_frame_set_reg_addr (this_cache,
			   regs->lo + gdbarch_num_regs (gdbarch),
			   sigcontext_base + N64_SIGCONTEXT_LO);

  if (regs->dspacc != -1)
    {
      trad_frame_set_reg_addr (this_cache,
			       regs->dspacc + 0 + gdbarch_num_regs (gdbarch),
			       sigcontext_base + N64_SIGCONTEXT_HI1);
      trad_frame_set_reg_addr (this_cache,
			       regs->dspacc + 1 + gdbarch_num_regs (gdbarch),
			       sigcontext_base + N64_SIGCONTEXT_LO1);
      trad_frame_set_reg_addr (this_cache,
			       regs->dspacc + 2 + gdbarch_num_regs (gdbarch),
			       sigcontext_base + N64_SIGCONTEXT_HI2);
      trad_frame_set_reg_addr (this_cache,
			       regs->dspacc + 3 + gdbarch_num_regs (gdbarch),
			       sigcontext_base + N64_SIGCONTEXT_LO2);
      trad_frame_set_reg_addr (this_cache,
			       regs->dspacc + 4 + gdbarch_num_regs (gdbarch),
			       sigcontext_base + N64_SIGCONTEXT_HI3);
      trad_frame_set_reg_addr (this_cache,
			       regs->dspacc + 5 + gdbarch_num_regs (gdbarch),
			       sigcontext_base + N64_SIGCONTEXT_LO3);
    }
  if (regs->dspctl != -1)
    trad_frame_set_reg_addr (this_cache,
			     regs->dspctl + gdbarch_num_regs (gdbarch),
			     sigcontext_base + N64_SIGCONTEXT_DSPCTL);

  /* Choice of the bottom of the sigframe is somewhat arbitrary.  */
  trad_frame_set_id (this_cache, frame_id_build (frame_sp, func));
}
static struct trad_frame_cache *
mips_sde_frame_cache (struct frame_info *this_frame, void **this_cache)
{
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  const struct mips_regnum *regs = mips_regnum (gdbarch);
  const int sizeof_reg_t = mips_abi_regsize (gdbarch);
  enum mips_abi abi = mips_abi (gdbarch);
  struct trad_frame_cache *cache;
  CORE_ADDR xcpt_frame;
  CORE_ADDR start_addr;
  CORE_ADDR stack_addr;
  CORE_ADDR pc;
  int i;

  if (*this_cache != NULL)
    return (struct trad_frame_cache *) *this_cache;
  cache = trad_frame_cache_zalloc (this_frame);
  *this_cache = cache;

  /* The previous registers are held in struct xcptcontext
     which is at $sp+offs

     struct xcptcontext {
       reg_t	sr;		CP0 Status
       reg_t	cr;		CP0 Cause
       reg_t	epc;		CP0 EPC
       reg_t	vaddr;		CP0 BadVAddr
       reg_t	regs[32];	General registers
       reg_t	mdlo;		LO
       reg_t	mdhi;		HI
       reg_t	mdex;		ACX
       ...
     };
  */

  stack_addr = get_frame_register_signed (this_frame,
					  gdbarch_sp_regnum (gdbarch));
  switch (abi)
    {
    case MIPS_ABI_O32:
      /* 40: XCPTCONTEXT
	 24: xcpt_gen() argspace		(16 bytes)
	 16: _xcptcall() saved ra, rounded up	( 8 bytes)
	 00: _xcptcall() argspace 		(16 bytes)  */
      xcpt_frame = stack_addr + 40;
      break;
    case MIPS_ABI_N32:
    case MIPS_ABI_N64:
    default:			/* Wild guess.  */
      /* 16: XCPTCONTEXT
	 16: xcpt_gen() argspace 		( 0 bytes)
	 00: _xcptcall() saved ra, rounded up	(16 bytes)  */
      xcpt_frame = stack_addr + 16;
      break;
    }

  trad_frame_set_reg_addr (cache,
			   MIPS_PS_REGNUM + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 0 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->cause + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 1 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->pc + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 2 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->badvaddr + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 3 * sizeof_reg_t);
  for (i = 0; i < MIPS_NUMREGS; i++)
    trad_frame_set_reg_addr (cache,
			     i + MIPS_ZERO_REGNUM + gdbarch_num_regs (gdbarch),
			     xcpt_frame + (4 + i) * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->lo + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 36 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->hi + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 37 * sizeof_reg_t);

  pc = get_frame_pc (this_frame);
  find_pc_partial_function (pc, NULL, &start_addr, NULL);
  trad_frame_set_id (cache, frame_id_build (start_addr, stack_addr));

  return cache;
}