OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [remote-or1k.c] - Diff between revs 107 and 113

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 107 Rev 113
Line 37... Line 37...
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <fcntl.h>
 
 
extern void jtag_init PARAMS ((char * args));
extern void jtag_init PARAMS ((char * args));
extern unsigned int jtag_read_reg PARAMS ((unsigned int regno));
extern unsigned long long int jtag_read_reg PARAMS ((unsigned int regno));
extern void jtag_write_reg PARAMS ((unsigned int regno, unsigned int data));
extern void jtag_write_reg PARAMS ((unsigned int regno, unsigned long long int data));
extern unsigned int jtag_read_tap_reg PARAMS ((unsigned int regno));
 
extern void jtag_write_tap_reg PARAMS ((unsigned int regno, unsigned int data));
 
extern void jtag_done PARAMS ((void));
extern void jtag_done PARAMS ((void));
 
extern void jtag_set_chain PARAMS ((int chain));
struct target_ops or1k_jtag_ops;
struct target_ops or1k_jtag_ops;
static struct or1k_target_ops or1k_target_jtag =
static struct or1k_target_ops or1k_target_jtag =
  {
  {
    "jtag",
    "jtag",
    jtag_init,
    jtag_init,
    jtag_done,
    jtag_done,
    jtag_read_reg,
    jtag_read_reg,
    jtag_write_reg,
    jtag_write_reg,
    jtag_read_tap_reg,
    jtag_set_chain,
    jtag_write_tap_reg,
 
    NULL,
    NULL,
    &or1k_jtag_ops,
    &or1k_jtag_ops,
    OPS_MAGIC
    OPS_MAGIC
  };
  };
 
 
Line 68... Line 65...
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
 
    &or1k_sim_ops,
    &or1k_sim_ops,
    OPS_MAGIC
    OPS_MAGIC
  };
  };
 
 
struct target_ops or1k_dummy_ops;
struct target_ops or1k_dummy_ops;
Line 83... Line 79...
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
 
    &or1k_dummy_ops,
    &or1k_dummy_ops,
    OPS_MAGIC
    OPS_MAGIC
  };
  };
 
 
const char *str_err[] =
const char *str_err[] =
Line 98... Line 93...
const char *status_name[] =
const char *status_name[] =
  {
  {
    "UNDEFINED", "CONNECTING", "DISCONNECTING", "RUNNING", "STOPPED"
    "UNDEFINED", "CONNECTING", "DISCONNECTING", "RUNNING", "STOPPED"
  };
  };
 
 
 
/* Names for matchpoint related stuff.  */
 
static char *ct_names[] =
 
  {
 
    "DIS", "IFEA", "LEA", "SEA", "AEA", "LDATA", "SDATA", "ADATA"
 
  };
 
 
 
static char *cc_names[] =
 
  {
 
    "&", "==", "<", "<=", ">", ">=", "!=", "ERR"
 
  };
 
 
 
static char *ch_names[] =
 
  {
 
    "ERR", "&", "|", "ERR"
 
  };
 
 
/* Implementation specific information.  Set by or1k_initialize.  */
/* Implementation specific information.  Set by or1k_initialize.  */
struct struct_or1k_implementation or1k_implementation;
struct struct_or1k_implementation or1k_implementation;
 
 
/* Current target status.  */
/* Current target status.  */
static enum target_status or1k_status = TARGET_UNDEFINED;
static enum target_status or1k_status = TARGET_UNDEFINED;
Line 122... Line 133...
static int err = 0;
static int err = 0;
 
 
/* Number of interrupts while waiting for process.  */
/* Number of interrupts while waiting for process.  */
static int interrupt_count = 0;
static int interrupt_count = 0;
 
 
 
/* Reason of last stop.  */
 
static int hit_watchpoint = 0;
 
 
/* Current register values.  */
/* Current register values.  */
static unsigned int dmr1 = 0;
static unsigned int dmr1 = 0;
static unsigned int dmr2 = 0;
static unsigned int dmr2 = 0;
static unsigned int dsr = 0;
static unsigned int dsr = 0;
static unsigned int drr = 0;
static unsigned int drr = 0;
Line 207... Line 221...
 
 
  while ((c = *string++) != '\0')
  while ((c = *string++) != '\0')
    fputc_readable (c, file);
    fputc_readable (c, file);
}
}
 
 
 
/* Sets scan chain.  */
 
 
 
static void
 
or1k_set_chain (chain)
 
     int chain;
 
{
 
  if (current_or1k_target != NULL && current_or1k_target->to_set_chain != NULL)
 
    current_or1k_target->to_set_chain (chain);
 
}
 
 
/* Sets register/memory regno to data.  */
/* Sets register/memory regno to data.  */
 
 
void
static void
or1k_write_reg (regno, data)
or1k_write_reg (regno, data)
     unsigned int regno;
     unsigned int regno;
     unsigned int data;
     unsigned long long int data;
{
{
  if (current_or1k_target != NULL && current_or1k_target->to_write_spr_reg != NULL)
  if (current_or1k_target != NULL && current_or1k_target->to_write_reg != NULL)
    current_or1k_target->to_write_spr_reg (regno, data);
    current_or1k_target->to_write_reg (regno, data);
}
}
 
 
/* Reads register/memory from regno.  */
/* Reads register/memory from regno.  */
 
 
unsigned int
static unsigned long long int
or1k_read_reg (regno)
or1k_read_reg (regno)
     unsigned int regno;
     unsigned int regno;
{
{
  if (current_or1k_target != NULL && current_or1k_target->to_read_spr_reg != NULL)
  if (current_or1k_target != NULL && current_or1k_target->to_read_reg != NULL)
    return current_or1k_target->to_read_spr_reg (regno);
    return current_or1k_target->to_read_reg (regno);
  else
  else
    return 0x1234;
    return 0x1234;
}
}
 
 
 
/* Sets SPR register regno to data.  */
 
 
 
void
 
or1k_write_spr_reg (regno, data)
 
     unsigned int regno;
 
     unsigned int data;
 
{
 
  or1k_set_chain (SC_RISC_DEBUG);
 
  or1k_write_reg (regno + REG_SPACE, data);
 
}
 
 
 
/* Reads register SPR from regno.  */
 
 
 
unsigned int
 
or1k_read_spr_reg (regno)
 
     unsigned int regno;
 
{
 
  or1k_set_chain (SC_RISC_DEBUG);
 
  return or1k_read_reg (regno + REG_SPACE);
 
}
 
 
/* Stalls the CPU.  */
/* Stalls the CPU.  */
 
 
static void
static void
or1k_stall ()
or1k_stall ()
{
{
  //!!! or1k_write_tap_reg (xxx, xxx);
  int val;
 
  or1k_set_chain (SC_REGISTER);
 
  val = or1k_read_reg (JTAG_RISCOP);
 
  or1k_write_reg (JTAG_RISCOP, val | 1);
 
  or1k_flush_pipeline ();
}
}
 
 
/* Unstalls the CPU.  */
/* Unstalls the CPU.  */
 
 
static void
static void
or1k_unstall ()
or1k_unstall ()
{
{
  //!!! or1k_write_tap_reg (xxx, xxx);
  unsigned int val;
 
  or1k_set_chain (SC_REGISTER);
 
  val = or1k_read_reg (JTAG_RISCOP);
 
  or1k_write_reg (JTAG_RISCOP, val & ~1);
 
}
 
 
 
/* Resets the CPU and stalls it.  */
 
static void
 
or1k_reset ()
 
{
 
  unsigned int val;
 
  or1k_set_chain (SC_REGISTER);
 
  val = or1k_read_reg (JTAG_RISCOP);
 
  val &= ~3;
 
  or1k_write_reg (JTAG_RISCOP, val | 3); /* Assert reset signal.  */
 
  usleep (1000);  /* give it some time */
 
  or1k_flush_pipeline ();
 
  or1k_write_reg (JTAG_RISCOP, val | 1); /* Release reset signal, but keep in stall state.  */
 
  or1k_flush_pipeline ();
}
}
 
 
static void
static void
or1k_set_undefined_cleanups (arg)
or1k_set_undefined_cleanups (arg)
     PTR arg;
     PTR arg;
Line 274... Line 341...
      warning ("internal error: or1k_initialize called twice");
      warning ("internal error: or1k_initialize called twice");
      return;
      return;
    }
    }
 
 
  or1k_status = TARGET_CONNECTING;
  or1k_status = TARGET_CONNECTING;
  or1k_stall ();
  or1k_reset ();
  if (current_or1k_target != NULL && current_or1k_target->to_init != NULL)
  if (current_or1k_target != NULL && current_or1k_target->to_init != NULL)
    current_or1k_target->to_init (args);
    current_or1k_target->to_init (args);
 
 
  /* Determine implementation configuration.  */
  /* Determine implementation configuration.  */
  or1k_implementation.VR = or1k_read_reg (VR_SPRNUM);
  or1k_implementation.VR = or1k_read_spr_reg (VR_SPRNUM);
  or1k_implementation.UPR = or1k_read_reg (UPR_SPRNUM);
  or1k_implementation.UPR = or1k_read_spr_reg (UPR_SPRNUM);
 
 
  /* Determine max number of supported matchpoints.  */
  /* Determine max number of supported matchpoints.  */
  or1k_implementation.num_matchpoints = 2;
  or1k_implementation.num_matchpoints = 2;
 
  or1k_implementation.num_used_matchpoints = 0;
  or1k_implementation.num_gpr_regs = 32;
  or1k_implementation.num_gpr_regs = 32;
  /*!!! FINISH */
  /*!!! FINISH */
 
 
 
 
  /* Is implementation supported? */
  /* Is implementation supported? */
Line 300... Line 368...
 
 
 
 
 
 
  /* Delete break, watch, catch points.  */
  /* Delete break, watch, catch points.  */
  for(i = 0; i < NUM_MATCHPOINTS; i++)
  for(i = 0; i < NUM_MATCHPOINTS; i++)
    or1k_write_reg (DCR0_SPRNUM + i, 0);
    or1k_write_spr_reg (DCR0_SPRNUM + i, 0);
 
 
  dmr1 = 0;
  dmr1 = 0;
  or1k_write_reg (DMR1_SPRNUM, dmr1);
  or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
  dmr2 = 0;
  dmr2 = 0;
  or1k_write_reg (DMR2_SPRNUM, dmr2);
  or1k_write_spr_reg (DMR2_SPRNUM, dmr2);
  if (err != 0)
  if (err != 0)
    error ("Cannot connect.");
    error ("Cannot connect.");
 
 
  /* Stop when breakpoint occurs.  */
  /* Stop when breakpoint occurs.  */
  or1k_write_reg (DSR_SPRNUM, 0x1000);
  or1k_write_spr_reg (DSR_SPRNUM, 0x1000);
 
 
  do_cleanups (old_cleanups);
  do_cleanups (old_cleanups);
 
 
  /* This should cause an error if not connected.  */
  /* This should cause an error if not connected.  */
  or1k_fetch_registers (-1);
  or1k_fetch_registers (-1);
Line 329... Line 397...
or1k_kill ()
or1k_kill ()
{
{
  if (or1k_status != TARGET_RUNNING)
  if (or1k_status != TARGET_RUNNING)
    return;
    return;
  or1k_status = TARGET_UNDEFINED;
  or1k_status = TARGET_UNDEFINED;
  /* HW STEP.  Set DMR1_ST.  */
  or1k_reset();
  dmr1 |= DMR1_ST;
  or1k_status = TARGET_STOPPED;
  or1k_write_reg (DMR1_SPRNUM, dmr1);
 
  dmr1 &= ~DMR1_ST;
 
  or1k_stall();
 
  or1k_status = TARGET_UNDEFINED;
 
 
 
  inferior_pid = 0;
  inferior_pid = 0;
}
}
 
 
/* Open a connection to the remote board.  */
/* Open a connection to the remote board.  */
Line 418... Line 482...
      error ("Program is already running.");
      error ("Program is already running.");
    else
    else
      error ("The program is not being run.");
      error ("The program is not being run.");
 
 
  /* Clear reason register for later.  */
  /* Clear reason register for later.  */
  or1k_write_reg (DRR_SPRNUM, 0);
  or1k_write_spr_reg (DRR_SPRNUM, 0);
 
 
  if (step)
  if (step)
    {
    {
      /* HW STEP.  Set DMR1_ST.  */
      /* HW STEP.  Set DMR1_ST.  */
      dmr1 |= DMR1_ST;
      dmr1 |= DMR1_ST;
      or1k_write_reg (DMR1_SPRNUM, dmr1);
      or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
      dmr1 &= ~DMR1_ST;
      dmr1 &= ~DMR1_ST;
    }
    }
 
 
  /* Run the target. */
  /* Run the target. */
  or1k_unstall ();
  or1k_unstall ();
Line 460... Line 524...
    or1k_error ("Remote failure: %s", or1k_err_name (err));
    or1k_error ("Remote failure: %s", or1k_err_name (err));
 
 
  /* Wait for or1k DRR register to be nonzero.  */
  /* Wait for or1k DRR register to be nonzero.  */
  do
  do
    {
    {
      drr = or1k_read_reg (DRR_SPRNUM);
      drr = or1k_read_spr_reg (DRR_SPRNUM);
      usleep (10);
      usleep (10);
    }
    }
  while (drr == 0);
  while (drr == 0);
 
 
  status->kind = TARGET_WAITKIND_STOPPED;
  status->kind = TARGET_WAITKIND_STOPPED;
 
 
 
  or1k_flush_pipeline ();
 
 
  if (drr & DRR_RSTE)
  if (drr & DRR_RSTE)
    status->value.sig = TARGET_SIGNAL_REALTIME_33;
    status->value.sig = TARGET_SIGNAL_REALTIME_33;
  else if (drr & DRR_BUSEE)
  else if (drr & DRR_BUSEE)
    status->value.sig = TARGET_SIGNAL_BUS;
    status->value.sig = TARGET_SIGNAL_BUS;
  else if (drr & DRR_DPFE)
  else if (drr & DRR_DPFE)
Line 499... Line 565...
    {
    {
      status->value.sig = TARGET_SIGNAL_UNKNOWN;
      status->value.sig = TARGET_SIGNAL_UNKNOWN;
      warning ("Invalid exception occured.");
      warning ("Invalid exception occured.");
    }
    }
 
 
 
  /* Log remote stop.  */
  or1k_status = TARGET_STOPPED;
  or1k_status = TARGET_STOPPED;
 
 
 
  /* Determine what caused trap - breakpoint or watchpoint.  */
 
  if (status->value.sig == TARGET_SIGNAL_TRAP)
 
    {
 
      /* Search all active breakpoints for a match.  */
 
      CORE_ADDR pc = read_pc ();
 
      int breakpoint = 0;
 
      int i;
 
      for (i = 0; i < or1k_implementation.num_used_matchpoints; i++)
 
        if (dvr[i] == pc && dcr[i].dp && dcr[i].cc == CC_EQUAL && !dcr[i].sc && dcr[i].ct == CT_FETCH)
 
          {
 
            breakpoint = 1;
 
            break;
 
          }
 
      hit_watchpoint = !breakpoint;
 
    }
 
  else
 
    hit_watchpoint = 0;
 
 
  /* If the stop PC is in the _exit function, assume
  /* If the stop PC is in the _exit function, assume
     we hit the 'break 0x3ff' instruction in _exit, so this
     we hit the 'break 0x3ff' instruction in _exit, so this
     is not a normal breakpoint.  */
     is not a normal breakpoint.  */
  {
  {
    char *func_name;
    char *func_name;
Line 517... Line 602...
      status->kind = TARGET_WAITKIND_EXITED;
      status->kind = TARGET_WAITKIND_EXITED;
  }
  }
  return 0;
  return 0;
}
}
 
 
/* Fetch a word from the target board.  */
/* Fetch a word from the target board.  All memory accesses to the
 
   remote board are word aligned.  */
 
 
static unsigned int
static unsigned int
or1k_fetch_word (addr)
or1k_fetch_word (addr)
     CORE_ADDR addr;
     CORE_ADDR addr;
{
{
 
  if (addr & 3)
 
    {
 
      int subaddr = addr & 3;
 
      unsigned char buf[8];
 
      unsigned int low, high;
 
      addr >>= 2;
 
      low = or1k_read_reg (addr + MEM_SPACE);
 
      high = or1k_read_reg (addr + 1 + MEM_SPACE);
 
      memcpy (&buf[0], &low, 4);
 
      memcpy (&buf[4], &high, 4);
 
      memcpy (&low, &buf[subaddr], 4);
 
      return low;
 
    }
 
  else
 
    {
 
      addr >>= 2;
  return or1k_read_reg (addr + MEM_SPACE);
  return or1k_read_reg (addr + MEM_SPACE);
}
}
 
}
 
 
/* Store a word to the target board.  Returns errno code or zero for
/* Store a word to the target board.  Returns errno code or zero for
   success.  */
   success.  All memory accesses to the remote board are word aligned.  */
static int
static int
or1k_store_word (addr, val)
or1k_store_word (addr, val)
     CORE_ADDR addr;
     CORE_ADDR addr;
     unsigned int val;
     unsigned int val;
{
{
 
  if (addr & 3)
 
    {
 
      int subaddr = addr & 3;
 
      unsigned char buf[8];
 
      unsigned int low, high;
 
      addr >>= 2;
 
      low = or1k_read_reg (addr + MEM_SPACE);
 
      high = or1k_read_reg (addr + 1 + MEM_SPACE);
 
      memcpy (&buf[0], &low, 4);
 
      memcpy (&buf[4], &high, 4);
 
      memcpy (&buf[subaddr], &val, 4);
 
      memcpy (&low, &buf[0], 4);
 
      memcpy (&high, &buf[4], 4);
 
      or1k_write_reg (addr + MEM_SPACE, low);
 
      or1k_write_reg (addr + 1 + MEM_SPACE, high);
 
    }
 
  else
 
    {
 
      addr >>= 2;
  or1k_write_reg (addr + MEM_SPACE, val);
  or1k_write_reg (addr + MEM_SPACE, val);
 
    }
  return err;
  return err;
}
}
 
 
/* Fetch the remote registers.  */
/* Fetch the remote registers.  */
 
 
Line 556... Line 679...
 
 
  if (regno >= NUM_REGS)
  if (regno >= NUM_REGS)
    error("Invalid register number!");
    error("Invalid register number!");
 
 
  /* Convert to SPRNUM and read.  */
  /* Convert to SPRNUM and read.  */
  val = or1k_read_reg (REGNUM_TO_SPRNUM(regno) + REG_SPACE);
  val = or1k_read_spr_reg (REGNUM_TO_SPRNUM(regno));
 
 
  {
  {
    char buf[MAX_REGISTER_RAW_SIZE];
    char buf[MAX_REGISTER_RAW_SIZE];
 
 
    /* We got the number the register holds, but gdb expects to see a
    /* We got the number the register holds, but gdb expects to see a
Line 585... Line 708...
  if (status)
  if (status)
    memory_error (status, addr);
    memory_error (status, addr);
  return extract_unsigned_integer (buf, OR1K_INSTLEN);
  return extract_unsigned_integer (buf, OR1K_INSTLEN);
}
}
 
 
 
/* Currently not needed.  */
 
 
static void
static void
or1k_prepare_to_store ()
or1k_prepare_to_store ()
{
{
}
}
 
 
Line 606... Line 731...
    }
    }
 
 
  if (regno >= NUM_REGS)
  if (regno >= NUM_REGS)
    error("Invalid register number!");
    error("Invalid register number!");
 
 
  or1k_write_reg (REGNUM_TO_SPRNUM(regno) + REG_SPACE, or1k_read_reg (REGNUM_TO_SPRNUM(regno) + REG_SPACE));
  or1k_write_spr_reg (REGNUM_TO_SPRNUM(regno), or1k_read_spr_reg (REGNUM_TO_SPRNUM(regno)));
  if (err)
  if (err)
    or1k_error ("Can't write register %d(%i): %s", regno, REGNUM_TO_SPRNUM(regno) + REG_SPACE, or1k_err_name (err));
    or1k_error ("Can't write register %d(%i): %s", regno, REGNUM_TO_SPRNUM(regno), or1k_err_name (err));
}
}
 
 
/* Read or write LEN bytes from inferior memory at MEMADDR,
/* Read or write LEN bytes from inferior memory at MEMADDR,
   transferring to or from debugger address MYADDR.  Write to inferior
   transferring to or from debugger address MYADDR.  Write to inferior
   if SHOULD_WRITE is nonzero.  Returns length of data written or
   if SHOULD_WRITE is nonzero.  Returns length of data written or
Line 697... Line 822...
      memcpy (myaddr, buffer + (memaddr & 3), len);
      memcpy (myaddr, buffer + (memaddr & 3), len);
    }
    }
  return len;
  return len;
}
}
 
 
 
/* Flushes pipeline. May not be needed by all implementations, but
 
   it doen't hurt to do it. This function should be called every time
 
   or1k stops.
 
   When or1k stops it still has instructions in pipeline.
 
   We do this by inserting nop instructions.
 
   IF cycle remains unaffacted by writing to DIR, and it still holds
 
   instruction, that caused break or watchpoint. */
 
 
 
void
 
or1k_flush_pipeline ()
 
{
 
  or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
 
  or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
 
  or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
 
}
 
 
/* Print info on this target.  */
/* Print info on this target.  */
 
 
static void
static void
or1k_files_info (ignore)
or1k_files_info (ignore)
     struct target_ops *ignore;
     struct target_ops *ignore;
Line 719... Line 860...
    }
    }
  /* Print target info. */
  /* Print target info. */
  printf_filtered ("Status: %s\n", status_name[or1k_status]);
  printf_filtered ("Status: %s\n", status_name[or1k_status]);
}
}
 
 

 
/* We can write a breakpoint and read the shadow contents in one
 
   operation.  */
 
 
 
/* Tell whether we can support a hardware breakpoint.  */
/* Tell whether we can support a hardware breakpoint.  */
static int
static int
or1k_can_use_hardware_breakpoint ()
or1k_can_use_hardware_breakpoint ()
{
{
  int i;
  int i;
  /* Search for unused breakpoint.  */
  /* Search for unused breakpoint.  */
  for (i = 0; i < NUM_MATCHPOINTS; i++)
  return or1k_implementation.num_used_matchpoints < or1k_implementation.num_matchpoints;
    if (dcr[i].dp == 0)
 
      return 1;
 
  return 0;
 
}
}
 
 
/* Insert a breakpoint.  On targets that don't have built-in breakpoint
/* Insert a breakpoint.  On targets that don't have built-in breakpoint
   support, we read the contents of the target location and stash it,
   support, we read the contents of the target location and stash it,
   then overwrite it with a breakpoint instruction.  ADDR is the target
   then overwrite it with a breakpoint instruction.  ADDR is the target
   location in the target machine.  CONTENTS_CACHE is a pointer to
   location in the target machine.  CONTENTS_CACHE is a pointer to
   memory allocated for saving the target contents.  It is guaranteed
   memory allocated for saving the target contents.  It is guaranteed
   by the caller to be long enough to save sizeof BREAKPOINT bytes (this
   by the caller to be long enough to save sizeof BREAKPOINT bytes (this
   is accomplished via BREAKPOINT_MAX).  */
   is accomplished via BREAKPOINT_MAX).  */
 
 
static int
int
or1k_insert_breakpoint (addr, contents_cache)
or1k_insert_breakpoint (addr, contents_cache)
     CORE_ADDR addr;
     CORE_ADDR addr;
     char *contents_cache;
     char *contents_cache;
{
{
  if (or1k_can_use_hardware_breakpoint())
  if (or1k_can_use_hardware_breakpoint())
    return set_breakpoint (addr);
    return set_breakpoint (addr);
  else
  else
    return memory_insert_breakpoint (addr, contents_cache);
    return memory_insert_breakpoint (addr, contents_cache);
}
}
 
 
static int
int
or1k_remove_breakpoint (addr, contents_cache)
or1k_remove_breakpoint (addr, contents_cache)
     CORE_ADDR addr;
     CORE_ADDR addr;
     char *contents_cache;
     char *contents_cache;
{
{
  /* First try to remove HW breakpoint at address */
  /* First try to remove HW breakpoint at address */
Line 766... Line 900...
    return memory_remove_breakpoint (addr, contents_cache);
    return memory_remove_breakpoint (addr, contents_cache);
  else
  else
    return 0;
    return 0;
}
}
 
 
 
/* Tell whether this target can support a hardware breakpoint.  CNT
 
   is the number of hardware breakpoints already installed.  This
 
   implements the TARGET_CAN_USE_HARDWARE_WATCHPOINT macro.
 
   Lower bound is estimated. !!! Can we estimate better? */
 
 
 
int
 
or1k_can_use_hardware_watchpoint (bp_type, cnt)
 
     enum bptype bp_type;
 
     int cnt;
 
{
 
  /* Are there at least two matchpoints left for watch? - estimate lower bound  */
 
  return cnt + ((bp_type == bp_hardware_watchpoint)?(1):(0))
 
    <= or1k_implementation.num_matchpoints;
 
}
 
 
 
/* Sifts unused matchpoints to higher indexses.  */
 
 
 
static void
 
sift_matchpoints ()
 
{
 
  int i, first_free = 0;
 
  unsigned int u;
 
  for (i = 0; i < or1k_implementation.num_matchpoints; i++)
 
    if (dcr[i].dp)
 
      {
 
        int chaining;
 
        dvr[first_free] = dvr[i];
 
        dcr[first_free] = dcr[i];
 
 
 
        /* Copy chaining bits.  */
 
        chaining = dmr1 & (3 << (2 * i));
 
        dmr1 &= ~(3 << (2 * first_free));
 
        dmr1 |= chaining << (2 * first_free);
 
        /* Copy watchpoint bits */
 
        chaining = dmr2 & (1 << i);
 
        dmr2 &= 1 << first_free;
 
        dmr2 |= chaining << first_free;
 
        /* !!! move references also */
 
 
 
        or1k_write_spr_reg (DVR0_SPRNUM + first_free, dvr[first_free]);
 
        memcpy (&u, &dcr[first_free], sizeof(dcr[first_free]));
 
        or1k_write_spr_reg (DCR0_SPRNUM + first_free, u);
 
        first_free++;
 
      }
 
  /* Disable unused.  */
 
  for (i = first_free; i < or1k_implementation.num_matchpoints; i++)
 
    {
 
      dmr2 &= ~(1 << i);
 
      dcr[i].dp = 0;
 
    }
 
  or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
 
  or1k_write_spr_reg (DMR2_SPRNUM, dmr2);
 
}
 
 
 
/* Translates gdb watchpoint type into one in DCR register.  */
 
 
 
static int
 
translate_type (gdb_type)
 
     int gdb_type;
 
{
 
  switch (gdb_type)
 
    {
 
    case 0:
 
      return CT_SDATA;
 
    case 1:
 
      return CT_LDATA;
 
    case 2:
 
      return CT_ADATA;
 
    default:
 
      error ("Invalid type.");
 
    }
 
}
 
 
 
/* Set a data watchpoint.  ADDR and LEN should be obvious.  TYPE is 0
 
   for a write watchpoint, 1 for a read watchpoint, or 2 for a read/write
 
   watchpoint. */
 
 
 
int
 
or1k_insert_watchpoint (addr, len, type)
 
     CORE_ADDR addr;
 
     int len;
 
     int type;
 
{
 
  int i;
 
  unsigned int u;
 
  if (len < 1)
 
    return -1;
 
 
 
  type = translate_type (type);
 
 
 
  /* Moves unused watchpoints to the top.  */
 
  sift_matchpoints ();
 
  /* Place at first free matchpoint.  */
 
  i = or1k_implementation.num_used_matchpoints;
 
  dvr[i] = addr;
 
  dcr[i].dp = 1;
 
  dcr[i].cc = CC_GREATE;
 
  dcr[i].sc = 0;
 
  dcr[i].ct = type;
 
  or1k_write_spr_reg (DVR0_SPRNUM + i, dvr[i]);
 
  memcpy (&u, &dcr[i], sizeof(dcr[i]));
 
  or1k_write_spr_reg (DCR0_SPRNUM + i, u);
 
 
 
  /* Set && chaining here.  */
 
  dmr1 &= ~(3 << (2 * i));
 
  dmr1 |= 2 << (2 * i);
 
  or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
 
 
 
  /* Set upper watchpoint bound.  */
 
  i++;
 
  dvr[i] = addr + len - 1;
 
  dcr[i].dp = 1;
 
  dcr[i].cc = CC_LESSE;
 
  dcr[i].sc = 0;
 
  dcr[i].ct = type;
 
  or1k_write_spr_reg (DVR0_SPRNUM + i, dvr[i]);
 
  memcpy (&u, &dcr[i], sizeof(dcr[i]));
 
  or1k_write_spr_reg (DCR0_SPRNUM + i, u);
 
 
 
  /* Matchpoints will cause breakpoints */
 
  or1k_write_spr_reg (DMR2_SPRNUM, dmr2 |= (1 << i));
 
  or1k_implementation.num_used_matchpoints += 2;
 
  return 0;
 
}
 
 
 
/* Removes a data watchpoint.  ADDR and LEN should be obvious.  TYPE is 0
 
   for a write watchpoint, 1 for a read watchpoint, or 2 for a read/write
 
   watchpoint. */
 
int
 
or1k_remove_watchpoint (addr, len, type)
 
     CORE_ADDR addr;
 
     int len;
 
     int type;
 
{
 
  int i, found = -1;
 
  unsigned int u;
 
  if (len < 1)
 
    return -1;
 
 
 
  type = translate_type (type);
 
 
 
  /* Find the right one.  */
 
  for (i = 0; i < or1k_implementation.num_used_matchpoints; i++)
 
    if (dvr[i] == addr && dcr[i].dp && dcr[i].cc == CC_GREATE && !dcr[i].sc && dcr[i].ct == type
 
        && dvr[i + 1] == addr + len - 1 && dcr[i + 1].dp && dcr[i + 1].cc == CC_LESSE
 
        && !dcr[i + 1].sc && dcr[i + 1].ct == type)
 
      {
 
        found = i;
 
        break;
 
      }
 
 
 
  if (found < 0)
 
    return -1;
 
 
 
  dcr[found].dp = 0;
 
  memcpy (&u, &dcr[found], sizeof(dcr[found]));
 
  or1k_write_spr_reg (DCR0_SPRNUM + found, u);
 
  dcr[found + 1].dp = 0;
 
  memcpy (&u, &dcr[found + 1], sizeof(dcr[found + 1]));
 
  or1k_write_spr_reg (DCR0_SPRNUM + found + 1, u);
 
 
 
  /* Matchpoints will not cause breakpoints anymore. */
 
  or1k_write_spr_reg (DMR2_SPRNUM, dmr2 &= ~(1 << i));
 
  or1k_implementation.num_used_matchpoints -= 2;
 
  return 0;
 
}
 
 
 
int
 
or1k_stopped_by_watchpoint (void)
 
{
 
  return hit_watchpoint;
 
}
 
 
/* Insert a breakpoint.  */
/* Insert a breakpoint.  */
 
 
int
int
set_breakpoint (addr)
set_breakpoint (addr)
     CORE_ADDR addr;
     CORE_ADDR addr;
Line 783... Line 1090...
  dvr[i] = addr;
  dvr[i] = addr;
  dcr[i].dp = 1;
  dcr[i].dp = 1;
  dcr[i].cc = CC_EQUAL;
  dcr[i].cc = CC_EQUAL;
  dcr[i].sc = 0;
  dcr[i].sc = 0;
  dcr[i].ct = CT_FETCH;
  dcr[i].ct = CT_FETCH;
  or1k_write_reg (DVR0_SPRNUM + i, dvr[i]);
  or1k_write_spr_reg (DVR0_SPRNUM + i, dvr[i]);
  memcpy (&u, &dcr[i], sizeof(dcr[i]));
  memcpy (&u, &dcr[i], sizeof(dcr[i]));
  or1k_write_reg (DCR0_SPRNUM + i, u);
  or1k_write_spr_reg (DCR0_SPRNUM + i, u);
 
  or1k_implementation.num_used_matchpoints++;
 
 
 
  /* No chaining here.  */
 
  dmr1 &= ~(3 << (2*i));
 
  or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
 
  /* Matchpoints will cause breakpoints */
 
  or1k_write_spr_reg (DMR2_SPRNUM, dmr2 |= (1 << i));
  return 0;
  return 0;
}
}
 
 
/* Clear a breakpoint.  */
/* Clear a breakpoint.  */
 
 
Line 805... Line 1119...
        && (dcr[i].sc == 0) && (dcr[i].ct == CT_FETCH)) break;
        && (dcr[i].sc == 0) && (dcr[i].ct == CT_FETCH)) break;
 
 
  if (i >= NUM_MATCHPOINTS) return 1;
  if (i >= NUM_MATCHPOINTS) return 1;
  dcr[i].dp = 0;
  dcr[i].dp = 0;
  memcpy (&u, &dcr[i], sizeof(dcr[i]));
  memcpy (&u, &dcr[i], sizeof(dcr[i]));
  or1k_write_reg (DCR0_SPRNUM + i, u);
  or1k_write_spr_reg (DCR0_SPRNUM + i, u);
 
  /* Matchpoints will cause breakpoints */
 
  or1k_write_spr_reg (DMR2_SPRNUM, dmr2 &= ~(1 << i));
 
  or1k_implementation.num_used_matchpoints--;
  return 0;
  return 0;
}
}
 
 
/* Start running on the target board.  */
/* Start running on the target board.  */
 
 
Line 837... Line 1154...
 
 
  entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd);
  entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd);
  init_wait_for_inferior ();
  init_wait_for_inferior ();
 
 
  /* FIXME: Should we set inferior_pid here?  */
  /* FIXME: Should we set inferior_pid here?  */
  //inferior_pid = 42;
 
  insert_breakpoints ();        /* Needed to get correct instruction in cache */
  insert_breakpoints ();        /* Needed to get correct instruction in cache */
  clear_proceed_status ();
  clear_proceed_status ();
  or1k_status = TARGET_STOPPED;
  or1k_status = TARGET_STOPPED;
  proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0);
  proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0);
}
}
Line 899... Line 1216...
    current_or1k_target->to_exec_command (args, from_tty);
    current_or1k_target->to_exec_command (args, from_tty);
  else
  else
    error ("Command not supported on this target. ");
    error ("Command not supported on this target. ");
}
}
 
 
 
/* Displays matchpoints usage.  */
 
 
 
void
 
info_matchpoints_command (char *args, int from_tty)
 
{
 
  int i;
 
  for (i = 0; i < or1k_implementation.num_matchpoints; i++)
 
    {
 
      printf_filtered ("WP%i ", i);
 
      if (dcr[i].dp)
 
        {
 
          int chaining = (dmr1 << 2*i) & 3;
 
          printf_filtered ("= %s ", ct_names[dcr[i].ct]);
 
          if (dcr[i]. sc)
 
            printf_filtered ("s%s %i", cc_names[dcr[i].cc], (int)dvr[i]);
 
          else
 
            printf_filtered ("%s %u", cc_names[dcr[i].cc], (unsigned int)dvr[i]);
 
          if (chaining)
 
            printf_filtered ("%s WP%i", ch_names[chaining], i - 1);
 
        }
 
      else
 
        printf_filtered ("NOT USED");
 
      if ((dmr2 >> i) & 1)
 
        printf_filtered (", causes breakpoint");
 
      if ((dmr2 >> (i + 11)) & 1)
 
        printf_filtered (", increments counter");
 
      printf_filtered ("\n");
 
    }
 
}
 
 
void
void
_initialize_remote_or1k ()
_initialize_remote_or1k ()
{
{
  /* Initialize the fields in or1k_ops that are common to all targets.  */
  /* Initialize the fields in or1k_ops that are common to all targets.  */
  or1k_dummy_ops.to_close = or1k_close;
  or1k_dummy_ops.to_close = or1k_close;
Line 925... Line 1272...
  or1k_dummy_ops.to_has_memory = 1;
  or1k_dummy_ops.to_has_memory = 1;
  or1k_dummy_ops.to_has_stack = 1;
  or1k_dummy_ops.to_has_stack = 1;
  or1k_dummy_ops.to_has_registers = 1;
  or1k_dummy_ops.to_has_registers = 1;
  or1k_dummy_ops.to_has_execution = 1;
  or1k_dummy_ops.to_has_execution = 1;
  or1k_dummy_ops.to_magic = OPS_MAGIC;
  or1k_dummy_ops.to_magic = OPS_MAGIC;
  //or1k_ops.to_wait = or1k_wait;
 
 
 
  /* Copy the common fields to all target vectors.  */
  /* Copy the common fields to all target vectors.  */
  or1k_jtag_ops = or1k_sim_ops = or1k_dummy_ops;
  or1k_jtag_ops = or1k_sim_ops = or1k_dummy_ops;
 
 
  /* Initialize target-specific fields in the target vectors adn add targets.  */
  /* Initialize target-specific fields in the target vectors adn add targets.  */
Line 950... Line 1296...
  or1k_sim_ops.to_shortname = "sim";
  or1k_sim_ops.to_shortname = "sim";
  or1k_sim_ops.to_longname = "Remote or1k debugging using architecture simulator";
  or1k_sim_ops.to_longname = "Remote or1k debugging using architecture simulator";
  or1k_sim_ops.to_doc = "Debug using an architecture simulator.\n";
  or1k_sim_ops.to_doc = "Debug using an architecture simulator.\n";
  or1k_sim_ops.to_open = or1k_sim_open;
  or1k_sim_ops.to_open = or1k_sim_open;
  add_target (&or1k_sim_ops);
  add_target (&or1k_sim_ops);
 
  add_info ("matchpoints", info_matchpoints_command, "Show current matchpoints allocation status.");
}
}
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.