diff --git a/lisp/breakpoint.c b/lisp/breakpoint.c
index cb9e84a55215e9f28e394145427b95a12d2137f9..06e6db9c096568bdeef73cc9811ad11db4dea198 100644
--- a/lisp/breakpoint.c
+++ b/lisp/breakpoint.c
@@ -1,6 +1,6 @@
 /*
 
- $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/breakpoint.c,v 1.6 1994/10/27 17:13:54 ram Exp $
+ $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/breakpoint.c,v 1.7 1997/11/25 15:53:30 dtc Exp $
 
  This code was written as part of the CMU Common Lisp project at
  Carnegie Mellon University, and has been placed in the public domain.
@@ -47,12 +47,13 @@ void breakpoint_remove(lispobj code_obj, int pc_offset,
 void breakpoint_do_displaced_inst(struct sigcontext *scp,
 				  unsigned long orig_inst)
 {
-#if !defined(hpux) && !defined(irix)
+#if !defined(hpux) && !defined(irix) && !defined(i386)
     undo_fake_foreign_function_call(scp);
 #endif
     arch_do_displaced_inst(scp, orig_inst);
 }
 
+#ifndef i386
 static lispobj find_code(struct sigcontext *scp)
 {
 #ifdef reg_CODE
@@ -71,6 +72,18 @@ static lispobj find_code(struct sigcontext *scp)
     return NIL;
 #endif
 }
+#endif
+
+#ifdef i386
+static lispobj find_code(struct sigcontext *scp)
+{
+  lispobj codeptr = component_ptr_from_pc(SC_PC(scp));
+
+  if (codeptr==NULL)
+    return NIL;
+  return (codeptr+type_OtherPointer);
+}
+#endif
 
 static int compute_offset(struct sigcontext *scp, lispobj code)
 {
@@ -101,15 +114,22 @@ static int compute_offset(struct sigcontext *scp, lispobj code)
 
 void handle_breakpoint(int signal, int subcode, struct sigcontext *scp)
 {
-    lispobj code;
+    lispobj code, scp_sap=alloc_sap(scp);
 
     fake_foreign_function_call(scp);
 
     code = find_code(scp);
+
+#ifdef i386
+    /* Don't disallow recursive breakpoint traps.  Otherwise, we can't */
+    /* use debugger breakpoints anywhere in here. */
+    sigsetmask(scp->sc_mask);
+#endif
+
     funcall3(SymbolFunction(HANDLE_BREAKPOINT),
 	     compute_offset(scp, code),
 	     code,
-	     alloc_sap(scp));
+	     scp_sap);
 
     undo_fake_foreign_function_call(scp);
 }
@@ -117,7 +137,7 @@ void handle_breakpoint(int signal, int subcode, struct sigcontext *scp)
 void *handle_function_end_breakpoint(int signal, int subcode,
 				     struct sigcontext *scp)
 {
-    lispobj code, lra;
+    lispobj code, lra, scp_sap=alloc_sap(scp);
     struct code *codeptr;
 
     fake_foreign_function_call(scp);
@@ -125,10 +145,16 @@ void *handle_function_end_breakpoint(int signal, int subcode,
     code = find_code(scp);
     codeptr = (struct code *)PTR(code);
 
+#ifdef i386
+    /* Don't disallow recursive breakpoint traps.  Otherwise, we can't */
+    /* use debugger breakpoints anywhere in here. */
+    sigsetmask(scp->sc_mask);
+#endif
+
     funcall3(SymbolFunction(HANDLE_BREAKPOINT),
 	     compute_offset(scp, code),
 	     code,
-	     alloc_sap(scp));
+	     scp_sap);
 
     lra = codeptr->constants[REAL_LRA_SLOT];
 #ifdef reg_CODE
@@ -138,5 +164,18 @@ void *handle_function_end_breakpoint(int signal, int subcode,
 
     undo_fake_foreign_function_call(scp);
 
+#ifdef i386
+    /* On the x86 the saved lra is a SAP; extract the return
+       address. */
+    if (!Pointerp(lra) || !(LowtagOf(lra)==type_OtherPointer))
+      fprintf(stderr,"* Return address not a SAP!\n");
+    {
+      struct sap *sap = (struct sap *)PTR(lra);
+      if (TypeOf(sap->header)!=type_Sap)
+	fprintf(stderr,"* Return address not a SAP!\n");
+      return (void *)(sap->pointer);
+    }
+#else
     return (void *)(lra-type_OtherPointer+sizeof(lispobj));
+#endif
 }
diff --git a/lisp/x86-arch.c b/lisp/x86-arch.c
index 4762c0a30270c0990e9f86da7c5c540dc5f7c237..4963d773dd82ffcc7fb32378e3e9233fbf5e4fee 100644
--- a/lisp/x86-arch.c
+++ b/lisp/x86-arch.c
@@ -79,9 +79,6 @@ struct sigcontext *context;
       /* Skip lisp error arg data bytes */
       while(vlen-- > 0) 
 	(char*)context->sc_pc++;
-      /* Align 2 */
-      /* (char*)context->sc_pc += 0x3;
-      context->sc_pc &= ~0x03; */
       break;
 
     case trap_Breakpoint:		/* Not tested */
@@ -94,7 +91,7 @@ struct sigcontext *context;
       break;
 
     default:
-      DPRINTF(1,(stderr,"[arch_skip_inst invalid code %d\n]\n",code));
+      fprintf(stderr,"[arch_skip_inst invalid code %d\n]\n",code);
       break;
     }
 
@@ -124,88 +121,117 @@ arch_set_pseudo_atomic_interrupted(struct sigcontext *context)
 unsigned long 
 arch_install_breakpoint(void *pc)
 {
-  char*ptr = (char*)pc;
-  unsigned long result = *(unsigned long*)ptr;
-  *ptr++ = BREAKPOINT_INST;		/* x86 INT3       */
-  *ptr++ = trap_Breakpoint;		/* Lisp trap code */
-  *ptr++ = 1;				/* vector length  */
-  *ptr++ = 0;				/* junk data      */
-  
-  os_flush_icache((os_vm_address_t)pc, sizeof(unsigned long));
+  unsigned long result = *(unsigned long*)pc;
 
+  *(char*)pc = BREAKPOINT_INST;		/* x86 INT3       */
+  *((char*)pc+1) = trap_Breakpoint;		/* Lisp trap code */
+  
   return result;
 }
 
 void 
 arch_remove_breakpoint(void *pc, unsigned long orig_inst)
 {
-  unsigned int *ptr=(unsigned int*)pc;
-  *ptr = orig_inst;
-  os_flush_icache((os_vm_address_t)pc, sizeof(unsigned long));
+  *((char *)pc) = orig_inst & 0xff;
+  *((char *)pc + 1) = (orig_inst & 0xff00) >> 8;
 }
 
-static unsigned int *skipped_break_addr, displaced_after_inst,
-     after_breakpoint;
-static int orig_sigmask;
-
-unsigned int
-emulate_branch(struct sigcontext *context,unsigned long orig_inst)
-{
-  /* This has to be invented for the X86. Maybe figure out how
-   * to use the trace trap. Shouldn't be hard. Gdb does it.
-   */
-  int next_pc = context->sc_pc;
-  return next_pc;
-}
 
 #ifdef __linux__
 _syscall1(int,sigreturn,struct sigcontext *,context)
 #endif
 
 
+/* When single stepping single_stepping holds the original instruction
+   pc location. */
+unsigned int *single_stepping=NULL;
+#ifndef __linux__
+unsigned int  single_step_save1;
+unsigned int  single_step_save2;
+unsigned int  single_step_save3;
+#endif
+
 void 
-arch_do_displaced_inst(struct sigcontext *context,
-				   unsigned long orig_inst)
+arch_do_displaced_inst(struct sigcontext *context, unsigned long orig_inst)
 {
-  /* Ditto the above for X86.
-   */
   unsigned int *pc = (unsigned int*)context->sc_pc;
-  unsigned int *next_pc;
-  unsigned int next_inst;
-  DPRINTF(0,(stderr,"[arch_do_displaced_inst %x %x NOT YET!]\n",
-	     context,orig_inst));
-  sigreturn(context);
+  unsigned int flags = context->sc_efl;
+
+  /* Put the original instruction back. */
+  *((char *)pc) = orig_inst & 0xff;
+  *((char *)pc + 1) = (orig_inst & 0xff00) >> 8;
+
+#ifdef __linux__
+  context->eflags |= 0x100;
+#else
+  /* Install helper instructions for the single step:
+     pushf; or [esp],0x100; popf. */
+  single_step_save1 = *(pc-3);
+  single_step_save2 = *(pc-2);
+  single_step_save3 = *(pc-1);
+  *(pc-3) = 0x9c909090;
+  *(pc-2) = 0x00240c81;
+  *(pc-1) = 0x9d000001;
+#endif
+
+  single_stepping=(unsigned int*)pc;
+
+#ifndef __linux__
+  (unsigned int*)context->sc_pc = ((char *)pc-9);
+#endif
 }
 
-#define AfterBreakpoint 100	/* pfw - what is this?? */
 
 void 
 sigtrap_handler(HANDLER_ARGS)
 {
+  unsigned int  trap;
+  
 #ifdef __linux__
   GET_CONTEXT
 #endif
+    /*
+    fprintf(stderr,"x86sigtrap: %8x %x\n",
+	    context->sc_pc, *(unsigned char *)(context->sc_pc-1));
+  fprintf(stderr,"sigtrap(%d %d %x)\n",signal,code,context);*/
 
-#ifdef __linux__
-    __setfpucw(contextstruct.fpstate->cw);
+  if (single_stepping && (signal==SIGTRAP))
+    {
+      /* fprintf(stderr,"* Single step trap %x\n", single_stepping); */
+
+#ifndef __linux__
+      /* Un-install single step helper instructions. */
+      *(single_stepping-3) = single_step_save1;
+      *(single_stepping-2) = single_step_save2;
+      *(single_stepping-1) = single_step_save3;
+#else  
+       context->eflags ^= 0x100;
 #endif
+      /* Re-install the breakpoint if possible. */
+      if ((int)context->sc_pc == (int)single_stepping + 1)
+	fprintf(stderr,"* Breakpoint not re-install\n");
+      else
+	{
+	  char*ptr = (char*)single_stepping;
+	  *((char *)single_stepping) = BREAKPOINT_INST;	/* x86 INT3 */
+	  *((char *)single_stepping+1) = trap_Breakpoint;
+	}
+
+      single_stepping=NULL;
+      return;
+    }
 
-  /*fprintf(stderr,"x86sigtrap: %8x %x\n", context->sc_pc, *(char*)(context->sc_pc-1));
-   */
-  DPRINTF(0,(stderr,"sigtrap(%d %d %x)\n",signal,code,context));
   SAVE_CONTEXT();
+
   /* this is just for info in case monitor wants to print an approx */
   current_control_stack_pointer = (unsigned long*)context->sc_sp;
+
  /* On entry %eip points just after the INT3 byte and aims at the
   * 'kind' value (eg trap_Cerror). For error-trap and Cerror-trap a
   * number of bytes will follow, the first is the length of the byte
   * arguments to follow.  */
-  if( *(unsigned char*)(context->sc_pc-1) == BREAKPOINT_INST)
-    {
-      if(after_breakpoint) code = AfterBreakpoint; /* ?? */
-      else code = (int)*(char*)context->sc_pc;
-    } 
-  switch (code)
+  trap = *(unsigned char *)(context->sc_pc);
+  switch (trap)
     {
     case trap_PendingInterrupt:
       DPRINTF(0,(stderr,"<trap Pending Interrupt.>\n"));
@@ -230,29 +256,18 @@ sigtrap_handler(HANDLER_ARGS)
 #endif
       break;
       
-    case trap_Breakpoint:		/* Not tested */
+    case trap_Breakpoint:
+      /*      fprintf(stderr,"*C break\n");*/
       (char*)context->sc_pc -= 1;
       handle_breakpoint(signal, code, context);
+      /*      fprintf(stderr,"*C break return\n");*/
       break;
       
-    case trap_FunctionEndBreakpoint:	/* not tested */
+    case trap_FunctionEndBreakpoint:
       (char*)context->sc_pc -= 1;
       context->sc_pc = (int)handle_function_end_breakpoint(signal, code, context);
       break;
       
-    case AfterBreakpoint:		/* not tested */
-      DPRINTF(1,(stderr,"[C--AfterBreakpoint NOT TESTED]\n"));
-      (char*)context->sc_pc -= 1;
-      *skipped_break_addr = BREAKPOINT_INST;
-      os_flush_icache((os_vm_address_t)skipped_break_addr,
-		      sizeof(unsigned long));
-      skipped_break_addr = NULL;
-      *(unsigned int *)context->sc_pc = displaced_after_inst;
-      os_flush_icache((os_vm_address_t)context->sc_pc, sizeof(unsigned long));
-      context->sc_mask = orig_sigmask;
-      after_breakpoint=NULL;
-      break;
-      
     default:
       DPRINTF(0,(stderr,"[C--trap default %d %d %x]\n",signal,code,context));
 #ifdef __linux__
diff --git a/lisp/x86-assem.S b/lisp/x86-assem.S
index 34ceea34fe2eeea96d97081c497ea7bb2194527a..eaed0c8b8d96cb564c951b17f145d82ae92f30f3 100644
--- a/lisp/x86-assem.S
+++ b/lisp/x86-assem.S
@@ -1,6 +1,6 @@
 ### x86-assem.S -*- Mode: Asm; -*-
 /**
- * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/x86-assem.S,v 1.5 1997/11/04 09:11:23 dtc Exp $
+ * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/x86-assem.S,v 1.6 1997/11/25 15:53:32 dtc Exp $
  *
  * Authors:	Paul F. Werkowski <pw@snoopy.mv.com>
  *		Douglas T. Crosher
@@ -311,10 +311,8 @@ Llra:
 	ret
 	.size	GNAME(call_into_lisp), . - GNAME(call_into_lisp)
 
-
-/* Fdefn objects for undefined functions have a 'raw' slot
-   pointing here. The RISC systems seem to have this set up
-   as an actual function object instead.
+/*
+ * The undefined-function trampoline.
  */
 	.text
 	.align	align_4byte,0x90
@@ -322,48 +320,61 @@ Llra:
 	.type	GNAME(undefined_tramp),@function
 GNAME(undefined_tramp):
 	int3
-	.byte	trap_Cerror
+	.byte	trap_Error
         .byte   2
         .byte   23
         .byte   sc_DescriptorReg # EAX in the Descriptor-reg SC.
 	ret
 	.size	GNAME(undefined_tramp), .-GNAME(undefined_tramp)
 
-/* This apparently gets called to hack on something in closures
-   that can't get done by the compiler.
-*/
-	.align align_4byte,0x90
+/*
+ * The closure trampoline.
+ */
+	.text
+	.align	align_4byte,0x90
 	.global GNAME(closure_tramp)
 	.type	GNAME(closure_tramp),@function
 GNAME(closure_tramp):
 	movl	FDEFN_FUNCTION_OFFSET(%eax),%eax
 	jmp	CLOSURE_FUNCTION_OFFSET(%eax)
-
 	.size	GNAME(closure_tramp), .-GNAME(closure_tramp)
 
-	.align align_4byte
-	.global GNAME(function_end_breakpoint_trap)
-	.global GNAME(function_end_breakpoint_end)
+/*
+ * Function-end breakpoint magic.
+ */
+	.text
 	.global	GNAME(function_end_breakpoint_guts)
-
-GNAME(function_end_breakpoint_trap):
-	ret
-	.align align_4byte
+	.align	align_4byte
 GNAME(function_end_breakpoint_guts):
-	ret
-	.align align_4byte
-GNAME(function_end_breakpoint_end):
-	ret
+	/* Multiple Value return */
+	jmp	multiple_value_return
+	/* Single value return */
+
+	/* The eventual return will now be a multi-value return so
+	   setup for it. Multi-value returns are not in general valid
+	   for one value so convert to 2 values. Perhaps the
+	   convertion should be changed? */
+	movl	$8,%ecx		# Setup ecx=2 for the debugger.
+	movl	$NIL,%edi	# Second value
+	movl	%esp,%ebx	# ebx has the ofp
+	subl	$8,%esp		# needed?
+		
+multiple_value_return:
+	
+	.global GNAME(function_end_breakpoint_trap)
+GNAME(function_end_breakpoint_trap):
+	int3
+	.byte 	trap_FunctionEndBreakpoint
 
-	.global	GNAME(test_point)
-	.align	align_4byte
-GNAME(test_point):
-	ret
+	/* Never returns here. */
+	.global GNAME(function_end_breakpoint_end)
+GNAME(function_end_breakpoint_end):
+	hlt
 
 
 	.global	GNAME(do_pending_interrupt)
 	.type	GNAME(do_pending_interrupt),@function
-	.align align_4byte,0x90
+	.align	align_4byte,0x90
 GNAME(do_pending_interrupt):
 	int3
 	.byte 	trap_PendingInterrupt