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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [insight/] [gdb/] [remote-or1k.c] - Rev 1765

Compare with Previous | Blame | View Log

/* Remote debugging interface for various or1k debugging protocols.
   Copyright 1993-1995, 2000 Free Software Foundation, Inc.
   Contributed by Cygnus Support.  Written by Marko Mlinar
   <markom@opencores.org>
 
   This file is part of GDB.
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the 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 of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
 
#include "defs.h"
#include "inferior.h"
#include "bfd.h"
#include "symfile.h"
#include "gdb_wait.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "target.h"
#include "remote-utils.h"
#include "gdb_string.h"
#include "tm.h"
 
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
 
extern void jtag_init PARAMS ((char * args));
extern unsigned int jtag_read_reg PARAMS ((unsigned int regno));
extern void jtag_write_reg PARAMS ((unsigned int regno, unsigned 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));
 
struct target_ops or1k_jtag_ops;
static struct or1k_target_ops or1k_target_jtag =
  {
    "jtag",
    jtag_init,
    jtag_done,
    jtag_read_reg,
    jtag_write_reg,
    jtag_read_tap_reg,
    jtag_write_tap_reg,
    NULL,
    &or1k_jtag_ops,
    OPS_MAGIC
  };
 
struct target_ops or1k_sim_ops;
static struct or1k_target_ops or1k_target_sim =
  {
    "simulator",
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    &or1k_sim_ops,
    OPS_MAGIC
  };
 
struct target_ops or1k_dummy_ops;
static struct or1k_target_ops or1k_target_dummy =
  {
    "dummy",
    NULL,
    NULL,
    NULL,
    NULL,    
    NULL,
    NULL,
    NULL,
    &or1k_dummy_ops,
    OPS_MAGIC
  };
 
const char *str_err[] =
  {
    "None", "CRC error"
  };
 
const char *status_name[] =
  {
    "UNDEFINED", "CONNECTING", "DISCONNECTING", "RUNNING", "STOPPED"
  };
 
/* Implementation specific information.  Set by or1k_initialize.  */
struct struct_or1k_implementation or1k_implementation;
 
/* Current target status.  */
static enum target_status or1k_status = TARGET_UNDEFINED;
 
/* The target vector.  */
struct target_ops or1k_dummy_ops, or1k_jtag_ops, or1k_sim_ops;
 
/* Currently active target description (if or1k_is_open == 1) */
static struct target_ops *current_ops;
 
/* Currently active or1k target operations.  */
static struct or1k_target_ops *current_or1k_target = NULL;
 
/* Set to 1 if the target is open.  */
static int or1k_is_open = 0;
 
/* Error last occured, zero = ok.  */
static int err = 0;
 
/* Number of interrupts while waiting for process.  */
static int interrupt_count = 0;
 
/* Current register values.  */
static unsigned int dmr1 = 0;
static unsigned int dmr2 = 0;
static unsigned int dsr = 0; 
static unsigned int drr = 0;
 
/* Current watchpoints.  */
static int dvr[8];
static struct dcr_struct dcr[8];
 
/* Handle low-level error that we can't recover from.  Note that just
   error()ing out from target_wait or some such low-level place will cause
   all hell to break loose--the rest of GDB will tend to get left in an
   inconsistent state.  */
 
static NORETURN void
or1k_error (char *string,...)
{
  va_list args;
 
  va_start (args, string);
 
  target_terminal_ours ();
  wrap_here ("");		/* Force out any buffered output */
  gdb_flush (gdb_stdout);
  if (error_pre_print)
    fprintf_filtered (gdb_stderr, error_pre_print);
  vfprintf_filtered (gdb_stderr, string, args);
  fprintf_filtered (gdb_stderr, "\n");
  va_end (args);
  gdb_flush (gdb_stderr);
 
  /* Clean up in such a way that or1k_close won't try to talk to the
     board (it almost surely won't work since we weren't able to talk to
     it).  */
  or1k_is_open = 0;
 
  printf_unfiltered ("Ending remote or1k debugging.\n");
  target_mourn_inferior ();
 
  return_to_top_level (RETURN_ERROR);
}
 
const char *
or1k_err_name (e)
     int e;
{
  return str_err[e];
}
 
/* putc_readable - print a character, displaying non-printable chars in
   ^x notation or in hex.  */
 
static void
fputc_readable (ch, file)
     int ch;
     struct ui_file *file;
{
  if (ch == '\n')
    fputc_unfiltered ('\n', file);
  else if (ch == '\r')
    fprintf_unfiltered (file, "\\r");
  else if (ch < 0x20)		/* ASCII control character */
    fprintf_unfiltered (file, "^%c", ch + '@');
  else if (ch >= 0x7f)		/* non-ASCII characters (rubout or greater) */
    fprintf_unfiltered (file, "[%02x]", ch & 0xff);
  else
    fputc_unfiltered (ch, file);
}
 
 
/* puts_readable - print a string, displaying non-printable chars in
   ^x notation or in hex.  */
 
static void
fputs_readable (string, file)
     char *string;
     struct ui_file *file;
{
  int c;
 
  while ((c = *string++) != '\0')
    fputc_readable (c, file);
}
 
/* Sets register/memory regno to data.  */
 
void
or1k_write_reg (regno, data)
     unsigned int regno;
     unsigned int data;
{
  if (current_or1k_target != NULL && current_or1k_target->to_write_spr_reg != NULL)
    current_or1k_target->to_write_spr_reg (regno, data);
}
 
/* Reads register/memory from regno.  */
 
unsigned int
or1k_read_reg (regno)
     unsigned int regno;
{ 
  if (current_or1k_target != NULL && current_or1k_target->to_read_spr_reg != NULL)
    return current_or1k_target->to_read_spr_reg (regno);
  else
    return 0x1234;
}
 
/* Stalls the CPU.  */
 
static void
or1k_stall ()
{
  //!!! or1k_write_tap_reg (xxx, xxx);
}
 
/* Unstalls the CPU.  */
 
static void
or1k_unstall ()
{
  //!!! or1k_write_tap_reg (xxx, xxx);
}
 
static void
or1k_set_undefined_cleanups (arg)
     PTR arg;
{
  or1k_status = TARGET_UNDEFINED;
}
 
/* Initialize a new connection to the or1k board, and make sure we are
   really connected.  */
 
static void
or1k_init (args)
     char *args;
{
  struct cleanup *old_cleanups = make_cleanup (or1k_set_undefined_cleanups, NULL);
  int i;
 
  /* What is this code doing here?  I don't see any way it can happen, and
     it might mean or1k_initializing didn't get cleared properly.
     So I'll make it a warning.  */
 
  if (or1k_status == TARGET_CONNECTING)
    {
      warning ("internal error: or1k_initialize called twice");
      return;
    }
 
  or1k_status = TARGET_CONNECTING;
  or1k_stall ();
  if (current_or1k_target != NULL && current_or1k_target->to_init != NULL)
    current_or1k_target->to_init (args);
 
  /* Determine implementation configuration.  */
  or1k_implementation.VR = or1k_read_reg (VR_SPRNUM);
  or1k_implementation.UPR = or1k_read_reg (UPR_SPRNUM);
 
  /* Determine max number of supported matchpoints.  */ 
  or1k_implementation.num_matchpoints = 2;
  or1k_implementation.num_gpr_regs = 32;
  /*!!! FINISH */
 
 
  /* Is implementation supported? */
 
  /* First we should have system and debug groups implemented. */
  if (or1k_implementation.VR & (1 << SPR_SYSTEM_GROUP) == 0)
    error ("System group should be available in the or1k implementation.");
  if (or1k_implementation.VR & (1 << SPR_DEBUG_GROUP) == 0)
    error ("Debug group should be available in the or1k implementation.");
 
 
 
  /* Delete break, watch, catch points.  */
  for(i = 0; i < NUM_MATCHPOINTS; i++)
    or1k_write_reg (DCR0_SPRNUM + i, 0);
 
  dmr1 = 0;
  or1k_write_reg (DMR1_SPRNUM, dmr1);
  dmr2 = 0;
  or1k_write_reg (DMR2_SPRNUM, dmr2);
  if (err != 0)
    error ("Cannot connect.");
 
  /* Stop when breakpoint occurs.  */
  or1k_write_reg (DSR_SPRNUM, 0x1000);
 
  do_cleanups (old_cleanups);
 
  /* This should cause an error if not connected.  */
  or1k_fetch_registers (-1);
 
  set_current_frame (create_new_frame (read_fp (), read_pc ()));
  select_frame (get_current_frame (), 0);
}
 
/* Kill the process running on the board.  */
 
void
or1k_kill ()
{
  if (or1k_status != TARGET_RUNNING)
    return;
  or1k_status = TARGET_UNDEFINED;
  /* HW STEP.  Set DMR1_ST.  */
  dmr1 |= DMR1_ST;
  or1k_write_reg (DMR1_SPRNUM, dmr1);
  dmr1 &= ~DMR1_ST;
  or1k_stall();
  or1k_status = TARGET_UNDEFINED;
 
  inferior_pid = 0;
}
 
/* Open a connection to the remote board.  */
 
static void
or1k_open (name, from_tty)
     char *name;
     int from_tty;
{
  or1k_init (name);
 
  /* Switch to using remote target now.  */
  current_ops = current_or1k_target->gdb_ops;
  or1k_is_open = 1;
  push_target (current_ops);
 
  /* FIXME: Should we call start_remote here?  */
 
/* This is really the job of start_remote however, that makes an assumption
   that the target is about to print out a status message of some sort.  That
   doesn't happen here (in fact, it may not be possible to get the monitor to
   send the appropriate packet).  */
 
  flush_cached_frames ();
  registers_changed ();
  stop_pc = read_pc ();
  set_current_frame (create_new_frame (read_fp (), stop_pc));
  select_frame (get_current_frame (), 0);
  print_stack_frame (selected_frame, -1, 1);
}
 
/* Close a connection to the remote board.  */
 
static void
or1k_close (quitting)
     int quitting;
{
  if (or1k_is_open)
    {
      or1k_kill ();
      if (current_or1k_target != NULL && current_or1k_target->to_done != NULL)
	current_or1k_target->to_done ();
      current_or1k_target = NULL;
    }
  generic_mourn_inferior ();
}
 
/* Detach from the remote board.  */
 
static void
or1k_detach (args, from_tty)
     char *args;
     int from_tty;
{
  if (args)
    error ("Argument given to \"detach\" when remotely debugging.");
 
  pop_target ();
 
  or1k_close (1);
 
  if (from_tty)
    printf_unfiltered ("Ending remote or1k debugging.\n");
}
 
/* Resume execution of the target process.  STEP says whether to single-step
   or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
   to the target, or zero for no signal.  */
 
static void
or1k_resume (pid, step, siggnal)
     int pid, step;
     enum target_signal siggnal;
{  
  if (or1k_status != TARGET_STOPPED)
    if (or1k_status == TARGET_RUNNING)
      error ("Program is already running.");
    else
      error ("The program is not being run.");
 
  /* Clear reason register for later.  */
  or1k_write_reg (DRR_SPRNUM, 0);
 
  if (step)
    {
      /* HW STEP.  Set DMR1_ST.  */
      dmr1 |= DMR1_ST;
      or1k_write_reg (DMR1_SPRNUM, dmr1);
      dmr1 &= ~DMR1_ST;
    }
 
  /* Run the target. */
  or1k_unstall ();
  or1k_status = TARGET_RUNNING;
}
 
/* Wait until the remote stops, and return a wait status.  */
 
static int
or1k_wait (pid, status)
     int pid;
     struct target_waitstatus *status;
{
  interrupt_count = 0;
 
  /* If we have not sent a single step or continue command, then the
     board is waiting for us to do something.  Return a status
     indicating that it is stopped.  */
  if (or1k_status != TARGET_RUNNING)
    {
      if (or1k_status != TARGET_STOPPED)
	error("Target in invalid state."); 
      status->kind = TARGET_WAITKIND_STOPPED;
      status->value.sig = TARGET_SIGNAL_TRAP;
      return 0;
    }
 
  if (err)
    or1k_error ("Remote failure: %s", or1k_err_name (err));
 
  /* Wait for or1k DRR register to be nonzero.  */
  do
    {
      drr = or1k_read_reg (DRR_SPRNUM);
      usleep (10);
    }
  while (drr == 0);
 
  status->kind = TARGET_WAITKIND_STOPPED;
 
  if (drr & DRR_RSTE)
    status->value.sig = TARGET_SIGNAL_REALTIME_33;
  else if (drr & DRR_BUSEE)
    status->value.sig = TARGET_SIGNAL_BUS;
  else if (drr & DRR_DPFE)
    status->value.sig = TARGET_SIGNAL_REALTIME_34;
  else if (drr & DRR_IPFE)
    status->value.sig = TARGET_SIGNAL_REALTIME_35;
  else if (drr & DRR_LPINTE)
    status->value.sig = TARGET_SIGNAL_INT;
  else if (drr & DRR_AE)
    status->value.sig = TARGET_SIGNAL_REALTIME_36;
  else if (drr & DRR_IIE)
    status->value.sig = TARGET_SIGNAL_ILL;
  else if (drr & DRR_HPINTE)
    status->value.sig = TARGET_SIGNAL_INT;
  else if (drr & DRR_DME)
    status->value.sig = TARGET_SIGNAL_REALTIME_37;
  else if (drr & DRR_IME)
    status->value.sig = TARGET_SIGNAL_REALTIME_38;
  else if (drr & DRR_RE)
    status->value.sig = TARGET_SIGNAL_REALTIME_39;
  else if (drr & DRR_SCE)
    status->value.sig = TARGET_SIGNAL_REALTIME_40;
  else if (drr & DRR_BE)
    status->value.sig = TARGET_SIGNAL_TRAP;
  else
    {
      status->value.sig = TARGET_SIGNAL_UNKNOWN;
      warning ("Invalid exception occured.");
    }
 
  or1k_status = TARGET_STOPPED;
 
  /* If the stop PC is in the _exit function, assume
     we hit the 'break 0x3ff' instruction in _exit, so this
     is not a normal breakpoint.  */
  {
    char *func_name;
    CORE_ADDR func_start;
    CORE_ADDR pc = read_pc ();
 
    find_pc_partial_function (pc, &func_name, &func_start, NULL);
    if (func_name != NULL && strcmp (func_name, "_exit") == 0
	&& func_start == pc)
      status->kind = TARGET_WAITKIND_EXITED;
  }
  return 0;
}
 
/* Fetch a word from the target board.  */
 
static unsigned int
or1k_fetch_word (addr)
     CORE_ADDR addr;
{
  return or1k_read_reg (addr + MEM_SPACE);
}
 
/* Store a word to the target board.  Returns errno code or zero for
   success.  */
static int
or1k_store_word (addr, val)
     CORE_ADDR addr;
     unsigned int val;
{
  or1k_write_reg (addr + MEM_SPACE, val); 
  return err;
}
 
/* Fetch the remote registers.  */
 
void
or1k_fetch_registers (regno)
     int regno;
{
  unsigned int val;
 
  if (regno == -1)
    {
      for (regno = 0; regno < NUM_REGS; regno++)
	or1k_fetch_registers (regno);
      return;
    }
 
  if (regno >= NUM_REGS)
    error("Invalid register number!");
 
  /* Convert to SPRNUM and read.  */
  val = or1k_read_reg (REGNUM_TO_SPRNUM(regno) + REG_SPACE);
 
  {
    char buf[MAX_REGISTER_RAW_SIZE];
 
    /* We got the number the register holds, but gdb expects to see a
       value in the target byte ordering.  */
    store_unsigned_integer (buf, REGISTER_RAW_SIZE (regno), val);
    supply_register (regno, buf);
  }
  if (err)
    or1k_error ("Can't read register %d(%i): %s", regno, REGNUM_TO_SPRNUM(regno) + REG_SPACE, or1k_err_name (err));
}
 
/* Fetch and return instruction from the specified location.  */
 
unsigned int
or1k_fetch_instruction (addr)
     CORE_ADDR addr;
{
  char buf[OR1K_INSTLEN];
  int status;
 
  status = read_memory_nobpt (addr, buf, OR1K_INSTLEN);
  if (status)
    memory_error (status, addr);
  return extract_unsigned_integer (buf, OR1K_INSTLEN);
}
 
static void
or1k_prepare_to_store ()
{
}
 
/* Store remote register(s).  */
 
static void
or1k_store_registers (regno)
     int regno;
{
  if (regno == -1)
    {
      for (regno = 0; regno < NUM_REGS; regno++)
	or1k_store_registers (regno);
      return;
    }
 
  if (regno >= NUM_REGS)
    error("Invalid register number!");
 
  or1k_write_reg (REGNUM_TO_SPRNUM(regno) + REG_SPACE, or1k_read_reg (REGNUM_TO_SPRNUM(regno) + REG_SPACE));
  if (err)
    or1k_error ("Can't write register %d(%i): %s", regno, REGNUM_TO_SPRNUM(regno) + REG_SPACE, or1k_err_name (err));
}
 
/* Read or write LEN bytes from inferior memory at MEMADDR,
   transferring to or from debugger address MYADDR.  Write to inferior
   if SHOULD_WRITE is nonzero.  Returns length of data written or
   read; 0 for error.  Note that protocol gives us the correct value
   for a longword, since it transfers values in ASCII.  We want the
   byte values, so we have to swap the longword values.  */
 
static int
or1k_xfer_memory (memaddr, myaddr, len, write, ignore)
     CORE_ADDR memaddr;
     char *myaddr;
     int len;
     int write;
     struct target_ops *ignore;
{
  register int i;
  /* Round starting address down to longword boundary.  */
  register CORE_ADDR addr = memaddr & ~3;
  /* Round ending address up; get number of longwords that makes.  */
  register int count = (((memaddr + len) - addr) + 3) / 4;
  /* Allocate buffer of that many longwords.  */
  register char *buffer = alloca (count * 4);
 
  int status;
 
  if (memaddr >= MEM_SPACE)
    error("Invalid address");
 
  if (write)
    {
      /* Fill start and end extra bytes of buffer with existing data.  */
      if (addr != memaddr || len < 4)
	{
	  /* Need part of initial word -- fetch it.  */
	  store_unsigned_integer (&buffer[0], 4, or1k_fetch_word (addr));
	}
 
      if (count > 1)
	{
	  /* Need part of last word -- fetch it.  FIXME: we do this even
	     if we don't need it.  */
	  store_unsigned_integer (&buffer[(count - 1) * 4], 4,
				  or1k_fetch_word (addr + (count - 1) * 4));
	}
 
      /* Copy data to be written over corresponding part of buffer */
 
      memcpy ((char *) buffer + (memaddr & 3), myaddr, len);
 
      /* Write the entire buffer.  */
 
      for (i = 0; i < count; i++, addr += 4)
	{
	  status = or1k_store_word (addr,
			       extract_unsigned_integer (&buffer[i * 4], 4));
	  /* Report each kilobyte (we download 32-bit words at a time) */
	  if (i % 256 == 255)
	    {
	      printf_unfiltered ("*");
	      gdb_flush (gdb_stdout);
	    }
	  if (status)
	    {
	      errno = status;
	      return 0;
	    }
	  /* FIXME: Do we want a QUIT here?  */
	}
      if (count >= 256)
	printf_unfiltered ("\n");
    }
  else
    {
      /* Read all the longwords */
      for (i = 0; i < count; i++, addr += 4)
	{
	  store_unsigned_integer (&buffer[i * 4], 4, or1k_fetch_word (addr));
	  QUIT;
	}
 
      /* Copy appropriate bytes out of the buffer.  */
      memcpy (myaddr, buffer + (memaddr & 3), len);
    }
  return len;
}
 
/* Print info on this target.  */
 
static void
or1k_files_info (ignore)
     struct target_ops *ignore;
{ 
  char *file = "nothing";
 
  if (exec_bfd)
    file = bfd_get_filename (exec_bfd);
 
  printf_filtered ("or1k_files_info: file \"%s\"\n", file);
 
  if (exec_bfd)
    {
      printf_filtered ("\tAttached to %s running program %s\n",
		       target_shortname, file);
    }
  /* Print target info. */
  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.  */
static int
or1k_can_use_hardware_breakpoint ()
{
  int i;
  /* Search for unused breakpoint.  */
  for (i = 0; i < NUM_MATCHPOINTS; i++)
    if (dcr[i].dp == 0)
      return 1;
  return 0;
}
 
/* Insert a breakpoint.  On targets that don't have built-in breakpoint
   support, we read the contents of the target location and stash it,
   then overwrite it with a breakpoint instruction.  ADDR is the target
   location in the target machine.  CONTENTS_CACHE is a pointer to 
   memory allocated for saving the target contents.  It is guaranteed
   by the caller to be long enough to save sizeof BREAKPOINT bytes (this
   is accomplished via BREAKPOINT_MAX).  */
 
static int
or1k_insert_breakpoint (addr, contents_cache)
     CORE_ADDR addr;
     char *contents_cache;
{
  if (or1k_can_use_hardware_breakpoint())
    return set_breakpoint (addr);
  else
    return memory_insert_breakpoint (addr, contents_cache);
}
 
static int
or1k_remove_breakpoint (addr, contents_cache)
     CORE_ADDR addr;
     char *contents_cache;
{
  /* First try to remove HW breakpoint at address */
  if (clear_breakpoint (addr))
    return memory_remove_breakpoint (addr, contents_cache);
  else
    return 0;
}
 
/* Insert a breakpoint.  */
 
int
set_breakpoint (addr)
     CORE_ADDR addr;
{
  int i;
  unsigned int u;
  /* Search for unused breakpoint.  */
  for (i = 0; i < NUM_MATCHPOINTS; i++)
    if (dcr[i].dp == 0) break;
  if (i >= NUM_MATCHPOINTS) return 1;
  dvr[i] = addr;
  dcr[i].dp = 1;
  dcr[i].cc = CC_EQUAL;
  dcr[i].sc = 0;
  dcr[i].ct = CT_FETCH;
  or1k_write_reg (DVR0_SPRNUM + i, dvr[i]);
  memcpy (&u, &dcr[i], sizeof(dcr[i]));
  or1k_write_reg (DCR0_SPRNUM + i, u);
  return 0;
}
 
/* Clear a breakpoint.  */
 
int
clear_breakpoint (addr)
     CORE_ADDR addr;
{
  int i;
  unsigned int u;
  /* Search for matching breakpoint.  */
  for (i = 0; i < NUM_MATCHPOINTS; i++)
    if ((dcr[i].dp == 1) && (dvr[i] == addr) && (dcr[i].cc == CC_EQUAL)
	&& (dcr[i].sc == 0) && (dcr[i].ct == CT_FETCH)) break;
 
  if (i >= NUM_MATCHPOINTS) return 1;
  dcr[i].dp = 0;
  memcpy (&u, &dcr[i], sizeof(dcr[i]));
  or1k_write_reg (DCR0_SPRNUM + i, u);
  return 0;
}
 
/* Start running on the target board.  */
 
static void
or1k_create_inferior (execfile, args, env)
     char *execfile;
     char *args;
     char **env;
{
  CORE_ADDR entry_pt;
 
  if (args && *args)
    {
      warning ("\
Can't pass arguments to remote OR1K board; arguments ignored.");
      /* And don't try to use them on the next "run" command.  */
      execute_command ("set args", 0);
    }
 
  if (execfile == 0 || exec_bfd == 0)
    error ("No executable file specified");
 
  or1k_kill ();
  remove_breakpoints ();
 
  entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd);
  init_wait_for_inferior ();
 
  /* FIXME: Should we set inferior_pid here?  */
  //inferior_pid = 42;
  insert_breakpoints ();	/* Needed to get correct instruction in cache */
  clear_proceed_status ();
  or1k_status = TARGET_STOPPED;
  proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0);
}
 
/* Clean up after a process.  Actually nothing to do.  */
 
static void
or1k_mourn_inferior ()
{
  generic_mourn_inferior ();
}
 
static void
or1k_dummy_open (name, from_tty)
     char *name;
     int from_tty;
{
  target_preopen (from_tty);
  if (or1k_is_open)
    unpush_target (current_ops);
  current_or1k_target = &or1k_target_dummy;
  or1k_open (name, from_tty);
}
 
static void
or1k_jtag_open (name, from_tty)
     char *name;
     int from_tty;
{
  target_preopen (from_tty);
  if (or1k_is_open)
    unpush_target (current_ops);
  current_or1k_target = &or1k_target_jtag;
  or1k_open (name, from_tty);
}
 
static void
or1k_sim_open (name, from_tty)
     char *name;
     int from_tty;
{
  /* target_preopen (from_tty); - do we need this ? */
  if (or1k_is_open)
    unpush_target (current_ops);
  current_or1k_target = &or1k_target_sim;
  or1k_open (name, from_tty);
}
 
/* Executes command on the target.  */
 
void
or1k_sim_cmd (char *args, int from_tty)
{
  if (current_or1k_target != NULL && current_or1k_target->to_exec_command != NULL)
    current_or1k_target->to_exec_command (args, from_tty);
  else
    error ("Command not supported on this target. ");
}
 
void
_initialize_remote_or1k ()
{
  /* Initialize the fields in or1k_ops that are common to all targets.  */
  or1k_dummy_ops.to_close = or1k_close;
  or1k_dummy_ops.to_detach = or1k_detach;
  or1k_dummy_ops.to_resume = or1k_resume;
  or1k_dummy_ops.to_wait = or1k_wait;
  or1k_dummy_ops.to_fetch_registers = or1k_fetch_registers;
  or1k_dummy_ops.to_store_registers = or1k_store_registers;
  or1k_dummy_ops.to_prepare_to_store = or1k_prepare_to_store;
  or1k_dummy_ops.to_xfer_memory = or1k_xfer_memory;
  or1k_dummy_ops.to_files_info = or1k_files_info;
  or1k_dummy_ops.to_insert_breakpoint = or1k_insert_breakpoint;
  or1k_dummy_ops.to_remove_breakpoint = or1k_remove_breakpoint;
  or1k_dummy_ops.to_kill = or1k_kill;
  or1k_dummy_ops.to_load = generic_load;
  or1k_dummy_ops.to_create_inferior = or1k_create_inferior;
  or1k_dummy_ops.to_mourn_inferior = or1k_mourn_inferior;
  or1k_dummy_ops.to_stratum = process_stratum;
  or1k_dummy_ops.to_has_all_memory = 0; /* We can access memory while program is running.  */
  or1k_dummy_ops.to_has_memory = 1;
  or1k_dummy_ops.to_has_stack = 1;
  or1k_dummy_ops.to_has_registers = 1;
  or1k_dummy_ops.to_has_execution = 1;
  or1k_dummy_ops.to_magic = OPS_MAGIC;
  //or1k_ops.to_wait = or1k_wait;
 
  /* Copy the common fields to all target vectors.  */
  or1k_jtag_ops = or1k_sim_ops = or1k_dummy_ops;
 
  /* Initialize target-specific fields in the target vectors adn add targets.  */
  or1k_jtag_ops.to_shortname = "jtag";
  or1k_jtag_ops.to_longname = "Remote or1k debugging over JTAG port";
  or1k_jtag_ops.to_doc = "\
Debug a board using the OR1K remote debugging protocol over a parallel line.\n\
The argument is the device it is connected to or, if it contains a colon,\n";
  or1k_jtag_ops.to_open = or1k_jtag_open;
  add_target (&or1k_jtag_ops);
 
  or1k_dummy_ops.to_shortname = "dummy";
  or1k_dummy_ops.to_longname = "Dummy target";
  or1k_dummy_ops.to_doc = "Actually no real target attached - more like /dev/null.\n";
  or1k_dummy_ops.to_open = or1k_dummy_open;
  add_target (&or1k_dummy_ops);
 
  or1k_sim_ops.to_shortname = "sim";
  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_open = or1k_sim_open;
  add_target (&or1k_sim_ops);
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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