예제 #1
0
static void
ppc_linux_collect_gregset (const struct regset *regset,
			   const struct regcache *regcache,
			   int regnum, void *gregs, size_t len)
{
  const struct ppc_reg_offsets *offsets = regset->descr;

  /* Clear areas in the linux gregset not written elsewhere.  */
  if (regnum == -1)
    memset (gregs, 0, len);

  ppc_collect_gregset (regset, regcache, regnum, gregs, len);

  if (ppc_linux_trap_reg_p (get_regcache_arch (regcache)))
    {
      /* "orig_r3" is stored 2 slots after "pc".  */
      if (regnum == -1 || regnum == PPC_ORIG_R3_REGNUM)
	ppc_collect_reg (regcache, PPC_ORIG_R3_REGNUM, gregs,
			 offsets->pc_offset + 2 * offsets->gpr_size,
			 offsets->gpr_size);

      /* "trap" is stored 8 slots after "pc".  */
      if (regnum == -1 || regnum == PPC_TRAP_REGNUM)
	ppc_collect_reg (regcache, PPC_TRAP_REGNUM, gregs,
			 offsets->pc_offset + 8 * offsets->gpr_size,
			 offsets->gpr_size);
    }
}
예제 #2
0
static void
ppc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);

  regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch), pc);

  /* Set special TRAP register to -1 to prevent the kernel from
     messing with the PC we just installed, if we happen to be
     within an interrupted system call that the kernel wants to
     restart.

     Note that after we return from the dummy call, the TRAP and
     ORIG_R3 registers will be automatically restored, and the
     kernel continues to restart the system call at this point.  */
  if (ppc_linux_trap_reg_p (gdbarch))
    regcache_cooked_write_unsigned (regcache, PPC_TRAP_REGNUM, -1);
}
예제 #3
0
static void
store_ppc_registers (const struct regcache *regcache, int tid)
{
  int i;
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  
  for (i = 0; i < ppc_num_gprs; i++)
    store_register (regcache, tid, tdep->ppc_gp0_regnum + i);
  if (tdep->ppc_fp0_regnum >= 0)
    for (i = 0; i < ppc_num_fprs; i++)
      store_register (regcache, tid, tdep->ppc_fp0_regnum + i);
  store_register (regcache, tid, gdbarch_pc_regnum (gdbarch));
  if (tdep->ppc_ps_regnum != -1)
    store_register (regcache, tid, tdep->ppc_ps_regnum);
  if (tdep->ppc_cr_regnum != -1)
    store_register (regcache, tid, tdep->ppc_cr_regnum);
  if (tdep->ppc_lr_regnum != -1)
    store_register (regcache, tid, tdep->ppc_lr_regnum);
  if (tdep->ppc_ctr_regnum != -1)
    store_register (regcache, tid, tdep->ppc_ctr_regnum);
  if (tdep->ppc_xer_regnum != -1)
    store_register (regcache, tid, tdep->ppc_xer_regnum);
  if (tdep->ppc_mq_regnum != -1)
    store_register (regcache, tid, tdep->ppc_mq_regnum);
  if (tdep->ppc_fpscr_regnum != -1)
    store_register (regcache, tid, tdep->ppc_fpscr_regnum);
  if (ppc_linux_trap_reg_p (gdbarch))
    {
      store_register (regcache, tid, PPC_ORIG_R3_REGNUM);
      store_register (regcache, tid, PPC_TRAP_REGNUM);
    }
  if (have_ptrace_getvrregs)
    if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
      store_altivec_registers (regcache, tid);
  if (have_ptrace_getsetvsxregs)
    if (tdep->ppc_vsr0_upper_regnum != -1)
      store_vsx_registers (regcache, tid);
  if (tdep->ppc_ev0_upper_regnum >= 0)
    store_spe_register (regcache, tid, -1);
}
예제 #4
0
static void
ppc_linux_supply_gregset (const struct regset *regset,
			  struct regcache *regcache,
			  int regnum, const void *gregs, size_t len)
{
  const struct ppc_reg_offsets *offsets = regset->descr;

  ppc_supply_gregset (regset, regcache, regnum, gregs, len);

  if (ppc_linux_trap_reg_p (get_regcache_arch (regcache)))
    {
      /* "orig_r3" is stored 2 slots after "pc".  */
      if (regnum == -1 || regnum == PPC_ORIG_R3_REGNUM)
	ppc_supply_reg (regcache, PPC_ORIG_R3_REGNUM, gregs,
			offsets->pc_offset + 2 * offsets->gpr_size,
			offsets->gpr_size);

      /* "trap" is stored 8 slots after "pc".  */
      if (regnum == -1 || regnum == PPC_TRAP_REGNUM)
	ppc_supply_reg (regcache, PPC_TRAP_REGNUM, gregs,
			offsets->pc_offset + 8 * offsets->gpr_size,
			offsets->gpr_size);
    }
}
예제 #5
0
static void
ppc_linux_sigtramp_cache (struct frame_info *this_frame,
			  struct trad_frame_cache *this_cache,
			  CORE_ADDR func, LONGEST offset,
			  int bias)
{
  CORE_ADDR base;
  CORE_ADDR regs;
  CORE_ADDR gpregs;
  CORE_ADDR fpregs;
  int i;
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);

  base = get_frame_register_unsigned (this_frame,
				      gdbarch_sp_regnum (gdbarch));
  if (bias > 0 && get_frame_pc (this_frame) != func)
    /* See below, some signal trampolines increment the stack as their
       first instruction, need to compensate for that.  */
    base -= bias;

  /* Find the address of the register buffer pointer.  */
  regs = base + offset;
  /* Use that to find the address of the corresponding register
     buffers.  */
  gpregs = read_memory_unsigned_integer (regs, tdep->wordsize, byte_order);
  fpregs = gpregs + 48 * tdep->wordsize;

  /* General purpose.  */
  for (i = 0; i < 32; i++)
    {
      int regnum = i + tdep->ppc_gp0_regnum;
      trad_frame_set_reg_addr (this_cache,
			       regnum, gpregs + i * tdep->wordsize);
    }
  trad_frame_set_reg_addr (this_cache,
			   gdbarch_pc_regnum (gdbarch),
			   gpregs + 32 * tdep->wordsize);
  trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum,
			   gpregs + 35 * tdep->wordsize);
  trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum,
			   gpregs + 36 * tdep->wordsize);
  trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum,
			   gpregs + 37 * tdep->wordsize);
  trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum,
			   gpregs + 38 * tdep->wordsize);

  if (ppc_linux_trap_reg_p (gdbarch))
    {
      trad_frame_set_reg_addr (this_cache, PPC_ORIG_R3_REGNUM,
			       gpregs + 34 * tdep->wordsize);
      trad_frame_set_reg_addr (this_cache, PPC_TRAP_REGNUM,
			       gpregs + 40 * tdep->wordsize);
    }

  if (ppc_floating_point_unit_p (gdbarch))
    {
      /* Floating point registers.  */
      for (i = 0; i < 32; i++)
	{
	  int regnum = i + gdbarch_fp0_regnum (gdbarch);
	  trad_frame_set_reg_addr (this_cache, regnum,
				   fpregs + i * tdep->wordsize);
	}
      trad_frame_set_reg_addr (this_cache, tdep->ppc_fpscr_regnum,
                         fpregs + 32 * tdep->wordsize);
    }
  trad_frame_set_id (this_cache, frame_id_build (base, func));
}