This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Merging OC gdb with official gdb


Andrew,

thanks for taking the time to look at ours code.

> Per, my other e-mail this is a new architecture that doesn't appear to
> require shared library support and hence shouldn't need the tm.h files.
>   If something needs to be shared between orxxx-tdep.c and other files
> then it should be declared in orxxx-tdep.h.
I think some macros are (currently) needed (see below).
Should I split our header file in two?
where should I place these *.h files? Do I need to set something in 
Makefiles/or32.tm file?

> If you find that you do appear to need to define certain macro's then
> post a question to check what is going on.
Ok, how should we handle following macros:
(I looked at the current code, but they look like they are not yet in gdbarch)

#define GDB_MULTI_ARCH 1
#define CANNOT_STEP_BREAKPOINT
#define target_insert_hw_breakpoint(addr, cache) or1k_insert_breakpoint (addr, 
cache)
#define target_remove_hw_breakpoint(addr, cache) or1k_remove_breakpoint (addr, 
cache)
#define TARGET_HAS_HARDWARE_WATCHPOINTS
#define target_insert_watchpoint(addr, len, type) \
        or1k_insert_watchpoint (addr, len, type)
#define target_remove_watchpoint(addr, len, type) \
        or1k_remove_watchpoint (addr, len, type)
#define HAVE_NONSTEPPABLE_WATCHPOINT
#define STOPPED_BY_WATCHPOINT(w) or1k_stopped_by_watchpoint ()
#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(bp_type, cnt, ot) \
  or1k_can_use_hardware_watchpoint(bp_type, cnt)
#define STEP_SKIPS_DELAY_P (1)
#define STEP_SKIPS_DELAY(pc) (or1k_step_skips_delay (pc))

> Some other notes on or1k-tdep.c:
> > #include "symcat.h"
>
> GDB assumes that an ISO C compiler is being used so "symcat.h" shouldn't
> be needed.
ok.

> > #define OR1K_IS_GPR(N) ((N) >= 0 && (N) < MAX_GPR_REGS)
> > #define OR1K_IS_VF(N) ((N) >= MAX_GPR_REGS && (N) < MAX_GPR_REGS +
> > MAX_VF_REGS)
>
> Macro's like this can simply be written as functions.  GDB's convention
> turns out to be:
>
> 	static int
> 	or1k_gpr_p (int regnum)
> 	{
> 	   return (regnum >= 0 && regnum < MAX_GPR_REGS);
> 	}
Is this a must? They are just macros for internal use ;)

> > char *or1k_reg_names[] = {
> >
> >   /* group 0 - general*/
> >   "VR", "UPR", "CPUCFGR", "DMMUCFGR", "IMMUCFGR", "DCCFGR", "ICCFGR",
> > "DCFGR", "PCCFGR", "SPR0_9", "SPR0_10", "SPR0_11", "SPR0_12", "SPR0_13",
> > "SPR0_14", "SPR0_15", "NPC", "SR", "PPC", "SPR0_19", "SPR0_20",
> > "SPR0_21", "SPR0_22", "SPR0_23", "SPR0_24", "SPR0_25", "SPR0_26",
> > "SPR0_27", "SPR0_28", "SPR0_29", "SPR0_30", "SPR0_31", "EPCR0", "EPCR1",
> > "EPCR2", "EPCR3", "EPCR4", "EPCR5", "EPCR6", "EPCR7", "EPCR8", "EPCR9",
> > "EPCR10", "EPCR11", "EPCR12", "EPCR13", "EPCR14", "EPCR15",
> > "EEAR0","EEAR1", "EEAR2", "EEAR3", "EEAR4", "EEAR5", "EEAR6", "EEAR7",
>
> Please change all the register names to lower case so that they are
> consistent with all other GDB targets.  Should the array be static.
ok.

> > /* Builds and returns register name.  */
> >
> > static char tmp_name[16];
> > static char *
> > or1k_spr_register_name (i)
> >      int i;
> > {
>
> GDB assumes ISO C so all K&R functions should be converted to ISO C.
done (huh!).

> This particular function now returns ``const char *''.  Can you please
> check that GDB configured with:
>
> 	--target=<your-target> --enable-gdb-build-warnings=,-Werror

> compiles (in particular your file).
It compiles now.

> >   int group = i >> SPR_GROUP_SIZE_BITS;
> >   int index = i & (SPR_GROUP_SIZE - 1);
> >   switch (group)
> >     {
> >       /* Names covered in or1k_reg_names.  */
> >     case 0:
> >
> >       /* Generate upper names.  */
> >       if (index >= SPR_GPR_START)
> > 	{
> > 	  if (index < SPR_VFPR_START)
> > 	    sprintf (tmp_name, "GPR%i", index - SPR_GPR_START);
> > 	  else
> > 	    sprintf (tmp_name, "VFR%i", index - SPR_VFPR_START);
> > 	  return (char *)&tmp_name;
>
> This code makes wrong assumptions about how the function will be used.
or1k architecture has special address space of registers called Special 
Purpose Registers. These include cache, tick timer, supervision registers, 
debug registers, etc.
They have to be separatedfrom General Purpose Registers, also GPRs.
Due to large number of SPRs (several thousands), I did not include them into 
gdb register space (except program counter PC).

> >   if (!frame_register_read (selected_frame, regnum, raw_buffer))
>
> Yes! Many targets incorrectly display the hardware registers instead of
> the current frame's registers.
no wonder I did it incorrectly :)

> Suggest passing the relevant frame in as a parameter though.
> selected_frame will one day go away
How do I get relevant frame? Is there a target already doing what you are 
proposing?

> >     error ("can't read register %d (%s)", regnum, REGISTER_NAME
> > (regnum));
> >
> >   flt = unpack_double (builtin_type_float, raw_buffer, &inv1);
> >   doub = unpack_double (builtin_type_double, raw_buffer, &inv3);
>
> Here use the ieee be/le size specific versions.  The code can't rely on
> float/double being something sensible.
What are be/le size specific versions?
Are you reffering to below printf_filtered?

> >   if (inv1)
> >     printf_filtered (" %-5s flt: <invalid float>", REGISTER_NAME
> > (regnum)); else
> >     printf_filtered (" %-5s flt:%-17.9g", REGISTER_NAME (regnum), flt);
> >   printf_filtered (inv3 ? " dbl: <invalid double> " :
> > 		   " dbl: %-24.17g ", doub);


> This should be ``info or1k spr''.  See ppc for an example of how to do
> this.
the command is already long, e.g.: info spr debug dmr1
since it is used a lot and it is registered only with or1k target, can we make 
an exception;) ?

> >   add_com ("spr", class_support, spr_command, "Set specified SPR
> > register.");
>
> This command shouldn't be needed.
> 	set $<sprreg> = <VAL>
>
> should work.
As I said above: the number of registers is too large and there is also some 
help involved with info spr/spr commands.

> >   /* hwatch command.  */
> >   add_com ("hwatch", class_breakpoint, hwatch_command, "Set hardware
> > watch" "point.\nExample: ($LEA == my_var)&&($LDATA < 50)||($SEA == my_"
> > "var)&&($SDATA >= 50).\nSee OR1k Architecture document for more" "
> > info.");
>
> I don't think this command is needed.  GDB already has hardware
> watchpoint commands.
We have proprietary hardware watches, which are resource limited and have some 
proprietary capabilities. Not all options can be set using gdb hardware 
watchpoints.

> >   /* htrace commands.  */
> >   add_prefix_cmd ("htrace", class_breakpoint, htrace_command,
> > 		  "Group of commands for handling hardware assisted trace\n\n"
> > 		  "See OR1k Architecture and gdb for or1k documents for more info.",
> > 		  &htrace_cmdlist, "htrace ", 0, &cmdlist);
> >   add_cmd ("info", class_breakpoint, htrace_info_command, "Display
> > information about HW trace.", &htrace_cmdlist);
> >   add_alias_cmd ("i", "info", class_breakpoint, 1, &htrace_cmdlist);
> >   add_cmd ("trigger", class_breakpoint, htrace_trigger_command, "Set
> > starting criteria for trace.", &htrace_cmdlist);
> >   add_alias_cmd ("t", "trigger", class_breakpoint, 1, &htrace_cmdlist);
> >   add_cmd ("qualifier", class_breakpoint, htrace_qualifier_command, "Set
> > acquisition qualifier for HW trace.", &htrace_cmdlist);
> >   add_alias_cmd ("q", "qualifier", class_breakpoint, 1, &htrace_cmdlist);
> >   add_cmd ("stop", class_breakpoint, htrace_stop_command, "Set HW trace
> > stopping criteria.", &htrace_cmdlist);
> >   add_alias_cmd ("s", "stop", class_breakpoint, 1, &htrace_cmdlist);
> >   add_cmd ("record", class_breakpoint, htrace_record_command, "Sets data
> > to be recorded when expression occurs.", &htrace_cmdlist);
> >   add_alias_cmd ("r", "record", class_breakpoint, 1, &htrace_cmdlist);
> >   add_cmd ("clear records", class_breakpoint,
> > htrace_clear_records_command, "Disposes all matchpoints used by
> > records.", &htrace_cmdlist); add_cmd ("enable", class_breakpoint,
> > htrace_enable_command, "Enables the HW trace.", &htrace_cmdlist);
> > add_alias_cmd ("e", "enable", class_breakpoint, 1, &htrace_cmdlist);
> > add_cmd ("disable", class_breakpoint, htrace_disable_command, "Disables
> > the HW trace.", &htrace_cmdlist); add_alias_cmd ("d", "disable",
> > class_breakpoint, 1, &htrace_cmdlist); add_cmd ("rewind",
> > class_breakpoint, htrace_rewind_command, "Clears currently recorded trace
> > data.\n" "If filename is specified, new trace file is made and any newly
> > collected data\n" "will be written there.", &htrace_cmdlist);
> >   add_cmd ("print", class_breakpoint, htrace_print_command,
> > 	   "Prints trace buffer, using current record configuration.\n"
> > 	   "htrace print [<start> [<len>]]\n"
> > 	   "htrace print"
> > 	   , &htrace_cmdlist);
> >   add_alias_cmd ("p", "print", class_breakpoint, 1, &htrace_cmdlist);
> >   add_prefix_cmd ("mode", class_breakpoint, htrace_mode_command,
> > 	   "Configures the HW trace.\n"
> > 	   "htrace mode [continuous|suspend]"
> > 	   , &htrace_mode_cmdlist, "htrace mode ", 0, &htrace_cmdlist);
> >   add_alias_cmd ("m", "mode", class_breakpoint, 1, &htrace_cmdlist);
> >   add_cmd ("continuous", class_breakpoint, htrace_mode_contin_command,
> > 	   "Set continuous trace mode.\n", &htrace_mode_cmdlist);
> >   add_cmd ("suspend", class_breakpoint, htrace_mode_suspend_command,
> > 	   "Set suspend trace mode.\n", &htrace_mode_cmdlist);
>
> Can I suggest, for the moment, moving this funcitonality out of
> or1k-tdep.c (to or1k-trace.c?).  This is a very significant chunk of
> work adding many new commands and hence is best separated and considered
> separatly.
ok. I will do this.

> >   /* Extra functions supported by simulator.  */
> >   add_com ("sim", class_obscure, sim_command,
> > 	   "Send a extended command to the simulator.");
>
> There is already a sim command.  See remote-sim.c.
ok, I've changed it to or1ksim.

I am reposting the files. Changes to config.gdb stays the same.

Marko
/* Remote debugging interface for JTAG debugging protocol.
   JTAG connects to or1k target ops. See or1k-tdep.c

   Copyright 1993-1995, 2000 Free Software Foundation, Inc.
   Contributed by Cygnus Support.  Written by Marko Mlinar
   <markom@opencores.org>
   Areas noted by (CZ) were modified by Chris Ziomkowski
   <chris@asics.ws>

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

#include "defs.h"
#include "inferior.h"
#include "bfd.h"
#include "symfile.h"
#include "gdb_wait.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "serial.h"
#include "target.h"
#include "remote-utils.h"
#include "gdb_string.h"
#include "tm.h"
/* Added by CZ 24/05/01 */
#include <sys/poll.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>

#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#define TCLK (0x01)
#define TRST (0x02)
#define JTAG_WAIT()
#define NUM_RETRIES (16)
#define JTAG_RETRY_WAIT() usleep (100)

/* Selects crc trailer size in bits. Currently supported: 8 */
#define CRC_SIZE (8)

/* Scan chain size in bits.  */
#define SC_SIZE (4)

/* Scan chain info. */
/* *INDENT-OFF* */
static int chain_addr_size[] = { 0,  32, 0,  0,  5  };
static int chain_data_size[] = { 0,  32, 0,  32, 32 };
static int chain_is_valid[]  = { 0,  1,  0,  1,  1  };
static int chain_has_crc[]   = { 0,  1,  0,  1,  1  };
static int chain_has_rw[]    = { 0,  1,  0,  0,  1  };
/* *INDENT-OFF* */

/* Currently selected scan chain - just to prevent unnecessary
   transfers. */
static int current_chain;

/* Designates whether we are in SELECT_DR state, otherwise in
   RUN TEST/IDLE */
static int select_dr = 0;

/* CZ - 24/05/01 - Changed to structure for remote/local */
typedef enum {
  JTAG_NOT_CONNECTED = 0,
  JTAG_LOCAL = 1,
  JTAG_REMOTE = 2,
} jtag_location;

typedef struct {
  union {
    /* Printer compatible device we have open.  */
    int lp;

    /* Socket for remote or1k jtag interface */ 
    int fd;
  } device;

  jtag_location location;
} jtag_connection;

/* Our current connect information */
static jtag_connection connection;

/* Crc of current read or written data.  */
static int crc_r, crc_w = 0;

/* Generates new crc, sending in new bit input_bit */

static int
crc_calc (int crc, int input_bit)
{
  int c;
  int new_crc;
  int d;

#if (CRC_SIZE == 8)
  d = input_bit & 1;
  c = crc;

  /* Move queue left.  */
  new_crc = crc << 1;

  /* Mask upper five bits.  */
  new_crc &= 0xF8;

  /* Set lower three bits */
  new_crc |= (d ^ ((c >> 7) & 1));
  new_crc |= (d ^ ((c >> 0) & 1) ^ ((c >> 7) & 1)) << 1;
  new_crc |= (d ^ ((c >> 1) & 1) ^ ((c >> 7) & 1)) << 2;
  return new_crc;
#else
  return 0;
#endif
}

/* Resets JTAG.
   Writes TRST=0
   and    TRST=1 */

static void
jp1_reset_JTAG ()
{
  unsigned char data;
  int lp = connection.device.lp;         /* CZ */

  if (connection.location != JTAG_LOCAL)
    error ("jp1_reset_JTAG called without a local connection!");

  data = 0;
  write (lp, &data, sizeof (data));
  JTAG_WAIT ();
  data = TRST;
  write (lp, &data, sizeof (data));
  JTAG_WAIT ();
}

/* Writes TCLK=0, TRST=1, TMS=bit0, TDI=bit1
   and    TCLK=1, TRST=1, TMS=bit0, TDI=bit1 */

static void
jp1_write_JTAG (unsigned char packet)
{
  unsigned char data;
  int lp = connection.device.lp;    /* CZ */

  if (connection.location != JTAG_LOCAL)
    error ("jp1_write_JTAG called without a local connection!");

  data = ((packet & 3) << 2) | TRST;
  write (lp, &data, sizeof (data));
  JTAG_WAIT ();
  crc_w = crc_calc (crc_w, (packet >> 1) & 1);
  
  /* rise clock */
  data |= TCLK;
  write (lp, &data, sizeof (data));
  JTAG_WAIT ();
}

/* Reads TDO, using IOCTL.  */

static int
jp1_read_JTAG ()
{
  int data;

  if (connection.location != JTAG_LOCAL)    /* CZ */
    error ("jp1_read_JTAG called without a local connection!");

  ioctl (data, 0x60b, &data);
  data = ((data & 0x80) != 0);
  crc_r = crc_calc (crc_r, data);
  return data;
}

/* Writes bitstream.  MS bit first.  */

static void
jp1_write_stream (ULONGEST stream, int len, int set_last_bit)
{
  int i;
  if (len <= 0) return; 
  for (i = len - 1; i > 0; i--)
    jp1_write_JTAG (((stream >> i) & 1) << 1);
  
  if (set_last_bit)
    jp1_write_JTAG (((stream & 1) << 1) | 1);
  else
    jp1_write_JTAG ((stream & 1) << 1);
}

/* Gets bitstream.  MS bit first.  */

static ULONGEST
jp1_read_stream (int len, unsigned long stream, int set_last_bit)
{
  int i;
  ULONGEST data;

  if (len <= 0) return 0;
  data = 0;
  for (i = 0; i < len - 1; i++)
    {      
      jp1_write_JTAG (0 + ((stream & 1) << 1));
      stream >>= 1;
      data <<= 1;
      data |= jp1_read_JTAG ();
    }
  
  if (set_last_bit)
    jp1_write_JTAG (1 + ((stream & 1) << 1));
  else
    jp1_write_JTAG (0 + ((stream & 1) << 1));
  data <<= 1;
  data |= jp1_read_JTAG ();
  return data;
}

/* Goes into SELECT_IR state. Should be called before every control write.  */

static void
jp1_prepare_control ()
{
  if (!select_dr)
    jp1_write_JTAG (1); /* SELECT_DR SCAN */
  jp1_write_JTAG (1);   /* SELECT_IR SCAN */
  select_dr = 0;
}

/* Added by CZ 24/05/01 */
static int jtag_proxy_write (int fd, void *buf, int len)
{
  int n;
  char *w_buf = (char *)buf;
  struct pollfd block;

  while (len)
    {
      if ((n = write (fd, w_buf, len)) < 0)
	{
	  switch (errno)
	    {
	    case EWOULDBLOCK: /* or EAGAIN */
	      /* We've been called on a descriptor marked
		 for nonblocking I/O. We better simulate
		 blocking behavior. */
	      block.fd = fd;
	      block.events = POLLOUT;
	      block.revents = 0;
	      poll (&block, 1, -1);
	      continue;
	    case EINTR:
	      continue;
	    case EPIPE:
	      return JTAG_PROXY_SERVER_TERMINATED;
	    default:
	      return errno;
	    }
	}
      else
        {
          len -= n;
          w_buf += n;
        }
    }
  return 0;
}

/* Added by CZ 24/05/01 */
static int jtag_proxy_read (int fd, void *buf, int len)
{
  int n;
  char *r_buf = (char *)buf;
  struct pollfd block;

  while (len)
    {
      if ((n = read (fd, r_buf, len)) < 0)
	{
	  switch (errno)
	    {
	    case EWOULDBLOCK: /* or EAGAIN */
	      /* We've been called on a descriptor marked
		 for nonblocking I/O. We better simulate
		 blocking behavior. */
	      block.fd = fd;
	      block.events = POLLIN;
	      block.revents = 0;
	      poll (&block, 1, -1);
	      continue;
	    case EINTR:
	      continue;
	    default:
	      return errno;
	    }
	}
      else if (n == 0)
	return JTAG_PROXY_SERVER_TERMINATED;
      else
        {
          len -= n;
          r_buf += n;
        }
    }
  return 0;
}

static int read_response (int fd, void *buffer, int len)
{
  int32_t status = 0;
  int result;
  char *buf = (char *)buffer;

	result = jtag_proxy_read (fd, &status, 4);

  status = ntohl (status);
  *((int32_t *)buffer) = status;

  if (result)
    {
      printf ("result %i %x\n", result, result);
      return result;
    }
  if (status)
    {
      printf ("status %i %x\n", status, status);
      return status;
    }

  result = jtag_proxy_read (fd, &buf[4], len - 4);
  return result;
}

/* Added by CZ 24/05/01 */
#ifndef ANSI_PROTOTYPES
static int jtag_send_proxy (va_alist)
va_dcl
#else
static int jtag_send_proxy (int command,...)
#endif
{
  va_list ap;
  int result = 0;
  int fd = connection.device.fd;
  jtag_proxy_write_message_t xmit_write;
  jtag_proxy_read_message_t xmit_read;
  jtag_proxy_chain_message_t xmit_chain;
  jtag_proxy_block_write_message_t *xmit_bwrite;
  jtag_proxy_block_read_message_t xmit_bread;
  jtag_proxy_write_response_t recv_write;
  jtag_proxy_read_response_t recv_read;
  jtag_proxy_chain_response_t recv_chain;
  jtag_proxy_block_write_response_t recv_bwrite;
  jtag_proxy_block_read_response_t recv_bread;
  unsigned long long data, *ret_val;

  /* Use word1 and word2 to ease portability to platforms */
  uint32_t word1;
  
  /* without long long and for alignment reasons */
  uint32_t word2;
  unsigned long address;
  unsigned long *b_data; 
  int nregs;
  int len,i;

#ifndef ANSI_PROTOTYPES
  int command;

  va_start (ap);
  command = va_arg (ap, int);
#else
  va_start (ap, command);
#endif

  if (connection.location == JTAG_REMOTE)
    {
      switch (command)
	{
	case JTAG_COMMAND_READ:
	  xmit_read.command = htonl (command);
	  xmit_read.length = htonl (sizeof (xmit_read) - 8);
	  xmit_read.address = htonl (va_arg (ap, int));
	  ret_val = va_arg (ap, unsigned long long *);
	  /* intentional single equals */
	  if ((result = jtag_proxy_write (fd, &xmit_read, sizeof (xmit_read))))
	    break;
	  if ((result = read_response (fd, &recv_read, sizeof (recv_read))))
	    break;
	  result = ntohl (recv_read.status);
	  word1 = ntohl (recv_read.data_H);
	  word2 = ntohl (recv_read.data_L);
	  *ret_val = (((unsigned long long)word1) << 32) | word2;
	  break;
	case JTAG_COMMAND_WRITE:
	  xmit_write.command = htonl (command);
	  xmit_write.length = htonl (sizeof (xmit_write) - 8);
	  xmit_write.address = htonl (va_arg (ap, int));
	  data = va_arg (ap, unsigned long long);
	  word1 = htonl (data >> 32);
	  word2 = htonl (data & 0xFFFFFFFF);
	  xmit_write.data_H = word1;
	  xmit_write.data_L = word2;
	  if ((result = jtag_proxy_write (fd, &xmit_write, sizeof (xmit_write))))
	    break;
	  if ((result = read_response (fd, &recv_write, sizeof (recv_write))))
	    break;
	  result = recv_write.status;
	  break;
	case JTAG_COMMAND_BLOCK_WRITE:
	  address = va_arg (ap, unsigned long);
	  b_data = va_arg (ap, unsigned long *);
	  nregs = va_arg (ap, int);
	  len = sizeof (jtag_proxy_block_write_message_t) + (nregs - 1) * 4;
	  xmit_bwrite = (jtag_proxy_block_write_message_t *)malloc (len);
	  xmit_bwrite->command = htonl (command);
	  xmit_bwrite->length = htonl (len - 8);
	  xmit_bwrite->address = htonl (address);
	  xmit_bwrite->nregs = htonl (nregs);
	  for (i = 0; i < nregs; i++)
	    xmit_bwrite->data[i] = htonl (b_data[i]);
	  if (!(result = jtag_proxy_write (fd, xmit_bwrite, len)) &&
	     !(result = read_response (fd, &recv_bwrite, sizeof (recv_bwrite))))
	    result = recv_bwrite.status;
	  free (xmit_bwrite);
	  xmit_bwrite = NULL;
	  break;
	case JTAG_COMMAND_BLOCK_READ:
	  address = va_arg (ap, unsigned long);
	  b_data = va_arg (ap, unsigned long *);
	  nregs = va_arg (ap, int);
	  xmit_bread.command = htonl (command);
	  xmit_bread.length = htonl (sizeof (xmit_bread) - 8);
	  xmit_bread.address = htonl (address);
	  xmit_bread.nregs = htonl (nregs);
	  if ((result = jtag_proxy_write (fd, &xmit_bread, sizeof (xmit_bread))))
	    break;
	  if ((result = read_response (fd, &recv_bread, sizeof (recv_bread))))
	    break;
	  b_data[0] = ntohl (recv_bread.data[0]);
	  recv_bread.nregs = ntohl (recv_bread.nregs);
	  if ((result = jtag_proxy_read (fd, &b_data[1], 4 * (recv_bread.nregs - 1))))
	    break;
	  if (recv_bread.nregs != nregs)
	    result = JTAG_PROXY_PROTOCOL_ERROR;
	  else
	    {
	      for (i = 1; i < nregs; i++)
		b_data[i] = ntohl (b_data[i]);
	    }
	  break;
	case JTAG_COMMAND_CHAIN:
	  xmit_chain.command = htonl (command);
	  xmit_chain.length = htonl (sizeof (xmit_chain) - 8);
	  xmit_chain.chain = htonl (va_arg (ap, unsigned int));
	  if ((result = jtag_proxy_write (fd, &xmit_chain, sizeof (xmit_chain))))
	    break;
	  if ((result = read_response (fd, &recv_chain, sizeof (recv_chain))))
	    break;
	  result = recv_chain.status;
	  break;
	default:
	  result = JTAG_PROXY_INVALID_COMMAND;
	  break;
	}
      va_end (ap);
    }
  else
    {
      va_end (ap);
      error ("jtag_send_proxy called without a remote proxy connection!");
      result = JTAG_PROXY_NO_CONNECTION;
    }

  if (result == JTAG_PROXY_SERVER_TERMINATED)
    {
      close (connection.device.fd);
      connection.device.fd = 0;
      connection.location = JTAG_NOT_CONNECTED;
    }

  return result;
}

/* Added by CZ 24/05/01 */
#ifndef ANSI_PROTOTYPES
static void jtag_proxy_error (va_alist)
va_dcl
#else
static void jtag_proxy_error (int result, int command,...)
#endif
{
  va_list ap;
  char stemp[256];

#ifndef ANSI_PROTOTYPES
  int result;
  int command;
 
  va_start (ap);
  result = va_arg (ap, int);
  command = va_arg (ap, int);
#else
  va_start (ap, command);
#endif

  switch (command)
    {
    case JTAG_COMMAND_READ:
      sprintf (stemp, "An error was reported by the proxy server. The command was:\n"
	      "\"JTAG_COMMAND_READ\",%u,0x%08lx\nThe command returned %d.\n",
	      va_arg (ap, unsigned int), (unsigned long) va_arg (ap, unsigned long long *),
              result);
      error (stemp);
      break;
    case JTAG_COMMAND_WRITE:
      sprintf (stemp, "An error was reported by the proxy server. The command was:\n"
	      "\"JTAG_COMMAND_WRITE\",%u,0x%016llx\nThe command returned %d.\n",
	      va_arg (ap, unsigned int), va_arg (ap, unsigned long long), result);
      error (stemp);
      break;
    case JTAG_COMMAND_CHAIN:
      sprintf (stemp, "An error was reported by the proxy server. The command was:\n"
	      "\"JTAG_COMMAND_CHAIN\",%u. The command returned %d.\n",
	      va_arg (ap, unsigned int), result);
      error (stemp);
      break;
    case JTAG_COMMAND_BLOCK_READ:
      sprintf (stemp, "An error was reported by the proxy server. The command was:\n"
	      "\"JTAG_COMMAND_BLOCK_READ\",0x%08lx,0x%08lx,%d\nThe command returned %d.\n",
	      va_arg (ap, unsigned long), va_arg (ap, unsigned long), va_arg (ap, int), result);
      error (stemp);
      break;
    case JTAG_COMMAND_BLOCK_WRITE:
    default:
      sprintf (stemp, "An error was reported by the proxy server. The command was:\n"
	      "\"JTAG_COMMAND_BLOCK_WRITE\",0x%08lx,0x%08lx,%d\nThe command returned %d.\n",
	      va_arg (ap, unsigned long), va_arg (ap, unsigned long), va_arg (ap, int), result);
      error (stemp);
      break;
    }
  va_end (ap);
}

/* Sets register/memory regno to data.  */

/* CZ 08/06/01: I am not sure how error checking is intended to
   be implemented here. It appears that no indication is returned
   to the caller as you have in standard unix system calls. Therefore,
   I guess the only way to use these functions when you want to know
   the exact position of the error is to manually clear err, call the
   function, and then manually check err. I have also made some changes
   where necessary because no value was returned at all int jtag_read_reg.
*/

void
jtag_write_reg (int regno, ULONGEST data)
{
  int result, retry;

#ifdef DEBUG_JTAG
  printf_unfiltered ("write reg %x <- %x\n", regno, data);
  fflush (stdout);
#endif
  switch (connection.location) /* CZ */
    {
    case JTAG_LOCAL:
      if (!select_dr)
	jp1_write_JTAG (1); /* SELECT_DR SCAN */
      select_dr = 1;

      /* If we don't have rw bit, we assume chain
	 is read only. */
      if (!chain_has_rw[current_chain])
	error ("Internal: Chain not writable.");

      for (retry = 0; retry < NUM_RETRIES; retry++)
	{
          int crc_read = 0, crc_write = 0, crc_ok = 0;
	  jp1_write_JTAG (0); /* CAPTURE_DR */
	  jp1_write_JTAG (0); /* SHIFT_DR */
	  crc_w = 0;

	  /* write addr */
	  jp1_write_stream (regno, chain_addr_size[current_chain], 0);

	  /* write (R/W=1) - we tested that previously. */
	  jp1_write_JTAG (2);

	  /* write data */
	  jp1_write_stream (data, chain_data_size[current_chain], 0); 
	  if (chain_has_crc[current_chain])
	    {
	      crc_write = crc_w;

	      /* write CRC, EXIT1_DR */
	      crc_read = jp1_read_stream (crc_write, CRC_SIZE, 1);
	    }
	  jp1_write_JTAG (1); /* UPDATE_DR */

	  /* Did JTAG receive packet correctly? */
	  if (chain_has_crc[current_chain])
	    crc_ok = jp1_read_JTAG ();
	  jp1_write_JTAG (1); /* SELECT_DR */
	  if (chain_has_crc[current_chain])
	    {
	      if ((crc_read == crc_write) && (crc_ok))
		return;
	      JTAG_RETRY_WAIT ();
	    }
	  else return;
	}
      err = ERR_CRC;
      break;
    case JTAG_REMOTE:
      if ((result = jtag_send_proxy (JTAG_COMMAND_WRITE,regno,data)))
	{
	  jtag_proxy_error (result,JTAG_COMMAND_WRITE,regno,data);
	  err = result;
	}
      break;
    default:
      error ("jtag_write_reg called with no connection!");
      break;
    }
#ifdef DEBUG_JTAG
  printf_unfiltered ("!write reg\n");
  fflush (stdout);
#endif
}

/* Reads register/memory from regno.  */

ULONGEST
jtag_read_reg (unsigned int regno)
{
  ULONGEST data;
  int result, retry;

#ifdef DEBUG_JTAG
  printf_unfiltered ("read reg %x\n", regno);
  fflush (stdout);
#endif
  switch (connection.location)
    {
    case JTAG_LOCAL:
      if (!select_dr)
	jp1_write_JTAG (1); /* SELECT_DR SCAN */
      select_dr = 1;

      for (retry = 0; retry < NUM_RETRIES; retry++)
	{      
          int crc_read = 0, crc_write = 0, crc_ok = 0, crc_actual_read = 0;
	  jp1_write_JTAG (0); /* CAPTURE_DR */
	  jp1_write_JTAG (0); /* SHIFT_DR */
	  crc_w = 0;

	  /* write addr */
	  jp1_write_stream (regno, chain_addr_size[current_chain], 0);
  
	  /* read (R/W=0) */
	  if (chain_has_rw[current_chain])
	    jp1_write_JTAG (0);
	  if (chain_has_crc[current_chain])
	    {
	      crc_r = 0;

	      /* data = 0 */
	      data = jp1_read_stream (0, chain_data_size[current_chain], 0);
	      crc_write = crc_w;
	      crc_actual_read = crc_read;

	      /* Send my crc, EXIT1_DR */
	      crc_read = jp1_read_stream (crc_write, CRC_SIZE, 1);
	    }
	  jp1_write_JTAG (1); /* UPDATE_DR */

	  /* Did JTAG receive packet correctly? */
	  if (chain_has_crc[current_chain])
	    crc_ok = jp1_read_JTAG ();
	  jp1_write_JTAG (1); /* SELECT_DR */
	  if (chain_has_crc[current_chain])
	    {
	      if ((crc_read == crc_actual_read) && (crc_ok))
		return -1;  /* CZ */
	      JTAG_RETRY_WAIT ();
	    }
	  else
	    return -1;  /* CZ */
	}
      err = ERR_CRC;
      break;
    case JTAG_REMOTE:
      if ((result = jtag_send_proxy (JTAG_COMMAND_READ, regno, &data)))
	{
	  jtag_proxy_error (result, JTAG_COMMAND_READ, regno, &data);
	  err = result;
	}
      break;
    default:
      error ("jtag_write_reg called with no connection!");
      break;
    }
  
#ifdef DEBUG_JTAG
  printf_unfiltered ("read reg %x\n", data);
  fflush (stdout);
#endif
  return data;  /* CZ */
}

int
jtag_write_block (unsigned int regno, void *data, int nregs)
{
  unsigned long *buffer = (unsigned long *)data;
  int i, result;

  if (nregs == 1) {
    jtag_write_reg (regno, *buffer);
    return err;
  }
  
#ifdef DEBUG_JTAG
  printf_unfiltered ("write block %x,%i\n", regno, nregs);
  fflush (stdout);
#endif

  err = 0;
  switch (connection.location)
    {
    case JTAG_LOCAL:         /* We can't do any better than this locally */
      for (i = 0;i < nregs;i++)
	jtag_write_reg (regno + i, (ULONGEST)buffer[i]);
      break;
    case JTAG_REMOTE:
      if ((result = jtag_send_proxy (JTAG_COMMAND_BLOCK_WRITE, regno, data, nregs)))
	{
	  jtag_proxy_error (result, JTAG_COMMAND_BLOCK_WRITE, regno, data, nregs);
	  err = result;
	}
      break;
    default:
      error ("jtag_write_reg called with no connection!");
      break;
    }
  
#ifdef DEBUG_JTAG
  printf_unfiltered ("!write block\n");
  fflush (stdout);
#endif
  return err;
}

int
jtag_read_block (unsigned int regno, void *data, int nregs)
{
  unsigned long *buffer = (unsigned long *)data;
  int i,result;

#ifdef DEBUG_JTAG
  printf_unfiltered ("read block %x,%i\n", regno, nregs);
  fflush (stdout);
#endif

#if 0
  if (nregs == 1)
    {
      *buffer = jtag_read_reg (regno);
      return err;
    }
#endif

  err = 0;
  switch (connection.location)
    {
    case JTAG_LOCAL:         /* We can't do any better than this locally */
      for (i = 0; i < nregs; i++)
	buffer[i] = (unsigned long)jtag_read_reg (regno + i);
      break;
    case JTAG_REMOTE:
      if ((result = jtag_send_proxy (JTAG_COMMAND_BLOCK_READ, regno, data, nregs)))
	{
	  jtag_proxy_error (result, JTAG_COMMAND_BLOCK_READ, regno, data, nregs);
	  err = result;
	}
      break;
    default:
      error ("jtag_write_reg called with no connection!");
      break;
    }

#ifdef DEBUG_JTAG
  printf_unfiltered ("read block\n");
  fflush (stdout);
#endif  
  return err;
}

/* Sets scan chain.  */

void
jtag_set_chain (int chain)
{
  int result;

#ifdef DEBUG_JTAG
  printf_unfiltered ("set chain %x\n", chain);
  fflush (stdout);
#endif
  switch (connection.location)
    {
    case JTAG_LOCAL:
      if (current_chain != chain)
	{
	  if (!chain_is_valid[chain])
	    error ("Chain not valid.");

	  current_chain = chain;
	  jp1_prepare_control ();

	  jp1_write_JTAG (0); /* CAPTURE_IR */
	  jp1_write_JTAG (0); /* SHIFT_IR */

	  /* write data, EXIT1_IR */
	  jp1_write_stream (JI_CHAIN_SELECT, JI_SIZE, 4);
            
	  jp1_write_JTAG (1); /* UPDATE_IR */
	  jp1_write_JTAG (1); /* SELECT_DR */
      
	  jp1_write_JTAG (0); /* CAPTURE_DR */
	  jp1_write_JTAG (0); /* SHIFT_DR */

	  /* write data, EXIT1_DR */
	  jp1_write_stream (chain, SC_SIZE, 1);
      
	  jp1_write_JTAG (1); /* UPDATE_DR */
	  jp1_write_JTAG (1); /* SELECT_DR */

	  /* Now we have to go out of SELECT_CHAIN mode.  */
	  jp1_write_JTAG (1); /* SELECT_IR */
	  jp1_write_JTAG (0); /* CAPTURE_IR */
	  jp1_write_JTAG (0); /* SHIFT_IR */

	  /* write data, EXIT1_IR */
	  jp1_write_stream (JI_DEBUG, JI_SIZE,1 );
            
	  jp1_write_JTAG (1); /* UPDATE_IR */
	  jp1_write_JTAG (1); /* SELECT_DR */
	  select_dr = 1;
	}
      break;
    case JTAG_REMOTE:
      if (current_chain != chain)
	{
	  if ((result = jtag_send_proxy (JTAG_COMMAND_CHAIN, chain)))
	    {
	      jtag_proxy_error (result, JTAG_COMMAND_CHAIN, chain);
	      err = result;
	    }
	}
      break;
    default:
      error ("jtag_set_chain called with no connection!");
      break;
    }
#ifdef DEBUG_JTAG
  printf_unfiltered ("!set chain\n");
  fflush (stdout);
#endif
}

/* Added by CZ 24/05/01 */
static int
jtag_connect_to_server (char *hostname, char *name)
{
  struct hostent *host;
  struct sockaddr_in sin;
  struct servent *service;
  struct protoent *protocol;
  int sock,flags;
  int fd;
  char stemp[256], stemp2[256];
  char *proto_name = "tcp";
  int port = 0;
  int on_off = 0; /* Turn off Nagel's algorithm on the socket */
  char *s;

  if (!(protocol = getprotobyname (proto_name)))
    {
      sprintf (stemp, "jtag_connect_to_server: Protocol \"%s\" not available.\n",
	      proto_name);
      error (stemp);
      return 0;
    }

  /* Convert name to an integer only if it is well formatted.
     Otherwise, assume that it is a service name. */

  port = strtol (name, &s, 10);
  if (*s)
    port = 0;

  if (!port)
    {
      if (!(service = getservbyname (name, protocol->p_name)))
	{
	  sprintf (stemp,"jtag_connect_to_server: Unknown service \"%s\".\n",name);
	  error (stemp);
	  return 0;
	}

      port = ntohs (service->s_port);
    }

  if (!(host = gethostbyname (hostname)))
    {
      sprintf (stemp,"jtag_connect_to_server: Unknown host \"%s\"\n",hostname);
      error (stemp);
      return 0;
    }

  if ((sock = socket (PF_INET,SOCK_STREAM,0)) < 0)
    {
      sprintf (stemp,"jtag_connect_to_server: can't create socket errno = %d\n",
	      errno);
      sprintf (stemp2,"%s\n",strerror (errno));
      strcat (stemp,stemp2);
      error (stemp);
      return 0;
    }

  if (fcntl (sock,F_GETFL,&flags) < 0)
    {
      sprintf (stemp,"Unable to get flags for JTAG proxy socket %d",sock);
      error (stemp);
      close (sock);
      return 0;
    }
  
  if (fcntl (sock,F_SETFL, flags & ~O_NONBLOCK) < 0)
    {
      sprintf (stemp,"Unable to set flags for JTAG proxy socket %d to value 0x%08x",
	      sock,flags | O_NONBLOCK);
      error (stemp);
      close (sock);
      return 0;
    }

  memset (&sin,0,sizeof (sin));
  sin.sin_family = host->h_addrtype;
  memcpy (&sin.sin_addr,host->h_addr_list[0],host->h_length);
  sin.sin_port = htons (port);

  if ((connect (sock,(struct sockaddr*)&sin, sizeof (sin)) < 0) 
     && errno != EINPROGRESS)
    {
      
      sprintf (stemp,"jtag_connect_to_server: connect failed  errno = %d\n",errno);
      sprintf (stemp2,"%s\n",strerror (errno));
      close (sock);
      strcat (stemp,stemp2);
      error (stemp); 
      return 0;
    }

  if (fcntl (sock,F_SETFL, flags | O_NONBLOCK) < 0)
    {
      sprintf (stemp,"Unable to set flags for JTAG proxy socket %d to value 0x%08x",
	      sock,flags | O_NONBLOCK);
      error (stemp);
      close (sock);
      return 0;
    }

  if (setsockopt (sock,protocol->p_proto,TCP_NODELAY,&on_off,sizeof (int)) < 0)
    {
      sprintf (stemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",sock);
      error (stemp);
      close (sock);
      return 0;
    }

  return sock;
}

/* Initialize a new connection to the or1k board, and make sure we are
   really connected.  */

void
jtag_init (char * args)
{
  char *ptype;
  char *port_name;
  char **argv;

#ifdef DEBUG_JTAG
  printf_unfiltered ("INIT\n");
  fflush (stdout);
#endif
  if (args == 0) /* CZ */
    error ( "To open a or1k remote debugging connection, you need to specify a "
	    "parallel port\nconnected to the target board, or else a remote "
	    "server which will proxy these\nservices for you.\nExample: "
	    "/dev/lp0 or jtag://debughost.mydomain.com:8100.\n");

  /* If we currently have an open connection, shut it
     down.  This is due to a temporary bug in gdb. */
  switch (connection.location)
    {
    case JTAG_REMOTE:
      if (connection.device.fd > 0)
	{
	  close (connection.device.fd);
	}
      break;
    case JTAG_LOCAL:
      if (connection.device.lp > 0)
	{
	  close (connection.device.lp);
	}
      break;
    default:
      break;
    }

  /* Parse the port name.  */
  if ((argv = buildargv (args)) == NULL)
    nomem (0);
  port_name = xstrdup (argv[0]);
  make_cleanup_freeargv (argv);
  
  /* CZ 24/05/01 - Check to see if we have specified a remote
     jtag interface or a local one. It is remote if it follows
     the URL naming convention jtag://<hostname>:<port> */
  if (!strncmp (port_name,"jtag://",7))
    {
      char *port = strchr (&port_name[7],':');
      char hostname[256];

      if (port)
	{
	  int len = port - port_name - 7;
	  strncpy (hostname,&port_name[7],len);
	  hostname[len] = '\0';
	  port++;
	}
      else
	strcpy (hostname,&port_name[7]);

      /* Interface is remote */
      if (!(connection.device.fd = jtag_connect_to_server (hostname,port)))
	{
	  char stemp[256];
	  sprintf (stemp,"Can not access JTAG Proxy Server at \"%s\"",
		  &port_name[5]);
	  error (stemp);
	}
      connection.location = JTAG_REMOTE;
      printf_unfiltered ("Remote or1k debugging using %s\n",port_name);
    }
  else
    {
      /* Interface is local */
      /* Open and initialize the parallel port.  */
      connection.device.lp = open (port_name, O_WRONLY);
      if (connection.device.lp < 0)
	error ("Cannot open device.");
      connection.location = JTAG_LOCAL; /* CZ */
      printf_unfiltered ("Local or1k debugging using %s\n", port_name);

    }

  current_chain = -1;
  if (connection.location == JTAG_LOCAL)
    jp1_reset_JTAG ();
  jtag_set_chain (SC_RISC_DEBUG);

  free (port_name);
}

static int
sync_close (int fd)
{
  int flags = 0;
  struct linger linger;
  char stemp[256];

  linger.l_onoff = 0;
  linger.l_linger = 0;

  /* First, make sure we're non blocking */
  if (fcntl (fd, F_GETFL, &flags) < 0)
    {
      sprintf (stemp, "Unable to get flags for JTAG proxy socket %d",fd);
      error (stemp);
    }
  if (fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) < 0)
    {
      sprintf (stemp, "Unable to set flags for JTAG proxy socket %d to value 0x%08x",
	      fd, flags | O_NONBLOCK);
      error (stemp);
    }
  
  /* Now, make sure we don't linger around */
  if (setsockopt (fd, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger)) < 0)
    {
      sprintf (stemp, "Unable to disable SO_LINGER for JTAG proxy socket %d.", fd);
      error (stemp);
    }
 
  return close (fd);
}

void
jtag_done ()  /* CZ */
{
  switch (connection.location)
    {
    case JTAG_LOCAL:
      sync_close (connection.device.lp);
      connection.device.lp = 0;
      break;
    case JTAG_REMOTE:
      sync_close (connection.device.fd);
      connection.device.fd = 0;
      break;
    default:
      break;
    }
  connection.location = JTAG_NOT_CONNECTED;
}

/* Remote debugging interface for various or1k debugging protocols.
   Currently supported or1k targets are: simulator, jtag, dummy.

   Copyright 1993-1995, 2000 Free Software Foundation, Inc.
   Contributed by Cygnus Support.  Written by Marko Mlinar
   <markom@opencores.org>

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

#include "defs.h"
#include "inferior.h"
#include "bfd.h"
#include "symfile.h"
#include "gdb_wait.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "target.h"
#include "remote-utils.h"
#include "gdb_string.h"
#include "tm.h"
#include "event-loop.h"
#include "event-top.h"
#include "inf-loop.h"
#include "regcache.h"

#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#define debug if (remote_debug) printf_unfiltered

/* Prototypes for local functions */
static void or1k_interrupt PARAMS ((int signo));
static void or1k_interrupt_twice PARAMS ((int signo));
static void interrupt_query PARAMS ((void));

/* The following prototype is necessary or the compiler will not
   correctly promote the data argument to ULONGEST */
static void or1k_write_reg PARAMS ((unsigned int, ULONGEST));
static int insn_modifies_gprs PARAMS ((unsigned int insn));
static int set_breakpoint PARAMS ((CORE_ADDR addr));
static int clear_breakpoint PARAMS ((CORE_ADDR addr));
static int or1k_load_block PARAMS ((CORE_ADDR, void *, int));
static int or1k_store_block PARAMS ((CORE_ADDR, void *, int));

/* JTAG or1k target ops.  */ 
extern void jtag_init PARAMS ((const char *args));
extern ULONGEST jtag_read_reg PARAMS ((unsigned int regno));
extern void jtag_write_reg PARAMS ((unsigned int regno, ULONGEST data));
extern void jtag_done PARAMS ((void));
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 void jtag_set_chain PARAMS ((int chain));
struct target_ops or1k_jtag_ops;
static struct or1k_target_ops or1k_target_jtag =
  {
    "jtag",
    jtag_init,
    jtag_done,
    jtag_read_reg,
    jtag_write_reg,
    jtag_read_block,
    jtag_write_block,
    jtag_set_chain,
    NULL,
    &or1k_jtag_ops,
    OPS_MAGIC
  };

/* simulator or1k target ops.  */
struct target_ops or1k_sim_ops;
static struct or1k_target_ops or1k_target_sim =
  {
    "simulator",
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    &or1k_sim_ops,
    OPS_MAGIC
  };

/* dummy or1k target ops.  */
struct target_ops or1k_dummy_ops;
static struct or1k_target_ops or1k_target_dummy =
  {
    "dummy",
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    &or1k_dummy_ops,
    OPS_MAGIC
  };

static const char *str_err[] =
  {
    "None", "CRC error"
  };

static const char *status_name[] =
  {
    "UNDEFINED", "CONNECTING", "DISCONNECTING", "RUNNING", "STOPPED"
  };

/* Names for matchpoint related stuff.  */
static const char *ct_names[] =
  {
    "DIS", "IFEA", "LEA", "SEA", "AEA", "LDATA", "SDATA", "ADATA"
  };

static const char *cc_names[] =
  {
    "&", "==", "<", "<=", ">", ">=", "!=", "ERR"
  };

static const char *ch_names[] =
  {
    "ERR", "&", "|", "ERR" 
  };

/* Implementation specific information.  Set by or1k_initialize.  */
struct struct_or1k_implementation or1k_implementation;

/* Current target status.  */
static enum target_status or1k_status = TARGET_UNDEFINED;

/* The target vector.  */
struct target_ops or1k_dummy_ops, or1k_jtag_ops, or1k_sim_ops;

/* Currently active target description (if or1k_is_open == 1) */
static struct target_ops *current_ops;

/* Currently active or1k target operations.  */
static struct or1k_target_ops *current_or1k_target = NULL;

/* Set to 1 if the target is open.  */
static int or1k_is_open = 0;

/* Error last occured, zero = ok.  */
int err = 0;

/* Nonzero, if we changed something (except DMR1 which is updated on every run anyway).  */
int debug_regs_changed;

/* Number of interrupts while waiting for process.  */
static int interrupt_count = 0;

/* Last value of step in resume function */
static int resume_stepped = 0;

/* Reason of last stop.  */
static int hit_watchpoint = 0;
static int hit_breakpoint = 0;
static int step_link_insn = 0;
static int new_pc_set = 0;

/* Current register values.  */
unsigned int dmr1 = 0;
unsigned int dmr2 = 0;
unsigned int dsr = 0; 
unsigned int drr = 0;
unsigned int lr = 0;

/* Current matchpoints.  */
unsigned int dvr[MAX_MATCHPOINTS];
struct dcr_struct dcr[MAX_MATCHPOINTS];

/* Number of matchpoint users */
int matchpoint_user_count[MAX_MATCHPOINTS] = {0};

/* Old SIGINT handler.  */
static void (*ofunc) PARAMS ((int));

/* Tokens for use by the asynchronous signal handlers for SIGINT */
PTR sigint_or1k_twice_token;
PTR sigint_or1k_token;


/* Handle low-level error that we can't recover from.  Note that just
   error()ing out from target_wait or some such low-level place will cause
   all hell to break loose--the rest of GDB will tend to get left in an
   inconsistent state.  */

static NORETURN void
or1k_error (const char *string,...)
{
  va_list args;

  va_start (args, string);

  target_terminal_ours ();
  wrap_here ("");		/* Force out any buffered output */
  gdb_flush (gdb_stdout);
  if (error_pre_print)
    fprintf_filtered (gdb_stderr, error_pre_print);
  vfprintf_filtered (gdb_stderr, string, args);
  fprintf_filtered (gdb_stderr, "\n");
  va_end (args);
  gdb_flush (gdb_stderr);

  /* Clean up in such a way that or1k_close won't try to talk to the
     board (it almost surely won't work since we weren't able to talk to
     it).  */
  or1k_is_open = 0;
 
  printf_unfiltered ("Ending remote or1k debugging.\n");
  target_mourn_inferior ();

  throw_exception (RETURN_QUIT);
}

const char *
or1k_err_name (int e)
{
  return str_err[e];
}

/* putc_readable - print a character, displaying non-printable chars in
   ^x notation or in hex.  */

static void
fputc_readable (int ch, struct ui_file *file)
{
  if (ch == '\n')
    fputc_unfiltered ('\n', file);
  else if (ch == '\r')
    fprintf_unfiltered (file, "\\r");
  else if (ch < 0x20)		/* ASCII control character */
    fprintf_unfiltered (file, "^%c", ch + '@');
  else if (ch >= 0x7f)		/* non-ASCII characters (rubout or greater) */
    fprintf_unfiltered (file, "[%02x]", ch & 0xff);
  else
    fputc_unfiltered (ch, file);
}


/* puts_readable - print a string, displaying non-printable chars in
   ^x notation or in hex.  */

static void
fputs_readable (const char *string, struct ui_file *file)
{
  int c;

  while ((c = *string++) != '\0')
    fputc_readable (c, file);
}

/* Sets scan chain.  */

static void
or1k_set_chain (int chain)
{
  if (current_or1k_target != NULL && current_or1k_target->to_set_chain != NULL)
    current_or1k_target->to_set_chain (chain); 
}

/* Sets register/memory regno to data.  */

static void
or1k_write_reg (unsigned int regno, ULONGEST data)
{
  if (current_or1k_target != NULL && current_or1k_target->to_write_reg != NULL)
    current_or1k_target->to_write_reg (regno, data);
}

/* Reads register/memory from regno.  */

static ULONGEST
or1k_read_reg (unsigned int regno)
{ 
  if (current_or1k_target != NULL && current_or1k_target->to_read_reg != NULL)
    return current_or1k_target->to_read_reg (regno);
  else
    return 0x1234;
}

/* Sets SPR register regno to data.  */

void
or1k_write_spr_reg (unsigned int regno, unsigned int data)
{
  or1k_set_chain (SC_RISC_DEBUG); 
  or1k_write_reg (regno, (ULONGEST)data);
  if (regno == PC_SPRNUM) {
    hit_breakpoint = 0;
    step_link_insn = 0;
    new_pc_set = 1;
  }
}

/* Reads register SPR from regno.  */

unsigned int
or1k_read_spr_reg (unsigned int regno)
{
  or1k_set_chain (SC_RISC_DEBUG); 
  return or1k_read_reg (regno);
}

/* Sets mem to data.  */

void
or1k_write_mem (unsigned int addr, unsigned int data)
{
  or1k_set_chain (SC_WISHBONE); 
  or1k_write_reg (addr, (ULONGEST)data);
}

/* Reads register SPR from regno.  */

unsigned int
or1k_read_mem (unsigned int addr)
{
  or1k_set_chain (SC_WISHBONE);
  return or1k_read_reg (addr);
}

/* Stalls the CPU.  */

static void
or1k_stall ()
{
  int val;
  or1k_set_chain (SC_REGISTER);  
  val = or1k_read_reg (JTAG_RISCOP);
  or1k_write_reg (JTAG_RISCOP, val | 1);
  or1k_read_reg (JTAG_RISCOP);

  /* Be cautious - disable trace.  */
  val = or1k_read_reg (JTAG_MODER);
  or1k_write_reg (JTAG_MODER, val & ~2);
}

/* Unstalls the CPU.  */

static void
or1k_unstall ()
{
  unsigned int val;


  or1k_set_chain (SC_REGISTER);
  val = or1k_read_reg (JTAG_RISCOP);
  or1k_write_reg (JTAG_RISCOP, val & ~1);
  or1k_read_reg (JTAG_RISCOP);
}

/* Resets the CPU and stalls it.  */

static void
or1k_reset ()
{
  unsigned int val;
  int i;
  debug ("%08llx\n", or1k_read_reg (JTAG_RISCOP));
  or1k_set_chain (SC_REGISTER);

  /* Be cautious - disable trace.  */
  val = or1k_read_reg (JTAG_MODER);
  or1k_write_reg (JTAG_MODER, val & ~2);

  val = or1k_read_reg (JTAG_RISCOP);
  val &= ~3;
  /* Assert reset signal.  */
  or1k_write_reg (JTAG_RISCOP, val | 3);

  /* Just do something */
  for (i = 0; i < 100; i++)
    or1k_read_reg (JTAG_RISCOP);

  /* give it some time */
  usleep (1000);

  or1k_set_chain (SC_REGISTER);
  /* Release reset signal, but keep in stall state.  */
  or1k_write_reg (JTAG_RISCOP, val | 1);
  or1k_read_reg (JTAG_RISCOP);
}

/* Synchronizes debug registers in memory with those on target,
   if there is any change.  */

static void
or1k_commit_debug_registers ()
{
  int i;
  unsigned int u;
  if (!debug_regs_changed)
    return;

  /* Matchpoints (breakpoints, watchpoints).  */
  for (i = 0; i < NUM_MATCHPOINTS; i++)
    {
      unsigned int u;
      or1k_write_spr_reg (DVR0_SPRNUM + i, dvr[i]);
      memcpy (&u, &dcr[i], sizeof(dcr[i]));
      or1k_write_spr_reg (DCR0_SPRNUM + i, u);
    }
  or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
  or1k_write_spr_reg (DMR2_SPRNUM, dmr2);

  /* Trace dependent.  */
  or1k_set_chain (SC_REGISTER);
  memcpy (&u, &or1k_htrace.trig, sizeof(or1k_htrace.trig));
  or1k_write_reg (JTAG_TSEL, u);
  memcpy (&u, &or1k_htrace.qual, sizeof(or1k_htrace.qual));
  or1k_write_reg (JTAG_QSEL, u);
  memcpy (&u, &or1k_htrace.stop, sizeof(or1k_htrace.stop));
  or1k_write_reg (JTAG_SSEL, u);
  debug_regs_changed = 0;
  for (i = 0; i < NUM_RECORDS; i++)
    {
      memcpy (&u, &or1k_htrace.recwp[i], sizeof(or1k_htrace.recwp[i]));
      or1k_write_reg (JTAG_RECWP0 + i, u);
    }
  memcpy (&u, &or1k_htrace.recbp, sizeof(or1k_htrace.recbp));
  or1k_write_reg (JTAG_RECBP0, u);
  memcpy (&u, &or1k_htrace.moder, sizeof(or1k_htrace.moder));
  or1k_write_reg (JTAG_MODER, u);
}

static void
or1k_set_undefined_cleanups (PTR arg)
{
  or1k_status = TARGET_UNDEFINED;
}

/* Initialize a new connection to the or1k board, and make sure we are
   really connected.  */

static void
or1k_init (const char *args)
{
  struct cleanup *old_cleanups = make_cleanup (or1k_set_undefined_cleanups, NULL);
  int i;
  unsigned int tmp;
  FILE *f;

  /* What is this code doing here?  I don't see any way it can happen, and
     it might mean or1k_initializing didn't get cleared properly.
     So I'll make it a warning.  */

  if (or1k_status == TARGET_CONNECTING)
    {
      warning ("internal error: or1k_initialize called twice");
      return;
    }

  or1k_status = TARGET_CONNECTING;
  if (current_or1k_target != NULL && current_or1k_target->to_init != NULL)
    current_or1k_target->to_init (args);

  debug("%08lx\n", read_pc ());
  or1k_stall ();
  debug("%08lx\n", read_pc ());
  usleep (1000);

  /* Determine implementation configuration.  */
  or1k_implementation.VR = or1k_read_spr_reg (VR_SPRNUM);
  or1k_implementation.UPR = or1k_read_spr_reg (UPR_SPRNUM);

  /* Determine number of gpr_regs.  */
  tmp = or1k_read_spr_reg (CPUCFGR_SPRNUM);
  or1k_implementation.num_gpr_regs = ((tmp >> 4) & 1)?(16):(32);

  /* Is any vector or floating point support present? */
  or1k_implementation.vf_present = ((tmp >> 7) & 7) != 0;
  or1k_implementation.num_vfpr_regs = (or1k_implementation.vf_present)?(32):(0);

  /* Determine max number of supported matchpoints.  */
  tmp = or1k_read_spr_reg (DCFGR_SPRNUM); 
  or1k_implementation.num_matchpoints = tmp & 7;
  or1k_implementation.num_used_matchpoints = 0;
  or1k_implementation.has_counters = (tmp & 4) == 1;

  /* Is implementation supported? */

  /* First we should have system and debug groups implemented. */
  if ((or1k_implementation.VR & (1 << SPR_SYSTEM_GROUP)) == 0)
    error ("System group should be available in the or1k implementation.");
  if ((or1k_implementation.VR & (1 << SPR_DEBUG_GROUP)) == 0)
    error ("Debug group should be available in the or1k implementation.");
  if (or1k_implementation.has_counters)
    warning ("Counters not supported.");

  /* Delete break, watch, catch points.  */
  for(i = 0; i < NUM_MATCHPOINTS; i++)
    {
      memset (&dcr[i], 0, sizeof (dcr[i]));
      matchpoint_user_count[i] = 0;
    }

  dmr1 = 0;
  dmr2 = 0;
  memset (&or1k_htrace, 0, sizeof (or1k_htrace));

  /* RECSELDEPEND = 0 does not match our trace scheme. */
  or1k_htrace.moder.rec_sel_dep = 1;

  debug_regs_changed = 0;//1;
  or1k_commit_debug_registers ();

  if (err != 0)
    error ("Cannot connect.");

  /* Stop when breakpoint occurs.  */
  or1k_write_spr_reg (DSR_SPRNUM, dsr = 0x2000);

  do_cleanups (old_cleanups);

  /* This should cause an error if not connected.  */
  or1k_fetch_registers (-1);

  set_current_frame (create_new_frame (read_fp (), read_pc ()));
  select_frame (get_current_frame ());

  /* Just empty it.  */
  if ((f = fopen (TRACE_FILENAME, "wb+")) == NULL)
    error ("Cannot open trace file.");
  fclose (f);
  trace_size = 0;
  or1k_status = TARGET_STOPPED;
}

/* Kill the process running on the board.  */

void
or1k_kill ()
{
  if (or1k_status != TARGET_RUNNING)
    return;
  or1k_status = TARGET_UNDEFINED;
  or1k_reset();
  or1k_status = TARGET_STOPPED;

  /* obsolete inferior_pid = 0; */
}

/* Open a connection to the remote board.  */

static void
or1k_open (const char *name, int from_tty)
{
  or1k_init (name);

  /* Switch to using remote target now.  */
  current_ops = current_or1k_target->gdb_ops;
  or1k_is_open = 1;
  push_target (current_ops);

  /* FIXME: Should we call start_remote here?  */

/* This is really the job of start_remote however, that makes an assumption
   that the target is about to print out a status message of some sort.  That
   doesn't happen here (in fact, it may not be possible to get the monitor to
   send the appropriate packet).  */

  flush_cached_frames ();
  registers_changed ();
  stop_pc = read_pc ();
  set_current_frame (create_new_frame (read_fp (), stop_pc));
  select_frame (get_current_frame ());
  print_stack_frame (selected_frame, -1, 1);
}

/* 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
   will eventually end up here. */
static void
or1k_stop ()
{
  /* Send a break or a ^C, depending on user preference.  */
  debug ("remote_stop called\n");

  /* 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
     on anything.  */
  or1k_stall ();
  /* HW STEP.  Set DMR1_ST.  */
  dmr1 |= DMR1_ST;
  or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
  dmr1 &= ~DMR1_ST;
  or1k_unstall ();
  or1k_status = TARGET_STOPPED;
}

/* Close a connection to the remote board.  */

static void
or1k_close (int quitting)
{
  if (or1k_is_open)
    {
      if (current_or1k_target != NULL && current_or1k_target->to_done != NULL)
	current_or1k_target->to_done ();
      current_or1k_target = NULL;
    }
  generic_mourn_inferior ();
}

/* Detach from the remote board.  */

static void
or1k_detach (char *args, int from_tty)
{
  if (args)
    error ("Argument given to \"detach\" when remotely debugging.");

  pop_target ();

  or1k_close (1);

  if (from_tty)
    printf_unfiltered ("Ending remote or1k debugging.\n");
}

/* Appends trace data to the trace file.  */

static void
or1k_read_trace ()
{
  struct htrace_data_struct data;
  ULONGEST tmp;
  int first = 1;
  FILE *fd;
  if ((fd = fopen (TRACE_FILENAME, "ab")) == NULL)
    {
      warning ("Cannot append to trace file.");
      return;
    }
  
  or1k_set_chain (SC_TRACE);
  while (1)
    {
      tmp = or1k_read_reg (0);
      memcpy (&data, &tmp, sizeof (data));
      
      /* Last record reached. */
      if (!data.valid)
	break;
      data.valid = first;
      first = 0;
      if (!fwrite (&data, sizeof (data), 1, fd))
	{
	  warning ("Cannot write trace data");
	  break;
	}
    }
  fclose (fd);
}

/* ^C Interrupt handling */

/* Ask the user what to do when an interrupt is received.  */
static void
interrupt_query ()
{
  target_terminal_ours ();

  if (query ("Interrupted while waiting for the program.\n\
Give up (and stop debugging it)? "))
    {
      target_mourn_inferior ();
      throw_exception (RETURN_QUIT);
    }

  target_terminal_inferior ();
}

/* Send ^C to target to halt it.  Target will respond, and send us a
   packet.  */
static void (*ofunc) PARAMS ((int));

/* The command line interface's stop routine. This function is installed
   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
   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. */
static void
or1k_interrupt (int signo)
{
  /* If this doesn't work, try more severe steps. */
  signal (signo, or1k_interrupt_twice);

  /* If we are stepping we should stop the command, rather than stop
     the processor */
  if (resume_stepped)
    quit_flag = 1;
  
  interrupt_count++;
    
  if (remote_debug)
    fprintf_unfiltered (gdb_stdlog, "or1k_interrupt called\n");
}

/* The user typed ^C twice.  */

static void
or1k_interrupt_twice (int signo)
{
  /* Try everything */
  quit_flag = 1;
  or1k_stop ();
  signal (signo, ofunc);
  interrupt_query ();
  signal (signo, or1k_interrupt_twice);
}

/* Resume execution of the target process.  STEP says whether to single-step
   or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
   to the target, or zero for no signal.  */

static void
or1k_resume (ptid_t pid, int step, enum target_signal siggnal)
{
  unsigned int pc;
  unsigned int ppc;
  unsigned int npc;
  unsigned int val;
  unsigned int ppc_insn;
  unsigned int pc_insn;

  /* Save step value for wait function */
  resume_stepped = step;
    
  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);
  if (or1k_status != TARGET_STOPPED)
    {
      if (or1k_status == TARGET_RUNNING)
        error ("Program is already running.");
      else
        error ("The program is not being run.");
    }
  

  /* Clear reason register for later.  */
  or1k_write_spr_reg (DRR_SPRNUM, 0);

  or1k_commit_debug_registers ();

  /* Fetch previous insn */
  ppc_insn = or1k_fetch_instruction (ppc);

  /* Fetch next insn */
  pc_insn = or1k_fetch_instruction (pc);

  if (step)
    {
      /* HW STEP.  Set DMR1_ST.  */
      dmr1 |= DMR1_ST;
      or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
      dmr1 &= ~DMR1_ST;

      if (new_pc_set)
        {
          debug("resume: 1\n");
          /* If new PC was set, then just set it again to fill the pipeline */ 

          or1k_write_spr_reg (PC_SPRNUM, pc);

          if (is_delayed (pc_insn) && insn_modifies_gprs (pc_insn))
            {
              debug("resume: 10\n");
              /* We are steping across jump an link insn - save link 
                 register, so we will be able to restore it when we will
                 step across delay slot insn */
              step_link_insn = 1;
              lr = or1k_read_spr_reg (REGNUM_TO_SPRNUM(9));
            }
        }
      else if (is_delayed (ppc_insn) && (ppc != pc))
        {
          debug("resume: 2\n");
          /* Steping across delay slot insn - we have to reexcute branch insn */

          if (breakpoint_here_p (ppc))
            or1k_write_mem(ppc, ppc_insn);

          if (insn_modifies_gprs (ppc_insn) && step_link_insn)
            {
              debug("resume: 11\n");
              /* If this is delay slot of jump an link insn that was 
                 allready executed - restore link register first */
              or1k_write_spr_reg (REGNUM_TO_SPRNUM(9), lr);
              step_link_insn = 0;
            }
 
          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 (hit_breakpoint && ((ppc + 4) != npc) && (pc != npc))
        {
          debug("resume: 3\n");
          /* Trapped on delay slot instruction. */
          /* Set PC to branch insn preceding delay slot. */
          or1k_write_spr_reg (PC_SPRNUM, ppc - 4);
          
          if (insn_modifies_gprs (or1k_fetch_instruction (ppc - 4)))
            {
              debug("resume: 12\n");
              /* We are steping across jump an link insn - save link 
                 register, so we will be able to restore it when we will
                 step across delay slot insn */
              step_link_insn = 1;
              lr = or1k_read_spr_reg (REGNUM_TO_SPRNUM(9));
            }

          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
        {
          debug("resume: 4\n");
          /* Steping across 'non delay slot' insn - set PC to fill the pipeline */

          or1k_write_spr_reg (PC_SPRNUM, pc);

          if (is_delayed (pc_insn) && insn_modifies_gprs (pc_insn))
            {
              debug("resume: 13\n");
              /* We are steping across jump an link insn - save link 
                 register, so we will be able to restore it when we will
                 step across delay slot insn */
              step_link_insn = 1;
              lr = or1k_read_spr_reg (REGNUM_TO_SPRNUM(9));
            }
        }
    }
  else
    {
      dmr1 &= ~DMR1_ST;
      or1k_write_spr_reg (DMR1_SPRNUM, dmr1);

      if (new_pc_set)
        {
          debug("resume: 5\n");
          /* If new PC was set, then just set it again to fill the pipeline */

          step_link_insn = 0;
          or1k_write_spr_reg (PC_SPRNUM, pc);
        }
      else if (is_delayed (ppc_insn) && !breakpoint_here_p (ppc))
        {
          debug("resume: 6\n");
          /* If next insn is delay slot insn - set PC to previous branch insn 
             and continue from there to refill the pipeline */

          if (insn_modifies_gprs (ppc_insn) && step_link_insn)
            {
              debug("resume: 14\n");
              /* If this is delay slot of jump an link insn that was 
                 allready executed - restore link register first */
              or1k_write_spr_reg (REGNUM_TO_SPRNUM(9), lr);
              step_link_insn = 0;
            }

           or1k_write_spr_reg (PC_SPRNUM, ppc);
        }
      else if (is_delayed (ppc_insn) && breakpoint_here_p (ppc))
        {
          debug("resume: 7\n");
          /* If next insn is delay slot insn and previous branch insn 
             is actually BP - replace BP with original branch insn, set PC 
             to that insn step over it, put back BP and continue */

          or1k_write_mem(ppc, ppc_insn);

          dmr1 |= DMR1_ST;
          or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
          dmr1 &= ~DMR1_ST;

          or1k_write_spr_reg (PC_SPRNUM, ppc);
          
          if (insn_modifies_gprs (ppc_insn) && step_link_insn)
            {
              debug("resume: 15\n");
              /* If this is delay slot of jump an link insn that was 
                 allready executed - restore link register first */
              or1k_write_spr_reg (REGNUM_TO_SPRNUM(9), lr);
              step_link_insn = 0;
            }

           or1k_unstall ();

          or1k_set_chain (SC_REGISTER);
          val = or1k_read_reg (JTAG_RISCOP);
          do {
            val = or1k_read_reg (JTAG_RISCOP);
          } while ((val & 1) == 0);
      
          or1k_write_mem(ppc, 0x21000001);

          or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
        }
      else
        {
          debug("resume: 8\n");
          /* Continue from 'non delay slot' insn - set PC to fill the pipeline */

          or1k_write_spr_reg (PC_SPRNUM, pc);
        }
    }

  /* Now we are in normal program flow again */
  new_pc_set = 0;

  /* We can now continue normally, independent of step */
  or1k_unstall ();
  or1k_status = TARGET_RUNNING;
  debug ("-resume %i, %i, %i\n",step, siggnal, or1k_status);
}

/* Wait until the remote stops, and return a wait status.  */

static ptid_t 
or1k_wait (ptid_t pid, struct target_waitstatus *status)
{
  unsigned long val;
  unsigned long pc;
  unsigned long ppc;
  char buf[MAX_REGISTER_RAW_SIZE];

  debug ("wait %i\n", or1k_status);
  /* If we have not sent a single step or continue command, then the
     board is waiting for us to do something.  Return a status
     indicating that it is stopped.  */
  if (or1k_status != TARGET_RUNNING)
    {
      if (or1k_status != TARGET_STOPPED)
	error("Target in invalid state."); 
      status->kind = TARGET_WAITKIND_STOPPED;
      status->value.sig = TARGET_SIGNAL_TRAP;
      return pid_to_ptid (0);
    }

  if (err)
    or1k_error ("Remote failure: %s", or1k_err_name (err));

  interrupt_count = 0;
  
  /* Set new signal handler */
  ofunc = signal (SIGINT, or1k_interrupt);

  /* Wait for risc to stop.  */ 
  do {
    or1k_set_chain (SC_REGISTER);
    val = or1k_read_reg (JTAG_RISCOP);

    /* When we press Ctrl-C, interrupt count is set, but we must wait
    	 for or1k_read_reg to finish, otherwise we would interrupt transaction.  */
    if (interrupt_count)
      or1k_stop ();

    usleep (10);
    debug ("%li", val);
  } while ((val & 1) == 0);

  /* If we had an error, wait just a while, so user can press another ^C */
  if (quit_flag)
    sleep(1);

  drr = or1k_read_spr_reg (DRR_SPRNUM);

  /* Restore old INT signal handler */
  signal (SIGINT, ofunc);

  /* Single step does not set trap exception, so we set it manually to simplify our code */
  dmr1 = or1k_read_spr_reg (DMR1_SPRNUM);
  if (dmr1 & DMR1_ST)
    drr |= DRR_TE;

  status->kind = TARGET_WAITKIND_STOPPED;  

  debug ("epcr0 = %08x\n", or1k_read_spr_reg (EPCR0_SPRNUM));
  debug ("drr = %08x\n", drr);

  registers_changed ();
  pc = read_pc ();
  ppc = or1k_read_spr_reg (PPC_SPRNUM);
  debug ("ppc = %08lx\n", ppc);

  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;
      drr &= ~DRR_RSTE;
    }
  else if (drr & DRR_BUSEE)
    {
      status->value.sig = TARGET_SIGNAL_BUS;
      drr &= ~DRR_BUSEE;
    }
  else if (drr & DRR_AE)
    {
      status->value.sig = TARGET_SIGNAL_REALTIME_36;
      drr &= ~DRR_AE;
    }
  else if (drr & DRR_IIE)
    {
      status->value.sig = TARGET_SIGNAL_ILL;
      drr &= ~DRR_IIE;
    }
  else if (drr & DRR_RE)
    {
      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)
    {
      status->value.sig = TARGET_SIGNAL_REALTIME_40;
      drr &= ~DRR_SCE;
    }
  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
    {
      status->value.sig = TARGET_SIGNAL_UNKNOWN;
      warning ("Invalid exception occured.");
    } 

  /* Update drr register */
  or1k_write_spr_reg (DRR_SPRNUM, drr);
  
  /* Write into PC flushes the pipeline! */
  /* We got the number the register holds, but gdb expects to see a
     value in the target byte ordering.  */
/*  write_pc (pc);
*/
  store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), pc);
  supply_register (PC_REGNUM, buf);

  hit_breakpoint = breakpoint_here_p (pc);
  
  /*or1k_write_spr_reg (PC_SPRNUM, pc);
  store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), pc);
  supply_register (PC_REGNUM, buf);*/

  /* Log remote stop.  */
  or1k_status = TARGET_STOPPED;
  
  /* Determine what caused trap - breakpoint or watchpoint.  */
  if (status->value.sig == TARGET_SIGNAL_TRAP)
    {
      /* Search all active breakpoints for a match.  */
      CORE_ADDR pc = read_pc ();
      int breakpoint = 0;
      int i;
      unsigned long value = pc;

      for (i = 0; i < or1k_implementation.num_used_matchpoints; i++)
	if (dvr[i] == pc && dcr[i].dp && dcr[i].cc == CC_EQUAL
	    && !dcr[i].sc && dcr[i].ct == CT_FETCH)
	  {
	    breakpoint = 1;
	    break;
	  }
      hit_watchpoint = !breakpoint;

      /* Cause the trap/breakpoint exception to be ignored. This is
	 the behavior of the simulator when the PC value is changed
	 by a write command. All pending exceptions are cleared and
	 the simulator continues at the PC value specified. We need
	 to do this if the instruction at the current PC has the
	 value BRK_INSTR_STRUCT */

      if(or1k_read_mem((pc & 3)) == BRK_INSTR)
	{
	  or1k_write_spr_reg(PC_SPRNUM,value);
	}
    }
  else
    hit_watchpoint = 0;

  /* If the stop PC is in the _exit function, assume
     we hit the 'break 0x3ff' instruction in _exit, so this
     is not a normal breakpoint.  */
  {
    char *func_name;
    CORE_ADDR func_start;
    CORE_ADDR pc = read_pc ();

    find_pc_partial_function (pc, &func_name, &func_start, NULL);
    if (func_name != NULL && strcmp (func_name, "_exit") == 0
	&& func_start == pc)
      status->kind = TARGET_WAITKIND_EXITED;
  }

  or1k_read_trace ();
  debug ("-wait %i\n", or1k_status);
  return pid_to_ptid (0);
}

/* Fetch a word from the target board.  All memory accesses to the
   remote board are word aligned.  */

unsigned int
or1k_fetch_word (CORE_ADDR addr)
{
  if (addr & 3)
    {
      int subaddr = addr & 3;
      unsigned char buf[8];
      unsigned int low, high;
      addr >>= 2;
      low = or1k_read_mem (addr << 2);
      high = or1k_read_reg ((addr + 1) << 2);
      memcpy (&buf[0], &low, 4);
      memcpy (&buf[4], &high, 4);
      memcpy (&low, &buf[subaddr], 4);
      return low;
    }
  else
    {
      return or1k_read_mem (addr);
    }
}

/* Store a word to the target board.  Returns errno code or zero for
   success.  All memory accesses to the remote board are word aligned.  */

static int
or1k_store_word (CORE_ADDR addr, unsigned int val)
{
  if (addr & 3)
    {
      int subaddr = addr & 3;
      unsigned char buf[8];
      unsigned int low, high;
      addr >>= 2;
      low = or1k_read_mem (addr << 2);
      high = or1k_read_mem ((addr + 1) << 2);
      memcpy (&buf[0], &low, 4);
      memcpy (&buf[4], &high, 4);
      memcpy (&buf[subaddr], &val, 4);
      memcpy (&low, &buf[0], 4);
      memcpy (&high, &buf[4], 4);
      or1k_write_mem (addr << 2, low);
      or1k_write_mem ((addr + 1) << 2, high);
    }
  else
    {      
      or1k_write_mem (addr, val);
    }
  return err;
}

/* Fetch the remote registers.  */

void
or1k_fetch_registers (int regno)
{
  unsigned int val;

  if (regno == -1)
    {
      for (regno = 0; regno < NUM_REGS; regno++)
	or1k_fetch_registers (regno);
      return;
    }

  if (regno >= NUM_REGS)
    error("Invalid register number!");

  /* Convert to SPRNUM and read.  */
  val = or1k_read_spr_reg (REGNUM_TO_SPRNUM(regno));

  {
    char buf[MAX_REGISTER_RAW_SIZE];

    /* We got the number the register holds, but gdb expects to see a
       value in the target byte ordering.  */
    store_unsigned_integer (buf, REGISTER_RAW_SIZE (regno), val);
    supply_register (regno, buf);
  }
  if (err)
    or1k_error ("Can't read register %d(%i): %s", regno,
		REGNUM_TO_SPRNUM(regno), or1k_err_name (err));
}

/* Fetch and return instruction from the specified location.  */

unsigned int
or1k_fetch_instruction (CORE_ADDR addr)
{
  char buf[OR1K_INSTLEN];
  int status;

  status = read_memory_nobpt (addr, buf, OR1K_INSTLEN);
  if (status)
    memory_error (status, addr);
  return extract_unsigned_integer (buf, OR1K_INSTLEN);
}

/* Currently not needed.  */

static void
or1k_prepare_to_store ()
{
}

/* Store remote register(s).  */

static void
or1k_store_registers (int regno)
{
  if (regno == -1)
    {
      for (regno = 0; regno < NUM_REGS; regno++)
	or1k_store_registers (regno);
      return;
    }

  if (regno >= NUM_REGS)
    error("Invalid register number!");

  or1k_write_spr_reg (REGNUM_TO_SPRNUM(regno), read_register (regno));
  if (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,
   transferring to or from debugger address MYADDR.  Write to inferior
   if SHOULD_WRITE is nonzero.  Returns length of data written or
   read; 0 for error.  Note that protocol gives us the correct value
   for a longword, since it transfers values in ASCII.  We want the
   byte values, so we have to swap the longword values.  */

static int
or1k_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
                  int write, struct mem_attrib *attrib, struct target_ops *target)
{
  register int i;
  /* Round starting address down to longword boundary.  */
  register CORE_ADDR addr = memaddr & ~3;
  /* Round ending address up; get number of longwords that makes.  */
  register int count = (((memaddr + len) - addr) + 3) / 4;
  /* Allocate buffer of that many longwords.  */
  register char *buffer = alloca (count * 4);
  int status;

  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 terminate = 0;  /* Terminate the printing of '*'s... */

#ifdef DEBUG_JTAG
  debug ("xfer_memory %s addr=%x, len=%i, \n", write ? "write" : "read", memaddr, len);
  fflush (stdout);
#endif

#if 0
  if (memaddr >= MEM_SPACE)
    error("Invalid address");
#endif

  /* (CZ 21/06/01 -- because upper layers which know nothing about
     Or1k or JTAG call this function directly, it is always necessary
     to set the chain to point to the Debug Unit. Otherwise, it may
     be pointing to the Development Interface chain, in which case
     we're going to get bupkiss... */

  if (write)
    {
      /* Fill start and end extra bytes of buffer with existing data.  */
      if (addr != memaddr || len < 4)
	{
	  /* Need part of initial word -- fetch it.  */
	  store_unsigned_integer (&buffer[0], 4, or1k_fetch_word (addr));
	}

      if (count > 1)
	{
	  /* Need part of last word -- fetch it.  FIXME: we do this even
	     if we don't need it.  */
	  store_unsigned_integer (&buffer[(count - 1) * 4], 4,
				  or1k_fetch_word (addr + (count - 1) * 4));
	}

      /* Copy data to be written over corresponding part of buffer */
      memcpy ((char *) buffer + (memaddr & 3), myaddr, len);

      /* CZ: rewrote the block transfer routines to make the code
	 a little more efficient for implementations that can handle
	 variable sized scan chains. Might be useful in the future.
	 Certainly makes downloads to the simulator more efficient. */
      for (i = 0; i < nblocks; i++, count -= block_xfer_size, addr += block_xfer_size * 4)
	{
	  int j;
	  int n = count < block_xfer_size ? count : block_xfer_size;
	  unsigned long *__buf;

	  if (!(__buf = (unsigned long*)malloc (n * sizeof (unsigned long))))
	    {
	      errno = ERR_MEM;
	      return 0;
	    }

	  for(j = 0; j < n; j++)
	    __buf[j] = (unsigned long) extract_unsigned_integer (&buffer[(i * block_xfer_size + j) * 4], 4);
	  or1k_set_chain (SC_WISHBONE);
	  status = or1k_store_block (addr,__buf,n);
	  free (__buf);
	  if (n == block_xfer_size)
	    {
	      debug ("*");
	      gdb_flush (gdb_stdout);
	    }
	  if (status)
	    {
	      errno = status;
	      return 0;
	    }
	  /* FIXME: Do we want a QUIT here?  */
	}
      if (terminate)
	debug ("\n");
    }
  else
    {
      for (i = 0; i < nblocks; i++, count -= block_xfer_size, addr += block_xfer_size * 4)
	{
	  int j;
	  int n = count < block_xfer_size ? count : block_xfer_size;
	  unsigned long *__buf;

          or1k_set_chain (SC_WISHBONE);
	  __buf = (unsigned long*)malloc (n * sizeof (unsigned long));
	  status = or1k_load_block (addr, __buf, n);
	  if (!status)
	    for (j = 0; j < n; j++)
	      store_unsigned_integer (&buffer[(i * block_xfer_size +j) * 4], 4, __buf[j]);
	  else
	    errno = status;
	  free(__buf);

	  if (status)
	    return 0;
	}
      /* Copy appropriate bytes out of the buffer.  */
      memcpy (myaddr, buffer + (memaddr & 3), len);
    }
  return len;
}

static int
or1k_load_block (CORE_ADDR addr, void *buffer, int nregs)
{
  int i = 0;
  unsigned int regno = addr;

  if (current_or1k_target != NULL && current_or1k_target->to_read_block != NULL)
    return current_or1k_target->to_read_block (regno, buffer, nregs);
  else
    for(i = 0; i < nregs; i++)
      ((unsigned long*) buffer)[i] = 0x1234;
  return 0;
}

static int
or1k_store_block (CORE_ADDR addr, void *buffer, int nregs)
{
  unsigned int regno = addr;
  
  if (current_or1k_target != NULL && current_or1k_target->to_write_block != NULL)
    return current_or1k_target->to_write_block (regno, buffer, nregs);
  return 0;
}

/* Print info on this target.  */

static void
or1k_files_info (struct target_ops *ignore)
{ 
  char *file = "nothing";

  if (exec_bfd)
    file = bfd_get_filename (exec_bfd);

  printf_filtered ("or1k_files_info: file \"%s\"\n", file);

  if (exec_bfd)
    {
      printf_filtered ("\tAttached to %s running program %s\n",
		       target_shortname, file);
    }
  /* Print target info. */
  printf_filtered ("Status: %s\n", status_name[or1k_status]);
}

/* Tell whether we can support a hardware breakpoint.  */

static int
or1k_can_use_hardware_breakpoint ()
{
  int i;

  /* Search for unused breakpoint.  */
  return or1k_implementation.num_used_matchpoints < or1k_implementation.num_matchpoints;
}

/* Insert a breakpoint.  On targets that don't have built-in breakpoint
   support, we read the contents of the target location and stash it,
   then overwrite it with a breakpoint instruction.  ADDR is the target
   location in the target machine.  CONTENTS_CACHE is a pointer to 
   memory allocated for saving the target contents.  It is guaranteed
   by the caller to be long enough to save sizeof BREAKPOINT bytes (this
   is accomplished via BREAKPOINT_MAX).  */

int
or1k_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
{
  if (or1k_can_use_hardware_breakpoint())
    return set_breakpoint (addr);
  else
    return memory_insert_breakpoint (addr, contents_cache);
}

int
or1k_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
{
  /* First try to remove HW breakpoint at address */
  if (clear_breakpoint (addr))
    return memory_remove_breakpoint (addr, contents_cache);
  else
    return 0;
}

/* Tell whether this target can support a hardware breakpoint.  CNT
   is the number of hardware breakpoints already installed.  This
   implements the TARGET_CAN_USE_HARDWARE_WATCHPOINT macro.
   Lower bound is estimated. !!! Can we estimate better? */

int
or1k_can_use_hardware_watchpoint (int bp_type, int cnt)
{
  /* Are there at least two matchpoints left for watch? - estimate lower bound  */
  return cnt + (((enum bptype) bp_type == bp_hardware_watchpoint)?(1):(0))
    <= or1k_implementation.num_matchpoints;
}

/* Moves matchpoint.  This is very tricky - we have to update
   all references to matchpoint indexes.  We assume here that
   matchpoint with index to is unused! */

static void
move_matchpoint (int from, int to)
{
  int i, j, tmp, chaining;
  if (matchpoint_user_count[to] != 0)
    error ("Internal: Destination matchpoint still has users");
  matchpoint_user_count[to] = matchpoint_user_count[from];
  matchpoint_user_count[from] = 0;
  debug_regs_changed = 1;

  dvr[to] = dvr[from];
  dcr[to] = dcr[from];
  dcr[from].dp = 0;

  /* Copy chaining bits.  */ 
  chaining = dmr1 & (3 << (2 * from));
  dmr1 &= ~(3 << (2 * to));
  dmr1 |= chaining << (2 * to);
  dmr1 &= ~(3 << (2 * from));

  /* Copy watchpoint bits */
  tmp = dmr2 & (1 << from);
  dmr2 &= 1 << to;
  dmr2 |= tmp << to;
  dmr2 &= 1 << from;

  /* Update hwatch table.  Here we assume that matchpoint
     group is connected (it cannot be implemented in HW
     otherwise), so if we move first, we will have to move
     others later.  */
  for (i = 0; i < num_hw_watches; i++)
    if (or1k_hwatch[i].matchpoint_start == from)
      or1k_hwatch[i].matchpoint_start = to;

  /* Update htrace struct.  */
  tmp = or1k_htrace.trig.wp_trig & (1 << from);
  or1k_htrace.trig.wp_trig &= 1 << to;
  or1k_htrace.trig.wp_trig |= tmp << to;
  or1k_htrace.trig.wp_trig &= 1 << from;
  
  tmp = or1k_htrace.qual.wp_trig & (1 << from);
  or1k_htrace.qual.wp_trig &= 1 << to;
  or1k_htrace.qual.wp_trig |= tmp << to;
  or1k_htrace.qual.wp_trig &= 1 << from;

  tmp = or1k_htrace.stop.wp_trig & (1 << from);
  or1k_htrace.stop.wp_trig &= 1 << to;
  or1k_htrace.stop.wp_trig |= tmp << to;
  or1k_htrace.stop.wp_trig &= 1 << from;

  for (i = 0; i < MAX_MATCHPOINTS; i++)
    {
      tmp = or1k_htrace.wp_record_uses[i] & (1 << from);
      or1k_htrace.wp_record_uses[i] &= 1 << to;
      or1k_htrace.wp_record_uses[i] |= tmp << to;
      or1k_htrace.wp_record_uses[i] &= 1 << from;
    }

  /* Do we need to move other references also? */
}

/* Sifts unused matchpoints to higher indexses.  */

void
sift_matchpoints ()
{
  int i, first_free = 0;
  for (i = 0; i < or1k_implementation.num_matchpoints; i++)
    if (dcr[i].dp)
      {
	/* Move references.  */
	move_matchpoint (i, first_free);
	
	first_free++;
      }

  /* Unused matchpoints should be disabled by move_matchpoint,
     so we are done here.  */
}

/* Translates gdb watchpoint type into one in DCR register.  */

static int
translate_type (int gdb_type)
{
  switch (gdb_type)
    {
    case 0:
      return CT_SDATA;
    case 1:
      return CT_LDATA;
    case 2:
      return CT_ADATA;
    default:
      error ("Invalid type.");
    }
}

/* Set a data watchpoint.  ADDR and LEN should be obvious.  TYPE is 0
   for a write watchpoint, 1 for a read watchpoint, or 2 for a read/write
   watchpoint. */

int
or1k_insert_watchpoint (CORE_ADDR addr, int len, int type)
{
  int i;
  
  if (len < 1)
    return -1;

  type = translate_type (type);

  /* Moves unused watchpoints to the top.  */ 
  sift_matchpoints ();

  /* Place at first free matchpoint.  */
  i = or1k_implementation.num_used_matchpoints;
  dvr[i] = addr;
  dcr[i].dp = 1;
  dcr[i].cc = CC_GREATE;
  dcr[i].sc = 0;
  dcr[i].ct = type;
    
  /* Set && chaining here.  */ 
  dmr1 &= ~(3 << (2 * i));
  dmr1 |= CHAINING_AND << (2 * i);
  
  /* Set upper watchpoint bound.  */
  i++;
  dvr[i] = addr + len - 1;
  dcr[i].dp = 1;
  dcr[i].cc = CC_LESSE;
  dcr[i].sc = 0;
  dcr[i].ct = type;
    
  /* Matchpoints will cause breakpoints */
  dmr2 |= (1 << i);
  or1k_implementation.num_used_matchpoints += 2;
  debug_regs_changed = 1;
  return 0;
}

/* Removes a data watchpoint.  ADDR and LEN should be obvious.  TYPE is 0
   for a write watchpoint, 1 for a read watchpoint, or 2 for a read/write
   watchpoint. */

int
or1k_remove_watchpoint (CORE_ADDR addr, int len, int type)
{
  int i, found = -1;

  if (len < 1)
    return -1;

  type = translate_type (type);

  /* Find the right one.  */
  for (i = 0; i < or1k_implementation.num_used_matchpoints; i++)
    if (dvr[i] == addr && dcr[i].dp && dcr[i].cc == CC_GREATE && !dcr[i].sc && dcr[i].ct == type
	&& dvr[i + 1] == addr + len - 1 && dcr[i + 1].dp && dcr[i + 1].cc == CC_LESSE
	&& !dcr[i + 1].sc && dcr[i + 1].ct == type)
      {
	found = i;
	break;
      }
  
  if (found < 0)
    return -1;

  dcr[found].dp = 0;
  dcr[found + 1].dp = 0;

  /* Matchpoints will not cause breakpoints anymore. */
  dmr2 &= ~(1 << i);
  or1k_implementation.num_used_matchpoints -= 2;
  debug_regs_changed = 1;
  return 0;
}

int
or1k_stopped_by_watchpoint ()
{
  /* For now, no watchpoints */
  return 0;

  /* return hit_watchpoint; */
}

/* Insert a breakpoint.  */

int
set_breakpoint (CORE_ADDR addr)
{
  int i;
  
  /* Search for unused breakpoint.  */
  for (i = 0; i < NUM_MATCHPOINTS; i++)
    if (dcr[i].dp == 0) break;
  if (i >= NUM_MATCHPOINTS) return 1;
  dvr[i] = addr;
  dcr[i].dp = 1;
  dcr[i].cc = CC_EQUAL;
  dcr[i].sc = 0;
  dcr[i].ct = CT_FETCH;
  or1k_implementation.num_used_matchpoints++;
  
  /* No chaining here.  */ 
  dmr1 &= ~(3 << (2*i));
  
  /* Matchpoints will cause breakpoints */
  dmr2 |= (1 << i);
  debug_regs_changed = 1;
  return 0;
}

/* Clear a breakpoint.  */

int
clear_breakpoint (CORE_ADDR addr)
{
  int i;
  
  /* Search for matching breakpoint.  */
  for (i = 0; i < NUM_MATCHPOINTS; i++)
    if ((dcr[i].dp == 1) && (dvr[i] == addr) && (dcr[i].cc == CC_EQUAL)
	&& (dcr[i].sc == 0) && (dcr[i].ct == CT_FETCH)) break;

  if (i >= NUM_MATCHPOINTS) return 1;
  dcr[i].dp = 0;
  
  /* Matchpoints will cause breakpoints */
  dmr2 &= ~(1 << i);
  or1k_implementation.num_used_matchpoints--;
  debug_regs_changed = 1;
  return 0;
}

/* Start running on the target board.  */

static void
or1k_create_inferior (char *execfile, char *args, char **env)
{
  CORE_ADDR entry_pt;

  if (args && *args)
    {
      warning ("Can't pass arguments to remote OR1K board; arguments ignored.");

      /* And don't try to use them on the next "run" command.  */
      execute_command ("set args", 0);
    }

  if (execfile == 0 || exec_bfd == 0)
    error ("No executable file specified");

  or1k_kill ();
  remove_breakpoints ();

  entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd);
  init_wait_for_inferior ();
  
  /* FIXME: Should we set inferior_pid here?  */

  /* Needed to get correct instruction in cache */
  insert_breakpoints ();
  clear_proceed_status ();
  or1k_status = TARGET_STOPPED;
  proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0);
}

/* Clean up after a process.  Actually nothing to do.  */

static void
or1k_mourn_inferior ()
{
  generic_mourn_inferior ();
}

static void
or1k_dummy_open (char *name, int from_tty)
{
  target_preopen (from_tty);
  if (or1k_is_open)
    unpush_target (current_ops);
  current_or1k_target = &or1k_target_dummy;
  or1k_open (name, from_tty);
}

static void
or1k_jtag_open (char *name, int from_tty)
{
  target_preopen (from_tty);
  if (or1k_is_open)
    unpush_target (current_ops);
  current_or1k_target = &or1k_target_jtag;
  or1k_open (name, from_tty);
}

static void
or1k_or1ksim_open (char *name, int from_tty)
{
  /* target_preopen (from_tty); - do we need this ? */
  if (or1k_is_open)
    unpush_target (current_ops);
  current_or1k_target = &or1k_target_sim;
  or1k_open (name, from_tty);
}

/* Executes command on the target.  */

void
or1k_or1ksim_cmd (const char *args, int from_tty)
{
  if (current_or1k_target != NULL && current_or1k_target->to_exec_command != NULL)
    current_or1k_target->to_exec_command (args, from_tty);
  else
    error ("Command not supported on this target. ");
}

/* Displays matchpoints usage.  */

void
info_matchpoints_command (char *args, int from_tty)
{
  int i;
  for (i = 0; i < or1k_implementation.num_matchpoints; i++)
    {
      printf_filtered ("WP%i ", i);
      if (dcr[i].dp)
	{
	  int chaining = (dmr1 << 2*i) & 3; 
	  printf_filtered ("= %s ", ct_names[dcr[i].ct]);
	  if (dcr[i]. sc)
	    printf_filtered ("s%s %i", cc_names[dcr[i].cc], (int)dvr[i]);
          else
	    printf_filtered ("%s %u", cc_names[dcr[i].cc], (unsigned int)dvr[i]);
	  if (chaining)
	    printf_filtered ("%s WP%i", ch_names[chaining], i - 1);
	}
      else
	printf_filtered ("NOT USED");
      if ((dmr2 >> i) & 1)
	printf_filtered (", causes breakpoint");
      if ((dmr2 >> (i + 11)) & 1)
	printf_filtered (", increments counter");
      printf_filtered ("\n");
    }
}

static int
insn_modifies_gprs (unsigned int insn)
{
  /* l.jal */
  if ((insn >> 26) == 0x01)
    return 1;

  /* l.jalr */
  if ((insn >> 26) == 0x12)
    return 1;

  return 0;
}

void
_initialize_remote_or1k ()
{
  /* Initialize the fields in or1k_ops that are common to all targets.  */
  or1k_dummy_ops.to_close = or1k_close;
  or1k_dummy_ops.to_detach = or1k_detach;
  or1k_dummy_ops.to_resume = or1k_resume;
  or1k_dummy_ops.to_wait = or1k_wait;  
  or1k_dummy_ops.to_fetch_registers = or1k_fetch_registers;
  or1k_dummy_ops.to_store_registers = or1k_store_registers;
  or1k_dummy_ops.to_prepare_to_store = or1k_prepare_to_store;
  or1k_dummy_ops.to_xfer_memory = or1k_xfer_memory;
  or1k_dummy_ops.to_files_info = or1k_files_info;
  or1k_dummy_ops.to_insert_breakpoint = or1k_insert_breakpoint;
  or1k_dummy_ops.to_remove_breakpoint = or1k_remove_breakpoint;
  or1k_dummy_ops.to_kill = or1k_kill;
  or1k_dummy_ops.to_load = generic_load;
  or1k_dummy_ops.to_create_inferior = or1k_create_inferior;
  or1k_dummy_ops.to_mourn_inferior = or1k_mourn_inferior;
  or1k_dummy_ops.to_stratum = process_stratum;
  or1k_dummy_ops.to_stop = or1k_stop;

  /* We can access memory while program is running.  */
  or1k_dummy_ops.to_has_all_memory = 0;
  
  or1k_dummy_ops.to_has_memory = 1;
  or1k_dummy_ops.to_has_stack = 1;
  or1k_dummy_ops.to_has_registers = 1;
  or1k_dummy_ops.to_has_execution = 1;
  or1k_dummy_ops.to_magic = OPS_MAGIC;
  
  /* Copy the common fields to all target vectors.  */
  or1k_jtag_ops = or1k_sim_ops = or1k_dummy_ops;
  
  /* Initialize target-specific fields in the target vectors adn add targets.  */  
  or1k_jtag_ops.to_shortname = "jtag";
  or1k_jtag_ops.to_longname = "Remote or1k debugging over JTAG port";
  or1k_jtag_ops.to_doc = "Debug a board using the OR1K remote debugging protocol"
    " over a parallel line.\nThe argument is the parallel port it is connected "
    "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";
  or1k_jtag_ops.to_open = or1k_jtag_open;  
  add_target (&or1k_jtag_ops);
  
  or1k_dummy_ops.to_shortname = "dummy";
  or1k_dummy_ops.to_longname = "Dummy target";
  or1k_dummy_ops.to_doc = "Actually no real target attached - more like /dev/null.\n";
  or1k_dummy_ops.to_open = or1k_dummy_open;
  add_target (&or1k_dummy_ops);

  or1k_sim_ops.to_shortname = "sim";
  or1k_sim_ops.to_longname = "Remote or1k debugging using architecture simulator";
  or1k_sim_ops.to_doc = "Debug using an architecture simulator.\n";
  or1k_sim_ops.to_open = or1k_or1ksim_open;
  add_target (&or1k_sim_ops);
  add_info ("matchpoints", info_matchpoints_command, "Show current matchpoints allocation status.");
}
/* Target-dependent code for the or1k architecture, for GDB, the GNU Debugger.

   Copyright 1988-1999, Free Software Foundation, Inc.
   Contributed by Alessandro Forin(af@cs.cmu.edu at CMU
   and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

#include <ctype.h>
#include "demangle.h"
#include "defs.h"
#include "gdb_string.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "value.h"
#include "gdbcmd.h"
#include "language.h"
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbtypes.h"
#include "target.h"
#include "regcache.h"
#include "osabi.h"
#include "arch-utils.h"

#include "opcode/or32.h"

/* *INDENT-OFF* */

/* Group reg name size.  See or1k_reg_names.  */
static int or1k_group_name_sizes[OR1K_NUM_SPR_GROUPS] = {
  80,   0,   0, 6, 4, 2,
  22, 16, 1, 3, 2, 8
};

static int or1k_group_name_start[OR1K_NUM_SPR_GROUPS] = {
  0,   0,   0, 253, 254, 256,
  0, 248,  16, 16,  255, 0
};

/* Generated reg names (max valid alias index).
   See or1k_spr_reg_name.  */
static int or1k_spr_valid_aliases[OR1K_NUM_SPR_GROUPS] = {
  2047+1, 2047+1, 2047+1, 258+1, 257+1, 257+1,
  78+1, 263+1, 16+1, 18+1, 256+1, 7+1
};

/* Register names.  */
static char *or1k_reg_names[] = {

  /* group 0 - general*/
  "vr", "upr", "cpucfgr", "dmmucfgr", "immucfgr", "dccfgr", "iccfgr", "dcfgr",
  "pccfgr", "spr0_9", "spr0_10", "spr0_11", "spr0_12", "spr0_13", "spr0_14", "spr0_15",
  "npc", "sr", "ppc", "spr0_19", "spr0_20", "spr0_21", "spr0_22", "spr0_23",
  "spr0_24", "spr0_25", "spr0_26", "spr0_27", "spr0_28", "spr0_29", "spr0_30", "spr0_31", 
  "epcr0", "epcr1", "epcr2", "epcr3", "epcr4", "epcr5", "epcr6", "epcr7",
  "epcr8", "epcr9", "epcr10", "epcr11", "epcr12", "epcr13", "epcr14", "epcr15",
  "eear0","eear1", "eear2", "eear3", "eear4", "eear5", "eear6", "eear7",
  "eear8", "eear9", "eear10", "eear11", "eear12", "eear13", "eear14", "eear15",
  "esr0", "esr1", "esr2", "esr3", "esr4", "esr5", "esr6", "esr7",
  "esr8", "esr9", "esr10", "esr11", "esr12", "esr13", "esr14", "esr15",

  /* gpr+vf registers generated */ 
  /* group 1 - Data MMU - not listed, generated */
  /* group 2 - Instruction MMU - not listed, generated */

  /* group 3 - Data cache */
  "dccr", "dcbpr", "dcbfr", "dcbir", "dcbwr", "dcblr",

  /* group 4 - Instruction cache */
  "iccr", "icbpr", "icbir", "icblr",

  /* group 5 - MAC */
  "maclo", "machi",

  /* group 6 - debug */
  "dvr0", "dvr1", "dvr2", "dvr3", "dvr4", "dvr5", "dvr6", "dvr7",
  "dcr0", "dcr1", "dcr2", "dcr3", "dcr4", "dcr5", "dcr6", "dcr7",
  "dmr1", "dmr2", "dcwr0","dcwr1","dsr",  "drr",

  /* group 7 - performance counters unit */
  "pccm0", "pcmr1", "pcmr2", "pcmr3", "pcmr4", "pcmr5", "pcmr6", "pcmr7",
  "pccr0", "pccr1", "pccr2", "pccr3", "pccr4", "pccr5", "pccr6", "pccr7",
    
  /* group 8 - power management */
  "pmr",
  
  /* group 9 - PIC */
  "picmr", "picpr",
  
  /* group 10 - tick timer */
  "ttmr", "ttcr",

  /* group 11 - configuration */
  "cpucfgr", "dmmucfgr", "immucfgr", "dccfgr", "iccfgr", "spr11_5", "dcfgr", "pccfgr"
};

static char *or1k_gdb_reg_names[] = {

  /* general purpose registers */
  "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
  "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",

  /* vector/floating point registers */
  "vfa0",  "vfa1",  "vfa2",  "vfa3",  "vfa4",  "vfa5",  "vfrv ", "vfr7", 
  "vfr8",  "vfr9",  "vfr10", "vfr11", "vfr12", "vfr13", "vfr14", "vfr15",
  "vfr16", "vfr17", "vfr18", "vfr19", "vfr20", "vfr21", "vfr22", "vfr23",
  "vfr24", "vfr25", "vfr26", "vfr27", "vfr28", "vfr29", "vfr30", "vfr31",
  "pc",    "sr",    "epcr", "expc", "exear", "exsr"
};

static char *or1k_group_names[] = {
  "sys", "dmmu", "immu", "dcache", "icache", "mac", "debug", "perf",
  "power", "pic", "timer", "config"
};

/* Table of or1k signals.  */
static struct
  {
  char *name;
  char *string;
  } or1k_signals [NUM_OR1K_SIGNALS + 1] =
  {
    {"RSTE", "Reset Exception"},
    {"BUSE", "Bus Error" },
    {"DFPE", "Data Page Fault Exception"},
    {"IFPE", "Instruction Page Fault Exception"},
    {"LPINTE", "Low Priority Interrupt Exception"},
    {"AE", "Alignment Exception"},
    {"ILINSE" "Illegal Instruction" },
    {"HPINTE", "High Priority Interrupt Exception"},
    {"DME", "DTLB Miss Exception"},
    {"IME", "ITLB Miss Exception"},
    {"RE", "Range Exception"},
    {"SCE", "SCE Exception"},
    {"BRKPTE", "Breakpoint Exception"},
    {NULL, NULL}
  };

/* *INDENT-ON* */

/* List of all saved register addresses, produced by skip_prologue.  
   Relative address to sp, not used if 0.  */
static int or1k_saved_reg_addr[OR1K_NUM_REGS];

/* Converts regno to sprno.  or1k debug unit has GPRs mapped to SPRs,
   which are not compact, so we are mapping them for GDB.  */
int
or1k_regnum_to_sprnum (int regno)
{
  if (regno < MAX_GPR_REGS)
    return SPR_REG (SPR_SYSTEM_GROUP, regno + CURRENT_CID * MAX_GPR_REGS + SPR_GPR_START);

  if (regno < MAX_GPR_REGS + MAX_VF_REGS)
    return SPR_REG (SPR_SYSTEM_GROUP, regno - MAX_GPR_REGS
		   + CURRENT_CID * MAX_GPR_REGS + SPR_VFPR_START);

  switch (regno)
    {
    case PS_REGNUM:         return SR_SPRNUM;
    case PC_REGNUM:         return PC_SPRNUM;
    /*case CCR_REGNUM:        return CCR_SPRNUM (CURRENT_CID);*/
    case EPCR_REGNUM:        return EPCR_SPRNUM (CURRENT_CID);
    /*case EAR_REGNUM:        return EAR_SPRNUM (CURRENT_CID);
    case ESR_REGNUM:        return ESR_SPRNUM (CURRENT_CID);*/
    default:
      error ("Invalid register number!");
      break;
    }

  return 0;
}

/* Builds and returns register name.  */

static char tmp_name[16];
static const char *
or1k_spr_register_name (int i)
{
  int group = i >> SPR_GROUP_SIZE_BITS;
  int index = i & (SPR_GROUP_SIZE - 1);
  switch (group)
    {
      /* Names covered in or1k_reg_names.  */
    case 0:

      /* Generate upper names.  */
      if (index >= SPR_GPR_START)
	{
	  if (index < SPR_VFPR_START)
	    sprintf (tmp_name, "gpr%i", index - SPR_GPR_START);
	  else
	    sprintf (tmp_name, "vfr%i", index - SPR_VFPR_START);
	  return (char *)&tmp_name;
	}
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
      {
	int group_start = 0;
	for (i = 0; i < group; i++) 
	  group_start += or1k_group_name_sizes[i];
	
	index -= or1k_group_name_start[group];
	if (index >= or1k_group_name_sizes[group])
	  {
	    sprintf (tmp_name, "spr%i_%i", group, index);
	    return (char *)&tmp_name;
	  }
	else
	  return or1k_reg_names[group_start + index];
      }

      /* Build names for DMMU group.  */
    case 1:
    case 2:
      strcpy (tmp_name, (group == 1) ? "D" : "I");
      switch (index)
	{
	case 16:
	  return strcat (tmp_name, "mmucr");
	case 17:
	  return strcat (tmp_name, "mmupr");
	case 18:
	  return strcat (tmp_name, "tlbeir");
	case 24:
	  return strcat (tmp_name, "atbmr0");
	case 25:
	  return strcat (tmp_name, "atbmr1");
	case 26:
	  return strcat (tmp_name, "atbmr2");
	case 27:
	  return strcat (tmp_name, "atbmr3");
	case 28:
	  return strcat (tmp_name, "atbtr0");
	case 29:
	  return strcat (tmp_name, "atbtr0");
	case 30:
	  return strcat (tmp_name, "atbtr0");
	case 31:
	  return strcat (tmp_name, "atbtr0");
	default:
	  if (index >= 1024) {
	    index -= 1024;
	    sprintf (tmp_name, "%stlbw%imr%i", (group == 1) ? "d" : "i",
                            index / 128, index % 128);
	    return (char *)&tmp_name;
	  }	  
	  sprintf (tmp_name, "spr%i_%i", group, index);
	  return (char *)&tmp_name;
      }
    default:
      sprintf (tmp_name, "spr%i_%i", group, index);
      return (char *)&tmp_name;
    }
}

/* Get register index in group from name.  Negative if no match.  */

static int
or1k_regno_from_name (int group, const char *name)
{
  int i;
  if (toupper (name[0]) == 'S' && toupper (name[1]) == 'P' && toupper (name[2]) == 'R')
    {
      char *ptr_c;      
      name += 3;
      i = (int) strtoul (name, &ptr_c, 10);
      if (*ptr_c != '_' || i != group)
	return -1;
      ptr_c++;
      i = (int) strtoul (name, &ptr_c, 10);
      if (*ptr_c)
	return -1;
      else return i;
    }
  for (i = or1k_group_name_start[group]; i < or1k_spr_valid_aliases[group]; i++)
    {
      const char *s;
      s = or1k_spr_register_name (SPR_REG (group, i));
      if (strcasecmp (name, s) == 0)
	return i;
    }
  return -1;
}

/* Returns gdb register name.  */

static const char *
or1k_register_name (int regno)
{
  return or1k_gdb_reg_names[regno];
}

/* Utility function to display vf regs.  */

static int
do_vf_register (int regnum)
{
  /* do values for FP (float) regs */
  char *raw_buffer;

   /* doubles extracted from raw hex data */
  double doub, flt;
  int inv1, inv3, byte;

  raw_buffer = (char *) alloca (OR1K_VF_REGSIZE);

  /* Get the data in raw format.  */

  if (!frame_register_read (selected_frame, regnum, raw_buffer))
    error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
  
  flt = unpack_double (builtin_type_float, raw_buffer, &inv1);
  doub = unpack_double (builtin_type_double, raw_buffer, &inv3);
  
  if (inv1)
    printf_filtered (" %-5s flt: <invalid float>", REGISTER_NAME (regnum));
  else
    printf_filtered (" %-5s flt:%-17.9g", REGISTER_NAME (regnum), flt);
  printf_filtered (inv3 ? " dbl: <invalid double> " :
		   " dbl: %-24.17g ", doub);

  /* pad small registers */
  for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
    printf_filtered ("  ");

  /* Now print the register value in hex, endian order. */
  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
    for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
	 byte < REGISTER_RAW_SIZE (regnum);
	 byte++)
      printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
  else
    for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
	 byte >= 0;
	 byte--)
      printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
  printf_filtered ("\n");
  
  regnum++;
  return regnum;
}

/* Print a row's worth of GP (int) registers, with name labels above */

static int
do_gp_register_row (int regnum)
{
  /* do values for GP (int) regs */
  char raw_buffer[MAX_REGISTER_RAW_SIZE];

  /* display cols per row */
  int ncols = (OR1K_64BIT_IMPLEMENTATION ? 4 : 8);
  int col, byte;
  int start_regnum = regnum;
  int numregs = OR1K_NUM_REGS;

  /* For GP registers, we print a separate row of names above the vals */
  printf_filtered ("     ");
  for (col = 0; col < ncols && regnum < numregs; regnum++)
    {
      if (*REGISTER_NAME (regnum) == '\0')
	continue;		/* unused register */
      if (OR1K_IS_VF (regnum))
	break;			/* end the row: reached VF register */
      printf_filtered (OR1K_64BIT_IMPLEMENTATION ? "%17s" : "%9s",
		       REGISTER_NAME (regnum));
      col++;
    }
  printf_filtered ("\n      ");

  regnum = start_regnum;	/* go back to start of row */

  /* now print the values in hex, 4 or 8 to the row */
  for (col = 0; col < ncols && regnum < numregs; regnum++)
    {
      /* unused register? */
      if (*REGISTER_NAME (regnum) == '\0')
	continue;		

      /* end row: reached VF register? */
      if (OR1K_IS_VF (regnum))
	break;			

      /* OK: get the data in raw format.  */
      if (!frame_register_read (selected_frame, regnum, raw_buffer))
	error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));

      /* pad small registers */
      for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
	printf_filtered ("  ");

      /* Now print the register value in hex, endian order. */
      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
	for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
	     byte < REGISTER_RAW_SIZE (regnum);
	     byte++)
	  printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      else
	for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
	     byte >= 0;
	     byte--)
	  printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      printf_filtered (" ");
      col++;
    }

  /* ie. if we actually printed anything... */
  if (col > 0)		    
    printf_filtered ("\n");

  return regnum;
}

/* Replacement for generic do_registers_info.  
   Print regs in pretty columns.  */

static void
print_register (int regnum, int all)
{
  int offset;
  char raw_buffer[MAX_REGISTER_RAW_SIZE];

  /* Get the data in raw format.  */
  if (!frame_register_read (selected_frame, regnum, raw_buffer))
    {
      printf_filtered ("%s: [Invalid]", REGISTER_NAME (regnum));
      return;
    }

  /* If virtual format is floating, print it that way.  */
  if (OR1K_IS_VF (regnum))
    do_vf_register (regnum);
  else
    {
      int byte;
      printf_filtered ("%-16s\t", REGISTER_NAME (regnum));
      
      /* pad small registers */
      for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
	printf_filtered ("  ");

      /* Now print the register value in hex, endian order. */
      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
	for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
	     byte < REGISTER_RAW_SIZE (regnum);
	     byte++)
	  printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      else
	for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
	     byte >= 0;
	     byte--)
	  printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      printf_filtered (" ");
    }
}

/* DO_REGISTERS_INFO: called by "info register" command */

static void
or1k_do_registers_info (int regnum, int fpregs)
{
  if (fpregs && !or1k_implementation.vf_present)
    {
      warning ("VF register set not present in this implementation.");
      fpregs = 0;
    }
  if (regnum != -1)		
    {
      /* do one specified register */
      if (*(REGISTER_NAME (regnum)) == '\0')
	error ("Not a valid register for the current processor type");

      print_register (regnum, 0);
      printf_filtered ("\n");
    }
  else
    /* do all (or most) registers */
    {
      regnum = 0;
      while (regnum < OR1K_NUM_REGS)
	{
	  if (OR1K_IS_VF (regnum))
	    /* true for "INFO ALL-REGISTERS" command */
	    if (fpregs)		
	      /* FP regs */
	      regnum = do_vf_register (regnum);	
	    else
	      /* skip floating point regs */
	      regnum++; 	
	  else
	    /* GP (int) regs */
	    regnum = do_gp_register_row (regnum);	
	}
    }
}

/* Return the string for a signal.
   Replacement for target_signal_to_string (sig).  NOT USED.  */

static const char *
or1k_signal_to_string (enum target_signal sig)
{
  if ((sig >= TARGET_SIGNAL_FIRST) && (sig <= TARGET_SIGNAL_LAST))
    return or1k_signals[sig].string;
  else
    if (sig <= TARGET_SIGNAL_LAST + NUM_OR1K_SIGNALS)
      return or1k_signals[sig - TARGET_SIGNAL_LAST].string;
    else
      return 0;
}

/* Return the name for a signal.  */

const char *
or1k_signal_to_name (enum target_signal sig)
{
  if (sig >= TARGET_SIGNAL_LAST)
    {
      if (sig <= TARGET_SIGNAL_LAST + NUM_OR1K_SIGNALS)
        return or1k_signals[sig - TARGET_SIGNAL_LAST].name;
      else

      /* I think the code which prints this will always print it along with
         the string, so no need to be verbose.  */
        return "?";
    }
  if (sig == TARGET_SIGNAL_UNKNOWN)
    return "?";
  return 0;
}

/* Given a name, return its signal.  NOT USED.  */
enum target_signal
or1k_signal_from_name (const char *name)
{
  enum target_signal sig;

  /* It's possible we also should allow "SIGCLD" as well as "SIGCHLD"
     for TARGET_SIGNAL_SIGCHLD.  SIGIOT, on the other hand, is more
     questionable; seems like by now people should call it SIGABRT
     instead.  */

  /* This ugly cast brought to you by the native VAX compiler.  */
  for (sig = TARGET_SIGNAL_FIRST;
       or1k_signal_to_name (sig) != NULL;
       sig = (enum target_signal) ((int) sig + 1))
    if (STREQ (name, or1k_signal_to_name (sig)))
      return sig;
  return TARGET_SIGNAL_UNKNOWN;
}

/* XFER a value from the big/little/left end of the register.
   Depending on the size of the value it might occupy the entire
   register or just part of it.  Make an allowance for this, aligning
   things accordingly.  */

static void
or1k_xfer_register (struct regcache *regcache, int reg_num, int length,
                    enum bfd_endian endian, bfd_byte *in, const bfd_byte *out,
                    int buf_offset)
{
  bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE);
  int reg_offset = 0;
  /* Need to transfer the left or right part of the register, based on
     the targets byte order.  */
     switch (endian)
       {
       case BFD_ENDIAN_BIG:
         reg_offset = REGISTER_RAW_SIZE (reg_num) - length;
         break;
       case BFD_ENDIAN_LITTLE:
         reg_offset = 0;
         break;
       case BFD_ENDIAN_UNKNOWN: /* Indicates no alignment.  */
         reg_offset = 0;
         break;
       default:
         internal_error (__FILE__, __LINE__, "bad switch");
       }
  if (gdbarch_debug) printf_unfiltered ("xfer $%d, reg offset %d, buf offset %d, length %d, ",
                  reg_num, reg_offset, buf_offset, length);
  if (out != NULL) 
    {
      int i;
      if (gdbarch_debug) printf_unfiltered ("out ");
      for (i = 0; i < length; i++)
        printf_unfiltered ("%02x", out[buf_offset + i]);
    }
  if (in != NULL)
    regcache_raw_read_part (regcache, reg_num, reg_offset, length, in + buf_offset);
  if (out != NULL)
    regcache_raw_write_part (regcache, reg_num, reg_offset, length, out + buf_offset);
  if (gdbarch_debug && in != NULL)
    {
      int i;
      printf_unfiltered ("in ");
      for (i = 0; i < length; i++)
        printf_unfiltered ("%02x", in[buf_offset + i]);
    }
  if (gdbarch_debug) printf_unfiltered ("\n");
}



/* Advance PC across any function entry prologue instructions
   to reach some "real" code.

   The or1k CC defines the following
   prologue:
00000000 <_proc1>:
   0:   d7 e1 17 e4     l.sw 0xffffffe4(r1),r2
   4:   9c 41 00 00     l.addi r2,r1,0x0
   8:   9c 21 ff e8     l.addi r1,r1,0xffffffe8
   c:   d7 e2 1f f8     l.sw 0xfffffff8(r2),r3
  10:   d7 e2 27 f4     l.sw 0xfffffff4(r2),r4
  14:   84 82 ff f8     l.lwz r4,0xfffffff8(r2)
  18:   9d 24 00 00     l.addi r9,r4,0x0
  1c:   00 00 00 02     l.j 0x2
  20:   15 00 00 00     l.nop 

00000024 <_L2>:
  24:   84 41 ff fc     l.lwz r2,0xfffffffc (r1)
  28:   48 00 58 00     l.jalr r11
  2c:   9c 21 00 18     l.addi r1,r1,0x18 */

static CORE_ADDR
or1k_skip_prologue (CORE_ADDR pc)
{
  unsigned long inst;
  CORE_ADDR skip_pc;
  CORE_ADDR func_addr, func_end;
  struct symtab_and_line sal;
  int i;
  int offset = 0;
  
  for (i = 0; i < MAX_GPR_REGS; i++)
    or1k_saved_reg_addr[i] = -1;

  /* Is there a prologue?  */
  inst = or1k_fetch_instruction (pc);
  if ((inst & 0xfc1ff800) != 0xd4011000) return pc; /* l.sw I (r1),r2 */
  or1k_saved_reg_addr[2] = offset++;
  inst = or1k_fetch_instruction (pc + OR1K_INSTLEN);
  if ((inst & 0xFFFF0000) != 0x9c410000) return pc; /* l.addi r2,r1,I */
  pc += 2 * OR1K_INSTLEN;
  inst = or1k_fetch_instruction (pc);
  if ((inst & 0xFFFF0000) != 0x9c210000) return pc; /* l.addi r1,r1,I */
  pc += OR1K_INSTLEN;

  /* Skip stored registers.  */
  inst = or1k_fetch_instruction (pc);
  while ((inst & 0xfc1ff800) != 0xd4020000)  /* l.sw 0x0(r2),rx */
    {
      /* get saved reg. */
      or1k_saved_reg_addr[(inst >> 11) & 0x1f] = offset++;
      pc += OR1K_INSTLEN;
      inst = or1k_fetch_instruction (pc);
    }
  return pc;
}

/* Determines whether this function has frame.  */

int
or1k_frameless_function_invocation (struct frame_info *fi)
{
  CORE_ADDR func_start, after_prologue;
  int frameless;
  func_start = (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
  after_prologue = SKIP_PROLOGUE (func_start);

  /* If we don't skip pc, we don't have even shortest possible  prologue.  */
  frameless = (after_prologue <= func_start);
  return frameless;
}

/* Given a GDB frame, determine the address of the calling function's frame.
   This will be used to create a new GDB frame struct, and then
   INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame. */

static CORE_ADDR
or1k_frame_chain (struct frame_info *frame)
{
  CORE_ADDR fp;
  if (USE_GENERIC_DUMMY_FRAMES)
    {
      if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
	/* dummy frame same as caller's frame */
	return frame->frame;
    }

  if (inside_entry_file (frame->pc) ||
      frame->pc == entry_point_address ())
    return 0;

  if (frame->signal_handler_caller)
    fp = read_memory_integer (frame->frame, 4);
  else if (frame->next != NULL
	   && frame->next->signal_handler_caller
	   && FRAMELESS_FUNCTION_INVOCATION (frame))
    /* A frameless function interrupted by a signal did not change the
       frame pointer.  */
    fp = FRAME_FP (frame);
  else
    {
      unsigned long func_pc = get_pc_function_start (frame->pc);
      unsigned long insn = read_memory_integer (func_pc,4);
      int i;
      int offset = 0;

      /* The first instruction should be the number of bytes
	 in our frame. If it isn't we're in trouble because
	 the function is without a prologue... */
      if (((insn & 0xFC000000) == 0x9C000000) &&
	 ((insn & 0x03E00000) == 0x00200000) &&
	 ((insn & 0x001F0000) == 0x00010000))
	{
	  short off = insn & 0xFFFF;

	  /* Look for the storage of the frame pointer in the
	     function prologue.. */
	  for (i = 1; i < 20; i++)
	    {
	      unsigned long insn = read_memory_integer (func_pc + 4 * i, 4);
	  
	      /* If bits are 31 - 26 are %110101,
		 and bits 20 - 16 are %00001,
		 and bits 15 - 11 are %00010,
		 then our frame pointer lies at the offset specified
		 by bits [25-21][10-0]. */
	  
	      int code = insn >> 26;
	      int r1    = (insn & 0x001F0000) >> 16;
	      int r2    = (insn & 0x0000F800) >> 11;
	      int idx_h = (insn & 0x03E00000) >> 10;
	      int idx   = (insn & 0x000007FF) | idx_h;

	      if (code == 0x35 && r1 == 1 && r2 == 2)
		{
		  offset = off + idx;
		  break;
		}
	    }
	}

      fp = read_memory_integer (frame->frame + offset, 4);
    }

  if (USE_GENERIC_DUMMY_FRAMES)
    {
      CORE_ADDR fpp, lr;

      lr = read_register (LR_REGNUM);
      if (lr == entry_point_address ())
	if (fp != 0 && (fpp = read_memory_integer (fp, 4)) != 0)
	  if (PC_IN_CALL_DUMMY (lr, fpp, fpp))
	    return fpp;
    }
  
  return fp;
}

/* The code to store, into a struct frame_saved_regs,
   the addresses of the saved registers of frame described by FRAME_INFO.
   This includes special registers such as pc and fp saved in special
   ways in the stack frame.  sp is even more special:
   the address we return for it IS the sp for the next frame.  */
static void
or1k_frame_init_saved_regs (struct frame_info *fi)
{
  int i;
  CORE_ADDR frame_addr;
  CORE_ADDR func_pc = get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET;
  int frame_size;
  int pc_found = 0;

  frame_saved_regs_zalloc (fi);
  
  /* Skip prologue sets or1k_saved_reg_addr[], we will use it later.  */
  or1k_skip_prologue (func_pc);

  frame_size = or1k_saved_reg_addr[1];
  or1k_saved_reg_addr[1] = -1;

  /* If the frame_size is less than 0, we have hit an assembly
     routine which we can't traverse beyond. Let's give up here,
     because attempting to continue will only lead to trouble. */
  if (frame_size < 0)
    {
      printf ("Found a function without a prologue at 0x%08lx\n",func_pc);
      printf ("Frame pc was at 0x%08lx\n",fi->pc);
      return;
    }

  for (i = 0; i < NUM_GPR_REGS + NUM_VF_REGS; i++)
    if (or1k_saved_reg_addr[i] >= 0)
      fi->saved_regs[i] = fi->frame - or1k_saved_reg_addr[i];

  /* We want to make sure we fill in the PC with the value of the
     r9 register from the NEXT frame, and that the value of r1 is
     the correct value of r1 for the next frame, which can be
     calculated by adding the frame_size to the frame pointer. */
  fi->saved_regs[1] = fi->frame - frame_size;

  if (fi->saved_regs[LR_REGNUM])
    fi->saved_regs[PC_REGNUM] = read_memory_integer (fi->saved_regs[LR_REGNUM],4);
  else
    fi->saved_regs[PC_REGNUM] = read_register (LR_REGNUM);
}

static CORE_ADDR
read_next_frame_reg (struct frame_info *fi, int regno)
{
  for (; fi; fi = fi->next)
    {
      /* We have to get the saved sp from the sigcontext
         if it is a signal handler frame.  */
      if (regno == SP_REGNUM && !fi->signal_handler_caller)
	return fi->frame;
      else
	{
	  if (fi->saved_regs == NULL)
	    or1k_frame_init_saved_regs (fi);
	  if (fi->saved_regs[regno])
	    {
	      if (regno == SP_REGNUM || regno == PC_REGNUM)
		return fi->saved_regs[regno];
	      else
		return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), OR1K_GPR_REGSIZE);
	    }
	}
    }
  return read_register (regno);
}

/* Return nonzero when instruction has delay slot.  */

int
is_delayed (unsigned long insn)
{
  int index;
  index = insn_decode (insn);
  return or32_opcodes[index].flags & OR32_IF_DELAY;
}

int
or1k_step_skips_delay (CORE_ADDR pc)
{
  char buf[OR1K_INSTLEN];

  if (target_read_memory (pc, buf, OR1K_INSTLEN) != 0)
    /* If error reading memory, guess that it is not a delayed branch.  */
    return 0;
  return is_delayed ((unsigned long) extract_unsigned_integer (buf, OR1K_INSTLEN));
}

/* Parses args for spr name and puts result into group and index.  */

static char *
parse_spr_params (char *args, int *group, int *index)
{
  *index = -1;
  if (args)
    {
      int i; 
      char *ptr_c;

      /* Check if group number was supplied.  */
      ptr_c = args;
      while (*ptr_c != ' ' && *ptr_c != 0)
	ptr_c++;
      *ptr_c = 0;

      *group = (int) strtoul (args, &ptr_c, 0);
      if (*ptr_c != 0)
	{
	  *group = OR1K_NUM_SPR_GROUPS;

	  /* check for group name */
	  for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
	    if (strcasecmp (or1k_group_names[i], args) == 0)
	      {
		*group = i;
		break;
	      }

	  /* Invalid group => check all register names in all groups.  */
	  if (*group >= OR1K_NUM_SPR_GROUPS)
	    {	      
	      for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
		{
		  int regno;
		  regno = or1k_regno_from_name (i, args);
		  if (regno >= 0)
		    {
		      *group = i;
		      *index = regno;
		      break;
		    }
		}
	    }
	}
      if (*group < 0 || *group >= OR1K_NUM_SPR_GROUPS)
	error ("Invalid group or register.\n");
      
      if (*index < 0)
	{
	  printf ("a'%s'\n", args);
	  args += strlen (args) + 1;
	  printf ("b'%s'\n", args);
	  if (*args != 0)
	    {
	      ptr_c = args;
	      while (*ptr_c != ' ' && *ptr_c != 0)
	        ptr_c++;
	      *ptr_c = 0;
	  
	      *index = (int) strtoul (args, &ptr_c, 0);
	      if (*ptr_c != 0)
	        *index = or1k_regno_from_name (*group, args);
	    }

	  if (*index < 0)
	    {
	      printf_filtered ("No register supplied. Valid registers are:\n");
	      for (i = 0; i < or1k_spr_valid_aliases[*group]; i++)
		{
		  char reg_name[16];
		  const char *gen_name = or1k_spr_register_name (SPR_REG (*group, i + or1k_group_name_start[*group]));
		  sprintf (reg_name, "SPR%i_%i", *group, i);
		  if (strcmp (reg_name, gen_name) != 0) 
		    printf_filtered ("%s\t", gen_name);
		}
	      printf_filtered ("\n");
	      return args + strlen (args) + 1;
	    }
	}
    }
  else
    {
      /* No parameters - print groups */
      int i;
      printf_filtered ("No parameter supplied. Valid groups are:\n");
      for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
	printf_filtered ("%s\t", or1k_group_names[i]);
      printf_filtered ("\nSingle register name or register name or number after the group can be also supplied.\n");
      return args;
    }
  return args + strlen (args) + 1;
}

/* SPR register info.  */

void
info_spr_command (char *args, int from_tty)
{
  int group, index;
  parse_spr_params (args, &group, &index);
  if (index >= 0)
    {
      unsigned long value = or1k_read_spr_reg (SPR_REG (group, index));
      printf_unfiltered ("%s.%s = SPR%i_%i = %li (%lx)\n", or1k_group_names[group], 
			 or1k_spr_register_name (SPR_REG (group, index)), group, index, value, value);
    }
}

/* Set SPR register.  */

void
spr_command (char *args, int from_tty)
{
  int group, index;
  char *nargs = parse_spr_params (args, &group, &index);
  if (index >= 0)
    {
      unsigned long prev;
      unsigned long value;
      char *ptr_c;

      /* Any arguments left?  */
      if (args + strlen (args) >= nargs)
	error ("Invalid register value.");

      prev = or1k_read_spr_reg (SPR_REG (group, index));

      ptr_c = nargs;
      while (*ptr_c != ' ' && *ptr_c != 0)
	ptr_c++;
      *ptr_c = 0;
      value = strtoul (nargs, &ptr_c, 0);
      if (*ptr_c != 0)
				error ("Invalid register value.");
			or1k_write_spr_reg (SPR_REG (group, index), value);
      printf_unfiltered ("%s.%s (spr%i_%i) set to %li (%lx), was:%li (%lx)\n", or1k_group_names[group], 
			 or1k_spr_register_name (SPR_REG (group, index)), group, index,
			 value, value, prev, prev);      
    }
}

/* Calls extended command on target.  */

void
or1ksim_command (char *args, int from_tty)
{
  or1k_or1ksim_cmd (args, from_tty);
}

int print_insn_big_or32 (bfd_vma, struct disassemble_info *);
int print_insn_little_or32 (bfd_vma, struct disassemble_info *);

/* returns nonzero, if register is readonly */
static int
or1k_cannot_store_register (int regnum)
{
  return regnum == ZERO_REGNUM;
}

/* Returns the byte position in the register cache for register regnum.  */

static int
or1k_register_byte (int regnum)
{
  if (regnum < 0 || regnum >= OR1K_NUM_REGS)
    internal_error (__FILE__, __LINE__,
                    "or1k_register_byte: illegal register number %d", regnum);
  else
    return regnum * OR1K_SPR_REGSIZE;
}

/* Number of bytes of storage in the actual machine representation for
   register N.  NOTE: This indirectly defines the register size
   transfered by the GDB protocol.  If we have 64bit processor
   implementation, GPR register raw size is 8B, otherwise 4B.  */
static int
or1k_register_raw_size (int regnum)
{
 if (regnum < 0 || regnum >= OR1K_NUM_REGS)
   internal_error (__FILE__, __LINE__,
                   "or1k_register_raw_size: illegal register number %d", regnum);
   /* Only the PC has 4 Byte, all other registers 2 Byte. */
   else
    return ((OR1K_IS_GPR(regnum) ? ((OR1K_64BIT_IMPLEMENTATION) ? (8) : (4))
                            : (OR1K_SPR_REGSIZE)));
}

/* Returns the default type for register N. */
static struct type *
or1k_reg_virtual_type (int regnum)
{
  if (regnum < 0 || regnum >= OR1K_NUM_REGS)
    internal_error (__FILE__, __LINE__,
                    "or1k_register_virtual_type: illegal register number %d", regnum);
  else if (OR1K_IS_GPR(regnum))
    return OR1K_64BIT_IMPLEMENTATION ? builtin_type_int64 : builtin_type_int;
  else if (OR1K_IS_VF(regnum))
    return builtin_type_float;
  else
    return builtin_type_uint32;
}

/* Find a register's saved value on the call stack. */

static void
or1k_get_saved_register (char *raw_buffer, int *optimized, CORE_ADDR *addrp,
                         struct frame_info *fi, int regnum, enum lval_type *lval)
{
  /* TODO: check if OK */
  generic_get_saved_register (raw_buffer, optimized, addrp, fi, regnum, lval);
}

/* Returns the previous PC immediately after a function call.
   This function is meant to bypass the regular get_saved_register
   mechanism, ie. it is meant to work even if the frame isn't complete.
   Called by step_over_function, and sometimes by get_prev_frame.  */

static CORE_ADDR
or1k_saved_pc_after_call (struct frame_info *ignore)
{
  return read_register(LR_REGNUM);
}

/* Find the caller of this frame.  We do this by seeing if LR_REGNUM
   is saved in the stack anywhere, otherwise we get it from the
   registers.  */

static CORE_ADDR
or1k_frame_saved_pc (struct frame_info *fi)
{
  CORE_ADDR saved_pc;
  
  /* We have to get the saved pc from the sigcontext
     if it is a signal handler frame.  */
  if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
    saved_pc = read_memory_integer (fi->frame, OR1K_GPR_REGSIZE);
  else
    saved_pc = read_next_frame_reg (fi, PC_REGNUM);

  return ADDR_BITS_REMOVE (saved_pc);
}

/* This is the constructor function for the frame_info struct,
   called whenever a new frame_info is created (from create_new_frame,
   and from get_prev_frame).  */

static void
or1k_init_extra_frame_info (int fromleaf, struct frame_info *fi)
{
  if (!fi->extra_info)
    {
#if 0
      fi->extra_info = (struct frame_extra_info *)
                       frame_obstack_alloc (sizeof (struct frame_extra_info));
      fi->extra_info->framesize = 0;
      fi->extra_info->frameless_p = 1;  /* Default frameless, detect framed */
#else
      fi->extra_info = NULL;
#endif

      /* By default, the fi->frame is set to the value of the FP reg by gdb.
         This may not always be right; we may be in a frameless function,
         or we may be in the prologue, before the FP has been set up.
         Unfortunately, we can't make this determination without first
         calling scan_prologue, and we can't do that unles we know the
         fi->pc.  */

      if (!fi->pc)
        {
          /* Sometimes we are called from get_prev_frame without
             the PC being set up first.  Long history, don't ask.
             Fortunately this will never happen from the outermost
             frame, so we should be able to get the saved pc from
             the next frame. */
          if (fi->next)
            fi->pc = or1k_frame_saved_pc (fi->next);
        }
      /* Take care of the saved_regs right here (non-lazy). */
      or1k_frame_init_saved_regs (fi);
  }
}

/* Setup the return address for GDB to call a function in the inferior.
   Called only in the context of a target function call from the debugger.
   Returns the value of the SP register when the operation is finished
   (which may or may not be the same as before).  */

static CORE_ADDR
or1k_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
  /* Set the return address register to point to the entry
     point of the program, where a breakpoint lies in wait.  */
  write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ());
  return sp;
}

/* Copy the function's return value into VALBUF.
   This function is called only in the context of "target function calls",
   ie. when the debugger forces a function to be called in the child, and
   when the debugger forces a function to return prematurely via the
   "return" command. */
        
static void
or1k_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
{
  CORE_ADDR return_buffer;
  int rv_regnum = (TYPE_CODE_FLT == TYPE_CODE (valtype)) ? VFRV_REGNUM : RV_REGNUM;

  if (TYPE_CODE (valtype) != TYPE_CODE_STRUCT
      && TYPE_CODE (valtype) != TYPE_CODE_UNION
      && TYPE_CODE (valtype) != TYPE_CODE_ARRAY
      && TYPE_LENGTH (valtype) <= OR1K_GPR_REGSIZE)
    {
      /* Scalar return values */
      memcpy (valbuf, &regbuf[REGISTER_BYTE (rv_regnum)], TYPE_LENGTH (valtype));
    }
  else
    {
      /* Aggregates */
      return_buffer = extract_address (regbuf + REGISTER_BYTE (rv_regnum),
                                       REGISTER_RAW_SIZE (rv_regnum));
                                       read_memory (return_buffer, valbuf, TYPE_LENGTH (valtype));
    }
}

/* Setup the function arguments for GDB to call a function in the inferior.
   Called only in the context of a target function call from the debugger.
   Returns the value of the SP register after the args are pushed.  */

static CORE_ADDR
or1k_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
                     int struct_return, CORE_ADDR struct_addr)
{
  int argreg;
  int float_argreg;
  int argnum;
  int len = 0;
  int stack_offset = 0;

  /* Initialize the integer and float register pointers.  */
  argreg = A0_REGNUM;
  float_argreg = VFA0_REGNUM;

  /* The struct_return pointer occupies the RV value register.  */
  if (struct_return)
    write_register (RV_REGNUM, struct_addr);

  /* Now load as many as possible of the first arguments into
     registers, and push the rest onto the stack.  Loop thru args
     from first to last.  */
  for (argnum = 0; argnum < nargs; argnum++)
    {
      char *val;
      char valbuf[MAX_REGISTER_RAW_SIZE];
      struct value *arg = args[argnum];
      struct type *arg_type = check_typedef (VALUE_TYPE (arg));
      int len = TYPE_LENGTH (arg_type);
      enum type_code typecode = TYPE_CODE (arg_type);

      /* The EABI passes structures that do not fit in a register by
         reference. In all other cases, pass the structure by value.  */
      if (len > OR1K_GPR_REGSIZE &&
	  (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
	{
	  store_address (valbuf, OR1K_GPR_REGSIZE, VALUE_ADDRESS (arg));
	  typecode = TYPE_CODE_PTR;
	  len = OR1K_GPR_REGSIZE;
	  val = valbuf;
	}
      else
	{
	  val = (char *) VALUE_CONTENTS (arg);
	  
	  if (typecode == TYPE_CODE_FLT
	      /* Doubles are not stored in regs on 32b target.  */
	      && len <= OR1K_VF_REGSIZE
	      && OR1K_VF_PRESENT)
	    {
	      if (float_argreg <= OR1K_LAST_FP_ARG_REGNUM)
		{
		  CORE_ADDR regval = extract_address (val, len);
		  write_register (float_argreg++, regval);
		}
	      else
		{
		  write_memory ((CORE_ADDR) sp, val, OR1K_VF_REGSIZE);	      
		  sp -= OR1K_STACK_ALIGN;
		}
	    }
	  else
	    {	
	      if (argreg <= OR1K_LAST_ARG_REGNUM)
		{
		  CORE_ADDR regval = extract_address (val, len);
		  write_register (argreg++, regval);
		}
	      else
		{
		  write_memory ((CORE_ADDR) sp, val, OR1K_GPR_REGSIZE);	      
		  sp -= OR1K_STACK_ALIGN;
		}
	    }
	}
    }

  /* Return adjusted stack pointer.  */
  return sp;
}

/* Discard from the stack the innermost frame, restoring all registers.  */

void
or1k_pop_frame ()
{
  register int regnum;
  struct frame_info *frame = get_current_frame ();
  CORE_ADDR new_sp = FRAME_FP (frame);

  write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
  if (frame->saved_regs == NULL)
    or1k_frame_init_saved_regs (frame);
  for (regnum = 0; regnum < OR1K_NUM_REGS; regnum++)    {
      if (regnum != SP_REGNUM && regnum != PC_REGNUM
	  && frame->saved_regs[regnum] >= 0)
	write_register (regnum,
			read_memory_integer (frame->saved_regs[regnum],
					     OR1K_GPR_REGSIZE));
    }
  write_register (SP_REGNUM, new_sp);
  flush_cached_frames ();
}

static void
or1k_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
  /* Nothing to do -- push_arguments does all the work.  */
}

/* Copy the function return value from VALBUF into the
   proper location for a function return.
   Called only in the context of the "return" command.  */

static void
or1k_store_return_value (struct type *type, char *valbuf)
{
  if (TYPE_CODE (type) == TYPE_CODE_FLT)
    write_register_bytes (REGISTER_BYTE (VFRV_REGNUM), valbuf, TYPE_LENGTH (type));
  else
    write_register_bytes (REGISTER_BYTE (RV_REGNUM), valbuf, TYPE_LENGTH (type));
}

/* Returns the address in which a function should return a struct value.
   Used in the contexts of the "return" command, and of
   target function calls from the debugger.  */

static CORE_ADDR
or1k_extract_struct_value_address (char *regbuf)
{
/* Extract from an array regbuf containing the (raw) register state
   the address in which a function should return its structure value,
   as a CORE_ADDR (or an expression that can be used as one).  */
  return extract_address (regbuf + REGISTER_BYTE (RV_REGNUM), REGISTER_RAW_SIZE (RV_REGNUM));
}

/* Returns non-zero if the given struct type will be returned using
   a special convention, rather than the normal function return method.
   Used in the contexts of the "return" command, and of
   target function calls from the debugger.  */

static int
or1k_use_struct_convention (int gcc_p, struct type *type)
{
  return (TYPE_LENGTH (type) > OR1K_STRUCT_CONV_SIZE);
}

/* Given the address at which to insert a breakpoint (BP_ADDR),
   what will that breakpoint be?

   For or1k, we have a breakpoint instruction. Since all or1k
   instructions are 32 bits, this is all we need, regardless of
   address. K is not used.  */

static const unsigned char *
or1k_breakpoint_from_pc (CORE_ADDR * bp_addr, int *bp_size)
{ 
  static char breakpoint[] = BRK_INSTR_STRUCT;
  *bp_size = OR1K_INSTLEN;
  return breakpoint;
}

/* Aligns address to valid stack entry */

static CORE_ADDR
or1k_stack_align (CORE_ADDR addr)
{
  if (OR1K_64BIT_IMPLEMENTATION)
    return addr & ~7;
  else
    return addr & ~3;
}

static struct gdbarch *
or1k_gdbarch_init (struct gdbarch_info info,
		   struct gdbarch_list *arches)
{
  static LONGEST call_dummy_words[1] = {0};
  struct gdbarch *gdbarch;
  struct gdbarch_tdep *tdep;
  int elf_flags;
  
  /* find a candidate among the list of pre-declared architectures. */
  arches = gdbarch_list_lookup_by_info (arches, &info);
  if (arches != NULL)
    return (arches->gdbarch);

  gdbarch = gdbarch_alloc (&info, NULL);

  /* Basic register fields and methods. */
  set_gdbarch_num_regs (gdbarch, OR1K_NUM_REGS);
  set_gdbarch_num_pseudo_regs (gdbarch, 0);
  set_gdbarch_sp_regnum (gdbarch, SP_REGNUM);
  set_gdbarch_fp_regnum (gdbarch, FP_REGNUM);
  set_gdbarch_pc_regnum (gdbarch, PC_REGNUM);
  set_gdbarch_cannot_store_register (gdbarch, or1k_cannot_store_register);
  set_gdbarch_register_name (gdbarch, or1k_register_name);
  set_gdbarch_register_size (gdbarch, OR1K_64BIT_IMPLEMENTATION ? 8 : 4);
  /* Total amount of space needed to store our copies of the machine's
     register state, the array `registers'.  */
  set_gdbarch_register_bytes (gdbarch, OR1K_NUM_REGS * OR1K_GPR_REGSIZE);
  set_gdbarch_register_byte (gdbarch, or1k_register_byte);
  set_gdbarch_register_raw_size (gdbarch, or1k_register_raw_size);
  /* Largest value REGISTER_RAW_SIZE can have.  */
  set_gdbarch_max_register_raw_size (gdbarch, OR1K_64BIT_IMPLEMENTATION ? 8 : 4);
  set_gdbarch_register_virtual_size (gdbarch, generic_register_size);
  /* Largest value REGISTER_VIRTUAL_SIZE can have.  */
  set_gdbarch_max_register_virtual_size (gdbarch, OR1K_64BIT_IMPLEMENTATION ? 8 : 4);
  set_gdbarch_register_virtual_type (gdbarch, or1k_reg_virtual_type);

  /* Frame Info */
#if 0
  set_gdbarch_init_extra_frame_info (gdbarch, or1k_init_extra_frame_info);
#endif
  set_gdbarch_frame_init_saved_regs (gdbarch, or1k_frame_init_saved_regs);
  set_gdbarch_get_saved_register (gdbarch, or1k_get_saved_register);
  set_gdbarch_saved_pc_after_call (gdbarch, or1k_saved_pc_after_call);
  set_gdbarch_frame_saved_pc (gdbarch, or1k_frame_saved_pc);
  set_gdbarch_skip_prologue (gdbarch, or1k_skip_prologue);
  set_gdbarch_frame_chain (gdbarch, or1k_frame_chain);
  set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
  set_gdbarch_frame_args_address (gdbarch, default_frame_address);
  set_gdbarch_frame_locals_address (gdbarch, default_frame_address);
  /* Offset from address of function to start of its code.  */
  set_gdbarch_frame_args_skip (gdbarch, 0);
  /* OK to default this value to 'unknown'. */
  set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);

#if 0 /* Do we need to define these? */
  set_gdbarch_in_function_epilogue_p (gdbarch, or1k_in_function_epilogue_p);
#endif

  /* Miscelany */
  /* Stack grows down. */
  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
  /* PC stops zero byte after a trap instruction
     (which means: exactly on trap instruction).  */
  set_gdbarch_decr_pc_after_break (gdbarch, 0);
  /* This value is almost never non-zero... */
  set_gdbarch_function_start_offset (gdbarch, 0);

  /* W/o prototype, coerce float args to double. */
  set_gdbarch_coerce_float_to_double (gdbarch,
                                      standard_coerce_float_to_double);

  /*
   * Call Dummies
   * These values and methods are used when gdb calls a target function.  */
  set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
  set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
  set_gdbarch_push_return_address (gdbarch, or1k_push_return_address);
  set_gdbarch_deprecated_extract_return_value (gdbarch, or1k_extract_return_value);
  /* Stack must be aligned on 32-bit boundaries when synthesizing
    function calls. or1k_push_arguments will handle it. */
  set_gdbarch_push_arguments (gdbarch, or1k_push_arguments);
  set_gdbarch_pop_frame (gdbarch, or1k_pop_frame);
  set_gdbarch_store_struct_return (gdbarch, or1k_store_struct_return);
  set_gdbarch_deprecated_store_return_value (gdbarch, or1k_store_return_value);
  set_gdbarch_deprecated_extract_struct_value_address (gdbarch, or1k_extract_struct_value_address);
  set_gdbarch_use_struct_convention (gdbarch, or1k_use_struct_convention);
  set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
  /* Return a location where we can set a breakpoint that will be hit
     when an inferior function call returns.  This is normally the
     program's entry point.  */
  set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
  set_gdbarch_call_dummy_start_offset (gdbarch, 0);
  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
  set_gdbarch_call_dummy_length (gdbarch, 0);
  set_gdbarch_pc_in_call_dummy (gdbarch, generic_pc_in_call_dummy);
  set_gdbarch_call_dummy_p (gdbarch, 1);
  set_gdbarch_call_dummy_words (gdbarch, call_dummy_words);
  set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0); //!
  /* set_gdbarch_call_dummy_stack_adjust */
  set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
  set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
#if 0
  /* probably not needed: Extract return value from RV reg */
  set_gdbarch_extract_struct_value_address (gdbarch, or1k_extract_struct_value_address);
#endif

  /* break- and watchpoints */
  set_gdbarch_breakpoint_from_pc (gdbarch, or1k_breakpoint_from_pc);

  /* Set target type sizes */
  set_gdbarch_short_bit (gdbarch, 16);
  set_gdbarch_int_bit (gdbarch, 32 /* OR1K_64BIT_IMPLEMENTATION ? 64 : 32 */);
  set_gdbarch_float_bit (gdbarch, 32);
  set_gdbarch_double_bit (gdbarch, 64);
  set_gdbarch_long_double_bit (gdbarch, 64);
  set_gdbarch_long_bit (gdbarch, 32 /* OR1K_64BIT_IMPLEMENTATION ? 64 : 32 */);
  set_gdbarch_ptr_bit (gdbarch, 32 /* OR1K_64BIT_IMPLEMENTATION ? 64 : 32 */);
  set_gdbarch_long_long_bit (gdbarch, 64 /* OR1K_64BIT_IMPLEMENTATION ? 128 : 64 */);

#if 0
  set_gdbarch_pointer_to_address (gdbarch, unsigned_pointer_to_address);
  set_gdbarch_address_to_pointer (gdbarch, address_to_unsigned_pointer);
#endif

  set_gdbarch_stack_align (gdbarch, or1k_stack_align);
  set_gdbarch_extra_stack_alignment_needed (gdbarch, 0);

#if 0 /* TODO */
  set_gdbarch_skip_trampoline_code (gdbarch, or1k_skip_trampoline_code);
  set_gdbarch_in_solib_call_trampoline (gdbarch, or1k_in_solib_call_trampoline);
  /* possibly: */
  set_gdbarch_pc_in_sigtramp (gdbarch, or1k_pc_in_sigtramp);
  set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub);
#endif
  set_gdbarch_do_registers_info (gdbarch, or1k_do_registers_info);
  return gdbarch;
}

void
_initialize_or1k_tdep ()
{
  build_automata ();
  register_gdbarch_init (bfd_arch_or32, or1k_gdbarch_init);

  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
    tm_print_insn = print_insn_big_or32;
  else
    tm_print_insn = print_insn_little_or32;
    
  /* Commands to show and set sprs.  */
  add_info ("spr", info_spr_command, "Show information about the spr registers.");
  add_com ("spr", class_support, spr_command, "Set specified SPR register.");

  add_htrace_commands ();

  /* Extra functions supported by simulator.  */
  add_com ("or1ksim", class_obscure, or1ksim_command,
	   "Send a extended command to the or1ksim simulator.");
}

/* Target-dependent code for the or1k architecture, for GDB, the GNU Debugger.

   Copyright 1988-1999, Free Software Foundation, Inc.
   Contributed by Alessandro Forin(af@cs.cmu.edu at CMU
   and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

#include <ctype.h>
#include "demangle.h"
#include "defs.h"
#include "gdb_string.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "value.h"
#include "gdbcmd.h"
#include "language.h"
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbtypes.h"
#include "target.h"
#include "regcache.h"
#include "osabi.h"
#include "arch-utils.h"

#include "opcode/or32.h"

/* *INDENT-OFF* */

static const char *compare_to_names[NUM_CT_NAMES] =
  {
    "DISABLED", "FETCH", "LEA", "SEA", "LDATA", "SDATA", "AEA", "ADATA"
  };

static const char *or1k_record_names[MAX_RECORD_NAMES] = 
  {
    "PC", "LSEA", "LDATA", "SDATA", "READSPR", "WRITESPR", "INSTR"
  };   

static const char *or1k_is_names[MAX_IS_NAMES] =
  {
    "IF_NONE", "IF_NORMAL", "IF_BRANCH", "IF_DELAY"
  };

static const char *or1k_ls_names[MAX_LS_NAMES] =
  {
    "LS_NONE", " ", "LBZ", "LBS", "LHZ", "LHS", "LWZ", "LWS",
    " ", " ", "SB", " ", "SH", " ", "SW", " "
  };

/* *INDENT-ON* */

/* The list of available "set or1k " and "show or1k " commands */
static struct cmd_list_element *htrace_cmdlist = NULL;
static struct cmd_list_element *htrace_mode_cmdlist = NULL;

struct htrace_struct or1k_htrace;
struct hwatch_struct or1k_hwatch[MAX_HW_WATCHES];
int num_hw_watches = 0;

/* Trace data.  */
char trace_filename[TRACE_FILENAME_SIZE] = "trace.dat";

/* Previous values for buffer display.  */
static int prev_length = 10;
static int prev_from = 0;

/* Size of trace file in records.  */
int trace_size = 0;

static union exp_element exp_error;

/* Parses compare variable and returns it into ct.  */

union exp_element *or1k_parse_ct (union exp_element *exp, int *ct)
{
  int i;
  if (exp->opcode != OP_INTERNALVAR)
    error ("Valid lvalue expected.");
  exp++;

  for (i = 1; i < NUM_CT_NAMES; i++)
    if (strcasecmp (compare_to_names[i], exp->internalvar->name) == 0) break;
 
  if (i >= NUM_CT_NAMES)
    error ("Invalid compare to operand.");
  *ct = i;
  exp++;

  if (exp->opcode != OP_INTERNALVAR)
    return &exp_error;
  exp++;
  return exp;
}

/* Parses compare value and returns it into cv.  */

union exp_element *or1k_parse_cv (union exp_element *exp, unsigned int *cv)
{
  switch (exp->opcode)
    {
    case UNOP_IND:
      exp++;
      exp = or1k_parse_cv (exp, cv);   
      *cv = or1k_fetch_word (*cv);
      break;
    case OP_LONG:
      exp += 2;
      *cv = exp->longconst;
      exp += 2;
      break;
    case OP_REGISTER:
      exp++;
      *cv = read_register (exp->longconst);
      exp += 2;
      break;
    default:
      error ("Value expected.");
    }
  return exp;
}

/* Parse conditional.
   Puts freshly allocated array of matchpoints into match.  */

union exp_element *
or1k_parse_cond (union exp_element *exp, struct matchpoint **match, int *nmatch)
{
  unsigned int ct;
  *match = (struct matchpoint *) malloc (sizeof (struct matchpoint));
  *nmatch = 1;
  switch (exp->opcode)
    {
    case BINOP_EQUAL:
      (*match)->dcr.cc = CC_EQUAL;
      break;
    case BINOP_NOTEQUAL:
      (*match)->dcr.cc = CC_NEQUAL;
      break;
    case BINOP_LESS:
      (*match)->dcr.cc = CC_LESS;
      break;
    case BINOP_GTR:
      (*match)->dcr.cc = CC_GREAT;
      break;
    case BINOP_LEQ:
      (*match)->dcr.cc = CC_LESSE;
      break;
    case BINOP_GEQ:
      (*match)->dcr.cc = CC_GREATE;
      break;
    case BINOP_BITWISE_AND:
      (*match)->dcr.cc = CC_MASKED;
      break;
    default:
      return &exp_error;
    }

  exp++;
  (*match)->dcr.dp = 1;
  (*match)->dcr.sc = 0;
  if (exp->opcode == OP_INTERNALVAR)
    {
      exp = or1k_parse_ct (exp, &ct);
      exp = or1k_parse_cv (exp, &(*match)->dvr);
    }
  else
    {
      exp = or1k_parse_cv (exp, &(*match)->dvr);
      exp = or1k_parse_ct (exp, &ct);
    }

  (*match)->dcr.ct = ct;
  (*match)->chain_type = CHAINING_NONE;
  (*match)->cause_breakpoint = 0;
  return exp;
}

/* Parses expression with && or || operators.
   Puts freshly allocated array of matchpoints into match.
   valid & 1: && is allowed,
   valid & 2: || is allowed.  */

union exp_element *
or1k_parse_any (union exp_element *exp, struct matchpoint **match, int *nmatch, int valid)
{
  union exp_element *tmp;
  int first_and_only = 0, first_or_only = 0;
  struct matchpoint *tmp_match1, *tmp_match2, *tmpm;
  int tmp_nmatch1, tmp_nmatch2, tmpn;

  switch (exp->opcode)
    {
    case BINOP_LOGICAL_AND:
      if (!(valid & 1))
	return &exp_error;
      exp++;

      /* Parse first argument.  */
      tmp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, 1);
      if (tmp == &exp_error)
	exp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, valid);
      else
	{
	  /* and_only successful */
	  exp = tmp;
	  first_and_only = 1;
	}
      if (exp == &exp_error)
	return &exp_error;

      /* Parse second argument.  */
      if (first_and_only)
	exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, valid);
      else
	exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, 1);

      if (exp == &exp_error)
	return &exp_error;

      if (first_and_only)
	{ 
	  /* Exchange structures, so that and_only is listed last.  */
	  struct matchpoint *tmpm = tmp_match1;
	  int tmpn = tmp_nmatch1;
	  tmp_match1 = tmp_match2;
	  tmp_nmatch1 = tmp_nmatch2;
	  tmp_match2 = tmpm;	  
	  tmp_nmatch2 = tmpn;
	}

      *nmatch = tmp_nmatch1 + tmp_nmatch2;
      *match = (struct matchpoint *)malloc (*nmatch * sizeof (struct matchpoint));
      memcpy (*match, tmp_match1, tmp_nmatch1 * sizeof (struct matchpoint));
      free (tmp_match1);
      tmp_match2[0].chain_type = CHAINING_AND;
      memcpy (*match + tmp_nmatch1, tmp_match2, tmp_nmatch2 * sizeof (struct matchpoint));
      free (tmp_match2);
      return exp;

    case BINOP_LOGICAL_OR:
      if (!(valid & 2))
	return &exp_error;
      exp++;

      /* Parse first argument.  */
      tmp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, 2);
      if (tmp == &exp_error)
	exp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, valid);
      else
	{
	  /* and_only successful */
	  exp = tmp;
	  first_or_only = 1;
	}
      if (exp == &exp_error)
	return &exp_error;
      
      /* Parse second argument.  */
      if (first_or_only)
	exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, valid);
      else
	exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, 2);

      if (exp == &exp_error)
	return &exp_error;

      if (first_or_only)
	{ 
	  /* Exchange structures, so that and_only is listed first.  */
	  struct matchpoint *tmpm = tmp_match1;
	  int tmpn = tmp_nmatch1;
	  tmp_match1 = tmp_match2;
	  tmp_nmatch1 = tmp_nmatch2;
	  tmp_match2 = tmpm;	  
	  tmp_nmatch2 = tmpn;
	}

      *nmatch = tmp_nmatch1 + tmp_nmatch2;
      *match = (struct matchpoint *)malloc (*nmatch * sizeof (struct matchpoint));
      memcpy (*match, tmp_match1, tmp_nmatch1 * sizeof (struct matchpoint));
      free (tmp_match1);
      tmp_match2[0].chain_type = CHAINING_OR;
      memcpy (*match + tmp_nmatch1, tmp_match2, tmp_nmatch2 * sizeof (struct matchpoint));
      free (tmp_match2);
      return exp;

    default:
      return or1k_parse_cond (exp, match, nmatch);
    }
}

/* Parses sequence of ||s.
   Puts freshly allocated array of matchpoints into match.  */

union exp_element *
or1k_parse_or (union exp_element *exp, struct matchpoint **match, int *nmatch, int set_break)
{ 
  struct matchpoint *tmp_match1, *tmp_match2;
  int tmp_nmatch1, tmp_nmatch2;

  switch (exp->opcode)
    {
    case BINOP_LOGICAL_OR:
      exp++;
      exp = or1k_parse_or (exp, &tmp_match1, &tmp_nmatch1, set_break);
      if (exp == &exp_error)
	return &exp_error;

      exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, 3);
      if (set_break)
	{
	  tmp_match1[tmp_nmatch1 - 1].cause_breakpoint = 1;
	  tmp_match2[tmp_nmatch2 - 1].cause_breakpoint = 1;
	}
      *nmatch = tmp_nmatch1 + tmp_nmatch2;
      *match = (struct matchpoint *)malloc (*nmatch * sizeof (struct matchpoint));
      memcpy (*match, tmp_match1, tmp_nmatch1 * sizeof (struct matchpoint));
      free (tmp_match1);
      memcpy (*match + tmp_nmatch1, tmp_match2, tmp_nmatch2 * sizeof (struct matchpoint));
      free (tmp_match2);
      return exp;

    default:
      return or1k_parse_any (exp, match, nmatch, 3);
      if (set_break)
	(*match)[*nmatch - 1].cause_breakpoint = 1;
    }
}

/* Prints single matchpoint from specified struct.  */

static void 
print_matchpoint_struct (struct matchpoint *mp)
{
  printf_filtered ("%-6s (%i) %u, ON=%i, chain_type=%i, cause break=%i\n", compare_to_names[mp->dcr.ct],
		   mp->dcr.cc, mp->dvr, mp->dcr.dp, mp->chain_type, mp->cause_breakpoint);
}

/* Build watchpoint (s) based on given structure.  */

static void
set_matchpoints (struct matchpoint *match, int nmatch)
{
  int i;
  debug_regs_changed = 1;
  sift_matchpoints ();
  for (i = 0; i < nmatch; i++)
    {
      int num = or1k_implementation.num_used_matchpoints;
      dcr[num] = match[i].dcr;
      dvr[num] = match[i].dvr;
      
      /* Set chaining bits.  */ 
      dmr1 &= ~(3 << (2 * num));
      dmr1 |= match[i].chain_type << (2 * num);
      
      /* Set watchpoint bits */
      dmr2 &= 1 << num;
      dmr2 |= match[i].cause_breakpoint << num;
      matchpoint_user_count[i]++;
      or1k_implementation.num_used_matchpoints++;
    }
}

/* Returns nonzero, if matchpoints [start .. start+nmatch-1] are
   equal to match record. */

static int
matchpoint_matches (int start, struct matchpoint *match, int nmatch)
{
  int i;
  if (nmatch + start >= or1k_implementation.num_matchpoints)
    return 0;
 
  for (i = 0; i < nmatch; i++)
    {
      int j = i + start;
   
      /* Everything exept cause breakpoint must match.  */
      if (dcr[j].dp != match[i].dcr.dp
	  || dcr[j].ct != match[i].dcr.ct
	  || dcr[j].cc != match[i].dcr.cc
	  || dcr[j].sc != match[i].dcr.sc
	  || dvr[j] != match[i].dvr
	  || match[i].chain_type != ((dmr1 >> (2 * j)) & 3))
	return 0;
    }
  return 1;
}

static void
hwatch_command (char *arg, int from_tty)
{
  struct expression *exp;
  int i, nfree, nmatch, remove = 0;
  struct matchpoint *match;

  if (arg == NULL)
    arg = "";
  if (strncasecmp ("remove ", arg, 7) == 0)
    {
      arg += 7;
      remove = 1;
    }

  /* Parse arguments.  */
  exp = parse_exp_1 (&arg, 0, 0);

#ifdef DEBUG
  dump_prefix_expression (exp, gdb_stdout, "expr1");
#endif  

  if (or1k_parse_or (&exp->elts[0], &match, &nmatch, 1) == &exp_error)
    error ("Watchpoint too complex.");

  for (i = 0; i < nmatch; i++)
    print_matchpoint_struct (&match[i]);
  
  if (remove)
    {
      int start = -1;
      int cleared = 0;

      if (num_hw_watches <= 0)
	error ("No extended hardware supported watchpoints present.");

      for (i = 0; i < num_hw_watches; i++)
	if (matchpoint_matches (or1k_hwatch[i].matchpoint_start, match, nmatch))
	  {
	    start = or1k_hwatch[i].matchpoint_start;
	    break;
	  }

      if (start < 0)
	error ("Watchpoint not found.");
      
      for (i = 0; i < nmatch; i++)
	{
	  int j = start + i;
	  if (--matchpoint_user_count[j] <= 0)
	    {
	      debug_regs_changed = 1;
	      memset (&dcr[j], 0, sizeof (dcr[j]));
	      or1k_implementation.num_used_matchpoints--;
	      cleared = 1;
	    }
	}
      if (!cleared)
	warning ("No matchpoint(s) freed. Resources are busy.");
    }
  else
    {
      if (num_hw_watches >= MAX_HW_WATCHES)
	error ("Number of watchpoints too large.");

      /* Now we have to find out if given prefix expression matches
	 our HW based support. It may take up to
	 or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints. */
      nfree = or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints;

      if (nmatch > nfree)
	error ("Not enough free matchpoint resources.");

      /* Build watchpoint(s) based on just built structure.  */
      or1k_hwatch[num_hw_watches].matchpoint_start = or1k_implementation.num_used_matchpoints;
      set_matchpoints (match, nmatch);
      num_hw_watches++;
      printf_unfiltered ("Watchpoint successfully allocated.\n");
    }
  free (match);
  free (exp);
}

static void
htrace_command (char *args, int from_tty)
{
  help_list (htrace_cmdlist, "htrace ", all_commands, gdb_stdout);
}

static void
htrace_mode_command (char *args, int from_tty)
{
  help_list (htrace_mode_cmdlist, "htrace mode ", all_commands, gdb_stdout);
}

static void
htrace_mode_contin_command (char *args, int from_tty)
{
  or1k_htrace.moder.contin = 1;
  printf_unfiltered ("Continuous trace mode set.\n");
}

static void
htrace_mode_suspend_command (char *args, int from_tty)
{
  or1k_htrace.moder.contin = 0;
  printf_unfiltered ("Suspend trace mode set.\n");
}

static void print_event_struct (struct htrace_event_struct *event, int stop)
{
  int i;
  if (event->operation == TRIGOP_ANY)
    if (stop)
      printf_filtered ("not active");
    else
      printf_filtered ("always active");
  else
    {
      char *comma;
      if (event->operation == TRIGOP_AND)
	comma = "&(";
      else
	comma = "|(";
      
      if (event->is_valid)
	{
	  printf_filtered ("%s%s", comma, or1k_is_names[event->is_trig]);
	  comma = ", ";
	}
      if (event->ls_valid)
	{
	  printf_filtered ("%s%s", comma, or1k_ls_names[event->ls_trig]);
	  comma = ", ";
	}
      if (event->bp_valid)
	{
	  printf_filtered ("%sbreak", comma);
	  comma = ", ";
	}
      if (event->wp_valid)
	for (i = 0; i < 11; i++)
	  if ((event->wp_trig >> i) & 1)
	    {
	      printf_filtered ("%sWP%i", comma, i);
	      comma = ", ";
	    }
      if (comma[0] == ',')
	printf_filtered (")");
      else
	printf_filtered ("not active");
    }
}

static void
print_record_struct (struct htrace_record_struct *record)
{
  int i;
  char *comma = "";
  for (i = 0; i < MAX_RECORD_NAMES; i++)
    {
      if ((record->rec >> i)&1)
	{
	  printf_filtered ("%s%s", comma, or1k_record_names[i]);
	  comma = ", ";
	}
    }
  if (!*comma)
    printf_unfiltered ("none");
}

static void
htrace_info_command (char *args, int from_tty)
{
  int i;
  printf_filtered ("Trace trigger: ");
  print_event_struct (&or1k_htrace.trig, 0);
  printf_filtered ("\nTrace qualifier: ");
  print_event_struct (&or1k_htrace.qual, 0);
  for (i = 0; i < MAX_MATCHPOINTS; i++)
    {
      printf_filtered ("\n WP%i records: ", i);
      print_record_struct (&or1k_htrace.recwp[i]);
    }
  printf_filtered ("\n BP records: ");
  print_record_struct (&or1k_htrace.recbp);
  printf_filtered ("\nTrace stop: ");
  print_event_struct (&or1k_htrace.stop, 1);
  printf_filtered ("\n");
}

/* Parses event from given string.
   Result is placed into event structure, and previously allocated
   resources are freed.  Parameter stop is nonzero, when we are parsing
   for stop criteria.  */

static void
parse_event (char *args, struct htrace_event_struct *event, int stop)
{
  int i, op_type = 0, was_last_op = 1, any = 0;

  /* Release previous resources.  */
  for (i = 0; i < MAX_MATCHPOINTS; i++)
    {
      if ((event->wp_trig << i) & 1)
	if (--matchpoint_user_count[i] <= 0)
	  {
	    memset (&dcr[i], 0, sizeof (dcr[i]));
	    debug_regs_changed = 1;
	    or1k_implementation.num_used_matchpoints--;
	  }
    }
 
  event->is_valid = event->is_trig = 0;
  event->ls_valid = event->ls_trig = 0;
  event->bp_valid = event->bp_trig = 0;
  event->wp_valid = event->wp_trig = 0;
  
  if (args == NULL)
    args = "";
  while (*args == ' ')
    args++;

  while (*args != '\0')
    {
      if (strncasecmp ("breakpoint", args, 10) == 0)
	{
	  if (!was_last_op)
	    error ("Syntax error.");
	  was_last_op = 0;
	  event->bp_valid = event->bp_trig = 1;
	}
      else if ((!stop && strncasecmp ("any", args, 3) == 0)
	       || (stop && strncasecmp ("none", args, 4) == 0))
	{
	  if (!was_last_op)
	    error ("Syntax error.");
	  was_last_op = 0;
	  any = 1;
	}
      else if (strncasecmp ("||", args, 2) == 0)
	{
	  if (op_type == TRIGOP_AND)
	    error ("Only one type of logical operator allowed at a time.");
	  op_type = TRIGOP_OR;
	  if (was_last_op)
	    error ("Syntax error.");
	  was_last_op = 1;
	  args += 2;
	}
      else if (strncasecmp ("&&", args, 2) == 0)
	{
	  if (op_type == TRIGOP_OR)
	    error ("Only one type of logical operator allowed at a time.");
	  op_type = TRIGOP_AND;
	  if (was_last_op)
	    error ("Syntax error.");
	  was_last_op = 1;
	  args += 2;
	}
      else
	{
	  int found = 0;
	  if (!was_last_op)
	    error ("Syntax error.");
	  was_last_op = 0;

	  /* Search through is and ls tables for a match.  */
	  for (i = 0; i < MAX_IS_NAMES; i++)
	    if (strncasecmp (args, or1k_is_names[i], strlen (or1k_is_names[i])) == 0)
	      {
		event->is_valid	= 1;
		event->is_trig = i;
		args +=  strlen (or1k_is_names[i]);
		found = 1;
		break;
	      }
	  if (!found)
	    {
	      for (i = 0; i < MAX_LS_NAMES; i++)
		if (strncasecmp (args, or1k_ls_names[i], strlen (or1k_ls_names[i])) == 0)
		  {
		    event->ls_valid = 1;
		    event->ls_trig = i;
		    args +=  strlen (or1k_ls_names[i]);
		    found = 1;
		    break;
		  }
	    }
	  if (!found)
	    {
	      /* No special name was found => parse expression.  */
	      struct expression *exp;
	      struct matchpoint *match;
	      int nmatch, nfree;

	      exp = parse_exp_1 (&args, 0, 0);

	      if (or1k_parse_any (&exp->elts[0], &match, &nmatch, 3) == &exp_error)
		error ("Expression too complex.");
	      for (i = 0; i < nmatch; i++)
		print_matchpoint_struct (&match[i]);

	      /* Now we have to find out if given prefix expression matches
		 our HW based support. It may take up to
		 or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints. */
	      nfree = or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints;
	      
	      if (nmatch > nfree)
		error ("Not enough free matchpoint resources.");
	      
	      /* Build matchpoint(s) based on just built structure.  */
	      set_matchpoints (match, nmatch);
	      event->wp_valid = 1;
	      event->wp_trig |= 1 << (or1k_implementation.num_used_matchpoints - 1);
	      printf_unfiltered ("Watchpoint successfully allocated.\n");
	      free (match);
	      free (exp);
	      found = 1;
	    }
	  if (!found)
	    warning ("Invalid event at '%s'", args);
	}
      while (*args == ' ') args++;
    }
  if (any)
    event->operation = TRIGOP_ANY;
  else
    {
      if (op_type == 0)
	op_type = TRIGOP_AND;
      event->operation = op_type;
    }
}

static void
htrace_trigger_command (char *args, int from_tty)
{
  parse_event (args, &or1k_htrace.trig, 0);
  printf_filtered ("Trace starts, when:\n");
  print_event_struct (&or1k_htrace.trig, 0);
  printf_filtered ("\n");
}

static void
htrace_qualifier_command (char *args, int from_tty)
{
  parse_event (args, &or1k_htrace.qual, 0);
  printf_filtered ("Trace records, when:\n");
  print_event_struct (&or1k_htrace.qual, 0);
  printf_filtered ("\n");
}

static void
htrace_stop_command (char *args, int from_tty)
{
  parse_event (args, &or1k_htrace.stop, 1);
  printf_filtered ("Trace stops, when:\n");
  print_event_struct (&or1k_htrace.stop, 1);
  printf_filtered ("\n");
}

static void
htrace_clear_records_command (char *args, int from_tty)
{
  int i, j, cleared = 0;

  /* Clear all. */
  for (i = 0; i < MAX_MATCHPOINTS; i++)
    {
      for (j = 0; j < MAX_MATCHPOINTS; j++)
	{
	  if ((or1k_htrace.wp_record_uses[i] << j) & 1)
	    if (--matchpoint_user_count[j] <= 0)
	    {
	      memset (&dcr[j], 0, sizeof (dcr[j]));
	      debug_regs_changed = 1;
	      cleared = 1;
	      or1k_implementation.num_used_matchpoints--;
	    }
	}
      or1k_htrace.wp_record_uses[i] = 0;
    }
  if (!cleared)
    warning ("No matchpoints freed. Resources are busy.");
}

/* Syntax: htrace record {data}* when {expr} */

static void
htrace_record_command (char *args, int from_tty)
{
  struct expression *exp;
  int i, nfree, nmatch, wp = -1;
  struct matchpoint *match;
  unsigned int recdata = 0;
  char *c;

  if (args == '\0')
    error ( "Please specify data to record, e.g.:\n"
	    "htrace record PC SDATA when $SEA == 100\n"
	    "htrace record when $SEA == 100 to remove record");

  for (i = 0; *args != '\0' && strncasecmp ("when ", args, 5); i++)
    {
      int j, found = 0;
      for (j = 0; j < MAX_RECORD_NAMES; j++)
	if (strncasecmp (args, or1k_record_names[j], strlen (or1k_record_names[j])) == 0)
	  {
	    recdata |= 1 << j;
	    found = 1;
	    break;
	  }
      if (!found)
	warning ("Invalid record data name at '%s'.", args);
      while (*args != ' ' && *args != '\0') args++;
      while (*args == ' ') args++;
    }
  
  if (strncasecmp ("when ", args, 5) != 0)
    if (*args == '\0')
      {
	warning ("Condition not set. Assuming breakpoint.");
	wp = -1;
      }
    else
      error ("Syntax error.");
  else
    {
      args += 5;
      if (strcasecmp ("breakpoint", args) == 0)
	wp = -1;
      else
	{
	  /* Parse arguments.  */
	  exp = parse_exp_1 (&args, 0, 0);
	  
#ifdef DEBUG
	  dump_prefix_expression (exp, gdb_stdout, "expr1");
#endif
	  if (or1k_parse_any (&exp->elts[0], &match, &nmatch, 3) == &exp_error)
	    error ("Expression too complex.");
	  
	  for (i = 0; i < nmatch; i++)
	    print_matchpoint_struct (&match[i]);
	
	  if (recdata)
	    {
	      /* Now we have to find out if given prefix expression matches
		 our HW based support. It may take up to
		 or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints. */
	      nfree = or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints;
	      
	      if (nmatch > nfree)
		error ("Not enough free matchpoint resources.");
	      
	      wp = or1k_implementation.num_used_matchpoints - 1;
	      or1k_htrace.wp_record_uses[wp] = 0;
	      for (i = or1k_implementation.num_used_matchpoints; i <= wp; i++)
		or1k_htrace.wp_record_uses[wp] |= 1 << i;
	      set_matchpoints (match, nmatch);	  
	    }
	  else
	    {
	      /* Remove record. */
	      int start = -1, cleared = 0;
	      
	      for (i = 0; i < MAX_MATCHPOINTS; i++)
		{
		  int mp_start = 0, j;
		  j = or1k_htrace.wp_record_uses[i];
		  while (j > 0 && (j & 1) == 0)
		    mp_start++;

		  if (matchpoint_matches (mp_start, match, nmatch))
		    {
		      start = mp_start;
		      or1k_htrace.wp_record_uses[i] = 0;
		      break;
		    }
		}
	      if (start < 0)
		error ("Record with such expression not found.");
		
	      for (i = 0; i < nmatch; i++)
		{
		  int j = i + start;
		  if (--matchpoint_user_count[j] <= 0)
		    {
		      memset (&dcr[j], 0, sizeof (dcr[j]));
		      debug_regs_changed = 1;
		      cleared = 1;
		    }
		}
	      if (!cleared)
		warning ("No matchpoint(s) freed.");
	    }
	}
    }

  /* If we reached this point we have matchpoints set, and wp
     holds the value of that watchpoint.  wp == -1, if breakpoint
     was specified.  */
  if (wp < 0)
    or1k_htrace.recbp.rec = recdata;
  else
    or1k_htrace.recwp[wp].rec = recdata;
 
  if (recdata)
    {
      printf_unfiltered ("Data");
      for (i = 0; i < MAX_RECORD_NAMES; i++)
	if ((recdata >> i) & 1)
	  printf_unfiltered (" %s,", or1k_record_names[i]);
    }
  else
    printf_unfiltered ("No data");
  if (wp < 0)
    printf_unfiltered (" will be recorded when breakpoint occurs\n");
  else
    printf_unfiltered (" will be recorded when watchpoint #%i occurs\n", wp);
}

static void
htrace_enable_command (char *args, int from_tty)
{
  or1k_htrace.moder.trace_enable = 1;
  printf_unfiltered ("HW Trace enabled.\n");
}

static void
htrace_disable_command (char *args, int from_tty)
{
  or1k_htrace.moder.trace_enable = 0;
  printf_unfiltered ("HW Trace disabled.\n");
}

static void
htrace_rewind_command (char *args, int from_tty)
{
  FILE *f;
  if (args != NULL && *args != '\0')
    strncpy (TRACE_FILENAME, args, TRACE_FILENAME_SIZE);

  /* Just empty it.  */
  if ((f = fopen (TRACE_FILENAME, "wb+")) == NULL)
    error ("Cannot open trace file.");
  fclose (f);
  printf_unfiltered ("Trace data cleared.\n");
}

static void
print_data_struct (unsigned int pos, struct htrace_data_struct *data)
{
  struct symbol *func;
  char *funname = NULL;
  
  if (data->type < 4)
    {
      /* Determine function name - copied from stack.c  */
      func = find_pc_function (data->data);
      if (func)
	{
	  struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (data->data);
	  if (msymbol != NULL
	      && (SYMBOL_VALUE_ADDRESS (msymbol)
		  > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
	    funname = SYMBOL_NAME (msymbol);
	  else
	    {
	      char *demangled;
	      funname = SYMBOL_NAME (func);
	      if (SYMBOL_LANGUAGE (func) == language_cplus)
		{
		  demangled = cplus_demangle (funname, DMGL_ANSI);
		  if (demangled == NULL)
		    funname = SYMBOL_SOURCE_NAME (func);
		}
	    }
	}
      else
	{
	  struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (data->data);
	  if (msymbol != NULL)
	    funname = SYMBOL_NAME (msymbol);
	}
    }

  printf_filtered ("%06X%c %-8s %08X", pos, data->valid ? '>' : ':',
		   or1k_record_names[data->type], data->data);
  if (funname)
    printf_filtered (" (%s)\n", funname);
  else
    printf_filtered ("\n");
}

/* Prints out trace buffer.  */

static void
htrace_print_command (char *args, int from_tty)
{
  int i, from = 0, length = prev_length;
  FILE *f;
  struct htrace_data_struct *td;

  if (args == NULL) args = "";
  while (*args == ' ') args++;
  if (*args == '\0')
    {
      /* We will display buffer further. */
      from = prev_from + prev_length;
    }
  else
    {
      /* Display buffer range.  */
      int numbers = 0;
      char *cnum = args;
      while (*args != ' ' && *args != '\0')
	args++;

      /* Any arguments?  */
      if (*args == '\0')
	numbers = 1;
      else
	{
	  *args = 0;
	  args++;
	  numbers = 2;
	}
      from = strtoul (cnum, &cnum, 0);
      if (*cnum != 0)
	error ("Invalid from value.");
      if (from < 0) from += trace_size;
      if (numbers == 2)
	{
	  while (*args == ' ') args++;
	  length = strtoul (cnum, &cnum, 0);
	  if (*args != 0)
	    error ("Invalid length value.");
	  if (length < 0)
	    {
	      from += length;
	      length = -length;
	    }
	}
    }
  
  if (from >= trace_size)
    from = trace_size - 1;
  if (from < 0)
    from = 0;
  if (from + length >= trace_size)
    length = trace_size - from;
  
  prev_length = length;
  prev_from = from;
  if (length == 0)
    error ("Nothing to print.");

  printf_filtered ("Trace buffer %06x:%06x (size = %i)\n", from, from + length - 1, length);
  if ((f = fopen (TRACE_FILENAME, "rb")) == NULL)
    error ("Cannot open trace file.");
  if (fseek (f, TRACE_DATA_SIZE * from, SEEK_SET))
    error ("Error reading trace file.");
  td = (struct htrace_data_struct *) malloc (TRACE_DATA_SIZE * length);
  length = fread (td, TRACE_DATA_SIZE, length, f);
  for (i = 0; i < length; i++)
    print_data_struct (from + i, &td[i]); 
  fclose (f);
}

/* Adds a group of hwatch commands to gdb */

void
add_htrace_commands ()
{
  /* hwatch command.  */
  add_com ("hwatch", class_breakpoint, hwatch_command, "Set hardware watch"
	   "point.\nExample: ($LEA == my_var)&&($LDATA < 50)||($SEA == my_"
	   "var)&&($SDATA >= 50).\nSee OR1k Architecture document for more"
	   " info.");

  /* htrace commands.  */
  add_prefix_cmd ("htrace", class_breakpoint, htrace_command,
		  "Group of commands for handling hardware assisted trace\n\n"
		  "See OR1k Architecture and gdb for or1k documents for more info.",
		  &htrace_cmdlist, "htrace ", 0, &cmdlist);
  add_cmd ("info", class_breakpoint, htrace_info_command, "Display information about HW trace.",
	   &htrace_cmdlist);
  add_alias_cmd ("i", "info", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("trigger", class_breakpoint, htrace_trigger_command, "Set starting criteria for trace.",
	   &htrace_cmdlist);
  add_alias_cmd ("t", "trigger", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("qualifier", class_breakpoint, htrace_qualifier_command, "Set acquisition qualifier for HW trace.",
	   &htrace_cmdlist);
  add_alias_cmd ("q", "qualifier", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("stop", class_breakpoint, htrace_stop_command, "Set HW trace stopping criteria.",
	   &htrace_cmdlist);
  add_alias_cmd ("s", "stop", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("record", class_breakpoint, htrace_record_command, "Sets data to be recorded when expression occurs.",
	   &htrace_cmdlist);
  add_alias_cmd ("r", "record", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("clear records", class_breakpoint, htrace_clear_records_command,
	   "Disposes all matchpoints used by records.", &htrace_cmdlist);
  add_cmd ("enable", class_breakpoint, htrace_enable_command, "Enables the HW trace.", &htrace_cmdlist);
  add_alias_cmd ("e", "enable", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("disable", class_breakpoint, htrace_disable_command, "Disables the HW trace.", &htrace_cmdlist);
  add_alias_cmd ("d", "disable", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("rewind", class_breakpoint, htrace_rewind_command, "Clears currently recorded trace data.\n"
	   "If filename is specified, new trace file is made and any newly collected data\n"
	   "will be written there.", &htrace_cmdlist);
  add_cmd ("print", class_breakpoint, htrace_print_command,
	   "Prints trace buffer, using current record configuration.\n"
	   "htrace print [<start> [<len>]]\n"
	   "htrace print"
	   , &htrace_cmdlist);
  add_alias_cmd ("p", "print", class_breakpoint, 1, &htrace_cmdlist);
  add_prefix_cmd ("mode", class_breakpoint, htrace_mode_command,
	   "Configures the HW trace.\n"
	   "htrace mode [continuous|suspend]"
	   , &htrace_mode_cmdlist, "htrace mode ", 0, &htrace_cmdlist);
  add_alias_cmd ("m", "mode", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("continuous", class_breakpoint, htrace_mode_contin_command,
	   "Set continuous trace mode.\n", &htrace_mode_cmdlist);
  add_cmd ("suspend", class_breakpoint, htrace_mode_suspend_command,
	   "Set suspend trace mode.\n", &htrace_mode_cmdlist);
}

/* Definitions to target GDB to or1k targets.
   Copyright 2001 Free Software Foundation, Inc.
   Contributed by Marko Mlinar, markom@opencores.org

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

#ifndef TM_OR1K_H
#define TM_OR1K_H

#define GDB_MULTI_ARCH 1

#ifndef TARGET_OR1K
#define TARGET_OR1K
#endif

#include "defs.h"
#include <inttypes.h>  /* CZ */

struct value;

struct struct_or1k_implementation
  {
    /* Implementation version.  */
    unsigned int VR;
    /* Units present.  */
    unsigned int UPR;
    /* Number of total available matchpoints in this implementation.  */
    unsigned int num_matchpoints;
    /* Number of currently used matchpoints.  */
    unsigned int num_used_matchpoints;
    /* Has watchpoint driven counters.  */
    int has_counters;
    /* Number of registers.  */
    unsigned int num_gpr_regs;
    unsigned int num_vfpr_regs;
    /* Is there any vf support?  */
    int vf_present;
 };

struct or1k_target_ops
  {
    /* Name this target type.  */
    char *to_shortname;

    /* Init target.  */
    void (*to_init) PARAMS ((const char *args));
    /* Destruct target.  */
    void (*to_done) PARAMS ((void));

    /* Read register.  
       Does not fail, places error no. in err instead or call error(), if fatal.  */
    ULONGEST (*to_read_reg) PARAMS ((unsigned int regno));
    /* Write register.  
       Does not fail, places error no. in err instead or call error(), if fatal.  */
    void (*to_write_reg) PARAMS ((unsigned int regno, ULONGEST value));
    
    /* Read a block...possibly more efficient than several isolated
       call to read_reg...worst case the same efficiency. Returns 0
       on success or errno if a failure occurred. */
    int (*to_read_block) PARAMS ((unsigned int regno, void* block, int nregs));

    /* Write a block...possibly more efficient than several isolated
       call to write_reg...worst case the same efficiency. Returns 0
       on success or errno if a failure occurred. */
    int (*to_write_block) PARAMS ((unsigned int regno, void* block, int nregs));
    
    /* Selects scan chain.  All register accesses are related to current scan chain.
       Does not fail, places error no. in err instead or call error(), if fatal.
       See jtag_chains enum.  */
    void (*to_set_chain) PARAMS ((int chain));
    
    /* Executes extended command on the target.  */
    void (*to_exec_command) PARAMS ((const char *args, int from_tty));
    
    /* Associated target_ops.  */
    struct target_ops *gdb_ops;
    /* Should be OPS_MAGIC. */
    int to_magic;
  };

/* Context stuff. */
#define CURRENT_CID (0)
#define MAX_CID     (15)

/* Instruction definitions. */
#define BRK_INSTR_STRUCT {0x21, 0x00, 0x00, 0x01}
#define BRK_INSTR (0x21000001)
#define NOP_INSTR (0x15000000)

/* Special purpose regisers.  */
#define SPR_GROUP_SIZE_BITS (11)
#define SPR_GROUP_SIZE (1 << SPR_GROUP_SIZE_BITS)
#define SPR_SYSTEM_GROUP (0)
#define SPR_DEBUG_GROUP (6)
#define SPR_GPR_START  (1024)
#define SPR_VFPR_START ((MAX_CID + 1) * MAX_GPR_REGS + SPR_GPR_START)
#define OR1K_NUM_SPR_GROUPS (12)

/* Define register values.  */
#define SPR_REG(group, index) (((group) << SPR_GROUP_SIZE_BITS) + (index))

#define VR_SPRNUM SPR_REG(SPR_SYSTEM_GROUP, 0)
#define UPR_SPRNUM SPR_REG(SPR_SYSTEM_GROUP, 1)
#define CPUCFGR_SPRNUM SPR_REG(SPR_SYSTEM_GROUP, 2)
#define DCFGR_SPRNUM SPR_REG(SPR_SYSTEM_GROUP, 7)
#define PC_SPRNUM SPR_REG(SPR_SYSTEM_GROUP, 16)
#define SR_SPRNUM SPR_REG(SPR_SYSTEM_GROUP, 17)
#define PPC_SPRNUM SPR_REG(SPR_SYSTEM_GROUP, 18)
#define CCR_SPRNUM(cid) SPR_REG(SPR_SYSTEM_GROUP, 4 + (cid))
#define EPCR_SPRNUM(cid) SPR_REG(SPR_SYSTEM_GROUP, 32 + (cid))
#define EPCR0_SPRNUM SPR_REG(SPR_SYSTEM_GROUP, 32)

#define DVR0_SPRNUM SPR_REG(SPR_DEBUG_GROUP, 0xee)
#define DCR0_SPRNUM SPR_REG(SPR_DEBUG_GROUP, 0xee)
#define DMR1_SPRNUM SPR_REG(SPR_DEBUG_GROUP, 16)
#define DMR2_SPRNUM SPR_REG(SPR_DEBUG_GROUP, 17)
#define DCWR0_SPRNUM SPR_REG(SPR_DEBUG_GROUP, 0xee)
#define DCWR1_SPRNUM SPR_REG(SPR_DEBUG_GROUP, 0xee)
#define DSR_SPRNUM SPR_REG(SPR_DEBUG_GROUP, 20)
#define DRR_SPRNUM SPR_REG(SPR_DEBUG_GROUP, 21)

#define ZERO_REGNUM (0)
#define SP_REGNUM (1)
#define FP_REGNUM (2)
#define A0_REGNUM (3)
#define A5_REGNUM (8)
#define LR_REGNUM (9)
#define RV_REGNUM (11)
#define VFA0_REGNUM (MAX_GPR_REGS + 0)
#define VFA5_REGNUM (MAX_GPR_REGS + 5)
#define VFRV_REGNUM (MAX_GPR_REGS + 6)
#define PC_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 0)
#define PS_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 1)
#define EPCR_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 2)
#define CCR_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 2)

/******** END OF ADDITIONS BY CZ ************/

extern int or1k_regnum_to_sprnum PARAMS ((int regno));
#define REGNUM_TO_SPRNUM(regno) (or1k_regnum_to_sprnum(regno))

/* Defines for SPR bits.  */
#define DMR1_ST    (0x00400000)

/* Changed by CZ 21/06/01 */
#define DRR_TE     (0x00002000)
#define DRR_SSE    (0x00001000)
#define DRR_SCE    (0x00000800)
#define DRR_RE     (0x00000400)
#define DRR_IME    (0x00000200)
#define DRR_DME    (0x00000100)
#define DRR_HPINTE (0x00000080)
#define DRR_IIE    (0x00000040)
#define DRR_AE     (0x00000020)
#define DRR_LPINTE (0x00000010)
#define DRR_IPFE   (0x00000008)
#define DRR_DPFE   (0x00000004)
#define DRR_BUSEE  (0x00000002)
#define DRR_RSTE   (0x00000001)

/* Number of matchpoints */
#define NUM_MATCHPOINTS (or1k_implementation.num_matchpoints)
#define MAX_MATCHPOINTS (8)

/* Number of machine GPR registers */
#define NUM_GPR_REGS (or1k_implementation.num_gpr_regs)
#define MAX_GPR_REGS (32)

/* Number of machine VF registers */
#define NUM_VF_REGS (or1k_implementation.num_vfpr_regs)
#define MAX_VF_REGS (32)

#define OR1K_NUM_REGS (MAX_GPR_REGS + MAX_VF_REGS + 3)

/* Size of stack entry - in bytes.  */
#define OR1K_STACK_ALIGN (OR1K_64BIT_IMPLEMENTATION ? (8) : (4))

/* Can act like a little or big endian.  */
#if !defined (TARGET_BYTE_ORDER_DEFAULT)
#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN
#define TARGET_BYTE_ORDER_SELECTABLE_P (1)
#endif

/* Size (in bytes) of registers.  */
#define OR1K_SPR_REGSIZE (4)
#define OR1K_VF_REGSIZE (8)
#define OR1K_GPR_REGSIZE ((OR1K_64BIT_IMPLEMENTATION) ? (8) : (4))
#define OR1K_VF_DOUBLE (0)

#define OR1K_IS_GPR(N) ((N) >= 0 && (N) < MAX_GPR_REGS)
#define OR1K_IS_VF(N) ((N) >= MAX_GPR_REGS && (N) < MAX_GPR_REGS + MAX_VF_REGS)

/* Is this implementation 64 or 32 bit. 
   WARNING: gdb or1k port is not yet prepared for 64b implementations!  */
#define OR1K_64BIT_IMPLEMENTATION 0

/* ABI uses R3 through R8 for args.  */
#define OR1K_LAST_ARG_REGNUM (A5_REGNUM)
#define OR1K_NUM_ARG_REGS (6)

/* ABI uses VFR0 through VFR5 for float args.  */
#define OR1K_LAST_FP_ARG_REGNUM (VFA5_REGNUM)
#define OR1K_NUM_FP_ARG_REGS (6)

/* Don't step over l.trap */
#define CANNOT_STEP_BREAKPOINT

extern int or1k_insert_breakpoint (CORE_ADDR addr, char *contents_cache);
#define target_insert_hw_breakpoint(addr, cache) or1k_insert_breakpoint (addr, cache)

extern int or1k_remove_breakpoint (CORE_ADDR addr, char *contents_cache);
#define target_remove_hw_breakpoint(addr, cache) or1k_remove_breakpoint (addr, cache)

/* Watchpoint support.  */
#define TARGET_HAS_HARDWARE_WATCHPOINTS

/* Use these macros for watchpoint insertion/deletion.  */
/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */
extern int or1k_insert_watchpoint PARAMS ((CORE_ADDR addr, int len, int type));
#define target_insert_watchpoint(addr, len, type) \
	or1k_insert_watchpoint (addr, len, type)

extern int or1k_remove_watchpoint PARAMS ((CORE_ADDR addr, int len, int type));
#define target_remove_watchpoint(addr, len, type) \
	or1k_remove_watchpoint (addr, len, type)

/* We need to remove watchpoints when stepping, else we hit them again! */
#define HAVE_NONSTEPPABLE_WATCHPOINT

extern int or1k_stopped_by_watchpoint PARAMS ((void));
#define STOPPED_BY_WATCHPOINT(w) or1k_stopped_by_watchpoint ()

extern int or1k_can_use_hardware_watchpoint PARAMS ((int bptype, int));
#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(bp_type, cnt, ot) \
  or1k_can_use_hardware_watchpoint(bp_type, cnt)


/* Catchpoint support.  */
/* HACK: how do we hook to signal namings otherwise? */
#include "target.h"
extern char *target_signal_to_string PARAMS ((enum target_signal));

/* Return the name (SIGHUP, etc.) for a signal.  */
extern const char *or1k_signal_to_name PARAMS ((enum target_signal));

/* Given a name (SIGHUP, etc.), return its signal.  */
extern enum target_signal or1k_signal_from_name PARAMS ((const char *));

#define NUM_OR1K_SIGNALS (14)

/* Is floating/vector unit present.  */
#define OR1K_VF_PRESENT (or1k_implementation.vf_present)

/* Maximum struct size, that is still stored onto stack.  */
#define OR1K_STRUCT_CONV_SIZE (8)

/* Stack must be aligned on 32-bit boundaries when synthesizing
   function calls. PUSH_ARGUMENTS will handle it. */

/* Return nonzero if instruction has delay slot */
extern int is_delayed PARAMS ((unsigned long));

/* Return non-zero if PC points to an instruction which will cause a step
   to execute both the instruction at PC and an instruction at PC+4.  */
extern int or1k_step_skips_delay PARAMS ((CORE_ADDR));
#define STEP_SKIPS_DELAY_P (1)
#define STEP_SKIPS_DELAY(pc) (or1k_step_skips_delay (pc))

/* Definitions and declarations used by or1k dependent files.  */
#define OR1K_INSTLEN 4		/* Length of an instruction */


/* Defined in remote-or1k.c */

/* Target state names.  */
extern const char *status_name[];

/* Target state.  */
enum target_status
  {
    TARGET_UNDEFINED,
    TARGET_CONNECTING,
    TARGET_DISCONNECTING,
    TARGET_RUNNING,
    TARGET_STOPPED
  };

/* Compare conditions for DCRx registers.  */ 
enum enum_compare_condition
  {
    CC_MASKED, CC_EQUAL, CC_LESS, CC_LESSE, CC_GREAT, CC_GREATE, CC_NEQUAL
  };

/* Compare operand to compare DVRx to.  */
enum enum_compare_to
  {
    CT_DISABLED, CT_FETCH, CT_LEA, CT_SEA, CT_LDATA, CT_SDATA, CT_AEA, CT_ADATA
  };

/* Matchpoint chaining types.  */ 
enum enum_chaining
  {
    CHAINING_NONE, CHAINING_AND, CHAINING_OR
  };

/* Names for cts.  */
#define NUM_CT_NAMES 8
extern const char *compare_to_names[NUM_CT_NAMES];

/* DRCx struct */
struct dcr_struct
  {
    enum enum_compare_to ct:3;
    unsigned int sc:1;
    enum enum_compare_condition cc:3;
    unsigned int dp:1;
  };

/* All data needed for a matchpoint.  */
struct matchpoint
  {
    struct dcr_struct dcr;
    unsigned int dvr;
    unsigned int chain_type;
    unsigned int cause_breakpoint;
  };

/* Trace related structures and data.  */
#define TRACE_FILENAME_SIZE (128)
extern char trace_filename[TRACE_FILENAME_SIZE];
#define TRACE_FILENAME (&trace_filename[0])
#define TRACE_DATA_SIZE (sizeof(struct htrace_data_struct))

struct htrace_data_struct
  {
    unsigned int unused:24;
    unsigned int data:32;
    unsigned int type:4;
    unsigned int reserved:3;
    unsigned int valid:1;
  };

enum enum_operation
  {
    TRIGOP_ANY, TRIGOP_OR, TRIGOP_AND
  };

struct htrace_event_struct
  {
    enum enum_operation operation:2;
    unsigned int reserved1:6;
    unsigned int is_valid:1;
    unsigned int is_trig:2;
    unsigned int ls_valid:1;
    unsigned int ls_trig:4;
    unsigned int reserved2:2;
    unsigned int bp_valid:1;
    unsigned int bp_trig:1;
    unsigned int wp_valid:1;
    unsigned int wp_trig:11;
  };

struct htrace_record_struct
  {
    unsigned int reserved:25;
    unsigned int rec:7;
  };

struct htrace_moder_struct
  {
    unsigned int reserved:29;
    unsigned int rec_sel_dep:1;
    unsigned int trace_enable:1;
    unsigned int contin:1;
  };

/* Number of records as defined in TAP.  */
#define NUM_RECORDS (8)

struct htrace_struct
  {
    /* Local copy of HW regs for trace.  */
    struct htrace_event_struct trig, qual, stop;
    struct htrace_record_struct recwp[MAX_MATCHPOINTS], recbp;
    struct htrace_moder_struct moder;
    /* Which matchpoints does record use?  Bitmask.  */ 
    unsigned int wp_record_uses[MAX_MATCHPOINTS];
  };

extern struct htrace_struct or1k_htrace;
extern int trace_size;

#define MAX_RECORD_NAMES 7
extern const char *or1k_record_names[MAX_RECORD_NAMES];
#define MAX_IS_NAMES 4
extern const char *or1k_is_names[MAX_IS_NAMES];
#define MAX_LS_NAMES 16
extern const char *or1k_ls_names[MAX_LS_NAMES];

/* Stuff for HW watches.  */
#define MAX_HW_WATCHES MAX_MATCHPOINTS

struct hwatch_struct
  {
    int matchpoint_start;
  };

extern int num_hw_watches; 
extern struct hwatch_struct or1k_hwatch[MAX_HW_WATCHES];

/* Possible errors are listed here.  */
enum enum_errors  /* modified <chris@asics.ws> CZ 24/05/01 */
{
  /* Codes > 0 are for system errors */

  ERR_NONE = 0,
  ERR_CRC = -1,
  ERR_MEM = -2,
  JTAG_PROXY_INVALID_COMMAND = -3,
  JTAG_PROXY_SERVER_TERMINATED = -4,
  JTAG_PROXY_NO_CONNECTION = -5,
  JTAG_PROXY_PROTOCOL_ERROR = -6,
  JTAG_PROXY_COMMAND_NOT_IMPLEMENTED = -7,
  JTAG_PROXY_INVALID_CHAIN = -8,
  JTAG_PROXY_INVALID_ADDRESS = -9,
  JTAG_PROXY_ACCESS_EXCEPTION = -10, /* Write to ROM */
  JTAG_PROXY_INVALID_LENGTH = -11,
  JTAG_PROXY_OUT_OF_MEMORY = -12,
};

/* All JTAG chains.  */
enum jtag_chains
  {
    SC_GLOBAL,      /* 0 Global BS Chain */
    SC_RISC_DEBUG,  /* 1 RISC Debug Interface chain */
    SC_RISC_TEST,   /* 2 RISC Test Chain */
    SC_TRACE,       /* 3 Trace Chain */
    SC_REGISTER,    /* 4 Register Chain */
    SC_WISHBONE,    /* 5 Wisbone Chain */
    SC_BLOCK        /* Block Chains */
  };

/* See JTAG documentation about these.  */
#define JI_SIZE (4)
enum jtag_instr
  {
    JI_EXTEST,
    JI_SAMPLE_PRELOAD,
    JI_IDCODE,
    JI_CHAIN_SELECT,
    JI_INTEST,
    JI_CLAMP,
    JI_CLAMPZ,
    JI_HIGHZ,
    JI_DEBUG,    
    JI_BYPASS = 0xF
  };

/* JTAG registers.  */
#define JTAG_MODER  (0x0)
#define JTAG_TSEL   (0x1)
#define JTAG_QSEL   (0x2)
#define JTAG_SSEL   (0x3)
#define JTAG_RISCOP (0x4)
#define JTAG_RECWP0 (0x10)
#define JTAG_RECBP0 (0x1b)


/* Current register values.  */
extern unsigned int dmr1;
extern unsigned int dmr2;
extern unsigned int dsr; 
extern unsigned int drr;

extern int matchpoint_user_count[MAX_MATCHPOINTS];

/* Current watchpoints.  */
extern unsigned int dvr[MAX_MATCHPOINTS];
extern struct dcr_struct dcr[MAX_MATCHPOINTS];
extern int debug_regs_changed;

/* Returns error name.  */
extern const char *or1k_err_name PARAMS ((int e));

/* Last error number.  */
extern int err;

extern struct struct_or1k_implementation or1k_implementation;
extern unsigned int or1k_fetch_instruction PARAMS ((CORE_ADDR addr));
extern void or1k_fetch_registers PARAMS ((int regno));

/* Sets register/memory regno to data.  */
extern void or1k_write_spr_reg PARAMS ((unsigned int regno, unsigned int data));

/* Sets register/memory regno to data.  */
extern unsigned int or1k_read_spr_reg PARAMS ((unsigned int regno));

/* Flushes or1k's pipeline.  */
extern void or1k_flush_pipeline PARAMS ((void));

/* Sifts unused matchpoints to higher indexses.  */
extern void sift_matchpoints ();

/* Issues or1ksim command */
extern void or1k_or1ksim_cmd PARAMS((const char *args, int from_tty));

/* Fetch a word from the target board.  All memory accesses to the
   remote board are word aligned.  */
extern unsigned int or1k_fetch_word (CORE_ADDR addr);

/* Adds a group of hwatch commands to gdb */
extern void add_htrace_commands ();

typedef enum {
  JTAG_COMMAND_READ = 1,
  JTAG_COMMAND_WRITE = 2,
  JTAG_COMMAND_BLOCK_READ = 3,
  JTAG_COMMAND_BLOCK_WRITE = 4,
  JTAG_COMMAND_CHAIN = 5,
} JTAG_proxy_protocol_commands;

/* Each transmit structure must begin with an integer
   which specifies the type of command. Information
   after this is variable. Make sure to have all information
   aligned properly. If we stick with 32 bit integers, it
   should be portable onto every platform. These structures
   will be transmitted across the network in network byte
   order.
*/

typedef struct {
  uint32_t command;
  uint32_t length;
  uint32_t address;
  uint32_t data_H;
  uint32_t data_L;
} jtag_proxy_write_message_t;

typedef struct {
  uint32_t command;
  uint32_t length;
  uint32_t address;
} jtag_proxy_read_message_t;

typedef struct {
  uint32_t command;
  uint32_t length;
  uint32_t address;
  int32_t  nregs;
  uint32_t data[1];
} jtag_proxy_block_write_message_t;

typedef struct {
  uint32_t command;
  uint32_t length;
  uint32_t address;
  int32_t  nregs;
} jtag_proxy_block_read_message_t;

typedef struct {
  uint32_t command;
  uint32_t length;
  uint32_t chain;
} jtag_proxy_chain_message_t;

/* The responses are messages specific, however convention
   states the first word should be an error code. Again,
   sticking with 32 bit integers should provide maximum
   portability. */

typedef struct {
  int32_t status;
} jtag_proxy_write_response_t;

typedef struct {
  int32_t status;
  uint32_t data_H;
  uint32_t data_L;
} jtag_proxy_read_response_t;
  
typedef struct {
  int32_t status;
} jtag_proxy_block_write_response_t;

typedef struct {
  int32_t status;
  int32_t nregs;
  uint32_t data[1];
  /* uint32_t data[nregs - 1] still unread */
} jtag_proxy_block_read_response_t;

typedef struct {
  int32_t status;
} jtag_proxy_chain_response_t;


#endif /* TM_OR1K_H */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]