diff packages/hal/mips/arch/current/src/mips-stub.c @ 10:d3fbcdfa1b2f ecos-sw-1999-05-29

Merge from eCos master repository on 1999-05-29-00:13:11-BST
author jlarmour
date Fri, 28 May 1999 16:43:09 +0000
parents ece80412419a
children 4741a3c3496a
line wrap: on
line diff
--- a/packages/hal/mips/arch/current/src/mips-stub.c
+++ b/packages/hal/mips/arch/current/src/mips-stub.c
@@ -27,6 +27,50 @@
 #include <cyg/hal/hal_arch.h>
 #include <cyg/hal/mips_opcode.h>
 
+typedef unsigned long t_inst;
+
+/*----------------------------------------------------------------------
+ * Asynchronous interrupt support
+ */
+
+static struct
+{
+  t_inst *targetAddr;
+  t_inst savedInstr;
+} asyncBuffer;
+
+/* Called to asynchronously interrupt a running program.
+   Must be passed address of instruction interrupted.
+   This is typically called in response to a debug port
+   receive interrupt.
+*/
+
+void
+install_async_breakpoint(void *epc)
+{
+  long gp_save;
+
+  /* This may be called from a separately linked program,
+     so we need to save and restore the incoming gp register
+     and setup our stub local gp register. 
+     Alternatively, we could skip this foolishness if we
+     compiled libstub with "-G 0". */
+
+  __asm__ volatile ( "move   %0,$28\n"
+		     ".extern _gp\n"
+		     "la     $28,_gp\n"
+		     : "=r" (gp_save) );
+
+  asyncBuffer.targetAddr = epc;
+  asyncBuffer.savedInstr = *(t_inst *)epc;
+  *(t_inst *)epc = *(t_inst *)_breakinst;
+  __instruction_cache(CACHE_FLUSH);
+  __data_cache(CACHE_FLUSH);
+
+  __asm__  volatile ( "move   $28,%0\n" :: "r"(gp_save) );
+}
+
+/*--------------------------------------------------------------------*/
 /* Given a trap value TRAP, return the corresponding signal. */
 
 int __computeSignal (unsigned int trap_number)
@@ -45,6 +89,15 @@ int __computeSignal (unsigned int trap_n
 
     case EXC_BP:
       /* Break point */
+      if (asyncBuffer.targetAddr != NULL)
+	{
+	  /* BP installed by serial driver to stop running program */
+	  *asyncBuffer.targetAddr = asyncBuffer.savedInstr;
+          __instruction_cache(CACHE_FLUSH);
+          __data_cache(CACHE_FLUSH);
+	  asyncBuffer.targetAddr = NULL;
+	  return SIGINT;
+	}
       return SIGTRAP;
 
     case EXC_OVF:
@@ -104,8 +157,6 @@ void set_pc (target_register_t pc)
 
 /* Saved instruction data for single step support.  */
 
-typedef unsigned long t_inst;
-
 static struct
 {
   t_inst *targetAddr;