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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [verilog/] [vpi/] [c/] [gdb.c] - Rev 46

Go to most recent revision | Compare with Previous | Blame | View Log

/*$$HEADER*/
/******************************************************************************/
/*                                                                            */
/*                    H E A D E R   I N F O R M A T I O N                     */
/*                                                                            */
/******************************************************************************/
 
// Project Name                   : ORPSoCv2
// File Name                      : gdb.c
// Prepared By                    : jb, rmd
// Project Start                  : 2008-10-01
 
/*$$COPYRIGHT NOTICE*/
/******************************************************************************/
/*                                                                            */
/*                      C O P Y R I G H T   N O T I C E                       */
/*                                                                            */
/******************************************************************************/
/*
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; 
  version 2.1 of the License, a copy of which is available from
  http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
 
  This library 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
  Lesser General Public License for more details.
 
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
 
/*$$DESCRIPTION*/
/******************************************************************************/
/*                                                                            */
/*                           D E S C R I P T I O N                            */
/*                                                                            */
/******************************************************************************/
//
// Implements RSP comatible GDB stub
//
 
 
/*$$CHANGE HISTORY*/
/******************************************************************************/
/*                                                                            */
/*                         C H A N G E  H I S T O R Y                         */
/*                                                                            */
/******************************************************************************/
 
// Date		Version	Description
//------------------------------------------------------------------------
// 081101		Imported code from "jp" project			jb
// 090219               Adapted code from Jeremy Bennett's RSP server
//                      for the or1ksim project.                       rmb
// 090304               Finished RSP server code import, added extra
//                      functions, adding stability when debugging on
//                      a remote target.                                jb
// 090608               A few hacks for VPI compatibilty added          jb
// 090827               Fixed endianness, block accesses, byte writes.  jb
 
#ifdef CYGWIN_COMPILE
 
#else
// linux includes		   
#include <time.h>
#include <sched.h>
#endif
 
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
 
/* Libraries for JTAG proxy server.  */
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <signal.h>
#include <inttypes.h>
#include <errno.h>
#include <arpa/inet.h>
 
 
#ifndef DEBUG_GDB
#define DEBUG_GDB 0
#endif
 
#ifndef DEBUG_GDB_DUMP_DATA
#define DEBUG_GDB_DUMP_DATA 0
#endif
 
#ifndef DEBUG_GDB_BLOCK_DATA
#define DEBUG_GDB_BLOCK_DATA 0
#endif
 
#ifndef DEBUG_CMDS
#define DEBUG_CMDS 0
#endif
 
/*! Name of the Or1ksim RSP service */
#define OR1KSIM_RSP_SERVICE  "or1ksim-rsp"
 
#include "gdb.h" /* partially copied from gdb/config/or1k */
#include "rsp-rtl_sim.h"
 
#define MAX_GPRS    (32)
 
/* Indices of GDB registers that are not GPRs. Must match GDB settings! */
#define PPC_REGNUM  (MAX_GPRS + 0)	/*!< Previous PC */
#define NPC_REGNUM  (MAX_GPRS + 1)	/*!< Next PC */
#define SR_REGNUM   (MAX_GPRS + 2)	/*!< Supervision Register */
#define NUM_REGS    (MAX_GPRS + 3)	/*!< Total GDB registers */
 
/* OR1k CPU registers address */
#define NPC_CPU_REG_ADD  	0x10							/* Next PC */
#define SR_CPU_REG_ADD   	0x11							/* Supervision Register */
#define PPC_CPU_REG_ADD  	0x12							/* Previous PC */
#define DMR1_CPU_REG_ADD	((6 << 11) + 16)	/* Debug Mode Register 1 (DMR1) 0x3010 */
#define DMR2_CPU_REG_ADD	((6 << 11) + 17)	/* Debug Mode Register 2 (DMR2) 0x3011 */
#define DSR_CPU_REG_ADD		((6 << 11) + 20)	/* Debug Stop Register (DSR) 0x3014 */
#define DRR_CPU_REG_ADD  	((6 << 11) + 21)	/* Debug Reason Register (DRR) 0x3015 */
 
/*! Trap instruction for OR32 */
#define OR1K_TRAP_INSTR  0x21000001
 
/*! The maximum number of characters in inbound/outbound buffers.  The largest
    packets are the 'G' packet, which must hold the 'G' and all the registers
    with two hex digits per byte and the 'g' reply, which must hold all the
    registers, and (in our implementation) an end-of-string (0)
    character. Adding the EOS allows us to print out the packet as a
    string. So at least NUMREGBYTES*2 + 1 (for the 'G' or the EOS) are needed
    for register packets */
#define GDB_BUF_MAX  ((NUM_REGS) * 8 + 1)
 
/*! Size of the matchpoint hash table. Largest prime < 2^10 */
#define MP_HASH_SIZE  1021
 
/* Definition of special-purpose registers (SPRs). */
#define MAX_SPRS (0x10000)
 
#define SPR_DMR1_ST	  		0x00400000  /* Single-step trace*/
#define SPR_DMR2_WGB	   	0x003ff000  /* Watchpoints generating breakpoint */
#define SPR_DSR_TE				0x00002000  /* Trap exception */
 
#define WORDSBIGENDIAN_N
 
/* Definition of OR1K exceptions */
#define EXCEPT_NONE     0x0000
#define EXCEPT_RESET	0x0100
#define EXCEPT_BUSERR	0x0200
#define EXCEPT_DPF	0x0300
#define EXCEPT_IPF	0x0400
#define EXCEPT_TICK	0x0500
#define EXCEPT_ALIGN	0x0600
#define EXCEPT_ILLEGAL	0x0700
#define EXCEPT_INT	0x0800
#define EXCEPT_DTLBMISS	0x0900
#define EXCEPT_ITLBMISS	0x0a00
#define EXCEPT_RANGE	0x0b00
#define EXCEPT_SYSCALL	0x0c00
#define EXCEPT_FPE	0x0d00
#define EXCEPT_TRAP	0x0e00
 
// Changed to #defines from static const int's due to compile error
// DRR (Debug Reason Register) Bits
#define SPR_DRR_RSTE  0x00000001  //!< Reset
#define SPR_DRR_BUSEE 0x00000002  //!< Bus error
#define SPR_DRR_DPFE  0x00000004  //!< Data page fault
#define SPR_DRR_IPFE  0x00000008  //!< Insn page fault
#define SPR_DRR_TTE   0x00000010  //!< Tick timer
#define SPR_DRR_AE    0x00000020  //!< Alignment
#define SPR_DRR_IIE   0x00000040  //!< Illegal instruction
#define SPR_DRR_IE    0x00000080  //!< Interrupt
#define SPR_DRR_DME   0x00000100  //!< DTLB miss
#define SPR_DRR_IME   0x00000200  //!< ITLB miss
#define SPR_DRR_RE    0x00000400  //!< Range fault
#define SPR_DRR_SCE   0x00000800  //!< System call
#define SPR_DRR_FPE   0x00001000  //!< Floating point
#define SPR_DRR_TE    0x00002000  //!< Trap
 
 
/*! Definition of GDB target signals. Data taken from the GDB 6.8
    source. Only those we use defined here. The exact meaning of 
    signal number is defined by the header `include/gdb/signals.h'
    in the GDB source code. For an explanation of what each signal
    means, see target_signal_to_string.*/
enum target_signal {
  TARGET_SIGNAL_NONE =  0,
  TARGET_SIGNAL_INT  =  2,
  TARGET_SIGNAL_ILL  =  4,
  TARGET_SIGNAL_TRAP =  5,
  TARGET_SIGNAL_FPE  =  8,
  TARGET_SIGNAL_BUS  = 10,
  TARGET_SIGNAL_SEGV = 11,
  TARGET_SIGNAL_ALRM = 14,
  TARGET_SIGNAL_USR2 = 31,
  TARGET_SIGNAL_PWR  = 32
};
 
/*! String to map hex digits to chars */
static const char hexchars[]="0123456789abcdef";
 
 
//! Is the NPC cached?
 
//! Setting the NPC flushes the pipeline, so subsequent reads will return
//! zero until the processor has refilled the pipeline. This will not be
//! happening if the processor is stalled (as it is when GDB had control),
//! so we must cache the NPC. As soon as the processor is unstalled, this
//! cached value becomes invalid. So we must track the stall state, and if
//! appropriate cache the NPC.
enum stallStates {
  STALLED,
  UNSTALLED,
  UNKNOWN
} stallState;
 
int      npcIsCached;		//!< Is the NPC cached - should be bool
uint32_t  npcCachedValue;		//!< Cached value of the NPC
 
static int err = 0;
 
 
/************************
   JTAG Server Routines
************************/
int serverIP = 0;
int serverPort = 0;
int server_fd = 0;
int gdb_fd = 0;
 
static int tcp_level = 0;
 
/* global to store what chain the debug unit is currently connected to 
(not the JTAG TAP, but the onchip debug module has selected) */
int gdb_chain = -1;
 
/*! Data structure for RSP buffers. Can't be null terminated, since it may
  include zero bytes */
struct rsp_buf
{
  char  data[GDB_BUF_MAX];
  int   len;
};
 
/*! Enumeration of different types of matchpoint. These have explicit values
    matching the second digit of 'z' and 'Z' packets. */
enum mp_type {
  BP_MEMORY   = 0,		// software-breakpoint Z0  break 
  BP_HARDWARE = 1,		// hardware-breakpoint Z1  hbreak 
  WP_WRITE    = 2,		// write-watchpoint    Z2  watch  
  WP_READ     = 3,		// read-watchpoint     Z3  rwatch  
  WP_ACCESS   = 4			// access-watchpoint   Z4  awatch
};										
 
/*! Data structure for a matchpoint hash table entry */
struct mp_entry
{
  enum mp_type       type;		/*!< Type of matchpoint */
  uint32_t  addr;		/*!< Address with the matchpoint */
  uint32_t  instr;		/*!< Substituted instruction */
  struct mp_entry   *next;		/*!< Next entry with this hash */
};
 
/*! Central data for the RSP connection */
static struct
{
  int            		client_waiting;	/*!< Is client waiting a response? */
// Not used  int                proto_num;		/*!< Number of the protocol used */
  int                client_fd;		/*!< FD for talking to GDB */
  int               sigval;			/*!< GDB signal for any exception */
  uint32_t start_addr;	/*!< Start of last run */
  struct mp_entry   *mp_hash[MP_HASH_SIZE];	/*!< Matchpoint hash table */
} rsp;
 
/* Forward declarations of static functions */
static char *printTime(void);
static int gdb_read(void*, int);
static int gdb_write(void*, int);
static void ProtocolClean(int, int32_t);
static void GDBRequest(void);
static void rsp_interrupt();
static char rsp_peek();
static struct rsp_buf *get_packet (void);
static void rsp_init (void);
static void set_npc (uint32_t  addr);
static uint32_t get_npc();
static void rsp_check_for_exception();
static int check_for_exception_vector(uint32_t ppc);
static void rsp_exception (uint32_t  except);
static int get_rsp_char (void);
static int hex (int  c);
static void rsp_get_client (void);
static void rsp_client_request (void);
static void rsp_client_close (void);
static void client_close (char err);
static void	put_str_packet (const char *str);
static void rsp_report_exception (void);
static void put_packet (struct rsp_buf *p_buf);
static void send_rsp_str (unsigned char *data, int len);
static void rsp_query (struct rsp_buf *p_buf);
static void rsp_vpkt (struct rsp_buf *p_buf);
static void	rsp_step (struct rsp_buf *p_buf);
static void	rsp_step_with_signal (struct rsp_buf *p_buf);
static void	rsp_step_generic (uint32_t  addr, uint32_t  except);
static void rsp_continue (struct rsp_buf *p_buf);
static void	rsp_continue_with_signal (struct rsp_buf *p_buf);
static void	rsp_continue_generic (uint32_t  addr, uint32_t  except);
static void rsp_read_all_regs (void);
static void rsp_write_all_regs (struct rsp_buf *p_buf);
static void rsp_read_mem (struct rsp_buf *p_buf);
static void rsp_write_mem (struct rsp_buf *p_buf);
static void rsp_write_mem_bin (struct rsp_buf *p_buf);
static int rsp_unescape (char *data, int len);
static void rsp_read_reg (struct rsp_buf *p_buf);
static void rsp_write_reg (struct rsp_buf *p_buf);
static void mp_hash_init (void);
static void	mp_hash_add (enum mp_type type, uint32_t  addr, uint32_t  instr);
static struct mp_entry * mp_hash_lookup (enum mp_type type, uint32_t  addr);
static struct mp_entry * mp_hash_delete (enum mp_type type,	uint32_t  addr);
static void rsp_remove_matchpoint (struct rsp_buf *p_buf);
static void rsp_insert_matchpoint (struct rsp_buf *p_buf);
static void rsp_command (struct rsp_buf *p_buf);
static void rsp_set (struct rsp_buf *p_buf);
static void rsp_restart (void);
static void  ascii2hex (char *dest,char *src);
static void  hex2ascii (char *dest,	char *src);
static uint32_t hex2reg (char *p_buf);
static void	reg2hex (uint32_t  val, char *p_buf);
static void swap_buf(char* p_buf, int len);
static void set_stall_state (int state);
static void reset_or1k (void);
static void gdb_ensure_or1k_stalled();
static int gdb_set_chain(int chain);
static int gdb_write_byte(uint32_t adr, uint8_t data);
static int gdb_write_short(uint32_t adr, uint16_t data);
static int gdb_write_reg(uint32_t adr, uint32_t data);
static int gdb_read_reg(uint32_t adr, uint32_t *data);
static int gdb_write_block(uint32_t adr, uint32_t *data, int len);
static int gdb_read_block(uint32_t adr, uint32_t *data, int len);
 
char *printTime(void)
{
  time_t tid;
  struct tm *strtm; 
  static char timeBuf[20];
 
  time(&tid); 
  strtm = localtime(&tid);
  sprintf(timeBuf,"[%.02d:%.02d:%.02d] ",strtm->tm_hour,strtm->tm_min,strtm->tm_sec);
  return timeBuf;
}
/*---------------------------------------------------------------------------*/
/*!Set the serverPort variable
                                                                             */
/*---------------------------------------------------------------------------*/
 
void 
set_rsp_server_port(int portNum)
{
  serverPort = portNum;
}
 
/*---------------------------------------------------------------------------*/
/*!Initialize the Remote Serial Protocol connection
 
   Set up the central data structures.                                       */
/*---------------------------------------------------------------------------*/
void
rsp_init (void)
{
  /* Clear out the central data structure */
  rsp.client_waiting =  0;		/* GDB client is not waiting for us */
  rsp.client_fd      = -1;		/* i.e. invalid */
  rsp.sigval         = 0;		/* No exception */
  rsp.start_addr     = EXCEPT_RESET;	/* Default restart point */
 
  /* Set up the matchpoint hash table */
  mp_hash_init ();
 
  /* RSP always starts stalled as though we have just reset the processor. */
  rsp_exception (EXCEPT_TRAP);
 
  /* Setup the NPC caching variables */
  stallState = STALLED;
  // Force a caching of the NPC
  npcIsCached = 0;
  get_npc();
 
}	/* rsp_init () */
 
/*---------------------------------------------------------------------------*/
/*!Look for action on RSP
 
   This function is called when the processor has stalled, which, except for
   initialization, must be due to an interrupt.
 
   If we have no RSP client, we get one. We can make no progress until the
   client is available.
 
   Then if the cause is an exception following a step or continue command, and
   the exception not been notified to GDB, a packet reporting the cause of the
   exception is sent.
 
   The next client request is then processed.                                */
/*---------------------------------------------------------------------------*/
void
handle_rsp (void)
{
  uint32_t		temp_uint32;
 
  rsp_init();
 
  while (1){
    /* If we have no RSP client, wait until we get one. */
    while (-1 == rsp.client_fd)
      {
	rsp_get_client ();
	rsp.client_waiting = 0;		/* No longer waiting */
      }
 
    /* If we have an unacknowledged exception tell the GDB client. If this
       exception was a trap due to a memory breakpoint, then adjust the NPC. */
    if (rsp.client_waiting)
      {
 
	// Check for exception
	rsp_check_for_exception();
 
	if(stallState == STALLED)
	  // Get the PPC if we're stalled
	  gdb_read_reg(PPC_CPU_REG_ADD, &temp_uint32);
 
 
	if ((TARGET_SIGNAL_TRAP == rsp.sigval) && (NULL != mp_hash_lookup (BP_MEMORY, temp_uint32)))
	  {
	  if (stallState != STALLED)
	    // This is a quick fix for a strange situation seen in some of the simulators where
	    // the sw bp would be detected, but the stalled state variable wasn't updated correctly
	    // indicating that last time it checked, it wasn't set but the processor has now hit the
	    // breakpoint. So run rsp_check_for_exception() to bring everything up to date.
	    rsp_check_for_exception();
 
	  if(DEBUG_GDB) printf("Software breakpoint hit at 0x%08x. Rolling back NPC to this instruction\n", temp_uint32);
 
	  set_npc (temp_uint32);
 
	  rsp_report_exception();
	  rsp.client_waiting = 0;		/* No longer waiting */
	}
	else if(stallState == STALLED) {
	  // If we're here, the thing has stalled, but not because of a breakpoint we set
	  // report back the exception
 
	  rsp_report_exception();
	  rsp.client_waiting = 0;		/* No longer waiting */
 
	}	      
      }
 
    // See if there's any incoming data from the client by peeking at the socket
    if (rsp_peek() > 0)
      {
	if (rsp_peek() == 0x03 && (stallState != STALLED)) // ETX, end of text control char
	  {
	    // Got an interrupt command from GDB, this function should
	    // pull the packet off the socket and stall the processor.
	    // and then send a stop reply packet with signal TARGET_SIGNAL_NONE
	    rsp_interrupt();
	    rsp.client_waiting = 0;
	  }
	else if (rsp.client_waiting == 0)
	  {
	    // Default handling of data from the client:
	    /* Get a RSP client request */
	    rsp_client_request ();
	  }
      } /* end if (rsp_peek() > 0) */
 
  }
 
}   /* handle_rsp () */
 
 
/*
  Check if processor is stalled - if it is, read the DRR
  and return the target signal code
*/
static void rsp_check_for_exception()
{
 
  unsigned char stalled;
  uint32_t drr;
  err = dbg_cpu0_read_ctrl(0, &stalled);				 /* check if we're stalled */
 
  if (!(stalled & 0x01))
    {
      // Processor not stalled. Just return;
      return;
    }
 
  if (DEBUG_GDB) printf("rsp_check_for_exception() detected processor was stalled\nChecking DRR\n");
 
  // We're stalled
  stallState = STALLED;
  npcIsCached = 0;
 
  gdb_set_chain(SC_RISC_DEBUG);
 
  // Now read the DRR (Debug Reason Register)
  gdb_read_reg(DRR_CPU_REG_ADD, &drr);
 
  if (DEBUG_GDB) printf("DRR: 0x%08x\n", drr);
 
  switch ((int)(drr&0xffffffff))
    {
    case SPR_DRR_RSTE:  rsp.sigval = TARGET_SIGNAL_PWR;  break;
    case SPR_DRR_BUSEE: rsp.sigval = TARGET_SIGNAL_BUS;  break;
    case SPR_DRR_DPFE:  rsp.sigval = TARGET_SIGNAL_SEGV; break;
    case SPR_DRR_IPFE:  rsp.sigval = TARGET_SIGNAL_SEGV; break;
    case SPR_DRR_TTE:   rsp.sigval = TARGET_SIGNAL_ALRM; break;
    case SPR_DRR_AE:    rsp.sigval = TARGET_SIGNAL_BUS;  break;
    case SPR_DRR_IIE:   rsp.sigval = TARGET_SIGNAL_ILL;  break;
    case SPR_DRR_IE:    rsp.sigval = TARGET_SIGNAL_INT;  break;
    case SPR_DRR_DME:   rsp.sigval = TARGET_SIGNAL_SEGV; break;
    case SPR_DRR_IME:   rsp.sigval = TARGET_SIGNAL_SEGV; break;
    case SPR_DRR_RE:    rsp.sigval = TARGET_SIGNAL_FPE;  break;
    case SPR_DRR_SCE:   rsp.sigval = TARGET_SIGNAL_USR2; break;
    case SPR_DRR_FPE:   rsp.sigval = TARGET_SIGNAL_FPE;  break;
    case SPR_DRR_TE:    rsp.sigval = TARGET_SIGNAL_TRAP; break;
 
    default:
      // This must be the case of single step (which does not set DRR)
      rsp.sigval = TARGET_SIGNAL_TRAP; break;
    }
 
  if (DEBUG_GDB) printf("rsp.sigval: 0x%x\n", rsp.sigval);
 
  return;  
}
 
/*---------------------------------------------------------------------------*/
/*!Check if PPC is in an exception vector that halts program flow
 
Compare the provided PPC with known exception vectors that are fatal
to a program's execution. Call rsp_exception(ppc) to set the appropriate
sigval and return.
 
@param[in] ppc  Value of current PPC, as read from debug unit
@return: 1 if we set a sigval and should return control to GDB, else 0       */
/*---------------------------------------------------------------------------*/
static int 
check_for_exception_vector(uint32_t ppc)
{
  switch(ppc)
    {
      // The following should return sigvals to GDB for processing
    case EXCEPT_BUSERR:   
    case EXCEPT_ALIGN:    
    case EXCEPT_ILLEGAL:  
    case EXCEPT_TRAP:     if(DEBUG_GDB) 
	                    printf("PPC at exception address\n");
                          rsp_exception(ppc); 
			  return 1;
 
    default:
      return 0;
    }
  return 1; 
}
 
/*---------------------------------------------------------------------------*/
/*!Note an exception for future processing
 
   The simulator has encountered an exception. Record it here, so that a
   future call to handle_exception will report it back to the client. The
   signal is supplied in Or1ksim form and recorded in GDB form.
 
   We flag up a warning if an exception is already pending, and ignore the
   earlier exception.
 
   @param[in] except  The exception (Or1ksim form)                           */
/*---------------------------------------------------------------------------*/
void
rsp_exception (uint32_t  except)
{
  int  sigval;			/* GDB signal equivalent to exception */
 
  switch (except)
    {
    case EXCEPT_RESET:    sigval = TARGET_SIGNAL_PWR;  break;
    case EXCEPT_BUSERR:   sigval = TARGET_SIGNAL_BUS;  break;
    case EXCEPT_DPF:      sigval = TARGET_SIGNAL_SEGV; break;
    case EXCEPT_IPF:      sigval = TARGET_SIGNAL_SEGV; break;
    case EXCEPT_TICK:     sigval = TARGET_SIGNAL_ALRM; break;
    case EXCEPT_ALIGN:    sigval = TARGET_SIGNAL_BUS;  break;
    case EXCEPT_ILLEGAL:  sigval = TARGET_SIGNAL_ILL;  break;
    case EXCEPT_INT:      sigval = TARGET_SIGNAL_INT;  break;
    case EXCEPT_DTLBMISS: sigval = TARGET_SIGNAL_SEGV; break;
    case EXCEPT_ITLBMISS: sigval = TARGET_SIGNAL_SEGV; break;
    case EXCEPT_RANGE:    sigval = TARGET_SIGNAL_FPE;  break;
    case EXCEPT_SYSCALL:  sigval = TARGET_SIGNAL_USR2; break;
    case EXCEPT_FPE:      sigval = TARGET_SIGNAL_FPE;  break;
    case EXCEPT_TRAP:     sigval = TARGET_SIGNAL_TRAP; break;
 
    default:
      fprintf (stderr, "Warning: Unknown RSP exception %u: Ignored\n", except);
      return;
    }
 
  if ((0 != rsp.sigval) && (sigval != rsp.sigval))
    {
      fprintf (stderr, "Warning: RSP signal %d received while signal "
	       "%d pending: Pending exception replaced\n", sigval, rsp.sigval);
    }
 
  rsp.sigval         = sigval;		/* Save the signal value */
 
}	/* rsp_exception () */
 
 
/*---------------------------------------------------------------------------*/
/*!Get a new client connection.
 
   Blocks until the client connection is available.
 
   A lot of this code is copied from remote_open in gdbserver remote-utils.c.
 
   This involves setting up a socket to listen on a socket for attempted
   connections from a single GDB instance (we couldn't be talking to multiple
   GDBs at once!).
 
   The service is specified either as a port number in the Or1ksim configuration
   (parameter rsp_port in section debug, default 51000) or as a service name
   in the constant OR1KSIM_RSP_SERVICE.
 
   The protocol used for communication is specified in OR1KSIM_RSP_PROTOCOL. */
/*---------------------------------------------------------------------------*/
static void
rsp_get_client (void)
{
  int                 tmp_fd;		/* Temporary descriptor for socket */
  int                 optval;		/* Socket options */
  struct sockaddr_in  sock_addr;	/* Socket address */
  socklen_t           len;		/* Size of the socket address */
 
  /* 0 is used as the RSP port number to indicate that we should use the
     service name instead. */
  if (0 == serverPort)
  {
    struct servent *service = getservbyname (OR1KSIM_RSP_SERVICE, "tcp");
    if (NULL == service)
      {
	fprintf (stderr, "Warning: RSP unable to find service \"%s\": %s \n",
		 OR1KSIM_RSP_SERVICE, strerror (errno));
	return;
      }
    serverPort = ntohs (service->s_port);
  }
 
  /* Open a socket on which we'll listen for clients */
  tmp_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (tmp_fd < 0)
    {
      fprintf (stderr, "ERROR: Cannot open RSP socket\n");
      exit (0);
    }
 
  /* Allow rapid reuse of the port on this socket */
  optval = 1;
  setsockopt (tmp_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval,
	      sizeof (optval));
 
  /* Bind the port to the socket */
  sock_addr.sin_family      = PF_INET;
  sock_addr.sin_port        = htons (serverPort);
  sock_addr.sin_addr.s_addr = INADDR_ANY;
  if (bind (tmp_fd, (struct sockaddr *) &sock_addr, sizeof (sock_addr)))
    {
      fprintf (stderr, "ERROR: Cannot bind to RSP socket\n");
      exit (0);
    }
 
  /* Listen for (at most one) client */
  if (0 != listen (tmp_fd, 1))
    {
      fprintf (stderr, "ERROR: Cannot listen on RSP socket\n");
      exit (0);
    }
 
  printf("Waiting for gdb connection on localhost:%d\n", serverPort);
  fflush (stdout);
 
  printf("Press CTRL+c and type 'finish' to exit.\n");
  fflush (stdout);
 
  /* Accept a client which connects */
  len = sizeof (sock_addr);
  rsp.client_fd = accept (tmp_fd, (struct sockaddr *)&sock_addr, &len);
 
  if (-1 == rsp.client_fd)
  {
    fprintf (stderr, "Warning: Failed to accept RSP client\n");
    return;
  }
 
  /* Enable TCP keep alive process */
  optval = 1;
  setsockopt (rsp.client_fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval,
	      sizeof (optval));
 
  int flags;
 
  /* If they have O_NONBLOCK, use the Posix way to do it */
 
#if defined(O_NONBLOCK)
  /* Fixme: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */
  if (-1 == (flags = fcntl(rsp.client_fd, F_GETFL, 0)))
    flags = 0;
 
  fcntl(rsp.client_fd, F_SETFL, flags | O_NONBLOCK);
#else
  /* Otherwise, use the old way of doing it */
  flags = 1;
  ioctl(fd, FIOBIO, &flags);
#endif
 
 
 
  /* Set socket to be non-blocking */
 
  /* We do this because when we're given a continue, or step
     instruction,command we set the processor stall off, then instnatly check
     if it's stopped. If it hasn't then we drop through and wait for input
     from GDB. Obviously this will cause problems when it will stop after we
     do the check. So now, rsp_peek() has been implemented to simply check if
     there's an incoming command from GDB (only interested in interrupt
     commands), otherwise it returns back to and poll the processor's PPC and
     stall bit. It can only do this if the socket is non-blocking.
 
     At first test, simply adding this line appeared to give no problems with
     the existing code. No "simulation" of blocking behaviour on the
     non-blocking socket was required (in the event that a read/write throws
     back a EWOULDBLOCK error, as was looked to be the case in the previous
     GDB handling code) -- Julius
  */
  if (ioctl(rsp.client_fd, FIONBIO, (char *)&optval) > 0 )
    {
      perror("ioctl() failed");
      close(rsp.client_fd);
      close(tmp_fd);
      exit(0);
    }
 
 
  /* Don't delay small packets, for better interactive response (disable
     Nagel's algorithm) */
  optval = 1;
  setsockopt (rsp.client_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&optval,
	      sizeof (optval));
 
  /* Socket is no longer needed */
  close (tmp_fd);			/* No longer need this */
  signal (SIGPIPE, SIG_IGN);		/* So we don't exit if client dies */
 
  printf ("Remote debugging from host %s\n", inet_ntoa (sock_addr.sin_addr));
}	/* rsp_get_client () */
 
 
/*---------------------------------------------------------------------------*/
/*!Deal with a request from the GDB client session
 
   In general, apart from the simplest requests, this function replies on
   other functions to implement the functionality.                           */
/*---------------------------------------------------------------------------*/
static void rsp_client_request (void)
{
  struct rsp_buf *p_buf = get_packet ();	/* Message sent to us */
 
  // Null packet means we hit EOF or the link was closed for some other
  // reason. Close the client and return
  if (NULL == p_buf)
    {
      rsp_client_close ();
      return;
    }
 
  if (DEBUG_GDB){
    printf("%s-----------------------------------------------------\n", printTime());
    printf ("Packet received %s: %d chars\n", p_buf->data, p_buf->len );
    fflush (stdout);
  }
 
  switch (p_buf->data[0])
    {
    case '!':
      /* Request for extended remote mode */
      put_str_packet ("OK"); // OK = supports and has enabled extended mode.
      return;
 
    case '?':
      /* Return last signal ID */
      rsp_report_exception();
      return;
 
    case 'A':
      /* Initialization of argv not supported */
      fprintf (stderr, "Warning: RSP 'A' packet not supported: ignored\n");
      put_str_packet ("E01");
      return;
 
    case 'b':
      /* Setting baud rate is deprecated */
      fprintf (stderr, "Warning: RSP 'b' packet is deprecated and not "
	       "supported: ignored\n");
      return;
 
    case 'B':
      /* Breakpoints should be set using Z packets */
      fprintf (stderr, "Warning: RSP 'B' packet is deprecated (use 'Z'/'z' "
	       "packets instead): ignored\n");
      return;
 
    case 'c':
      /* Continue */
      rsp_continue (p_buf);
      return;
 
    case 'C':
      /* Continue with signal */
      rsp_continue_with_signal (p_buf);
      return;
 
    case 'd':
      /* Disable debug using a general query */
      fprintf (stderr, "Warning: RSP 'd' packet is deprecated (define a 'Q' "
	       "packet instead: ignored\n");
      return;
 
    case 'D':
      /* Detach GDB. Do this by closing the client. The rules say that
	 execution should continue. TODO. Is this really then intended
	 meaning? Or does it just mean that only vAttach will be recognized
	 after this? */
      put_str_packet ("OK");
      // In VPI disconnect everyone and exit
      rsp_client_close();
      client_close('0');
      dbg_client_detached();   // Send message to sim that the client detached
      exit(0);
      //reset_or1k ();
      //set_stall_state (0);
      return;
 
    case 'F':
      /* File I/O is not currently supported */
      fprintf (stderr, "Warning: RSP file I/O not currently supported: 'F' "
	       "packet ignored\n");
      return;
 
    case 'g':
      rsp_read_all_regs ();
      return;
 
    case 'G':
      rsp_write_all_regs (p_buf);
      return;
 
    case 'H':
      /* Set the thread number of subsequent operations. For now ignore
	    silently and just reply "OK" */
      put_str_packet ("OK");
      return;
 
    case 'i':
      /* Single instruction step */
      fprintf (stderr, "Warning: RSP cycle stepping not supported: target "
	       "stopped immediately\n");
      rsp.client_waiting = 1;			/* Stop reply will be sent */
      return;
 
    case 'I':
      /* Single instruction step with signal */
      fprintf (stderr, "Warning: RSP cycle stepping not supported: target "
	       "stopped immediately\n");
      rsp.client_waiting = 1;			/* Stop reply will be sent */
      return;
 
    case 'k':
      /* Kill request. Do nothing for now. */
      return;
 
    case 'm':
      /* Read memory (symbolic) */
      rsp_read_mem (p_buf);
      return;
 
    case 'M':
      /* Write memory (symbolic) */
      rsp_write_mem (p_buf);
      return;
 
    case 'p':
      /* Read a register */
      rsp_read_reg (p_buf);
      return;
 
    case 'P':
      /* Write a register */
      rsp_write_reg (p_buf);
      return;
 
    case 'q':
      /* Any one of a number of query packets */
      rsp_query (p_buf);
      return;
 
    case 'Q':
      /* Any one of a number of set packets */
      rsp_set (p_buf);
      return;
 
    case 'r':
      /* Reset the system. Deprecated (use 'R' instead) */
      fprintf (stderr, "Warning: RSP 'r' packet is deprecated (use 'R' "
	       "packet instead): ignored\n");
      return;
 
    case 'R':
      /* Restart the program being debugged. */
      rsp_restart ();
      return;
 
    case 's':
      /* Single step (one high level instruction). This could be hard without
			DWARF2 info */
      rsp_step (p_buf);
      return;
 
    case 'S':
      /* Single step (one high level instruction) with signal. This could be
			hard without DWARF2 info */
      rsp_step_with_signal (p_buf);
      return;
 
    case 't':
      /* Search. This is not well defined in the manual and for now we don't
	 		support it. No response is defined. */
      fprintf (stderr, "Warning: RSP 't' packet not supported: ignored\n");
      return;
 
    case 'T':
      /* Is the thread alive. We are bare metal, so don't have a thread
	 		context. The answer is always "OK". */
      put_str_packet ("OK");
      return;
 
    case 'v':
      /* Any one of a number of packets to control execution */
      rsp_vpkt (p_buf);
      return;
 
    case 'X':
      /* Write memory (binary) */
      rsp_write_mem_bin (p_buf);
      return;
 
    case 'z':
      /* Remove a breakpoint/watchpoint. */
      rsp_remove_matchpoint (p_buf);
      return;
 
    case 'Z':
      /* Insert a breakpoint/watchpoint. */
      rsp_insert_matchpoint (p_buf);
      return;
 
    default:
      /* Unknown commands are ignored */
      fprintf (stderr, "Warning: Unknown RSP request %s\n", p_buf->data);
      return;
    }
}	/* rsp_client_request () */
 
 
/*---------------------------------------------------------------------------*/
/*!Close the connection to the client if it is open                          */
/*---------------------------------------------------------------------------*/
static void
rsp_client_close (void)
{
  if (-1 != rsp.client_fd)
    {
      close (rsp.client_fd);
      rsp.client_fd = -1;
    }
}	/* rsp_client_close () */
 
 
/*---------------------------------------------------------------------------*/
/*!Send a packet to the GDB client
 
   Modeled on the stub version supplied with GDB. Put out the data preceded by
   a '$', followed by a '#' and a one byte checksum. '$', '#', '*' and '}' are
   escaped by preceding them with '}' and then XORing the character with
   0x20.
 
   @param[in] p_buf  The data to send                                          */
/*---------------------------------------------------------------------------*/
static void
put_packet (struct rsp_buf *p_buf)
{
  unsigned char  data[GDB_BUF_MAX * 2];
  int   len;
  int   ch;				/* Ack char */
 
  /* Construct $<packet info>#<checksum>. Repeat until the GDB client
     acknowledges satisfactory receipt. */
  do
  {
    unsigned char checksum = 0;	/* Computed checksum */
    int           count    = 0;	/* Index into the buffer */
 
    if (DEBUG_GDB_DUMP_DATA){
      printf ("Putting %s\n\n", p_buf->data);
      fflush (stdout);
    }
 
    len = 0;
    data[len++] =  '$';			/* Start char */
 
    /* Body of the packet */
    for (count = 0; count < p_buf->len; count++)
		{
		  unsigned char  ch = p_buf->data[count];
 
		  /* Check for escaped chars */
		  if (('$' == ch) || ('#' == ch) || ('*' == ch) || ('}' == ch))
		    {
		      ch       ^= 0x20;
		      checksum += (unsigned char)'}';
					data[len++] =  '}';
		    }
 
		  checksum += ch;
			data[len++] =  ch;
		}
 
		data[len++] =  '#';			/* End char */
 
    /* Computed checksum */
    data[len++] =	(hexchars[checksum >> 4]);
		data[len++] =	(hexchars[checksum % 16]);
 
		send_rsp_str ((unsigned char *) &data, len);
 
    /* Check for ack of connection failure */
    ch = get_rsp_char ();
    if (0 > ch)
		{
		  return;			/* Fail the put silently. */
		}
  }
  while ('+' != ch);
 
}	/* put_packet () */
 
 
/*---------------------------------------------------------------------------*/
/*!Convenience to put a constant string packet
 
   param[in] str  The text of the packet                                     */
/*---------------------------------------------------------------------------*/
static void
put_str_packet (const char *str)
{
  struct rsp_buf  buffer;
  int    len = strlen (str);
 
  /* Construct the packet to send, so long as string is not too big,
     otherwise truncate. Add EOS at the end for convenient debug printout */
 
  if (len >= GDB_BUF_MAX)
    {
      fprintf (stderr, "Warning: String %s too large for RSP packet: "
	       "truncated\n", str);
      len = GDB_BUF_MAX - 1;
    }
 
  strncpy (buffer.data, str, len);
  buffer.data[len] = 0;
  buffer.len       = len;
 
  put_packet (&buffer);
 
}	/* put_str_packet () */
 
 
/*---------------------------------------------------------------------------*/
/*!Get a packet from the GDB client
 
   Modeled on the stub version supplied with GDB. The data is in a static
   buffer. The data should be copied elsewhere if it is to be preserved across
   a subsequent call to get_packet().
 
   Unlike the reference implementation, we don't deal with sequence
   numbers. GDB has never used them, and this implementation is only intended
   for use with GDB 6.8 or later. Sequence numbers were removed from the RSP
   standard at GDB 5.0.
 
   @return  A pointer to the static buffer containing the data                */
/*---------------------------------------------------------------------------*/
static struct rsp_buf *
get_packet (void)
{
  static struct rsp_buf  buf;		/* Survives the return */
 
  /* Keep getting packets, until one is found with a valid checksum */
  while (1)
	{
		unsigned char checksum;		/* The checksum we have computed */
		int           count;			/* Index into the buffer */
		int 	     		ch;					/* Current character */
 
    /* Wait around for the start character ('$'). Ignore all other
	  characters */
    ch = get_rsp_char ();
 
    while (ch != '$')
		{
		  if (-1 == ch)
		    {
		      return  NULL;		/* Connection failed */
		    }
 
		  ch = get_rsp_char ();
 
		  // Potentially handle an interrupt character (0x03) here		  
		}
 
    /* Read until a '#' or end of buffer is found */
    checksum =  0;
    count    =  0;
    while (count < GDB_BUF_MAX - 1)
		{
		  ch = get_rsp_char ();
 
		  if(rsp.client_waiting && DEBUG_GDB)
		    {
		      printf("%x\n",ch);
		    }
 
 
		  /* Check for connection failure */
		  if (0 > ch)
		    {
		      return  NULL;
		    }
 
		  /* If we hit a start of line char begin all over again */
		  if ('$' == ch)
		    {
		      checksum =  0;
		      count    =  0;
 
		      continue;
		    }
 
		  /* Break out if we get the end of line char */
		  if ('#' == ch)
		    {
		      break;
		    }
 
		  /* Update the checksum and add the char to the buffer */
 
		  checksum        = checksum + (unsigned char)ch;
		  buf.data[count] = (char)ch;
		  count           = count + 1;
		}
 
    /* Mark the end of the buffer with EOS - it's convenient for non-binary
	  data to be valid strings. */
    buf.data[count] = 0;
    buf.len         = count;
 
    /* If we have a valid end of packet char, validate the checksum */
    if ('#' == ch)
		{
		  unsigned char  xmitcsum;	/* The checksum in the packet */
 
		  ch = get_rsp_char ();
		  if (0 > ch)
		    {
		      return  NULL;		/* Connection failed */
		    }
		  xmitcsum = hex (ch) << 4;
 
		  ch = get_rsp_char ();
		  if (0 > ch)
		    {
		      return  NULL;		/* Connection failed */
		    }
 
		  xmitcsum += hex (ch);
 
		  /* If the checksums don't match print a warning, and put the
		     negative ack back to the client. Otherwise put a positive ack. */
		  if (checksum != xmitcsum)
		    {
		      fprintf (stderr, "Warning: Bad RSP checksum: Computed "
			       "0x%02x, received 0x%02x\n", checksum, xmitcsum);
 
					ch = '-';
		      send_rsp_str ((unsigned char *) &ch, 1);	/* Failed checksum */
		    }
		  else
		    {
					ch = '+';
		      send_rsp_str ((unsigned char *) &ch, 1);	/* successful transfer */
		      break;
		    }
		}
    else
		{
		  fprintf (stderr, "Warning: RSP packet overran buffer\n");
		}
  }
  return &buf;				/* Success */
}	/* get_packet () */
 
 
/*---------------------------------------------------------------------------*/
/*!Put a single character out onto the client socket
 
   This should only be called if the client is open, but we check for safety.
 
   @param[in] c  The character to put out                                    */
/*---------------------------------------------------------------------------*/
static void
send_rsp_str (unsigned char *data, int len)
{
  if (-1 == rsp.client_fd)
    {
      fprintf (stderr, "Warning: Attempt to write '%s' to unopened RSP "
	       "client: Ignored\n", data);
      return;
    }
 
  /* Write until successful (we retry after interrupts) or catastrophic
     failure. */
  while (1)
    {
      switch (write (rsp.client_fd, data, len))
			{
			case -1:
			  /* Error: only allow interrupts or would block */
			  if ((EAGAIN != errno) && (EINTR != errno))
			    {
			      fprintf (stderr, "Warning: Failed to write to RSP client: "
				       "Closing client connection: %s\n",
				       strerror (errno));
			      rsp_client_close ();
			      return;
			    }
 
			  break;
 
			case 0:
			  break;		/* Nothing written! Try again */
 
			default:
			  return;		/* Success, we can return */
			}
    }
}	/* send_rsp_str () */
 
 
/*---------------------------------------------------------------------------*/
/*!Get a single character from the client socket
 
   This should only be called if the client is open, but we check for safety.
 
   @return  The character read, or -1 on failure                             */
/*---------------------------------------------------------------------------*/
static int
get_rsp_char ()
{
  if (-1 == rsp.client_fd)
    {
      fprintf (stderr, "Warning: Attempt to read from unopened RSP "
	       "client: Ignored\n");
      return  -1;
    }
 
  /* Non-blocking read until successful (we retry after interrupts) or
     catastrophic failure. */
  while (1)
    {
      unsigned char  c;
 
      switch (read (rsp.client_fd, &c, sizeof (c)))
	{
	case -1:
	  /* Error: only allow interrupts */
	  if ((EAGAIN != errno) && (EINTR != errno))
	    {
	      fprintf (stderr, "Warning: Failed to read from RSP client: "
		       "Closing client connection: %s\n",
		       strerror (errno));
	      rsp_client_close ();
	      return  -1;
	    }
 
	  break;
 
	case 0:
	  // EOF
	  rsp_client_close ();
	  return  -1;
 
	default:
	  return  c & 0xff; /* Success, we can return (no sign extend!) */
	}
    }
}	/* get_rsp_char () */
 
/*---------------------------------------------------------------------------*/
/* !Peek at data coming into server from GDB
 
   Useful for polling for ETX (0x3) chars being sent when GDB wants to
   interrupt
 
   @return the char we peeked, 0 otherwise                                   */
/*---------------------------------------------------------------------------*/
static char 
rsp_peek()
{
  /*
  if (-1 == rsp.client_fd)
    {
      fprintf (stderr, "Warning: Attempt to read from unopened RSP "
	       "client: Ignored\n");
      return  -1;
    }
  */
  char  c;
  int n;
  // Using recv here instead of read becuase we can pass the MSG_PEEK
  // flag, which lets us look at what's on the socket, without actually
  // taking it off
 
  //if (DEBUG_GDB) 
  //  printf("peeking at GDB socket...\n");
 
  n = recv (rsp.client_fd, &c, sizeof (c), MSG_PEEK);
 
  //if (DEBUG_GDB) 
  //  printf("peeked, got n=%d, c=0x%x\n",n, c);
 
  if (n > 0)
    return c;
  else
    return '\0';
 
}
 
/*---------------------------------------------------------------------------*/
/*!Handle an interrupt from GDB
 
 Detect an interrupt from GDB and stall the processor                        */
/*---------------------------------------------------------------------------*/
static void 
rsp_interrupt()
{
  unsigned char  c;
 
  if (read (rsp.client_fd, &c, sizeof (c)) <= 0)
    {
      // Had issues, just return
      return;
    }
 
  // Ensure this is a ETX control char (0x3), currently, we only call this
  // function when we've peeked and seen it, otherwise, ignore, return and pray
  // things go back to normal...
  if (c != 0x03)
    {
      printf("Warning: Interrupt character expected but not found on socket.\n");
      return;
    }
 
  // Otherwise, it's an interrupt packet, stall the processor, and upon return
  // to the main handle_rsp() loop, it will inform GDB.
 
  if (DEBUG_GDB) printf("Interrupt received from GDB. Stalling processor.\n");
 
  set_stall_state (1);
 
  // Send a stop reply response, manually set rsp.sigval to TARGET_SIGNAL_NONE
  rsp.sigval = TARGET_SIGNAL_NONE;
  rsp_report_exception();
  rsp.client_waiting = 0;		/* No longer waiting */  
 
  return;
 
}
 
 
/*---------------------------------------------------------------------------*/
/*!"Unescape" RSP binary data
 
   '#', '$' and '}' are escaped by preceding them by '}' and oring with 0x20.
 
   This function reverses that, modifying the data in place.
 
   @param[in] data  The array of bytes to convert
   @para[in]  len   The number of bytes to be converted
 
   @return  The number of bytes AFTER conversion                             */
/*---------------------------------------------------------------------------*/
static int
rsp_unescape (char *data,
	      int   len)
{
  int  from_off = 0;		/* Offset to source char */
  int  to_off   = 0;		/* Offset to dest char */
 
  while (from_off < len)
    {
      /* Is it escaped */
      if ( '}' == data[from_off])
			{
			  from_off++;
			  data[to_off] = data[from_off] ^ 0x20;
			}
		  else
			{
			  data[to_off] = data[from_off];
			}
 
      from_off++;
      to_off++;
    }
 
  return  to_off;
 
}	/* rsp_unescape () */
 
 
/*---------------------------------------------------------------------------*/
/*!Initialize the matchpoint hash table
 
   This is an open hash table, so this function clears all the links to
   NULL.                                                                     */
/*---------------------------------------------------------------------------*/
static void
mp_hash_init (void)
{
  int  i;
 
  for (i = 0; i < MP_HASH_SIZE; i++)
    {
      rsp.mp_hash[i] = NULL;
    }
}	/* mp_hash_init () */
 
 
/*---------------------------------------------------------------------------*/
/*!Add an entry to the matchpoint hash table
 
   Add the entry if it wasn't already there. If it was there do nothing. The
   match just be on type and addr. The instr need not match, since if this is
   a duplicate insertion (perhaps due to a lost packet) they will be
   different.
 
   @param[in] type   The type of matchpoint
   @param[in] addr   The address of the matchpoint
   @para[in]  instr  The instruction to associate with the address           */
/*---------------------------------------------------------------------------*/
static void
mp_hash_add (enum mp_type type,
	     uint32_t  addr,
	     uint32_t  instr)
{
  int              hv    = addr % MP_HASH_SIZE;
  struct mp_entry *curr;
 
  /* See if we already have the entry */
  for(curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next)
  {
    if ((type == curr->type) && (addr == curr->addr))
		{
		  return;		/* We already have the entry */
		}
  }
 
  /* Insert the new entry at the head of the chain */
  curr = (struct mp_entry*) malloc (sizeof (*curr));
 
  curr->type  = type;
  curr->addr  = addr;
  curr->instr = instr;
  curr->next  = rsp.mp_hash[hv];
 
  rsp.mp_hash[hv] = curr;
 
}	/* mp_hash_add () */
 
 
/*---------------------------------------------------------------------------*/
/*!Look up an entry in the matchpoint hash table
 
   The match must be on type AND addr.
 
   @param[in] type   The type of matchpoint
   @param[in] addr   The address of the matchpoint
 
   @return  The entry deleted, or NULL if the entry was not found            */
/*---------------------------------------------------------------------------*/
static struct mp_entry * mp_hash_lookup (enum mp_type type,	uint32_t addr)
{
  int    hv = addr % MP_HASH_SIZE;
  struct mp_entry *curr;
 
  /* Search */
  for (curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next)
  {
    if ((type == curr->type) && (addr == curr->addr))
		{
		  return  curr;		/* The entry found */