Index: /trunk/source/lisp-kernel/arm-constants.h
===================================================================
--- /trunk/source/lisp-kernel/arm-constants.h	(revision 14964)
+++ /trunk/source/lisp-kernel/arm-constants.h	(revision 14965)
@@ -40,4 +40,10 @@
 #define nargs imm2
 #define allocbase temp0         /* while consing */
+
+/* Non-volatile pseudo node regs kept in s28-s31 */
+#define save0 28
+#define save1 29
+#define save2 30
+#define save3 31
 
 #define nbits_in_word 32
@@ -220,22 +226,4 @@
 
 
-/*
-  The GC also needs to know what a catch_frame looks like.
-*/
-
-typedef struct catch_frame {
-  LispObj header;
-  LispObj catch_tag;
-  LispObj link;
-  LispObj mvflag;
-  LispObj csp;
-  LispObj db_link;
-  LispObj regs[8];
-  LispObj xframe;
-  LispObj tsp_segment;
-} catch_frame;
-
-#define catch_frame_element_count ((sizeof(catch_frame)/sizeof(LispObj))-1)
-#define catch_frame_header make_header(subtag_catch_frame,catch_frame_element_count)
 
 typedef struct lisp_frame {
Index: /trunk/source/lisp-kernel/arm-constants.s
===================================================================
--- /trunk/source/lisp-kernel/arm-constants.s	(revision 14964)
+++ /trunk/source/lisp-kernel/arm-constants.s	(revision 14965)
@@ -65,4 +65,12 @@
 define(`pc',`r15')
 
+/* We can keep node values in some single-float registers.  By definition,
+   those registers aren't general-purpose, but copying between them and
+   GPRs may be faster than using the stack would be. */
+define(`save0',`s28')
+define(`save1',`s29')
+define(`save2',`s30')
+define(`save3',`s31')
+                                                
 nargregs = 3
                 
@@ -321,4 +329,5 @@
          _node(last_lisp_frame) /* from TCR */
          _node(code_vector)     /* of fn in lisp_frame, or 0 */
+         _field(nvrs,4*node_size)
 	_endstructf
 
@@ -658,9 +667,6 @@
 r15 = 15
 pc = 15
+                
         
-        
-/* Lisp code keeps 0.0 in fp_zero */
-define(`fp_zero',`f31')   /* a non-volatile reg as far as FFI is concerned. */
-define(`fp_s32conv',`f30')   /* for s32->fp conversion */
 	
 /* registers, as used in destrucuring-bind/macro-bind */
Index: /trunk/source/lisp-kernel/arm-exceptions.c
===================================================================
--- /trunk/source/lisp-kernel/arm-exceptions.c	(revision 14964)
+++ /trunk/source/lisp-kernel/arm-exceptions.c	(revision 14965)
@@ -610,4 +610,5 @@
 reset_lisp_process(ExceptionInformation *xp)
 {
+#if 0
   TCR *tcr = get_tcr(true);
   catch_frame *last_catch = (catch_frame *) ptr_from_lispobj(untag(tcr->catch_top));
@@ -618,4 +619,5 @@
 
   start_lisp(tcr, 1);
+#endif
 }
 
Index: /trunk/source/lisp-kernel/arm-gc.c
===================================================================
--- /trunk/source/lisp-kernel/arm-gc.c	(revision 14964)
+++ /trunk/source/lisp-kernel/arm-gc.c	(revision 14965)
@@ -1055,4 +1055,7 @@
 mark_xp(ExceptionInformation *xp)
 {
+#ifdef LINUX
+  void *find_vfp_info(ExceptionInformation *);
+#endif
   natural *regs = (natural *) xpGPRvector(xp);
   int r;
@@ -1070,9 +1073,23 @@
     mark_root((regs[r]));
   }
-
+#ifdef LINUX
+  {
+    LispObj *vfp_info = (LispObj *)find_vfp_info(xp);
+    int nvr;
+
+    if (vfp_info == NULL) {
+      Bug(NULL, "No VFP info in exception context!");
+    }
+    
+    for (nvr = save0;nvr <= save3;nvr++) {
+      mark_root(vfp_info[nvr]);
+    }
+  }
+#endif
 
 
   mark_pc_root(ptr_to_lispobj(xpPC(xp)));
   mark_pc_root(ptr_to_lispobj(xpLR(xp)));
+  
 }
 
@@ -1351,4 +1368,14 @@
   }
 
+#ifdef LINUX
+  {
+    void *find_vfp_info(ExceptionInformation *);
+    LispObj* nvrs = (LispObj *)find_vfp_info(xp);
+
+    for (r=save0;r<=save3;r++) {
+      update_noderef(&nvrs[r]);
+    }
+  }
+#endif
 
   update_locref((LispObj*) (&(xpPC(xp))));
Index: /trunk/source/lisp-kernel/arm-macros.s
===================================================================
--- /trunk/source/lisp-kernel/arm-macros.s	(revision 14964)
+++ /trunk/source/lisp-kernel/arm-macros.s	(revision 14965)
@@ -333,5 +333,5 @@
 */        
    
-define(`push_fprs',`
+define(`push_foreign_fprs',`
         __(movc16(imm0,make_header(8,subtag_double_float_vector)))
         __(mov imm1,#0)
@@ -340,28 +340,45 @@
 ')
 
+/* Save the lisp non-volatile FPRs. */
+define(`push_lisp_fprs',`
+        __(movc16(imm0,make_header(6,subtag_double_float_vector)))
+        __(mov imm1,#0)
+        __(fmdrr d7,imm0,imm1)
+        __(fstmfdd sp!,{d7-d13})
+')
+        
 /* Pop the non-volatile FPRs (d8-d15) from the stack-consed vector
    on top of the stack.  This loads the vector header
    into d7 as a side-effect. */
-define(`pop_fprs',`
+define(`pop_foreign_fprs',`
         __(fldmfdd sp!,{d7-d15})
 ')
 
-/* Reload the non-volatile FPRs (d8-d15) from the stack-consed vector
+/* Pop the lisp non-volatile FPRs */        
+define(`pop_lisp_fprs',`
+        __(fldmfdd sp!,{d7-d13})
+')
+
+/* Reload the non-volatile lisp FPRs (d8-d13) from the stack-consed vector
    on top of the stack, leaving the vector in place.  d7 winds up with
    a denormalized float in it, if anything cares. */
-define(`restore_fprs',`
-        __(fldmfdd $1,{d7-d15})
+define(`restore_lisp_fprs',`
+        __(fldmfdd $1,{d7-d13})
 ')                
 
 /* discard the stack-consed vector which contains a set of 8 non-volatile
    FPRs. */
-define(`discard_fprs',`
-        __(add sp,sp,#9*8)
+define(`discard_lisp_fprs',`
+        __(add sp,sp,#7*8)
 ')                        
         
 define(`mkcatch',`
         new_macro_labels()
-        __(push_fprs())
+        __(push_lisp_fprs())
 	__(build_lisp_frame(imm0))
+        __(movc16(imm0,make_header(catch_frame.element_count,subtag_u32_vector)))
+        __(mov imm1,#catch_frame.element_count<<word_shift)
+        __(dnode_align(imm1,imm1,node_size))
+        __(stack_allocate_zeroed_ivector(imm0,imm1))
         __(movc16(imm0,make_header(catch_frame.element_count,subtag_catch_frame)))
         __(movs temp2,fn)
@@ -373,7 +390,9 @@
         __(ldr arg_x,[rcontext,#tcr.db_link])
         __(ldr temp0,[rcontext,#tcr.xframe])
-        __(stmdb sp!,{imm0,imm1,imm2,arg_z,arg_x,temp0,temp1,temp2})
+        __(stmia sp,{imm0,imm1,imm2,arg_z,arg_x,temp0,temp1,temp2})
         __(add imm0,sp,#fulltag_misc)
         __(str imm0,[rcontext,#tcr.catch_top])
+        __(add imm0,imm0,#catch_frame.nvrs)
+        __(fstmias imm0,{save0-save3})
         __(add lr,lr,#4)
 ')	
Index: /trunk/source/lisp-kernel/arm-spentry.s
===================================================================
--- /trunk/source/lisp-kernel/arm-spentry.s	(revision 14964)
+++ /trunk/source/lisp-kernel/arm-spentry.s	(revision 14965)
@@ -2349,5 +2349,5 @@
 _spentry(progvrestore)
         __(skip_stack_vector(imm0,imm1,sp))
-        __(ldr imm0,[imm0,#lisp_frame.size+(9*8)+node_size]) /* 9*8 = size of saved FPR vector, with header */
+        __(ldr imm0,[imm0,#lisp_frame.size+(7*8)+node_size]) /* 7*8 = size of saved FPR vector, with header */
         __(cmp imm0,#0)
         __(unbox_fixnum(imm0,imm0))
@@ -2859,4 +2859,5 @@
         __(ldr arg_y,[rcontext,#tcr.last_lisp_frame])
         __(stmdb vsp!,{arg_y,arg_x,temp0,temp1,temp2})
+        __(fstmdbs vsp!,{save0-save3})
         __(str vsp,[rcontext,#tcr.save_vsp])
 /* There's a u32 vector on top of the stack ; its first data word points
@@ -2894,4 +2895,8 @@
         __(mov arg_x,#0)
         __(mov fn,#0)
+        __(fmsr save0,arg_z)
+        __(fcpys save1,save0)
+        __(fcpys save2,save0)
+        __(fcpys save3,save0)
         __(mov allocptr,#VOID_ALLOCPTR)
         __(mov rcontext,temp0)
@@ -2900,4 +2905,5 @@
         __(ldr allocptr,[rcontext,#tcr.save_allocptr])
         __(restore_lisp_frame(temp0))
+        __(fldmias vsp!,{save0-save3})
         __(ldmia vsp!,{arg_y,arg_x,temp0,temp1,temp2})
         __(str arg_y,[rcontext,#tcr.last_lisp_frame])
@@ -3107,4 +3113,5 @@
         __(orr imm0,imm0,#subtag_u32_vector)
         __(stmdb sp!,{imm0,imm2})
+        __(push_foreign_fprs())
         __(mov arg_x,#0)
         __(mov temp0,#0)
@@ -3114,4 +3121,8 @@
         __(mov fn,#0)
         __(ldr vsp,[rcontext,#tcr.save_vsp])
+        __(fmsr save0,arg_z)
+        __(fcpys save1,save0)
+        __(fcpys save2,save0)
+        __(fcpys save3,save0)        
         __(mov imm0,#TCR_STATE_LISP)
         __(str imm0,[rcontext,#tcr.valence])
@@ -3123,9 +3134,10 @@
         __(blx lr)
         __(str vsp,[rcontext,#tcr.save_vsp])
-        __(ldr imm1,[sp,#4])
+        __(ldr imm1,[sp,#(9*8)+4])
         __(str imm1,[rcontext,#tcr.last_lisp_frame])
         __(str allocptr,[rcontext,#tcr.save_allocptr])
         __(mov imm0,#TCR_STATE_FOREIGN)
         __(str imm0,[rcontext,#tcr.valence])
+        __(pop_foreign_fprs())
         __(ldr sp,[sp,#node_size*2])   /* drop the ivector that hides foreign stack contents and restore (possibly misaligned) sp */
         __(ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr})
@@ -3987,8 +3999,10 @@
         __(ldr imm0,[temp0,#catch_frame.link])
         __(str imm0,[rcontext,#tcr.catch_top])
+        __(add imm0,sp,#catch_frame.nvrs+fulltag_misc)
+        __(fldmias imm0,{save0-save3})
         __(ldr fn,[sp,#catch_frame.size+lisp_frame.savefn])
         __(ldr lr,[sp,#catch_frame.size+lisp_frame.savelr])
         __(add sp,sp,#catch_frame.size+lisp_frame.size)
-        __(pop_fprs())
+        __(pop_lisp_fprs())
         __(bx lr)
 _endfn(C(_throw_found))        
@@ -4019,5 +4033,5 @@
         __(ldreq vsp,[sp,#catch_frame.size+lisp_frame.savevsp])
         __(add sp,sp,#catch_frame.size+lisp_frame.size)
-        __(pop_fprs())
+        __(pop_lisp_fprs())
         __(b local_label(_nthrow1v_nextframe))
 local_label(_nthrow1v_do_unwind):
@@ -4026,4 +4040,8 @@
         /* Save our caller's LR and FN in the csp frame created by the unwind-  */
         /* protect.  (Clever, eh ?)  */
+	__(flds save0,[sp,#fulltag_misc+catch_frame.nvrs+(0*node_size)])
+	__(flds save1,[sp,#fulltag_misc+catch_frame.nvrs+(1*node_size)])
+	__(flds save2,[sp,#fulltag_misc+catch_frame.nvrs+(2*node_size)])
+	__(flds save3,[sp,#fulltag_misc+catch_frame.nvrs+(3*node_size)])
         __(add sp,sp,#catch_frame.size)
         /* We used to use a swp instruction to exchange the lr with
@@ -4055,5 +4073,5 @@
         __(mov fn,nfn)
         __(add temp0,temp0,#lisp_frame.size)
-        __(restore_fprs(temp0))
+        __(restore_lisp_fprs(temp0))
         __(str imm1,[rcontext,#tcr.unwinding])
         __(blx lr)
@@ -4064,5 +4082,5 @@
         __(add sp,sp,#4*node_size)
         __(restore_lisp_frame(imm0))
-        __(discard_fprs())
+        __(discard_lisp_fprs())
         __(b local_label(_nthrow1v_nextframe))
 local_label(_nthrow1v_done):
@@ -4111,5 +4129,5 @@
 local_label(nthrownv_skip):     
         __(add sp,sp,#catch_frame.size+lisp_frame.size)
-        __(pop_fprs())
+        __(pop_lisp_fprs())          
         __(b local_label(nthrownv_nextframe))                
 local_label(nthrownv_do_unwind):
@@ -4119,4 +4137,8 @@
         __(str arg_x,[rcontext,#tcr.xframe])
         __(str arg_z,[rcontext,#tcr.last_lisp_frame])
+	__(flds save0,[sp,#fulltag_misc+catch_frame.nvrs+(0*node_size)])
+	__(flds save1,[sp,#fulltag_misc+catch_frame.nvrs+(1*node_size)])
+	__(flds save2,[sp,#fulltag_misc+catch_frame.nvrs+(2*node_size)])
+	__(flds save3,[sp,#fulltag_misc+catch_frame.nvrs+(3*node_size)]) 
         __(add sp,sp,#catch_frame.size)
         __(add imm1,nargs,#node_size)
@@ -4152,5 +4174,5 @@
         __(ldr vsp,[arg_z,#lisp_frame.savevsp])
         __(add arg_z,arg_z,#lisp_frame.size)
-        __(restore_fprs(arg_z))
+        __(restore_lisp_fprs(arg_z))
         __(str imm1,[rcontext,#tcr.unwinding])
         __(mov fn,nfn)
@@ -4177,5 +4199,5 @@
         __(ldr lr,[sp,#lisp_frame.savelr])
         __(discard_lisp_frame())
-        __(discard_fprs())
+        __(discard_lisp_fprs())
         __(b local_label(nthrownv_nextframe))
 local_label(nthrownv_done):     
@@ -4370,12 +4392,19 @@
         __(orr imm0,imm0,#subtag_u32_vector)
         __(stmdb sp!,{imm0,imm2})
+        __(push_foreign_fprs())
+        __(fmsr save0,arg_z)
+        __(fcpys save1,save0)
+        __(fcpys save2,save0)
+        __(fcpys save3,save0)       
         __(mov imm0,#TCR_STATE_LISP)
         __(str imm0,[rcontext,#tcr.valence])
         __(ldr allocptr,[rcontext,#tcr.save_allocptr])
         __(bl toplevel_loop)
-        __(ldmia sp!,{imm0,imm1})
+        __(ldr imm1,[sp,#(9*8)+4])
         __(mov imm0,#TCR_STATE_FOREIGN)
         __(str imm1,[rcontext,#tcr.last_lisp_frame])
         __(str imm0,[rcontext,#tcr.valence])
+        __(pop_foreign_fprs())
+        __(add sp,sp,#2*node_size)
         __(mov imm0,#nil_value)
         __(ldr sp,[sp])
Index: /trunk/source/lisp-kernel/lisp-debug.c
===================================================================
--- /trunk/source/lisp-kernel/lisp-debug.c	(revision 14964)
+++ /trunk/source/lisp-kernel/lisp-debug.c	(revision 14965)
@@ -54,4 +54,53 @@
 #else
 char *kernel_svn_revision = "unknown";
+#endif
+
+#ifdef ARM
+#ifdef LINUX
+
+/* This stuff is buried in kernel headers.  Why ? */
+
+/* The uc_regspace field of a ucontext can contain coprocessor
+   info in structures whose first word is one of these magic
+   values; the structure list is terminated by something that's
+   not one of these magic values.
+
+   Good thinking! That'll make the mechanism easy to extend!
+   (In practice, a word of 0 seems to terminate the structure
+   list.)
+*/
+#define VFP_MAGIC		0x56465001
+#define IWMMXT_MAGIC		0x12ef842a
+#define CRUNCH_MAGIC		0x5065cf03
+
+
+struct user_vfp {
+	unsigned long long fpregs[32];
+	unsigned long fpscr;
+};
+
+struct user_vfp *
+find_vfp_info(ExceptionInformation *xp)
+{
+  char *p = (char *)(xp->uc_regspace);
+  unsigned *q, magic;
+
+  while (1) {
+    q = (unsigned *)p;                        
+    magic = *q;
+    if (magic == VFP_MAGIC) {
+      return (struct user_vfp *)(q+2);
+    }
+    if ((magic == CRUNCH_MAGIC) ||
+        (magic == IWMMXT_MAGIC)) {
+      p += q[1];
+    }
+    else {
+      return NULL;
+    }
+  }
+}
+
+#endif
 #endif
 
@@ -743,4 +792,17 @@
       show_lisp_register(xp, "temp1/fname/next_method_context", temp1);
       show_lisp_register(xp, "temp2/nfn", temp2);
+#ifdef LINUX
+      {
+        LispObj *nvrs = (LispObj *)find_vfp_info(xp);
+
+        if (nvrs != NULL) {
+          int r;
+
+          for(r=save0;r<=save3;r++) {
+            fprintf(dbgout,"s%02d (save%d) = %s\n",r,r-save0,print_lisp_object(nvrs[r]));
+          }
+        }
+      }
+#endif
     }
 #endif
@@ -1051,4 +1113,16 @@
 	    b, xpGPR(xp, b));
   }
+#ifdef LINUX
+  {
+    LispObj *nvrs = (LispObj *)find_vfp_info(xp);
+    
+    if (nvrs != NULL) {
+      for(a=save0,b=save2;a<save2;a++,b++) {
+        fprintf(dbgout,"s%02d = 0x%08lX    s%02d = 0x%08lX\n",
+                a, nvrs[a], b, nvrs[b]);
+      }
+    }
+  }
+#endif
 #endif
 
@@ -1056,52 +1130,4 @@
 }
 
-#ifdef ARM
-#ifdef LINUX
-
-/* This stuff is buried in kernel headers.  Why ? */
-
-/* The uc_regspace field of a ucontext can contain coprocessor
-   info in structures whose first word is one of these magic
-   values; the structure list is terminated by something that's
-   not one of these magic values.
-
-   Good thinking! That'll make the mechanism easy to extend!
-   (In practice, a word of 0 seems to terminate the structure
-   list.)
-*/
-#define VFP_MAGIC		0x56465001
-#define IWMMXT_MAGIC		0x12ef842a
-#define CRUNCH_MAGIC		0x5065cf03
-
-
-struct user_vfp {
-	unsigned long long fpregs[32];
-	unsigned long fpscr;
-};
-
-struct user_vfp *
-find_vfp_info(ExceptionInformation *xp)
-{
-  char *p = (char *)(xp->uc_regspace);
-  unsigned *q, magic;
-
-  while (1) {
-    q = (unsigned *)p;                        
-    magic = *q;
-    if (magic == VFP_MAGIC) {
-      return (struct user_vfp *)(q+2);
-    }
-    if ((magic == CRUNCH_MAGIC) ||
-        (magic == IWMMXT_MAGIC)) {
-      p += q[1];
-    }
-    else {
-      return NULL;
-    }
-  }
-}
-
-#endif
-#endif
 
 debug_command_return
@@ -1203,5 +1229,6 @@
     int dn,fn;
 
-    for (dn=0,fn=0;dn<16;dn++) {
+
+    for (dn=0,fn=0;dn<14;dn++) { /* d14/d15 (s28-s31) contain lisp values */
       fprintf(dbgout, "s%02d = %10e (0x%08x)        s%02d = %10e (0x%08x)\n",fn,fp[fn],up[fn],fn+1,fp[fn+1],up[fn+1]);
       fn+=2;
