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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [remote-or1k.c] - Diff between revs 363 and 372

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 363 Rev 372
/* Remote debugging interface for various or1k debugging protocols.
/* Remote debugging interface for various or1k debugging protocols.
   Currently supported or1k targets are: simulator, jtag, dummy.
   Currently supported or1k targets are: simulator, jtag, dummy.
 
 
   Copyright 1993-1995, 2000 Free Software Foundation, Inc.
   Copyright 1993-1995, 2000 Free Software Foundation, Inc.
   Contributed by Cygnus Support.  Written by Marko Mlinar
   Contributed by Cygnus Support.  Written by Marko Mlinar
   <markom@opencores.org>
   <markom@opencores.org>
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
   Boston, MA 02111-1307, USA.  */
 
 
#include "defs.h"
#include "defs.h"
#include "inferior.h"
#include "inferior.h"
#include "bfd.h"
#include "bfd.h"
#include "symfile.h"
#include "symfile.h"
#include "gdb_wait.h"
#include "gdb_wait.h"
#include "gdbcmd.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "gdbcore.h"
#include "target.h"
#include "target.h"
#include "remote-utils.h"
#include "remote-utils.h"
#include "gdb_string.h"
#include "gdb_string.h"
#include "tm.h"
#include "tm.h"
 
 
#include <signal.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <fcntl.h>
 
 
#define debug if (remote_debug) printf_unfiltered
#define debug if (remote_debug) printf_unfiltered
 
 
/* The following prototype is necessary or the compiler will not
/* The following prototype is necessary or the compiler will not
   correctly promote the data argument to ULONGEST */
   correctly promote the data argument to ULONGEST */
static void or1k_write_reg (unsigned int, ULONGEST);
static void or1k_write_reg (unsigned int, ULONGEST);
 
static int insn_has_delay_slot (unsigned int);
 
 
/* JTAG or1k target ops.  */
/* JTAG or1k target ops.  */
extern void jtag_init PARAMS ((char * args));
extern void jtag_init PARAMS ((char * args));
extern ULONGEST jtag_read_reg PARAMS ((unsigned int regno));
extern ULONGEST jtag_read_reg PARAMS ((unsigned int regno));
extern void jtag_write_reg PARAMS ((unsigned int regno, ULONGEST data));
extern void jtag_write_reg PARAMS ((unsigned int regno, ULONGEST data));
extern void jtag_done PARAMS ((void));
extern void jtag_done PARAMS ((void));
extern int jtag_read_block PARAMS ((unsigned int regno, void* block, int nRegisters));
extern int jtag_read_block PARAMS ((unsigned int regno, void* block, int nRegisters));
extern int jtag_write_block PARAMS ((unsigned int regno, void* block, int nRegisters));
extern int jtag_write_block PARAMS ((unsigned int regno, void* block, int nRegisters));
extern void jtag_set_chain PARAMS ((int chain));
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_block,
    jtag_read_block,
    jtag_write_block,
    jtag_write_block,
    jtag_set_chain,
    jtag_set_chain,
    NULL,
    NULL,
    &or1k_jtag_ops,
    &or1k_jtag_ops,
    OPS_MAGIC
    OPS_MAGIC
  };
  };
 
 
/* simulator or1k target ops.  */
/* simulator or1k target ops.  */
struct target_ops or1k_sim_ops;
struct target_ops or1k_sim_ops;
static struct or1k_target_ops or1k_target_sim =
static struct or1k_target_ops or1k_target_sim =
  {
  {
    "simulator",
    "simulator",
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    &or1k_sim_ops,
    &or1k_sim_ops,
    OPS_MAGIC
    OPS_MAGIC
  };
  };
 
 
/* dummy or1k target ops.  */
/* dummy or1k target ops.  */
struct target_ops or1k_dummy_ops;
struct target_ops or1k_dummy_ops;
static struct or1k_target_ops or1k_target_dummy =
static struct or1k_target_ops or1k_target_dummy =
  {
  {
    "dummy",
    "dummy",
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    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[] =
  {
  {
    "None", "CRC error"
    "None", "CRC error"
  };
  };
 
 
const char *status_name[] =
const char *status_name[] =
  {
  {
    "UNDEFINED", "CONNECTING", "DISCONNECTING", "RUNNING", "STOPPED"
    "UNDEFINED", "CONNECTING", "DISCONNECTING", "RUNNING", "STOPPED"
  };
  };
 
 
/* Names for matchpoint related stuff.  */
/* Names for matchpoint related stuff.  */
static char *ct_names[] =
static char *ct_names[] =
  {
  {
    "DIS", "IFEA", "LEA", "SEA", "AEA", "LDATA", "SDATA", "ADATA"
    "DIS", "IFEA", "LEA", "SEA", "AEA", "LDATA", "SDATA", "ADATA"
  };
  };
 
 
static char *cc_names[] =
static char *cc_names[] =
  {
  {
    "&", "==", "<", "<=", ">", ">=", "!=", "ERR"
    "&", "==", "<", "<=", ">", ">=", "!=", "ERR"
  };
  };
 
 
static char *ch_names[] =
static char *ch_names[] =
  {
  {
    "ERR", "&", "|", "ERR"
    "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;
 
 
/* The target vector.  */
/* The target vector.  */
struct target_ops or1k_dummy_ops, or1k_jtag_ops, or1k_sim_ops;
struct target_ops or1k_dummy_ops, or1k_jtag_ops, or1k_sim_ops;
 
 
/* Currently active target description (if or1k_is_open == 1) */
/* Currently active target description (if or1k_is_open == 1) */
static struct target_ops *current_ops;
static struct target_ops *current_ops;
 
 
/* Currently active or1k target operations.  */
/* Currently active or1k target operations.  */
static struct or1k_target_ops *current_or1k_target = NULL;
static struct or1k_target_ops *current_or1k_target = NULL;
 
 
/* Set to 1 if the target is open.  */
/* Set to 1 if the target is open.  */
static int or1k_is_open = 0;
static int or1k_is_open = 0;
 
 
/* Error last occured, zero = ok.  */
/* Error last occured, zero = ok.  */
int err = 0;
int err = 0;
 
 
/* Nonzero, if we changed something (except DMR1 which is updated on every run anyway).  */
/* Nonzero, if we changed something (except DMR1 which is updated on every run anyway).  */
int debug_regs_changed;
int debug_regs_changed;
 
 
/* 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.  */
/* Reason of last stop.  */
static int hit_watchpoint = 0;
static int hit_watchpoint = 0;
 
 
/* Current register values.  */
/* Current register values.  */
unsigned int dmr1 = 0;
unsigned int dmr1 = 0;
unsigned int dmr2 = 0;
unsigned int dmr2 = 0;
unsigned int dsr = 0;
unsigned int dsr = 0;
unsigned int drr = 0;
unsigned int drr = 0;
 
 
/* Current matchpoints.  */
/* Current matchpoints.  */
unsigned int dvr[MAX_MATCHPOINTS];
unsigned int dvr[MAX_MATCHPOINTS];
struct dcr_struct dcr[MAX_MATCHPOINTS];
struct dcr_struct dcr[MAX_MATCHPOINTS];
 
 
/* Number of matchpoint users */
/* Number of matchpoint users */
int matchpoint_user_count[MAX_MATCHPOINTS] = {0};
int matchpoint_user_count[MAX_MATCHPOINTS] = {0};
 
 
/* Old SIGINT handler.  */
/* Old SIGINT handler.  */
static void (*ofunc) PARAMS ((int));
static void (*ofunc) PARAMS ((int));
 
 
 
 
/* Handle low-level error that we can't recover from.  Note that just
/* 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
   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
   all hell to break loose--the rest of GDB will tend to get left in an
   inconsistent state.  */
   inconsistent state.  */
 
 
static NORETURN void
static NORETURN void
or1k_error (char *string,...)
or1k_error (char *string,...)
{
{
  va_list args;
  va_list args;
 
 
  va_start (args, string);
  va_start (args, string);
 
 
  target_terminal_ours ();
  target_terminal_ours ();
  wrap_here ("");               /* Force out any buffered output */
  wrap_here ("");               /* Force out any buffered output */
  gdb_flush (gdb_stdout);
  gdb_flush (gdb_stdout);
  if (error_pre_print)
  if (error_pre_print)
    fprintf_filtered (gdb_stderr, error_pre_print);
    fprintf_filtered (gdb_stderr, error_pre_print);
  vfprintf_filtered (gdb_stderr, string, args);
  vfprintf_filtered (gdb_stderr, string, args);
  fprintf_filtered (gdb_stderr, "\n");
  fprintf_filtered (gdb_stderr, "\n");
  va_end (args);
  va_end (args);
  gdb_flush (gdb_stderr);
  gdb_flush (gdb_stderr);
 
 
  /* Clean up in such a way that or1k_close won't try to talk to the
  /* 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
     board (it almost surely won't work since we weren't able to talk to
     it).  */
     it).  */
  or1k_is_open = 0;
  or1k_is_open = 0;
 
 
  printf_unfiltered ("Ending remote or1k debugging.\n");
  printf_unfiltered ("Ending remote or1k debugging.\n");
  target_mourn_inferior ();
  target_mourn_inferior ();
 
 
  return_to_top_level (RETURN_ERROR);
  return_to_top_level (RETURN_ERROR);
}
}
 
 
const char *
const char *
or1k_err_name (e)
or1k_err_name (e)
     int e;
     int e;
{
{
  return str_err[e];
  return str_err[e];
}
}
 
 
/* putc_readable - print a character, displaying non-printable chars in
/* putc_readable - print a character, displaying non-printable chars in
   ^x notation or in hex.  */
   ^x notation or in hex.  */
 
 
static void
static void
fputc_readable (ch, file)
fputc_readable (ch, file)
     int ch;
     int ch;
     struct ui_file *file;
     struct ui_file *file;
{
{
  if (ch == '\n')
  if (ch == '\n')
    fputc_unfiltered ('\n', file);
    fputc_unfiltered ('\n', file);
  else if (ch == '\r')
  else if (ch == '\r')
    fprintf_unfiltered (file, "\\r");
    fprintf_unfiltered (file, "\\r");
  else if (ch < 0x20)           /* ASCII control character */
  else if (ch < 0x20)           /* ASCII control character */
    fprintf_unfiltered (file, "^%c", ch + '@');
    fprintf_unfiltered (file, "^%c", ch + '@');
  else if (ch >= 0x7f)          /* non-ASCII characters (rubout or greater) */
  else if (ch >= 0x7f)          /* non-ASCII characters (rubout or greater) */
    fprintf_unfiltered (file, "[%02x]", ch & 0xff);
    fprintf_unfiltered (file, "[%02x]", ch & 0xff);
  else
  else
    fputc_unfiltered (ch, file);
    fputc_unfiltered (ch, file);
}
}
 
 
 
 
/* puts_readable - print a string, displaying non-printable chars in
/* puts_readable - print a string, displaying non-printable chars in
   ^x notation or in hex.  */
   ^x notation or in hex.  */
 
 
static void
static void
fputs_readable (string, file)
fputs_readable (string, file)
     char *string;
     char *string;
     struct ui_file *file;
     struct ui_file *file;
{
{
  int c;
  int c;
 
 
  while ((c = *string++) != '\0')
  while ((c = *string++) != '\0')
    fputc_readable (c, file);
    fputc_readable (c, file);
}
}
 
 
/* Sets scan chain.  */
/* Sets scan chain.  */
 
 
static void
static void
or1k_set_chain (chain)
or1k_set_chain (chain)
     int chain;
     int chain;
{
{
  if (current_or1k_target != NULL && current_or1k_target->to_set_chain != NULL)
  if (current_or1k_target != NULL && current_or1k_target->to_set_chain != NULL)
    current_or1k_target->to_set_chain (chain);
    current_or1k_target->to_set_chain (chain);
}
}
 
 
/* Sets register/memory regno to data.  */
/* Sets register/memory regno to data.  */
 
 
static void
static void
or1k_write_reg (regno, data)
or1k_write_reg (regno, data)
     unsigned int regno;
     unsigned int regno;
     ULONGEST data;
     ULONGEST data;
{
{
  if (current_or1k_target != NULL && current_or1k_target->to_write_reg != NULL)
  if (current_or1k_target != NULL && current_or1k_target->to_write_reg != NULL)
    current_or1k_target->to_write_reg (regno, data);
    current_or1k_target->to_write_reg (regno, data);
}
}
 
 
/* Reads register/memory from regno.  */
/* Reads register/memory from regno.  */
 
 
static ULONGEST
static ULONGEST
or1k_read_reg (regno)
or1k_read_reg (regno)
     unsigned int regno;
     unsigned int regno;
{
{
  if (current_or1k_target != NULL && current_or1k_target->to_read_reg != NULL)
  if (current_or1k_target != NULL && current_or1k_target->to_read_reg != NULL)
    return current_or1k_target->to_read_reg (regno);
    return current_or1k_target->to_read_reg (regno);
  else
  else
    return 0x1234;
    return 0x1234;
}
}
 
 
/* Sets SPR register regno to data.  */
/* Sets SPR register regno to data.  */
 
 
void
void
or1k_write_spr_reg (regno, data)
or1k_write_spr_reg (regno, data)
     unsigned int regno;
     unsigned int regno;
     unsigned int data;
     unsigned int data;
{
{
  or1k_set_chain (SC_RISC_DEBUG);
  or1k_set_chain (SC_RISC_DEBUG);
  or1k_write_reg (regno, (ULONGEST)data);
  or1k_write_reg (regno, (ULONGEST)data);
}
}
 
 
/* Reads register SPR from regno.  */
/* Reads register SPR from regno.  */
 
 
unsigned int
unsigned int
or1k_read_spr_reg (regno)
or1k_read_spr_reg (regno)
     unsigned int regno;
     unsigned int regno;
{
{
  or1k_set_chain (SC_RISC_DEBUG);
  or1k_set_chain (SC_RISC_DEBUG);
  return or1k_read_reg (regno);
  return or1k_read_reg (regno);
}
}
 
 
/* Sets mem to data.  */
/* Sets mem to data.  */
 
 
void
void
or1k_write_mem (addr, data)
or1k_write_mem (addr, data)
     unsigned int addr;
     unsigned int addr;
     unsigned int data;
     unsigned int data;
{
{
  or1k_set_chain (SC_WISHBONE);
  or1k_set_chain (SC_WISHBONE);
  or1k_write_reg (addr, (ULONGEST)data);
  or1k_write_reg (addr, (ULONGEST)data);
}
}
 
 
/* Reads register SPR from regno.  */
/* Reads register SPR from regno.  */
 
 
unsigned int
unsigned int
or1k_read_mem (addr)
or1k_read_mem (addr)
     unsigned int addr;
     unsigned int addr;
{
{
  or1k_set_chain (SC_WISHBONE);
  or1k_set_chain (SC_WISHBONE);
  return or1k_read_reg (addr);
  return or1k_read_reg (addr);
}
}
 
 
/* Stalls the CPU.  */
/* Stalls the CPU.  */
 
 
static void
static void
or1k_stall ()
or1k_stall ()
{
{
  int val;
  int val;
  or1k_set_chain (SC_REGISTER);
  or1k_set_chain (SC_REGISTER);
  val = or1k_read_reg (JTAG_RISCOP);
  val = or1k_read_reg (JTAG_RISCOP);
  or1k_write_reg (JTAG_RISCOP, val | 1);
  or1k_write_reg (JTAG_RISCOP, val | 1);
  or1k_read_reg (JTAG_RISCOP);
  or1k_read_reg (JTAG_RISCOP);
 
 
  /* Be cautious - disable trace.  */
  /* Be cautious - disable trace.  */
  val = or1k_read_reg (JTAG_MODER);
  val = or1k_read_reg (JTAG_MODER);
  or1k_write_reg (JTAG_MODER, val & ~2);
  or1k_write_reg (JTAG_MODER, val & ~2);
}
}
 
 
/* Unstalls the CPU.  */
/* Unstalls the CPU.  */
 
 
static void
static void
or1k_unstall ()
or1k_unstall ()
{
{
  unsigned int val;
  unsigned int val;
 
 
 
 
  or1k_set_chain (SC_REGISTER);
  or1k_set_chain (SC_REGISTER);
  val = or1k_read_reg (JTAG_RISCOP);
  val = or1k_read_reg (JTAG_RISCOP);
  or1k_write_reg (JTAG_RISCOP, val & ~1);
  or1k_write_reg (JTAG_RISCOP, val & ~1);
  or1k_read_reg (JTAG_RISCOP);
  or1k_read_reg (JTAG_RISCOP);
}
}
 
 
/* Resets the CPU and stalls it.  */
/* Resets the CPU and stalls it.  */
 
 
static void
static void
or1k_reset ()
or1k_reset ()
{
{
  unsigned int val;
  unsigned int val;
  int i;
  int i;
  debug ("%08x\n", or1k_read_reg (JTAG_RISCOP));
  debug ("%08x\n", or1k_read_reg (JTAG_RISCOP));
  or1k_set_chain (SC_REGISTER);
  or1k_set_chain (SC_REGISTER);
 
 
  /* Be cautious - disable trace.  */
  /* Be cautious - disable trace.  */
  val = or1k_read_reg (JTAG_MODER);
  val = or1k_read_reg (JTAG_MODER);
  or1k_write_reg (JTAG_MODER, val & ~2);
  or1k_write_reg (JTAG_MODER, val & ~2);
 
 
  val = or1k_read_reg (JTAG_RISCOP);
  val = or1k_read_reg (JTAG_RISCOP);
  val &= ~3;
  val &= ~3;
  /* Assert reset signal.  */
  /* Assert reset signal.  */
  or1k_write_reg (JTAG_RISCOP, val | 3);
  or1k_write_reg (JTAG_RISCOP, val | 3);
 
 
  /* Just do something */
  /* Just do something */
  for (i = 0; i < 100; i++)
  for (i = 0; i < 100; i++)
    or1k_read_reg (JTAG_RISCOP);
    or1k_read_reg (JTAG_RISCOP);
 
 
  /* give it some time */
  /* give it some time */
  usleep (1000);
  usleep (1000);
 
 
  or1k_set_chain (SC_REGISTER);
  or1k_set_chain (SC_REGISTER);
  /* Release reset signal, but keep in stall state.  */
  /* Release reset signal, but keep in stall state.  */
  or1k_write_reg (JTAG_RISCOP, val | 1);
  or1k_write_reg (JTAG_RISCOP, val | 1);
  or1k_read_reg (JTAG_RISCOP);
  or1k_read_reg (JTAG_RISCOP);
}
}
 
 
/* Synchronizes debug registers in memory with those on target,
/* Synchronizes debug registers in memory with those on target,
   if there is any change.  */
   if there is any change.  */
 
 
static void
static void
or1k_commit_debug_registers ()
or1k_commit_debug_registers ()
{
{
  int i;
  int i;
  unsigned int u;
  unsigned int u;
  if (!debug_regs_changed)
  if (!debug_regs_changed)
    return;
    return;
 
 
  /* Matchpoints (breakpoints, watchpoints).  */
  /* Matchpoints (breakpoints, watchpoints).  */
  for (i = 0; i < NUM_MATCHPOINTS; i++)
  for (i = 0; i < NUM_MATCHPOINTS; i++)
    {
    {
      unsigned int u;
      unsigned int u;
      or1k_write_spr_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_spr_reg (DCR0_SPRNUM + i, u);
      or1k_write_spr_reg (DCR0_SPRNUM + i, u);
    }
    }
  or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
  or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
  or1k_write_spr_reg (DMR2_SPRNUM, dmr2);
  or1k_write_spr_reg (DMR2_SPRNUM, dmr2);
 
 
  /* Trace dependent.  */
  /* Trace dependent.  */
  or1k_set_chain (SC_REGISTER);
  or1k_set_chain (SC_REGISTER);
  memcpy (&u, &or1k_htrace.trig, sizeof(or1k_htrace.trig));
  memcpy (&u, &or1k_htrace.trig, sizeof(or1k_htrace.trig));
  or1k_write_reg (JTAG_TSEL, u);
  or1k_write_reg (JTAG_TSEL, u);
  memcpy (&u, &or1k_htrace.qual, sizeof(or1k_htrace.qual));
  memcpy (&u, &or1k_htrace.qual, sizeof(or1k_htrace.qual));
  or1k_write_reg (JTAG_QSEL, u);
  or1k_write_reg (JTAG_QSEL, u);
  memcpy (&u, &or1k_htrace.stop, sizeof(or1k_htrace.stop));
  memcpy (&u, &or1k_htrace.stop, sizeof(or1k_htrace.stop));
  or1k_write_reg (JTAG_SSEL, u);
  or1k_write_reg (JTAG_SSEL, u);
  debug_regs_changed = 0;
  debug_regs_changed = 0;
  for (i = 0; i < NUM_RECORDS; i++)
  for (i = 0; i < NUM_RECORDS; i++)
    {
    {
      memcpy (&u, &or1k_htrace.recwp[i], sizeof(or1k_htrace.recwp[i]));
      memcpy (&u, &or1k_htrace.recwp[i], sizeof(or1k_htrace.recwp[i]));
      or1k_write_reg (JTAG_RECWP0 + i, u);
      or1k_write_reg (JTAG_RECWP0 + i, u);
    }
    }
  memcpy (&u, &or1k_htrace.recbp, sizeof(or1k_htrace.recbp));
  memcpy (&u, &or1k_htrace.recbp, sizeof(or1k_htrace.recbp));
  or1k_write_reg (JTAG_RECBP0, u);
  or1k_write_reg (JTAG_RECBP0, u);
  memcpy (&u, &or1k_htrace.moder, sizeof(or1k_htrace.moder));
  memcpy (&u, &or1k_htrace.moder, sizeof(or1k_htrace.moder));
  or1k_write_reg (JTAG_MODER, u);
  or1k_write_reg (JTAG_MODER, u);
}
}
 
 
static void
static void
or1k_set_undefined_cleanups (arg)
or1k_set_undefined_cleanups (arg)
     PTR arg;
     PTR arg;
{
{
  or1k_status = TARGET_UNDEFINED;
  or1k_status = TARGET_UNDEFINED;
}
}
 
 
/* Initialize a new connection to the or1k board, and make sure we are
/* Initialize a new connection to the or1k board, and make sure we are
   really connected.  */
   really connected.  */
 
 
static void
static void
or1k_init (args)
or1k_init (args)
     char *args;
     char *args;
{
{
  struct cleanup *old_cleanups = make_cleanup (or1k_set_undefined_cleanups, NULL);
  struct cleanup *old_cleanups = make_cleanup (or1k_set_undefined_cleanups, NULL);
  int i;
  int i;
  unsigned int tmp;
  unsigned int tmp;
  FILE *f;
  FILE *f;
 
 
  /* What is this code doing here?  I don't see any way it can happen, and
  /* 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.
     it might mean or1k_initializing didn't get cleared properly.
     So I'll make it a warning.  */
     So I'll make it a warning.  */
 
 
  if (or1k_status == TARGET_CONNECTING)
  if (or1k_status == TARGET_CONNECTING)
    {
    {
      warning ("internal error: or1k_initialize called twice");
      warning ("internal error: or1k_initialize called twice");
      return;
      return;
    }
    }
 
 
  or1k_status = TARGET_CONNECTING;
  or1k_status = TARGET_CONNECTING;
  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);
 
 
  debug("%08x\n", read_pc ());
  debug("%08x\n", read_pc ());
  or1k_stall ();
  or1k_stall ();
  debug("%08x\n", read_pc ());
  debug("%08x\n", read_pc ());
  usleep (1000);
  usleep (1000);
 
 
  /* Determine implementation configuration.  */
  /* Determine implementation configuration.  */
  or1k_implementation.VR = or1k_read_spr_reg (VR_SPRNUM);
  or1k_implementation.VR = or1k_read_spr_reg (VR_SPRNUM);
  or1k_implementation.UPR = or1k_read_spr_reg (UPR_SPRNUM);
  or1k_implementation.UPR = or1k_read_spr_reg (UPR_SPRNUM);
 
 
  /* Determine number of gpr_regs.  */
  /* Determine number of gpr_regs.  */
  tmp = or1k_read_spr_reg (CPUCFGR_SPRNUM);
  tmp = or1k_read_spr_reg (CPUCFGR_SPRNUM);
  or1k_implementation.num_gpr_regs = ((tmp >> 4) & 1)?(16):(32);
  or1k_implementation.num_gpr_regs = ((tmp >> 4) & 1)?(16):(32);
 
 
  /* Is any vector or floating point support present? */
  /* Is any vector or floating point support present? */
  or1k_implementation.vf_present = ((tmp >> 7) & 7) != 0;
  or1k_implementation.vf_present = ((tmp >> 7) & 7) != 0;
  or1k_implementation.num_vfpr_regs = (or1k_implementation.vf_present)?(32):(0);
  or1k_implementation.num_vfpr_regs = (or1k_implementation.vf_present)?(32):(0);
 
 
  /* Determine max number of supported matchpoints.  */
  /* Determine max number of supported matchpoints.  */
  tmp = or1k_read_spr_reg (DCFGR_SPRNUM);
  tmp = or1k_read_spr_reg (DCFGR_SPRNUM);
  or1k_implementation.num_matchpoints = tmp & 7;
  or1k_implementation.num_matchpoints = tmp & 7;
  or1k_implementation.num_used_matchpoints = 0;
  or1k_implementation.num_used_matchpoints = 0;
  or1k_implementation.has_counters = tmp & 4 == 1;
  or1k_implementation.has_counters = tmp & 4 == 1;
 
 
  /* Is implementation supported? */
  /* Is implementation supported? */
 
 
  /* First we should have system and debug groups implemented. */
  /* First we should have system and debug groups implemented. */
  if (or1k_implementation.VR & (1 << SPR_SYSTEM_GROUP) == 0)
  if (or1k_implementation.VR & (1 << SPR_SYSTEM_GROUP) == 0)
    error ("System group should be available in the or1k implementation.");
    error ("System group should be available in the or1k implementation.");
  if (or1k_implementation.VR & (1 << SPR_DEBUG_GROUP) == 0)
  if (or1k_implementation.VR & (1 << SPR_DEBUG_GROUP) == 0)
    error ("Debug group should be available in the or1k implementation.");
    error ("Debug group should be available in the or1k implementation.");
  if (or1k_implementation.has_counters)
  if (or1k_implementation.has_counters)
    warning ("Counters not supported.");
    warning ("Counters not supported.");
 
 
  /* Delete break, watch, catch points.  */
  /* Delete break, watch, catch points.  */
  for(i = 0; i < NUM_MATCHPOINTS; i++)
  for(i = 0; i < NUM_MATCHPOINTS; i++)
    {
    {
      memset (&dcr[i], 0, sizeof (dcr[i]));
      memset (&dcr[i], 0, sizeof (dcr[i]));
      matchpoint_user_count[i] = 0;
      matchpoint_user_count[i] = 0;
    }
    }
 
 
  dmr1 = 0;
  dmr1 = 0;
  dmr2 = 0;
  dmr2 = 0;
  memset (&or1k_htrace, 0, sizeof (or1k_htrace));
  memset (&or1k_htrace, 0, sizeof (or1k_htrace));
 
 
  /* RECSELDEPEND = 0 does not match our trace scheme. */
  /* RECSELDEPEND = 0 does not match our trace scheme. */
  or1k_htrace.moder.rec_sel_dep = 1;
  or1k_htrace.moder.rec_sel_dep = 1;
 
 
  debug_regs_changed = 1;
  debug_regs_changed = 1;
  or1k_commit_debug_registers ();
  or1k_commit_debug_registers ();
 
 
  if (err != 0)
  if (err != 0)
    error ("Cannot connect.");
    error ("Cannot connect.");
 
 
  /* Enable exceptions */
  /* Enable exceptions */
  or1k_write_spr_reg (SR_SPRNUM, or1k_read_spr_reg(SR_SPRNUM) | 0x2);
  or1k_write_spr_reg (SR_SPRNUM, or1k_read_spr_reg(SR_SPRNUM) | 0x2);
 
 
  /* Stop when breakpoint occurs.  */
  /* Stop when breakpoint occurs.  */
  or1k_write_spr_reg (DSR_SPRNUM, 0x2000);
  or1k_write_spr_reg (DSR_SPRNUM, dsr = 0x2000);
 
 
  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);
 
 
  set_current_frame (create_new_frame (read_fp (), read_pc ()));
  set_current_frame (create_new_frame (read_fp (), read_pc ()));
  select_frame (get_current_frame (), 0);
  select_frame (get_current_frame (), 0);
 
 
  /* Just empty it.  */
  /* Just empty it.  */
  if ((f = fopen (TRACE_FILENAME, "wb+")) == NULL)
  if ((f = fopen (TRACE_FILENAME, "wb+")) == NULL)
    error ("Cannot open trace file.");
    error ("Cannot open trace file.");
  fclose (f);
  fclose (f);
  trace_size = 0;
  trace_size = 0;
  or1k_status = TARGET_STOPPED;
  or1k_status = TARGET_STOPPED;
}
}
 
 
/* Kill the process running on the board.  */
/* Kill the process running on the board.  */
 
 
void
void
or1k_kill ()
or1k_kill ()
{
{
  if (or1k_status != TARGET_RUNNING)
  if (or1k_status != TARGET_RUNNING)
    return;
    return;
  or1k_status = TARGET_UNDEFINED;
  or1k_status = TARGET_UNDEFINED;
  or1k_reset();
  or1k_reset();
  or1k_status = TARGET_STOPPED;
  or1k_status = TARGET_STOPPED;
 
 
  inferior_pid = 0;
  inferior_pid = 0;
}
}
 
 
/* Open a connection to the remote board.  */
/* Open a connection to the remote board.  */
 
 
static void
static void
or1k_open (name, from_tty)
or1k_open (name, from_tty)
     char *name;
     char *name;
     int from_tty;
     int from_tty;
{
{
  or1k_init (name);
  or1k_init (name);
 
 
  /* Switch to using remote target now.  */
  /* Switch to using remote target now.  */
  current_ops = current_or1k_target->gdb_ops;
  current_ops = current_or1k_target->gdb_ops;
  or1k_is_open = 1;
  or1k_is_open = 1;
  push_target (current_ops);
  push_target (current_ops);
 
 
  /* FIXME: Should we call start_remote here?  */
  /* FIXME: Should we call start_remote here?  */
 
 
/* This is really the job of start_remote however, that makes an assumption
/* 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
   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
   doesn't happen here (in fact, it may not be possible to get the monitor to
   send the appropriate packet).  */
   send the appropriate packet).  */
 
 
  flush_cached_frames ();
  flush_cached_frames ();
  registers_changed ();
  registers_changed ();
  stop_pc = read_pc ();
  stop_pc = read_pc ();
  set_current_frame (create_new_frame (read_fp (), stop_pc));
  set_current_frame (create_new_frame (read_fp (), stop_pc));
  select_frame (get_current_frame (), 0);
  select_frame (get_current_frame (), 0);
  print_stack_frame (selected_frame, -1, 1);
  print_stack_frame (selected_frame, -1, 1);
}
}
 
 
/* This is the generic stop called via the target vector. When a target
/* This is the generic stop called via the target vector. When a target
   interrupt is requested, either by the command line or the GUI, we
   interrupt is requested, either by the command line or the GUI, we
   will eventually end up here. */
   will eventually end up here. */
static void
static void
or1k_stop ()
or1k_stop ()
{
{
  /* Send a break or a ^C, depending on user preference.  */
  /* Send a break or a ^C, depending on user preference.  */
  debug ("remote_stop called\n");
  debug ("remote_stop called\n");
 
 
  /* We should not stop the target immediately, since it can be in an
  /* We should not stop the target immediately, since it can be in an
     unfinished state.  So we do a single step.  This should not affect
     unfinished state.  So we do a single step.  This should not affect
     on anything.  */
     on anything.  */
  or1k_stall ();
  or1k_stall ();
  /* HW STEP.  Set DMR1_ST.  */
  /* HW STEP.  Set DMR1_ST.  */
  dmr1 |= DMR1_ST;
  dmr1 |= DMR1_ST;
  or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
  or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
  dmr1 &= ~DMR1_ST;
  dmr1 &= ~DMR1_ST;
  or1k_unstall ();
  or1k_unstall ();
}
}
 
 
/* Close a connection to the remote board.  */
/* Close a connection to the remote board.  */
 
 
static void
static void
or1k_close (quitting)
or1k_close (quitting)
     int quitting;
     int quitting;
{
{
  if (or1k_is_open)
  if (or1k_is_open)
    {
    {
      or1k_kill ();
      or1k_kill ();
      if (current_or1k_target != NULL && current_or1k_target->to_done != NULL)
      if (current_or1k_target != NULL && current_or1k_target->to_done != NULL)
        current_or1k_target->to_done ();
        current_or1k_target->to_done ();
      current_or1k_target = NULL;
      current_or1k_target = NULL;
    }
    }
  generic_mourn_inferior ();
  generic_mourn_inferior ();
}
}
 
 
/* Detach from the remote board.  */
/* Detach from the remote board.  */
 
 
static void
static void
or1k_detach (args, from_tty)
or1k_detach (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  if (args)
  if (args)
    error ("Argument given to \"detach\" when remotely debugging.");
    error ("Argument given to \"detach\" when remotely debugging.");
 
 
  pop_target ();
  pop_target ();
 
 
  or1k_close (1);
  or1k_close (1);
 
 
  if (from_tty)
  if (from_tty)
    printf_unfiltered ("Ending remote or1k debugging.\n");
    printf_unfiltered ("Ending remote or1k debugging.\n");
}
}
 
 
/* Appends trace data to the trace file.  */
/* Appends trace data to the trace file.  */
 
 
static void
static void
or1k_read_trace ()
or1k_read_trace ()
{
{
  struct htrace_data_struct data;
  struct htrace_data_struct data;
  ULONGEST tmp;
  ULONGEST tmp;
  int first = 1;
  int first = 1;
  FILE *fd;
  FILE *fd;
  if ((fd = fopen (TRACE_FILENAME, "ab")) == NULL)
  if ((fd = fopen (TRACE_FILENAME, "ab")) == NULL)
    {
    {
      warning ("Cannot append to trace file.");
      warning ("Cannot append to trace file.");
      return;
      return;
    }
    }
 
 
  or1k_set_chain (SC_TRACE);
  or1k_set_chain (SC_TRACE);
  while (1)
  while (1)
    {
    {
      tmp = or1k_read_reg (0);
      tmp = or1k_read_reg (0);
      memcpy (&data, &tmp, sizeof (data));
      memcpy (&data, &tmp, sizeof (data));
 
 
      /* Last record reached. */
      /* Last record reached. */
      if (!data.valid)
      if (!data.valid)
        break;
        break;
      data.valid = first;
      data.valid = first;
      first = 0;
      first = 0;
      if (!fwrite (&data, sizeof (data), 1, fd))
      if (!fwrite (&data, sizeof (data), 1, fd))
        {
        {
          warning ("Cannot write trace data");
          warning ("Cannot write trace data");
          break;
          break;
        }
        }
    }
    }
  fclose (fd);
  fclose (fd);
}
}
 
 
/* ^C Interrupt handling */
/* ^C Interrupt handling */
 
 
/* Ask the user what to do when an interrupt is received.  */
/* Ask the user what to do when an interrupt is received.  */
static void
static void
interrupt_query ()
interrupt_query ()
{
{
  target_terminal_ours ();
  target_terminal_ours ();
 
 
  if (query ("Interrupted while waiting for the program.\n\
  if (query ("Interrupted while waiting for the program.\n\
Give up (and stop debugging it)? "))
Give up (and stop debugging it)? "))
    {
    {
      target_mourn_inferior ();
      target_mourn_inferior ();
      return_to_top_level (RETURN_QUIT);
      return_to_top_level (RETURN_QUIT);
    }
    }
 
 
  target_terminal_inferior ();
  target_terminal_inferior ();
}
}
 
 
static void or1k_interrupt_twice (int signo);
static void or1k_interrupt_twice (int signo);
 
 
 
 
/* The command line interface's stop routine. This function is installed
/* The command line interface's stop routine. This function is installed
   as a signal handler for SIGINT. The first time a user requests a
   as a signal handler for SIGINT. The first time a user requests a
   stop, we call remote_stop to send a break or ^C. If there is no
   stop, we call remote_stop to send a break or ^C. If there is no
   response from the target (it didn't stop when the user requested it),
   response from the target (it didn't stop when the user requested it),
   we ask the user if he'd like to detach from the target. */
   we ask the user if he'd like to detach from the target. */
static void
static void
or1k_interrupt (signo)
or1k_interrupt (signo)
     int signo;
     int signo;
{
{
        debug ("interrupt");
        debug ("interrupt");
  /* If this doesn't work, try more severe steps. */
  /* If this doesn't work, try more severe steps. */
  signal (signo, or1k_interrupt_twice);
  signal (signo, or1k_interrupt_twice);
 
 
  debug ("remote_interrupt called\n");
  debug ("remote_interrupt called\n");
 
 
  interrupt_count++;
  interrupt_count++;
}
}
 
 
/* The user typed ^C twice.  */
/* The user typed ^C twice.  */
 
 
static void
static void
or1k_interrupt_twice (signo)
or1k_interrupt_twice (signo)
     int signo;
     int signo;
{
{
        debug ("interrupt2");
        debug ("interrupt2");
  signal (signo, ofunc);
  signal (signo, ofunc);
  interrupt_query ();
  interrupt_query ();
  signal (signo, or1k_interrupt);
  signal (signo, or1k_interrupt);
}
}
 
 
/* Resume execution of the target process.  STEP says whether to single-step
/* 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
   or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
   to the target, or zero for no signal.  */
   to the target, or zero for no signal.  */
 
 
static void
static void
or1k_resume (pid, step, siggnal)
or1k_resume (pid, step, siggnal)
     int pid, step;
     int pid, step;
     enum target_signal siggnal;
     enum target_signal siggnal;
{
{
        debug ("pc = %08x\n", read_pc());
  unsigned int pc;
 
  unsigned int ppc;
 
  unsigned int npc;
 
  unsigned int val;
 
 
 
  pc = read_pc();
 
  npc = or1k_read_spr_reg (PC_SPRNUM);
 
  ppc = or1k_read_spr_reg (PPC_SPRNUM);
 
  debug ("pc = %08x BP = %x npc = %08x ppc = %08x\n", pc, breakpoint_here_p (pc), npc, ppc);
  debug ("resume %i, %i, %i\n",step, siggnal, or1k_status);
  debug ("resume %i, %i, %i\n",step, siggnal, or1k_status);
  if (or1k_status != TARGET_STOPPED)
  if (or1k_status != TARGET_STOPPED)
    if (or1k_status == TARGET_RUNNING)
    if (or1k_status == TARGET_RUNNING)
      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_spr_reg (DRR_SPRNUM, 0);
  or1k_write_spr_reg (DRR_SPRNUM, 0);
 
 
  or1k_commit_debug_registers ();
  or1k_commit_debug_registers ();
 
 
  /* Else clause added by CZ 26/06/01 */
  /* Else clause added by CZ 26/06/01 */
  if (step)
  if (step)
    {
    {
      /* HW STEP.  Set DMR1_ST.  */
      /* HW STEP.  Set DMR1_ST.  */
      dmr1 |= DMR1_ST;
      dmr1 |= DMR1_ST;
      or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
      or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
      dmr1 &= ~DMR1_ST;
      dmr1 &= ~DMR1_ST;
 
 
 
      if (breakpoint_here_p (pc) && ((ppc + 4) != npc))
 
       {
 
          /* Trapped on delay slot instruction. */
 
          /* Set PC to branch insn preceding delay slot. */
 
          or1k_write_spr_reg (PC_SPRNUM, ppc - 4);
 
 
 
          or1k_unstall ();
 
 
 
          or1k_set_chain (SC_REGISTER);
 
          val = or1k_read_reg (JTAG_RISCOP);
 
          do {
 
            val = or1k_read_reg (JTAG_RISCOP);
 
          } while ((val & 1) == 0);
 
        }
 
      else if (breakpoint_here_p (npc) && insn_has_delay_slot (or1k_fetch_instruction (ppc)))
 
        {
 
          /* Steping to the trap insn in delay slot - we need to execute branch insn again */
 
          debug ("resume: steping to the trap insn in delay slot\n");
 
          or1k_write_spr_reg (PC_SPRNUM, ppc);
 
 
 
          or1k_unstall ();
 
 
 
          or1k_set_chain (SC_REGISTER);
 
          val = or1k_read_reg (JTAG_RISCOP);
 
          do {
 
            val = or1k_read_reg (JTAG_RISCOP);
 
          } while ((val & 1) == 0);
 
        }
 
      else if (breakpoint_here_p (pc))
 
        or1k_write_spr_reg (PC_SPRNUM, pc);
    }
    }
  else
  else
    {
    {
      dmr1 &= ~DMR1_ST;
      dmr1 &= ~DMR1_ST;
      or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
      or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
    }
    }
 
 
  /* We can now continue normally, independent of step */
  /* We can now continue normally, independent of step */
  or1k_unstall ();
  or1k_unstall ();
  or1k_status = TARGET_RUNNING;
  or1k_status = TARGET_RUNNING;
  debug ("-resume %i, %i, %i\n",step, siggnal, or1k_status);
  debug ("-resume %i, %i, %i\n",step, siggnal, or1k_status);
}
}
 
 
/* Wait until the remote stops, and return a wait status.  */
/* Wait until the remote stops, and return a wait status.  */
 
 
static int
static int
or1k_wait (pid, status)
or1k_wait (pid, status)
     int pid;
     int pid;
     struct target_waitstatus *status;
     struct target_waitstatus *status;
{
{
  unsigned long val;
  unsigned long val;
  unsigned long pc;
  unsigned long pc;
 
  unsigned long npc;
 
  unsigned long ppc;
  char buf[MAX_REGISTER_RAW_SIZE];
  char buf[MAX_REGISTER_RAW_SIZE];
  interrupt_count = 0;
  interrupt_count = 0;
 
 
  debug ("pc = %08x\n", read_pc());
 
  debug ("wait %i %i\n", pid, or1k_status);
  debug ("wait %i %i\n", pid, or1k_status);
  /* If we have not sent a single step or continue command, then the
  /* If we have not sent a single step or continue command, then the
     board is waiting for us to do something.  Return a status
     board is waiting for us to do something.  Return a status
     indicating that it is stopped.  */
     indicating that it is stopped.  */
  if (or1k_status != TARGET_RUNNING)
  if (or1k_status != TARGET_RUNNING)
    {
    {
      if (or1k_status != TARGET_STOPPED)
      if (or1k_status != TARGET_STOPPED)
        error("Target in invalid state.");
        error("Target in invalid state.");
      status->kind = TARGET_WAITKIND_STOPPED;
      status->kind = TARGET_WAITKIND_STOPPED;
      status->value.sig = TARGET_SIGNAL_TRAP;
      status->value.sig = TARGET_SIGNAL_TRAP;
      return 0;
      return 0;
    }
    }
 
 
  if (err)
  if (err)
    or1k_error ("Remote failure: %s", or1k_err_name (err));
    or1k_error ("Remote failure: %s", or1k_err_name (err));
 
 
  /* Set new signal handler */
  /* Set new signal handler */
  ofunc = signal (SIGINT, or1k_interrupt);
  ofunc = signal (SIGINT, or1k_interrupt);
 
 
  /* Wait for risc to stop.  */
  /* Wait for risc to stop.  */
  do {
  do {
    or1k_set_chain (SC_REGISTER);
    or1k_set_chain (SC_REGISTER);
    val = or1k_read_reg (JTAG_RISCOP);
    val = or1k_read_reg (JTAG_RISCOP);
 
 
    /* When we press Ctrl-C, interrupt count is set, but we must wait
    /* When we press Ctrl-C, interrupt count is set, but we must wait
         for or1k_read_reg to finish, otherwise we would interrupt transaction.  */
         for or1k_read_reg to finish, otherwise we would interrupt transaction.  */
    if (interrupt_count)
    if (interrupt_count)
        or1k_stop ();
      or1k_stop ();
 
 
    usleep (10);
    usleep (10);
    debug ("%i", val);
    debug ("%i", val);
  } while ((val & 1) == 0);
  } while ((val & 1) == 0);
 
 
  drr = or1k_read_spr_reg (DRR_SPRNUM);
  drr = or1k_read_spr_reg (DRR_SPRNUM);
 
 
  /* Restore old INT signal handler */
  /* Restore old INT signal handler */
  signal (SIGINT, ofunc);
  signal (SIGINT, ofunc);
 
 
  /* If we encounter breakpoint, drr is not set, so we set it manually.  */
  /* Single step does not set trap exception, so we set it manually to simplify our code */
  if (!drr)
  dmr1 = or1k_read_spr_reg (DMR1_SPRNUM);
    drr |= DRR_BE;
  if (dmr1 & DMR1_ST)
 
    drr |= DRR_TE;
 
 
  status->kind = TARGET_WAITKIND_STOPPED;
  status->kind = TARGET_WAITKIND_STOPPED;
 
 
  debug ("epcr0 = %08x\n", or1k_read_spr_reg (EPCR0_SPRNUM));
  debug ("epcr0 = %08x\n", or1k_read_spr_reg (EPCR0_SPRNUM));
  debug ("drr = %08x\n", drr);
  debug ("drr = %08x\n", drr);
 
 
  registers_changed ();
  registers_changed ();
  pc = read_pc ();
  pc = read_pc ();
  debug ("pc = %08x\n", pc);
  npc = or1k_read_spr_reg (PC_SPRNUM);
 
  ppc = or1k_read_spr_reg (PPC_SPRNUM);
 
  debug ("npc = %08x ppc = %08x\n", npc, ppc);
 
 
  if (drr & DRR_RSTE)
  if (drr & DRR_TE)
 
    {
 
      /* If single step is not set, we should correct the pc.  */
 
      if (!(dmr1 & DMR1_ST))
 
        /* PC has already stepped over the l.trap instruction.  */
 
        pc = ppc;
 
      status->value.sig = TARGET_SIGNAL_TRAP;
 
      drr &= ~DRR_TE;
 
    }
 
  else if (drr & DRR_RSTE)
 
    {
    status->value.sig = TARGET_SIGNAL_REALTIME_33;
    status->value.sig = TARGET_SIGNAL_REALTIME_33;
 
      drr &= ~DRR_RSTE;
 
    }
  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)
      drr &= ~DRR_BUSEE;
    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)
  else if (drr & DRR_AE)
 
    {
    status->value.sig = TARGET_SIGNAL_REALTIME_36;
    status->value.sig = TARGET_SIGNAL_REALTIME_36;
 
      drr &= ~DRR_AE;
 
    }
  else if (drr & DRR_IIE)
  else if (drr & DRR_IIE)
 
    {
    status->value.sig = TARGET_SIGNAL_ILL;
    status->value.sig = TARGET_SIGNAL_ILL;
  else if (drr & DRR_HPINTE)
      drr &= ~DRR_IIE;
    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)
  else if (drr & DRR_RE)
 
    {
    status->value.sig = TARGET_SIGNAL_REALTIME_39;
    status->value.sig = TARGET_SIGNAL_REALTIME_39;
 
      drr &= ~DRR_RE;
 
    }
 
  else if (drr & DRR_IME)
 
    {
 
      status->value.sig = TARGET_SIGNAL_REALTIME_38;
 
      drr &= ~DRR_IME;
 
    }
 
  else if (drr & DRR_DME)
 
    {
 
      status->value.sig = TARGET_SIGNAL_REALTIME_37;
 
      drr &= ~DRR_DME;
 
    }
 
  else if (drr & DRR_DPFE)
 
    {
 
      status->value.sig = TARGET_SIGNAL_REALTIME_34;
 
      drr &= ~DRR_DPFE;
 
    }
 
  else if (drr & DRR_IPFE)
 
    {
 
      status->value.sig = TARGET_SIGNAL_REALTIME_35;
 
      drr &= ~DRR_DPFE;
 
    }
  else if (drr & DRR_SCE)
  else if (drr & DRR_SCE)
 
    {
    status->value.sig = TARGET_SIGNAL_REALTIME_40;
    status->value.sig = TARGET_SIGNAL_REALTIME_40;
  else if (drr & DRR_BE)
      drr &= ~DRR_SCE;
    status->value.sig = TARGET_SIGNAL_TRAP;
    }
  else if (drr & DRR_TE)
  else if (drr & DRR_HPINTE)
 
    {
 
      status->value.sig = TARGET_SIGNAL_INT;
 
      drr &= ~DRR_HPINTE;
 
    }
 
  else if (drr & DRR_LPINTE)
 
    {
 
      status->value.sig = TARGET_SIGNAL_INT;
 
      drr &= ~DRR_LPINTE;
 
    }
 
  else
    {
    {
      /* PC has already stepped over the l.trap instruction.  */
 
      pc -= 8;
 
      status->value.sig = TARGET_SIGNAL_TRAP;
 
    } else {
 
      status->value.sig = TARGET_SIGNAL_UNKNOWN;
      status->value.sig = TARGET_SIGNAL_UNKNOWN;
      warning ("Invalid exception occured.");
      warning ("Invalid exception occured.");
    }
    }
 
 
 
  /* Update drr register */
 
  or1k_write_spr_reg (DRR_SPRNUM, drr);
 
 
  /* Write into PC flushes the pipeline! */
  /* Write into PC flushes the pipeline! */
  /* 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
     value in the target byte ordering.  */
     value in the target byte ordering.  */
  write_pc (pc);
/*  write_pc (pc);
 
*/
 
  store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), pc);
 
  supply_register (PC_REGNUM, buf);
 
 
  /*or1k_write_spr_reg (PC_SPRNUM, pc);
  /*or1k_write_spr_reg (PC_SPRNUM, pc);
  store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), pc);
  store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), pc);
  supply_register (PC_REGNUM, buf);*/
  supply_register (PC_REGNUM, buf);*/
 
 
  /* Log remote stop.  */
  /* Log remote stop.  */
  or1k_status = TARGET_STOPPED;
  or1k_status = TARGET_STOPPED;
 
 
  /* Determine what caused trap - breakpoint or watchpoint.  */
  /* Determine what caused trap - breakpoint or watchpoint.  */
  if (status->value.sig == TARGET_SIGNAL_TRAP)
  if (status->value.sig == TARGET_SIGNAL_TRAP)
    {
    {
      /* Search all active breakpoints for a match.  */
      /* Search all active breakpoints for a match.  */
      CORE_ADDR pc = read_pc ();
      CORE_ADDR pc = read_pc ();
      int breakpoint = 0;
      int breakpoint = 0;
      int i;
      int i;
      unsigned char break_bytes[4] = BRK_INSTR_STRUCT;
      unsigned char break_bytes[4] = BRK_INSTR_STRUCT;
      unsigned long b_insn = ntohl(*((unsigned long*)break_bytes));
      unsigned long b_insn = ntohl(*((unsigned long*)break_bytes));
      unsigned long value = pc;
      unsigned long value = pc;
 
 
      for (i = 0; i < or1k_implementation.num_used_matchpoints; i++)
      for (i = 0; i < or1k_implementation.num_used_matchpoints; i++)
        if (dvr[i] == pc && dcr[i].dp && dcr[i].cc == CC_EQUAL
        if (dvr[i] == pc && dcr[i].dp && dcr[i].cc == CC_EQUAL
            && !dcr[i].sc && dcr[i].ct == CT_FETCH)
            && !dcr[i].sc && dcr[i].ct == CT_FETCH)
          {
          {
            breakpoint = 1;
            breakpoint = 1;
            break;
            break;
          }
          }
      hit_watchpoint = !breakpoint;
      hit_watchpoint = !breakpoint;
 
 
      /* Cause the trap/breakpoint exception to be ignored. This is
      /* Cause the trap/breakpoint exception to be ignored. This is
         the behavior of the simulator when the PC value is changed
         the behavior of the simulator when the PC value is changed
         by a write command. All pending exceptions are cleared and
         by a write command. All pending exceptions are cleared and
         the simulator continues at the PC value specified. We need
         the simulator continues at the PC value specified. We need
         to do this if the instruction at the current PC has the
         to do this if the instruction at the current PC has the
         value BRK_INSTR_STRUCT */
         value BRK_INSTR_STRUCT */
 
 
      if(b_insn == or1k_read_mem((pc & 3)))
      if(b_insn == or1k_read_mem((pc & 3)))
        {
        {
          or1k_write_spr_reg(PC_SPRNUM,value);
          or1k_write_spr_reg(PC_SPRNUM,value);
        }
        }
    }
    }
  else
  else
    hit_watchpoint = 0;
    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;
    CORE_ADDR func_start;
    CORE_ADDR func_start;
    CORE_ADDR pc = read_pc ();
    CORE_ADDR pc = read_pc ();
 
 
    find_pc_partial_function (pc, &func_name, &func_start, NULL);
    find_pc_partial_function (pc, &func_name, &func_start, NULL);
    if (func_name != NULL && strcmp (func_name, "_exit") == 0
    if (func_name != NULL && strcmp (func_name, "_exit") == 0
        && func_start == pc)
        && func_start == pc)
      status->kind = TARGET_WAITKIND_EXITED;
      status->kind = TARGET_WAITKIND_EXITED;
  }
  }
 
 
  or1k_read_trace ();
  or1k_read_trace ();
  debug ("-wait %i %i\n", pid, or1k_status);
  debug ("-wait %i %i\n", pid, or1k_status);
  return 0;
  return 0;
}
}
 
 
/* Fetch a word from the target board.  All memory accesses to the
/* Fetch a word from the target board.  All memory accesses to the
   remote board are word aligned.  */
   remote board are word aligned.  */
 
 
unsigned int
unsigned int
or1k_fetch_word (addr)
or1k_fetch_word (addr)
     CORE_ADDR addr;
     CORE_ADDR addr;
{
{
  if (addr & 3)
  if (addr & 3)
    {
    {
      int subaddr = addr & 3;
      int subaddr = addr & 3;
      unsigned char buf[8];
      unsigned char buf[8];
      unsigned int low, high;
      unsigned int low, high;
      addr >>= 2;
      addr >>= 2;
      low = or1k_read_mem (addr << 2);
      low = or1k_read_mem (addr << 2);
      high = or1k_read_reg ((addr + 1) << 2);
      high = or1k_read_reg ((addr + 1) << 2);
      memcpy (&buf[0], &low, 4);
      memcpy (&buf[0], &low, 4);
      memcpy (&buf[4], &high, 4);
      memcpy (&buf[4], &high, 4);
      memcpy (&low, &buf[subaddr], 4);
      memcpy (&low, &buf[subaddr], 4);
      return low;
      return low;
    }
    }
  else
  else
    {
    {
      return or1k_read_mem (addr);
      return or1k_read_mem (addr);
    }
    }
}
}
 
 
/* 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.  All memory accesses to the remote board are word aligned.  */
   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)
  if (addr & 3)
    {
    {
      int subaddr = addr & 3;
      int subaddr = addr & 3;
      unsigned char buf[8];
      unsigned char buf[8];
      unsigned int low, high;
      unsigned int low, high;
      addr >>= 2;
      addr >>= 2;
      low = or1k_read_mem (addr << 2);
      low = or1k_read_mem (addr << 2);
      high = or1k_read_mem ((addr + 1) << 2);
      high = or1k_read_mem ((addr + 1) << 2);
      memcpy (&buf[0], &low, 4);
      memcpy (&buf[0], &low, 4);
      memcpy (&buf[4], &high, 4);
      memcpy (&buf[4], &high, 4);
      memcpy (&buf[subaddr], &val, 4);
      memcpy (&buf[subaddr], &val, 4);
      memcpy (&low, &buf[0], 4);
      memcpy (&low, &buf[0], 4);
      memcpy (&high, &buf[4], 4);
      memcpy (&high, &buf[4], 4);
      or1k_write_mem (addr << 2, low);
      or1k_write_mem (addr << 2, low);
      or1k_write_mem ((addr + 1) << 2, high);
      or1k_write_mem ((addr + 1) << 2, high);
    }
    }
  else
  else
    {
    {
      or1k_write_mem (addr, val);
      or1k_write_mem (addr, val);
    }
    }
  return err;
  return err;
}
}
 
 
/* Fetch the remote registers.  */
/* Fetch the remote registers.  */
 
 
void
void
or1k_fetch_registers (regno)
or1k_fetch_registers (regno)
     int regno;
     int regno;
{
{
  unsigned int val;
  unsigned int val;
 
 
  if (regno == -1)
  if (regno == -1)
    {
    {
      for (regno = 0; regno < NUM_REGS; regno++)
      for (regno = 0; regno < NUM_REGS; regno++)
        or1k_fetch_registers (regno);
        or1k_fetch_registers (regno);
      return;
      return;
    }
    }
 
 
  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_spr_reg (REGNUM_TO_SPRNUM(regno));
  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
       value in the target byte ordering.  */
       value in the target byte ordering.  */
    store_unsigned_integer (buf, REGISTER_RAW_SIZE (regno), val);
    store_unsigned_integer (buf, REGISTER_RAW_SIZE (regno), val);
    supply_register (regno, buf);
    supply_register (regno, buf);
  }
  }
  if (err)
  if (err)
    or1k_error ("Can't read register %d(%i): %s", regno,
    or1k_error ("Can't read register %d(%i): %s", regno,
                REGNUM_TO_SPRNUM(regno), or1k_err_name (err));
                REGNUM_TO_SPRNUM(regno), or1k_err_name (err));
}
}
 
 
/* Fetch and return instruction from the specified location.  */
/* Fetch and return instruction from the specified location.  */
 
 
unsigned int
unsigned int
or1k_fetch_instruction (addr)
or1k_fetch_instruction (addr)
     CORE_ADDR addr;
     CORE_ADDR addr;
{
{
  char buf[OR1K_INSTLEN];
  char buf[OR1K_INSTLEN];
  int status;
  int status;
 
 
  status = read_memory_nobpt (addr, buf, OR1K_INSTLEN);
  status = read_memory_nobpt (addr, buf, OR1K_INSTLEN);
  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.  */
/* Currently not needed.  */
 
 
static void
static void
or1k_prepare_to_store ()
or1k_prepare_to_store ()
{
{
}
}
 
 
/* Store remote register(s).  */
/* Store remote register(s).  */
 
 
static void
static void
or1k_store_registers (regno)
or1k_store_registers (regno)
     int regno;
     int regno;
{
{
  if (regno == -1)
  if (regno == -1)
    {
    {
      for (regno = 0; regno < NUM_REGS; regno++)
      for (regno = 0; regno < NUM_REGS; regno++)
        or1k_store_registers (regno);
        or1k_store_registers (regno);
      return;
      return;
    }
    }
 
 
  if (regno >= NUM_REGS)
  if (regno >= NUM_REGS)
    error("Invalid register number!");
    error("Invalid register number!");
 
 
  or1k_write_spr_reg (REGNUM_TO_SPRNUM(regno), read_register (regno));
  or1k_write_spr_reg (REGNUM_TO_SPRNUM(regno), read_register (regno));
  if (err)
  if (err)
    or1k_error ("Can't write register %d(%i): %s", regno, REGNUM_TO_SPRNUM(regno), 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
   read; 0 for error.  Note that protocol gives us the correct value
   read; 0 for error.  Note that protocol gives us the correct value
   for a longword, since it transfers values in ASCII.  We want the
   for a longword, since it transfers values in ASCII.  We want the
   byte values, so we have to swap the longword values.  */
   byte values, so we have to swap the longword values.  */
 
 
static int
static int
or1k_xfer_memory (memaddr, myaddr, len, write, ignore)
or1k_xfer_memory (memaddr, myaddr, len, write, ignore)
     CORE_ADDR memaddr;
     CORE_ADDR memaddr;
     char *myaddr;
     char *myaddr;
     int len;
     int len;
     int write;
     int write;
     struct target_ops *ignore;
     struct target_ops *ignore;
{
{
  register int i;
  register int i;
  /* Round starting address down to longword boundary.  */
  /* Round starting address down to longword boundary.  */
  register CORE_ADDR addr = memaddr & ~3;
  register CORE_ADDR addr = memaddr & ~3;
  /* Round ending address up; get number of longwords that makes.  */
  /* Round ending address up; get number of longwords that makes.  */
  register int count = (((memaddr + len) - addr) + 3) / 4;
  register int count = (((memaddr + len) - addr) + 3) / 4;
  /* Allocate buffer of that many longwords.  */
  /* Allocate buffer of that many longwords.  */
  register char *buffer = alloca (count * 4);
  register char *buffer = alloca (count * 4);
  int status;
  int status;
 
 
  int block_xfer_size = 256; /* CZ 21/06/01 ... number of 32 bit words */
  int block_xfer_size = 256; /* CZ 21/06/01 ... number of 32 bit words */
  int nBlocks = (count + block_xfer_size -1)/block_xfer_size;
  int nBlocks = (count + block_xfer_size -1)/block_xfer_size;
  int terminate = 0;  /* Terminate the printing of '*'s... */
  int terminate = 0;  /* Terminate the printing of '*'s... */
 
 
#ifdef DEBUG_JTAG
#ifdef DEBUG_JTAG
  debug ("xfer_memory %s addr=%x, len=%i, \n", write?"write":"read", memaddr, len);
  debug ("xfer_memory %s addr=%x, len=%i, \n", write?"write":"read", memaddr, len);
  fflush(stdout);
  fflush(stdout);
#endif
#endif
 
 
#if 0
#if 0
  if (memaddr >= MEM_SPACE)
  if (memaddr >= MEM_SPACE)
    error("Invalid address");
    error("Invalid address");
#endif
#endif
 
 
  /* (CZ 21/06/01 -- because upper layers which know nothing about
  /* (CZ 21/06/01 -- because upper layers which know nothing about
     Or1k or JTAG call this function directly, it is always necessary
     Or1k or JTAG call this function directly, it is always necessary
     to set the chain to point to the Debug Unit. Otherwise, it may
     to set the chain to point to the Debug Unit. Otherwise, it may
     be pointing to the Development Interface chain, in which case
     be pointing to the Development Interface chain, in which case
     we're going to get bupkiss... */
     we're going to get bupkiss... */
 
 
  if (write)
  if (write)
    {
    {
      /* Fill start and end extra bytes of buffer with existing data.  */
      /* Fill start and end extra bytes of buffer with existing data.  */
      if (addr != memaddr || len < 4)
      if (addr != memaddr || len < 4)
        {
        {
          /* Need part of initial word -- fetch it.  */
          /* Need part of initial word -- fetch it.  */
          store_unsigned_integer (&buffer[0], 4, or1k_fetch_word (addr));
          store_unsigned_integer (&buffer[0], 4, or1k_fetch_word (addr));
        }
        }
 
 
      if (count > 1)
      if (count > 1)
        {
        {
          /* Need part of last word -- fetch it.  FIXME: we do this even
          /* Need part of last word -- fetch it.  FIXME: we do this even
             if we don't need it.  */
             if we don't need it.  */
          store_unsigned_integer (&buffer[(count - 1) * 4], 4,
          store_unsigned_integer (&buffer[(count - 1) * 4], 4,
                                  or1k_fetch_word (addr + (count - 1) * 4));
                                  or1k_fetch_word (addr + (count - 1) * 4));
        }
        }
 
 
      /* Copy data to be written over corresponding part of buffer */
      /* Copy data to be written over corresponding part of buffer */
      memcpy ((char *) buffer + (memaddr & 3), myaddr, len);
      memcpy ((char *) buffer + (memaddr & 3), myaddr, len);
 
 
      /* CZ: rewrote the block transfer routines to make the code
      /* CZ: rewrote the block transfer routines to make the code
         a little more efficient for implementations that can handle
         a little more efficient for implementations that can handle
         variable sized scan chains. Might be useful in the future.
         variable sized scan chains. Might be useful in the future.
         Certainly makes downloads to the simulator more efficient. */
         Certainly makes downloads to the simulator more efficient. */
      for(i=0;i<nBlocks;i++,count-=block_xfer_size,addr += block_xfer_size*4)
      for(i=0;i<nBlocks;i++,count-=block_xfer_size,addr += block_xfer_size*4)
        {
        {
          int j;
          int j;
          int n = count < block_xfer_size ? count : block_xfer_size;
          int n = count < block_xfer_size ? count : block_xfer_size;
          unsigned long *__buf;
          unsigned long *__buf;
 
 
          if(!(__buf = (unsigned long*)malloc(n*sizeof(unsigned long))))
          if(!(__buf = (unsigned long*)malloc(n*sizeof(unsigned long))))
            {
            {
              errno = ERR_MEM;
              errno = ERR_MEM;
              return 0;
              return 0;
            }
            }
 
 
          for(j=0;j<n;j++)
          for(j=0;j<n;j++)
            __buf[j] = (unsigned long)extract_unsigned_integer(&buffer[(i * block_xfer_size +j)*4], 4);
            __buf[j] = (unsigned long)extract_unsigned_integer(&buffer[(i * block_xfer_size +j)*4], 4);
          or1k_set_chain (SC_WISHBONE);
          or1k_set_chain (SC_WISHBONE);
          status = or1k_store_block(addr,__buf,n);
          status = or1k_store_block(addr,__buf,n);
          free(__buf);
          free(__buf);
          if(n == block_xfer_size)
          if(n == block_xfer_size)
            {
            {
              debug ("*");
              debug ("*");
              gdb_flush (gdb_stdout);
              gdb_flush (gdb_stdout);
            }
            }
          if (status)
          if (status)
            {
            {
              errno = status;
              errno = status;
              return 0;
              return 0;
            }
            }
          /* FIXME: Do we want a QUIT here?  */
          /* FIXME: Do we want a QUIT here?  */
        }
        }
      if (terminate)
      if (terminate)
        debug ("\n");
        debug ("\n");
    }
    }
  else
  else
    {
    {
      for(i=0;i<nBlocks;i++,count-=block_xfer_size,addr += block_xfer_size*4)
      for(i=0;i<nBlocks;i++,count-=block_xfer_size,addr += block_xfer_size*4)
        {
        {
          int j;
          int j;
          int n = count < block_xfer_size ? count : block_xfer_size;
          int n = count < block_xfer_size ? count : block_xfer_size;
          unsigned long *__buf;
          unsigned long *__buf;
 
 
    or1k_set_chain (SC_WISHBONE);
    or1k_set_chain (SC_WISHBONE);
          __buf = (unsigned long*)malloc(n*sizeof(unsigned long));
          __buf = (unsigned long*)malloc(n*sizeof(unsigned long));
          status = or1k_load_block(addr,__buf,n);
          status = or1k_load_block(addr,__buf,n);
          if (!status)
          if (!status)
            for(j=0;j<n;j++)
            for(j=0;j<n;j++)
              store_unsigned_integer (&buffer[(i * block_xfer_size +j)*4], 4, __buf[j]);
              store_unsigned_integer (&buffer[(i * block_xfer_size +j)*4], 4, __buf[j]);
          else
          else
            errno = status;
            errno = status;
          free(__buf);
          free(__buf);
 
 
          if(status)
          if(status)
            return 0;
            return 0;
        }
        }
      /* Copy appropriate bytes out of the buffer.  */
      /* Copy appropriate bytes out of the buffer.  */
      memcpy (myaddr, buffer + (memaddr & 3), len);
      memcpy (myaddr, buffer + (memaddr & 3), len);
    }
    }
  return len;
  return len;
}
}
 
 
int or1k_load_block(CORE_ADDR addr,void* buffer,int nRegisters)
int or1k_load_block(CORE_ADDR addr,void* buffer,int nRegisters)
{
{
  int i=0;
  int i=0;
  unsigned int regno = addr;
  unsigned int regno = addr;
 
 
  if (current_or1k_target != NULL && current_or1k_target->to_read_block != NULL)
  if (current_or1k_target != NULL && current_or1k_target->to_read_block != NULL)
    return current_or1k_target->to_read_block (regno,buffer,nRegisters);
    return current_or1k_target->to_read_block (regno,buffer,nRegisters);
  else
  else
    for(i=0;i<nRegisters;i++)
    for(i=0;i<nRegisters;i++)
      ((unsigned long*)buffer)[i] = 0x1234;
      ((unsigned long*)buffer)[i] = 0x1234;
  return 0;
  return 0;
}
}
 
 
int or1k_store_block(CORE_ADDR addr,void* buffer,int nRegisters)
int or1k_store_block(CORE_ADDR addr,void* buffer,int nRegisters)
{
{
  unsigned int regno = addr;
  unsigned int regno = addr;
 
 
  if (current_or1k_target != NULL && current_or1k_target->to_write_block != NULL)
  if (current_or1k_target != NULL && current_or1k_target->to_write_block != NULL)
    return current_or1k_target->to_write_block (regno,buffer,nRegisters);
    return current_or1k_target->to_write_block (regno,buffer,nRegisters);
  return 0;
  return 0;
}
}
 
 
/* 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;
{
{
  char *file = "nothing";
  char *file = "nothing";
 
 
  if (exec_bfd)
  if (exec_bfd)
    file = bfd_get_filename (exec_bfd);
    file = bfd_get_filename (exec_bfd);
 
 
  printf_filtered ("or1k_files_info: file \"%s\"\n", file);
  printf_filtered ("or1k_files_info: file \"%s\"\n", file);
 
 
  if (exec_bfd)
  if (exec_bfd)
    {
    {
      printf_filtered ("\tAttached to %s running program %s\n",
      printf_filtered ("\tAttached to %s running program %s\n",
                       target_shortname, file);
                       target_shortname, file);
    }
    }
  /* Print target info. */
  /* Print target info. */
  printf_filtered ("Status: %s\n", status_name[or1k_status]);
  printf_filtered ("Status: %s\n", status_name[or1k_status]);
}
}
 
 
/* 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.  */
  return or1k_implementation.num_used_matchpoints < or1k_implementation.num_matchpoints;
  return or1k_implementation.num_used_matchpoints < or1k_implementation.num_matchpoints;
}
}
 
 
/* 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).  */
 
 
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);
}
}
 
 
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 */
  if (clear_breakpoint (addr))
  if (clear_breakpoint (addr))
    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
/* Tell whether this target can support a hardware breakpoint.  CNT
   is the number of hardware breakpoints already installed.  This
   is the number of hardware breakpoints already installed.  This
   implements the TARGET_CAN_USE_HARDWARE_WATCHPOINT macro.
   implements the TARGET_CAN_USE_HARDWARE_WATCHPOINT macro.
   Lower bound is estimated. !!! Can we estimate better? */
   Lower bound is estimated. !!! Can we estimate better? */
 
 
int
int
or1k_can_use_hardware_watchpoint (bp_type, cnt)
or1k_can_use_hardware_watchpoint (bp_type, cnt)
     enum bptype bp_type;
     enum bptype bp_type;
     int cnt;
     int cnt;
{
{
  /* Are there at least two matchpoints left for watch? - estimate lower bound  */
  /* Are there at least two matchpoints left for watch? - estimate lower bound  */
  return cnt + ((bp_type == bp_hardware_watchpoint)?(1):(0))
  return cnt + ((bp_type == bp_hardware_watchpoint)?(1):(0))
    <= or1k_implementation.num_matchpoints;
    <= or1k_implementation.num_matchpoints;
}
}
 
 
/* Moves matchpoint.  This is very tricky - we have to update
/* Moves matchpoint.  This is very tricky - we have to update
   all references to matchpoint indexes.  We assume here that
   all references to matchpoint indexes.  We assume here that
   matchpoint with index to is unused! */
   matchpoint with index to is unused! */
 
 
static void
static void
move_matchpoint (int from, int to)
move_matchpoint (int from, int to)
{
{
  int i, j, tmp, chaining;
  int i, j, tmp, chaining;
  if (matchpoint_user_count[to] != 0)
  if (matchpoint_user_count[to] != 0)
    error ("Internal: Destination matchpoint still has users");
    error ("Internal: Destination matchpoint still has users");
  matchpoint_user_count[to] = matchpoint_user_count[from];
  matchpoint_user_count[to] = matchpoint_user_count[from];
  matchpoint_user_count[from] = 0;
  matchpoint_user_count[from] = 0;
  debug_regs_changed = 1;
  debug_regs_changed = 1;
 
 
  dvr[to] = dvr[from];
  dvr[to] = dvr[from];
  dcr[to] = dcr[from];
  dcr[to] = dcr[from];
  dcr[from].dp = 0;
  dcr[from].dp = 0;
 
 
  /* Copy chaining bits.  */
  /* Copy chaining bits.  */
  chaining = dmr1 & (3 << (2 * from));
  chaining = dmr1 & (3 << (2 * from));
  dmr1 &= ~(3 << (2 * to));
  dmr1 &= ~(3 << (2 * to));
  dmr1 |= chaining << (2 * to);
  dmr1 |= chaining << (2 * to);
  dmr1 &= ~(3 << (2 * from));
  dmr1 &= ~(3 << (2 * from));
 
 
  /* Copy watchpoint bits */
  /* Copy watchpoint bits */
  tmp = dmr2 & (1 << from);
  tmp = dmr2 & (1 << from);
  dmr2 &= 1 << to;
  dmr2 &= 1 << to;
  dmr2 |= tmp << to;
  dmr2 |= tmp << to;
  dmr2 &= 1 << from;
  dmr2 &= 1 << from;
 
 
  /* Update hwatch table.  Here we assume that matchpoint
  /* Update hwatch table.  Here we assume that matchpoint
     group is connected (it cannot be implemented in HW
     group is connected (it cannot be implemented in HW
     otherwise), so if we move first, we will have to move
     otherwise), so if we move first, we will have to move
     others later.  */
     others later.  */
  for (i = 0; i < num_hw_watches; i++)
  for (i = 0; i < num_hw_watches; i++)
    if (or1k_hwatch[i].matchpoint_start == from)
    if (or1k_hwatch[i].matchpoint_start == from)
      or1k_hwatch[i].matchpoint_start = to;
      or1k_hwatch[i].matchpoint_start = to;
 
 
  /* Update htrace struct.  */
  /* Update htrace struct.  */
  tmp = or1k_htrace.trig.wp_trig & (1 << from);
  tmp = or1k_htrace.trig.wp_trig & (1 << from);
  or1k_htrace.trig.wp_trig &= 1 << to;
  or1k_htrace.trig.wp_trig &= 1 << to;
  or1k_htrace.trig.wp_trig |= tmp << to;
  or1k_htrace.trig.wp_trig |= tmp << to;
  or1k_htrace.trig.wp_trig &= 1 << from;
  or1k_htrace.trig.wp_trig &= 1 << from;
 
 
  tmp = or1k_htrace.qual.wp_trig & (1 << from);
  tmp = or1k_htrace.qual.wp_trig & (1 << from);
  or1k_htrace.qual.wp_trig &= 1 << to;
  or1k_htrace.qual.wp_trig &= 1 << to;
  or1k_htrace.qual.wp_trig |= tmp << to;
  or1k_htrace.qual.wp_trig |= tmp << to;
  or1k_htrace.qual.wp_trig &= 1 << from;
  or1k_htrace.qual.wp_trig &= 1 << from;
 
 
  tmp = or1k_htrace.stop.wp_trig & (1 << from);
  tmp = or1k_htrace.stop.wp_trig & (1 << from);
  or1k_htrace.stop.wp_trig &= 1 << to;
  or1k_htrace.stop.wp_trig &= 1 << to;
  or1k_htrace.stop.wp_trig |= tmp << to;
  or1k_htrace.stop.wp_trig |= tmp << to;
  or1k_htrace.stop.wp_trig &= 1 << from;
  or1k_htrace.stop.wp_trig &= 1 << from;
 
 
  for (i = 0; i < MAX_MATCHPOINTS; i++)
  for (i = 0; i < MAX_MATCHPOINTS; i++)
    {
    {
      tmp = or1k_htrace.wp_record_uses[i] & (1 << from);
      tmp = or1k_htrace.wp_record_uses[i] & (1 << from);
      or1k_htrace.wp_record_uses[i] &= 1 << to;
      or1k_htrace.wp_record_uses[i] &= 1 << to;
      or1k_htrace.wp_record_uses[i] |= tmp << to;
      or1k_htrace.wp_record_uses[i] |= tmp << to;
      or1k_htrace.wp_record_uses[i] &= 1 << from;
      or1k_htrace.wp_record_uses[i] &= 1 << from;
    }
    }
 
 
  /* Do we need to move other references also? */
  /* Do we need to move other references also? */
}
}
 
 
/* Sifts unused matchpoints to higher indexses.  */
/* Sifts unused matchpoints to higher indexses.  */
 
 
void
void
sift_matchpoints ()
sift_matchpoints ()
{
{
  int i, first_free = 0;
  int i, first_free = 0;
  for (i = 0; i < or1k_implementation.num_matchpoints; i++)
  for (i = 0; i < or1k_implementation.num_matchpoints; i++)
    if (dcr[i].dp)
    if (dcr[i].dp)
      {
      {
        /* Move references.  */
        /* Move references.  */
        move_matchpoint (i, first_free);
        move_matchpoint (i, first_free);
 
 
        first_free++;
        first_free++;
      }
      }
 
 
  /* Unused matchpoints should be disabled by move_matchpoint,
  /* Unused matchpoints should be disabled by move_matchpoint,
     so we are done here.  */
     so we are done here.  */
}
}
 
 
/* Translates gdb watchpoint type into one in DCR register.  */
/* Translates gdb watchpoint type into one in DCR register.  */
 
 
static int
static int
translate_type (gdb_type)
translate_type (gdb_type)
     int gdb_type;
     int gdb_type;
{
{
  switch (gdb_type)
  switch (gdb_type)
    {
    {
    case 0:
    case 0:
      return CT_SDATA;
      return CT_SDATA;
    case 1:
    case 1:
      return CT_LDATA;
      return CT_LDATA;
    case 2:
    case 2:
      return CT_ADATA;
      return CT_ADATA;
    default:
    default:
      error ("Invalid type.");
      error ("Invalid type.");
    }
    }
}
}
 
 
/* Set a data watchpoint.  ADDR and LEN should be obvious.  TYPE is 0
/* 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
   for a write watchpoint, 1 for a read watchpoint, or 2 for a read/write
   watchpoint. */
   watchpoint. */
 
 
int
int
or1k_insert_watchpoint (addr, len, type)
or1k_insert_watchpoint (addr, len, type)
     CORE_ADDR addr;
     CORE_ADDR addr;
     int len;
     int len;
     int type;
     int type;
{
{
  int i;
  int i;
 
 
  if (len < 1)
  if (len < 1)
    return -1;
    return -1;
 
 
  type = translate_type (type);
  type = translate_type (type);
 
 
  /* Moves unused watchpoints to the top.  */
  /* Moves unused watchpoints to the top.  */
  sift_matchpoints ();
  sift_matchpoints ();
 
 
  /* Place at first free matchpoint.  */
  /* Place at first free matchpoint.  */
  i = or1k_implementation.num_used_matchpoints;
  i = or1k_implementation.num_used_matchpoints;
  dvr[i] = addr;
  dvr[i] = addr;
  dcr[i].dp = 1;
  dcr[i].dp = 1;
  dcr[i].cc = CC_GREATE;
  dcr[i].cc = CC_GREATE;
  dcr[i].sc = 0;
  dcr[i].sc = 0;
  dcr[i].ct = type;
  dcr[i].ct = type;
 
 
  /* Set && chaining here.  */
  /* Set && chaining here.  */
  dmr1 &= ~(3 << (2 * i));
  dmr1 &= ~(3 << (2 * i));
  dmr1 |= CHAINING_AND << (2 * i);
  dmr1 |= CHAINING_AND << (2 * i);
 
 
  /* Set upper watchpoint bound.  */
  /* Set upper watchpoint bound.  */
  i++;
  i++;
  dvr[i] = addr + len - 1;
  dvr[i] = addr + len - 1;
  dcr[i].dp = 1;
  dcr[i].dp = 1;
  dcr[i].cc = CC_LESSE;
  dcr[i].cc = CC_LESSE;
  dcr[i].sc = 0;
  dcr[i].sc = 0;
  dcr[i].ct = type;
  dcr[i].ct = type;
 
 
  /* Matchpoints will cause breakpoints */
  /* Matchpoints will cause breakpoints */
  dmr2 |= (1 << i);
  dmr2 |= (1 << i);
  or1k_implementation.num_used_matchpoints += 2;
  or1k_implementation.num_used_matchpoints += 2;
  debug_regs_changed = 1;
  debug_regs_changed = 1;
  return 0;
  return 0;
}
}
 
 
/* Removes a data watchpoint.  ADDR and LEN should be obvious.  TYPE is 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
   for a write watchpoint, 1 for a read watchpoint, or 2 for a read/write
   watchpoint. */
   watchpoint. */
 
 
int
int
or1k_remove_watchpoint (addr, len, type)
or1k_remove_watchpoint (addr, len, type)
     CORE_ADDR addr;
     CORE_ADDR addr;
     int len;
     int len;
     int type;
     int type;
{
{
  int i, found = -1;
  int i, found = -1;
 
 
  if (len < 1)
  if (len < 1)
    return -1;
    return -1;
 
 
  type = translate_type (type);
  type = translate_type (type);
 
 
  /* Find the right one.  */
  /* Find the right one.  */
  for (i = 0; i < or1k_implementation.num_used_matchpoints; i++)
  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
    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
        && 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)
        && !dcr[i + 1].sc && dcr[i + 1].ct == type)
      {
      {
        found = i;
        found = i;
        break;
        break;
      }
      }
 
 
  if (found < 0)
  if (found < 0)
    return -1;
    return -1;
 
 
  dcr[found].dp = 0;
  dcr[found].dp = 0;
  dcr[found + 1].dp = 0;
  dcr[found + 1].dp = 0;
 
 
  /* Matchpoints will not cause breakpoints anymore. */
  /* Matchpoints will not cause breakpoints anymore. */
  dmr2 &= ~(1 << i);
  dmr2 &= ~(1 << i);
  or1k_implementation.num_used_matchpoints -= 2;
  or1k_implementation.num_used_matchpoints -= 2;
  debug_regs_changed = 1;
  debug_regs_changed = 1;
  return 0;
  return 0;
}
}
 
 
int
int
or1k_stopped_by_watchpoint (void)
or1k_stopped_by_watchpoint (void)
{
{
  /* For now, no watchpoints */
  /* For now, no watchpoints */
  return 0;
  return 0;
 
 
  /* return hit_watchpoint; */
  /* return hit_watchpoint; */
}
}
 
 
/* Insert a breakpoint.  */
/* Insert a breakpoint.  */
 
 
int
int
set_breakpoint (addr)
set_breakpoint (addr)
     CORE_ADDR addr;
     CORE_ADDR addr;
{
{
  int i;
  int i;
 
 
  /* Search for unused breakpoint.  */
  /* Search for unused breakpoint.  */
  for (i = 0; i < NUM_MATCHPOINTS; i++)
  for (i = 0; i < NUM_MATCHPOINTS; i++)
    if (dcr[i].dp == 0) break;
    if (dcr[i].dp == 0) break;
  if (i >= NUM_MATCHPOINTS) return 1;
  if (i >= NUM_MATCHPOINTS) return 1;
  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_implementation.num_used_matchpoints++;
  or1k_implementation.num_used_matchpoints++;
 
 
  /* No chaining here.  */
  /* No chaining here.  */
  dmr1 &= ~(3 << (2*i));
  dmr1 &= ~(3 << (2*i));
 
 
  /* Matchpoints will cause breakpoints */
  /* Matchpoints will cause breakpoints */
  dmr2 |= (1 << i);
  dmr2 |= (1 << i);
  debug_regs_changed = 1;
  debug_regs_changed = 1;
  return 0;
  return 0;
}
}
 
 
/* Clear a breakpoint.  */
/* Clear a breakpoint.  */
 
 
int
int
clear_breakpoint (addr)
clear_breakpoint (addr)
     CORE_ADDR addr;
     CORE_ADDR addr;
{
{
  int i;
  int i;
 
 
  /* Search for matching breakpoint.  */
  /* Search for matching breakpoint.  */
  for (i = 0; i < NUM_MATCHPOINTS; i++)
  for (i = 0; i < NUM_MATCHPOINTS; i++)
    if ((dcr[i].dp == 1) && (dvr[i] == addr) && (dcr[i].cc == CC_EQUAL)
    if ((dcr[i].dp == 1) && (dvr[i] == addr) && (dcr[i].cc == CC_EQUAL)
        && (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;
 
 
  /* Matchpoints will cause breakpoints */
  /* Matchpoints will cause breakpoints */
  dmr2 &= ~(1 << i);
  dmr2 &= ~(1 << i);
  or1k_implementation.num_used_matchpoints--;
  or1k_implementation.num_used_matchpoints--;
  debug_regs_changed = 1;
  debug_regs_changed = 1;
  return 0;
  return 0;
}
}
 
 
/* Start running on the target board.  */
/* Start running on the target board.  */
 
 
static void
static void
or1k_create_inferior (execfile, args, env)
or1k_create_inferior (execfile, args, env)
     char *execfile;
     char *execfile;
     char *args;
     char *args;
     char **env;
     char **env;
{
{
  CORE_ADDR entry_pt;
  CORE_ADDR entry_pt;
 
 
  if (args && *args)
  if (args && *args)
    {
    {
      warning ("Can't pass arguments to remote OR1K board; arguments ignored.");
      warning ("Can't pass arguments to remote OR1K board; arguments ignored.");
 
 
      /* And don't try to use them on the next "run" command.  */
      /* And don't try to use them on the next "run" command.  */
      execute_command ("set args", 0);
      execute_command ("set args", 0);
    }
    }
 
 
  if (execfile == 0 || exec_bfd == 0)
  if (execfile == 0 || exec_bfd == 0)
    error ("No executable file specified");
    error ("No executable file specified");
 
 
  or1k_kill ();
  or1k_kill ();
  remove_breakpoints ();
  remove_breakpoints ();
 
 
  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?  */
 
 
  /* Needed to get correct instruction in cache */
  /* Needed to get correct instruction in cache */
  insert_breakpoints ();
  insert_breakpoints ();
  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);
}
}
 
 
/* Clean up after a process.  Actually nothing to do.  */
/* Clean up after a process.  Actually nothing to do.  */
 
 
static void
static void
or1k_mourn_inferior ()
or1k_mourn_inferior ()
{
{
  generic_mourn_inferior ();
  generic_mourn_inferior ();
}
}
 
 
static void
static void
or1k_dummy_open (name, from_tty)
or1k_dummy_open (name, from_tty)
     char *name;
     char *name;
     int from_tty;
     int from_tty;
{
{
  target_preopen (from_tty);
  target_preopen (from_tty);
  if (or1k_is_open)
  if (or1k_is_open)
    unpush_target (current_ops);
    unpush_target (current_ops);
  current_or1k_target = &or1k_target_dummy;
  current_or1k_target = &or1k_target_dummy;
  or1k_open (name, from_tty);
  or1k_open (name, from_tty);
}
}
 
 
static void
static void
or1k_jtag_open (name, from_tty)
or1k_jtag_open (name, from_tty)
     char *name;
     char *name;
     int from_tty;
     int from_tty;
{
{
  target_preopen (from_tty);
  target_preopen (from_tty);
  if (or1k_is_open)
  if (or1k_is_open)
    unpush_target (current_ops);
    unpush_target (current_ops);
  current_or1k_target = &or1k_target_jtag;
  current_or1k_target = &or1k_target_jtag;
  or1k_open (name, from_tty);
  or1k_open (name, from_tty);
}
}
 
 
static void
static void
or1k_sim_open (name, from_tty)
or1k_sim_open (name, from_tty)
     char *name;
     char *name;
     int from_tty;
     int from_tty;
{
{
  /* target_preopen (from_tty); - do we need this ? */
  /* target_preopen (from_tty); - do we need this ? */
  if (or1k_is_open)
  if (or1k_is_open)
    unpush_target (current_ops);
    unpush_target (current_ops);
  current_or1k_target = &or1k_target_sim;
  current_or1k_target = &or1k_target_sim;
  or1k_open (name, from_tty);
  or1k_open (name, from_tty);
}
}
 
 
/* Executes command on the target.  */
/* Executes command on the target.  */
 
 
void
void
or1k_sim_cmd (char *args, int from_tty)
or1k_sim_cmd (char *args, int from_tty)
{
{
  if (current_or1k_target != NULL && current_or1k_target->to_exec_command != NULL)
  if (current_or1k_target != NULL && current_or1k_target->to_exec_command != NULL)
    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.  */
/* Displays matchpoints usage.  */
 
 
void
void
info_matchpoints_command (char *args, int from_tty)
info_matchpoints_command (char *args, int from_tty)
{
{
  int i;
  int i;
  for (i = 0; i < or1k_implementation.num_matchpoints; i++)
  for (i = 0; i < or1k_implementation.num_matchpoints; i++)
    {
    {
      printf_filtered ("WP%i ", i);
      printf_filtered ("WP%i ", i);
      if (dcr[i].dp)
      if (dcr[i].dp)
        {
        {
          int chaining = (dmr1 << 2*i) & 3;
          int chaining = (dmr1 << 2*i) & 3;
          printf_filtered ("= %s ", ct_names[dcr[i].ct]);
          printf_filtered ("= %s ", ct_names[dcr[i].ct]);
          if (dcr[i]. sc)
          if (dcr[i]. sc)
            printf_filtered ("s%s %i", cc_names[dcr[i].cc], (int)dvr[i]);
            printf_filtered ("s%s %i", cc_names[dcr[i].cc], (int)dvr[i]);
          else
          else
            printf_filtered ("%s %u", cc_names[dcr[i].cc], (unsigned int)dvr[i]);
            printf_filtered ("%s %u", cc_names[dcr[i].cc], (unsigned int)dvr[i]);
          if (chaining)
          if (chaining)
            printf_filtered ("%s WP%i", ch_names[chaining], i - 1);
            printf_filtered ("%s WP%i", ch_names[chaining], i - 1);
        }
        }
      else
      else
        printf_filtered ("NOT USED");
        printf_filtered ("NOT USED");
      if ((dmr2 >> i) & 1)
      if ((dmr2 >> i) & 1)
        printf_filtered (", causes breakpoint");
        printf_filtered (", causes breakpoint");
      if ((dmr2 >> (i + 11)) & 1)
      if ((dmr2 >> (i + 11)) & 1)
        printf_filtered (", increments counter");
        printf_filtered (", increments counter");
      printf_filtered ("\n");
      printf_filtered ("\n");
    }
    }
}
}
 
static int
 
insn_has_delay_slot (insn)
 
     unsigned int insn;
 
{
 
  if (((insn >> 26) <= 4) || ((insn >> 26) == 17) || ((insn >> 26) == 18))
 
    return 1;
 
  else
 
    return 0;
 
}
 
 
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;
  or1k_dummy_ops.to_detach = or1k_detach;
  or1k_dummy_ops.to_detach = or1k_detach;
  or1k_dummy_ops.to_resume = or1k_resume;
  or1k_dummy_ops.to_resume = or1k_resume;
  or1k_dummy_ops.to_wait = or1k_wait;
  or1k_dummy_ops.to_wait = or1k_wait;
  or1k_dummy_ops.to_fetch_registers = or1k_fetch_registers;
  or1k_dummy_ops.to_fetch_registers = or1k_fetch_registers;
  or1k_dummy_ops.to_store_registers = or1k_store_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_prepare_to_store = or1k_prepare_to_store;
  or1k_dummy_ops.to_xfer_memory = or1k_xfer_memory;
  or1k_dummy_ops.to_xfer_memory = or1k_xfer_memory;
  or1k_dummy_ops.to_files_info = or1k_files_info;
  or1k_dummy_ops.to_files_info = or1k_files_info;
  or1k_dummy_ops.to_insert_breakpoint = or1k_insert_breakpoint;
  or1k_dummy_ops.to_insert_breakpoint = or1k_insert_breakpoint;
  or1k_dummy_ops.to_remove_breakpoint = or1k_remove_breakpoint;
  or1k_dummy_ops.to_remove_breakpoint = or1k_remove_breakpoint;
  or1k_dummy_ops.to_kill = or1k_kill;
  or1k_dummy_ops.to_kill = or1k_kill;
  or1k_dummy_ops.to_load = generic_load;
  or1k_dummy_ops.to_load = generic_load;
  or1k_dummy_ops.to_create_inferior = or1k_create_inferior;
  or1k_dummy_ops.to_create_inferior = or1k_create_inferior;
  or1k_dummy_ops.to_mourn_inferior = or1k_mourn_inferior;
  or1k_dummy_ops.to_mourn_inferior = or1k_mourn_inferior;
  or1k_dummy_ops.to_stratum = process_stratum;
  or1k_dummy_ops.to_stratum = process_stratum;
  or1k_dummy_ops.to_stop = or1k_stop;
  or1k_dummy_ops.to_stop = or1k_stop;
 
 
  /* We can access memory while program is running.  */
  /* We can access memory while program is running.  */
  or1k_dummy_ops.to_has_all_memory = 0;
  or1k_dummy_ops.to_has_all_memory = 0;
 
 
  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;
 
 
  /* 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.  */
  or1k_jtag_ops.to_shortname = "jtag";
  or1k_jtag_ops.to_shortname = "jtag";
  or1k_jtag_ops.to_longname = "Remote or1k debugging over JTAG port";
  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"
  or1k_jtag_ops.to_doc = "Debug a board using the OR1K remote debugging protocol"
    " over a parallel line.\nThe argument is the parallel port it is connected "
    " over a parallel line.\nThe argument is the parallel port it is connected "
    "to, or, if it is formatted\nas a URL of the form jtag://<hostname>:<port>,"
    "to, or, if it is formatted\nas a URL of the form jtag://<hostname>:<port>,"
    " then the argument refers to\na remote JTAG proxy server.\n";
    " then the argument refers to\na remote JTAG proxy server.\n";
  or1k_jtag_ops.to_open = or1k_jtag_open;
  or1k_jtag_ops.to_open = or1k_jtag_open;
  add_target (&or1k_jtag_ops);
  add_target (&or1k_jtag_ops);
 
 
  or1k_dummy_ops.to_shortname = "dummy";
  or1k_dummy_ops.to_shortname = "dummy";
  or1k_dummy_ops.to_longname = "Dummy target";
  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_doc = "Actually no real target attached - more like /dev/null.\n";
  or1k_dummy_ops.to_open = or1k_dummy_open;
  or1k_dummy_ops.to_open = or1k_dummy_open;
  add_target (&or1k_dummy_ops);
  add_target (&or1k_dummy_ops);
 
 
  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.");
  add_info ("matchpoints", info_matchpoints_command, "Show current matchpoints allocation status.");
}
}
 
 

powered by: WebSVN 2.1.0

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