static int
cris_insert_point (char type, CORE_ADDR addr, int len)
{
  int bp;
  unsigned long bp_ctrl;
  unsigned long start, end;
  unsigned long ccs;
  struct regcache *regcache;

  /* Breakpoint/watchpoint types (GDB terminology):
     0 = memory breakpoint for instructions
     (not supported; done via memory write instead)
     1 = hardware breakpoint for instructions (not supported)
     2 = write watchpoint (supported)
     3 = read watchpoint (supported)
     4 = access watchpoint (supported).  */

  if (type < '2' || type > '4')
    {
      /* Unsupported.  */
      return 1;
    }

  regcache = get_thread_regcache (current_inferior, 1);

  /* Read watchpoints are set as access watchpoints, because of GDB's
     inability to deal with pure read watchpoints.  */
  if (type == '3')
    type = '4';

  /* Get the configuration register.  */
  collect_register_by_name (regcache, "s0", &bp_ctrl);

  /* The watchpoint allocation scheme is the simplest possible.
     For example, if a region is watched for read and
     a write watch is requested, a new watchpoint will
     be used.  Also, if a watch for a region that is already
     covered by one or more existing watchpoints, a new
     watchpoint will be used.  */

  /* First, find a free data watchpoint.  */
  for (bp = 0; bp < 6; bp++)
    {
      /* Each data watchpoint's control registers occupy 2 bits
	 (hence the 3), starting at bit 2 for D0 (hence the 2)
	 with 4 bits between for each watchpoint (yes, the 4).  */
      if (!(bp_ctrl & (0x3 << (2 + (bp * 4)))))
	break;
    }

  if (bp > 5)
    {
      /* We're out of watchpoints.  */
      return -1;
    }

  /* Configure the control register first.  */
  if (type == '3' || type == '4')
    {
      /* Trigger on read.  */
      bp_ctrl |= (1 << (2 + bp * 4));
    }
  if (type == '2' || type == '4')
    {
      /* Trigger on write.  */
      bp_ctrl |= (2 << (2 + bp * 4));
    }

  /* Setup the configuration register.  */
  supply_register_by_name (regcache, "s0", &bp_ctrl);

  /* Setup the range.  */
  start = addr;
  end = addr + len - 1;

  /* Configure the watchpoint register.  */
  cris_write_data_breakpoint (regcache, bp, start, end);

  collect_register_by_name (regcache, "ccs", &ccs);
  /* Set the S1 flag to enable watchpoints.  */
  ccs |= (1 << 19);
  supply_register_by_name (regcache, "ccs", &ccs);

  return 0;
}
Esempio n. 2
0
static int
cris_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
		   int len, struct raw_breakpoint *bp)
{
  int bp;
  unsigned long bp_ctrl;
  unsigned long start, end;
  unsigned long ccs;
  struct regcache *regcache;

  regcache = get_thread_regcache (current_thread, 1);

  /* Read watchpoints are set as access watchpoints, because of GDB's
     inability to deal with pure read watchpoints.  */
  if (type == raw_bkpt_type_read_wp)
    type = raw_bkpt_type_access_wp;

  /* Get the configuration register.  */
  collect_register_by_name (regcache, "s0", &bp_ctrl);

  /* The watchpoint allocation scheme is the simplest possible.
     For example, if a region is watched for read and
     a write watch is requested, a new watchpoint will
     be used.  Also, if a watch for a region that is already
     covered by one or more existing watchpoints, a new
     watchpoint will be used.  */

  /* First, find a free data watchpoint.  */
  for (bp = 0; bp < 6; bp++)
    {
      /* Each data watchpoint's control registers occupy 2 bits
	 (hence the 3), starting at bit 2 for D0 (hence the 2)
	 with 4 bits between for each watchpoint (yes, the 4).  */
      if (!(bp_ctrl & (0x3 << (2 + (bp * 4)))))
	break;
    }

  if (bp > 5)
    {
      /* We're out of watchpoints.  */
      return -1;
    }

  /* Configure the control register first.  */
  if (type == raw_bkpt_type_read_wp || type == raw_bkpt_type_access_wp)
    {
      /* Trigger on read.  */
      bp_ctrl |= (1 << (2 + bp * 4));
    }
  if (type == raw_bkpt_type_write_wp || type == raw_bkpt_type_access_wp)
    {
      /* Trigger on write.  */
      bp_ctrl |= (2 << (2 + bp * 4));
    }

  /* Setup the configuration register.  */
  supply_register_by_name (regcache, "s0", &bp_ctrl);

  /* Setup the range.  */
  start = addr;
  end = addr + len - 1;

  /* Configure the watchpoint register.  */
  cris_write_data_breakpoint (regcache, bp, start, end);

  collect_register_by_name (regcache, "ccs", &ccs);
  /* Set the S1 flag to enable watchpoints.  */
  ccs |= (1 << 19);
  supply_register_by_name (regcache, "ccs", &ccs);

  return 0;
}