]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ppc/cswtch.s
xnu-344.12.2.tar.gz
[apple/xnu.git] / osfmk / ppc / cswtch.s
index d9ef060224f1f1807fd051f425ab0f64e5303381..14873039354c17371ababc5df269d0eb3423e8af 100644 (file)
@@ -30,6 +30,7 @@
 #include <debug.h>
 #include <mach/ppc/vm_param.h>
 #include <ppc/exception.h>
+#include <ppc/savearea.h>
 
 #define FPVECDBG 0
 #define GDDBG 0
  * otherwise both entry points are identical.
  */
 
-ENTRY2(load_context, Load_context, TAG_NO_FRAME_USED)
+                       .align  5
+                       .globl  EXT(load_context)
+
+LEXT(load_context)
+
+                       .globl  EXT(Load_context)
+
+LEXT(Load_context)
 
 /*
  * Since this is the first thread, we came in on the interrupt
  * stack. The first thread never returns, so there is no need to
* worry about saving its frame, hence we can reset the istackptr
e worry about saving its frame, hence we can reset the istackptr
  * back to the saved_state structure at it's top
  */
                        
@@ -63,29 +71,26 @@ ENTRY2(load_context, Load_context, TAG_NO_FRAME_USED)
        
                        mfsprg  r6,0
                        lwz             r0,PP_INTSTACK_TOP_SS(r6)
-                       lwz             r11,PP_CPU_DATA(r6)
                        stw             r0,PP_ISTACKPTR(r6)
-                       stw             r3,CPU_ACTIVE_THREAD(r11)
+                       stw             r3,PP_ACTIVE_THREAD(r6)
 
 /* Find the new stack and store it in active_stacks */
        
                        lwz             r12,PP_ACTIVE_STACKS(r6)
                        lwz             r1,THREAD_KERNEL_STACK(r3)
                        lwz             r9,THREAD_TOP_ACT(r3)                   /* Point to the active activation */
+                       mtsprg          1,r9
                        stw             r1,0(r12)
                        li              r0,0                                                    /* Clear a register */
                        lwz             r8,ACT_MACT_PCB(r9)                             /* Get the savearea used */
-                       lwz             r10,SAVflags(r8)                                /* Get the savearea flags */
                        rlwinm  r7,r8,0,0,19                                    /* Switch to savearea base */
                        lwz             r11,SAVprev(r8)                                 /* Get the previous savearea */
                        mfmsr   r5                                                              /* Since we are passing control, get our MSR values */
                        lwz             r1,saver1(r8)                                   /* Load new stack pointer */
-                       rlwinm  r10,r10,0,1,31                                  /* Remove the attached flag */
                        stw             r0,saver3(r8)                                   /* Make sure we pass in a 0 for the continuation */
                        lwz             r7,SACvrswap(r7)                                /* Get the translation from virtual to real */
                        stw             r0,FM_BACKPTR(r1)                               /* zero backptr */
                        stw             r5,savesrr1(r8)                                 /* Pass our MSR to the new guy */
-                       stw             r10,SAVflags(r8)                                /* Pass back the flags */
                        xor             r3,r7,r8                                                /* Get the physical address of the new context save area */
                        stw             r11,ACT_MACT_PCB(r9)                    /* Unstack our savearea */
                        b               EXT(exception_exit)                             /* Go end it all... */
@@ -102,10 +107,14 @@ ENTRY2(load_context, Load_context, TAG_NO_FRAME_USED)
 /* void Call_continuation( void (*continuation)(void),  vm_offset_t stack_ptr)
  */
 
-ENTRY(Call_continuation, TAG_NO_FRAME_USED)
-       mtlr    r3
-       mr      r1, r4          /* Load new stack pointer */
-       blr                     /* Jump to the continuation */
+                       .align  5
+                       .globl  EXT(Call_continuation)
+
+LEXT(Call_continuation)
+
+                       mtlr    r3
+                       mr              r1, r4                                                  /* Load new stack pointer */
+                       blr                                                                             /* Jump to the continuation */
 
 /*
  * Get the old kernel stack, and store into the thread structure.
@@ -129,45 +138,59 @@ ENTRY(Call_continuation, TAG_NO_FRAME_USED)
  */
 
 
-ENTRY(Switch_context, TAG_NO_FRAME_USED)
+                       .align  5
+                       .globl  EXT(Switch_context)
 
-                       mfsprg  r6,0                                                    /* Get the per_proc block */
-                       lwz             r12,PP_ACTIVE_STACKS(r6)
+LEXT(Switch_context)
+
+                       mfsprg  r12,0                                                   ; Get the per_proc block
+                       lwz             r10,PP_ACTIVE_STACKS(r12)               ; Get the pointer to the current stack
 #if DEBUG
-                       lwz             r11,PP_ISTACKPTR(r6)                    ; (DEBUG/TRACE) make sure we are not
+                       lwz             r11,PP_ISTACKPTR(r12)                   ; (DEBUG/TRACE) make sure we are not
                        mr.             r11,r11                                                 ; (DEBUG/TRACE) on the interrupt
                        bne+    notonintstack                                   ; (DEBUG/TRACE) stack
                        BREAKPOINT_TRAP
 notonintstack:
 #endif 
-                       stw             r4,THREAD_CONTINUATION(r3)
-                       cmpwi   cr1,r4,0                                                /* used waaaay down below */
-                       lwz             r11,0(r12)
-                       stw             r11,THREAD_KERNEL_STACK(r3)
+                       stw             r4,THREAD_CONTINUATION(r3)              ; Set continuation into the thread
+                       cmpwi   cr1,r4,0                                                ; used waaaay down below 
+                       lwz             r7,0(r10)                                               ; Get the current stack
 /*
  * Make the new thread the current thread.
  */
        
-                       lwz             r11,PP_CPU_DATA(r6)
-                       stw             r5,     CPU_ACTIVE_THREAD(r11)
+                       stw             r7,THREAD_KERNEL_STACK(r3)              ; Remember the current stack in the thread (do not need???)
+                       stw             r5,     PP_ACTIVE_THREAD(r12)           ; Make the new thread current
                        
-                       lwz             r11,THREAD_KERNEL_STACK(r5)
+                       lwz             r11,THREAD_KERNEL_STACK(r5)             ; Get the new stack pointer
                
-                       lwz             r5,THREAD_TOP_ACT(r5)
-                       lwz             r10,PP_ACTIVE_STACKS(r6)
+                       lwz             r5,THREAD_TOP_ACT(r5)                   ; Get the new activation
+                       mtsprg          1,r5
                        lwz             r7,CTHREAD_SELF(r5)                             ; Pick up the user assist word
-                       lwz             r8,ACT_MACT_PCB(r5)                             /* Get the PCB for the new guy */
-               
-                       stw             r11,0(r10)                                              ; Save the kernel stack address
-                       stw             r7,UAW(r6)                                              ; Save the assist word for the "ultra fast path"
+                       lwz             r8,ACT_MACT_PCB(r5)                             ; Get the PCB for the new guy
+                       
+#if 0
+                       lwz             r0,SAVflags(r8)                                 ; (TEST/DEBUG)
+                       rlwinm  r0,r0,24,24,31                                  ; (TEST/DEBUG)
+                       cmplwi  r0,SAVempty                                             ; (TEST/DEBUG)
+                       bne+    nnnn                                                    ; (TEST/DEBUG)
+                       b               .                                                               ; (TEST/DEBUG)
+nnnn:                                                                                          ; (TEST/DEBUG)
+#endif                 
+                       
+                       stw             r11,0(r10)                                              ; Save the new kernel stack address
+                       stw             r7,UAW(r12)                                             ; Save the assist word for the "ultra fast path"
+                       
+                       lwz             r11,ACT_MACT_BTE(r5)                    ; Get BlueBox Task Environment
                
                        lwz             r7,ACT_MACT_SPF(r5)                             ; Get the special flags
                        
                        lwz             r10,ACT_KLOADED(r5)
+                       stw             r11,ppbbTaskEnv(r12)                    ; Save the bb task env
                        li              r0,0
                        cmpwi   cr0,r10,0
-                       lwz             r10,PP_ACTIVE_KLOADED(r6)
-                       stw             r7,spcFlags(r6)                                 ; Set per_proc copy of the special flags
+                       lwz             r10,PP_ACTIVE_KLOADED(r12)
+                       stw             r7,spcFlags(r12)                                ; Set per_proc copy of the special flags
                        beq             cr0,.L_sw_ctx_not_kld
                
                        stw             r5,0(r10)
@@ -194,26 +217,131 @@ notonintstack:
                        
 cswNoTrc:      mfmsr   r6                                                              /* Get the MSR because the switched to thread should inherit it */
                        lwz             r7,SACvrswap(r7)                                /* Get the translation from virtual to real */
-                       lis             r0,hi16(SwitchContextCall)              /* Top part of switch context */
-                       lis             r9,hi16(EXT(switch_in))                 /* Get top of switch in routine */
                        stw             r11,ACT_MACT_PCB(r5)                    /* Dequeue the savearea we're switching to */
 
                        rlwinm  r6,r6,0,MSR_FP_BIT+1,MSR_FP_BIT-1       /* Turn off the FP */
-                       ori             r9,r9,lo16(EXT(switch_in))              /* Bottom half of switch in */
-                       lwz             r5,savesrr0(r8)                                 /* Set up the new SRR0 */
+                       lwz             r2,curctx(r5)                                   ; Grab our current context pointer
                        rlwinm  r6,r6,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     /* Turn off the vector */
                        mr              r4,r3                                                   /* Save our old thread to pass back */
+                       
+                       lhz             r0,PP_CPU_NUMBER(r12)                   ; Get our CPU number
+                       lwz             r10,FPUowner(r12)                               ; Grab the owner of the FPU                     
+                       lwz             r9,VMXowner(r12)                                ; Grab the owner of the vector
+                       cmplw   r10,r2                                                  ; Do we have the live float context?
+                       lwz             r10,FPUlevel(r2)                                ; Get the live level
+                       cmplw   cr5,r9,r2                                               ; Do we have the live vector context?           
+                       bne+    cswnofloat                                              ; Float is not ours...
+                       
+                       cmplw   r10,r11                                                 ; Is the level the same?
+                       lwz             r5,FPUcpu(r2)                                   ; Get the owning cpu
+                       bne+    cswnofloat                                              ; Level not the same, this is not live...
+                       
+                       cmplw   r5,r0                                                   ; Still owned by this cpu?
+                       lwz             r10,FPUsave(r2)                                 ; Get the level
+                       bne+    cswnofloat                                              ; CPU claimed by someone else...
+                       
+                       mr.             r10,r10                                                 ; Is there a savearea here?
+                       ori             r6,r6,lo16(MASK(MSR_FP))                ; Enable floating point
+                       
+                       beq-    cswnofloat                                              ; No savearea to check...
+                       
+                       lwz             r3,SAVlevel(r10)                                ; Get the level
+                       lwz             r5,SAVprev(r10)                                 ; Get the previous of this savearea
+                       cmplw   r3,r11                                                  ; Is it for the current level?
+                       
+                       bne+    cswnofloat                                              ; Nope...
+                       
+                       stw             r5,FPUsave(r2)                                  ; Pop off this savearea
+                       rlwinm  r5,r10,0,0,19                                   ; Move back to start of page
+                       lwz             r5,SACvrswap(r5)                                ; Get the virtual to real conversion
+                       la              r9,quickfret(r12)                               ; Point to the quickfret chain header                                   
+                       xor             r5,r10,r5                                               ; Convert savearea address to real
+
+#if FPVECDBG
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x4401                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
+                       lhz             r0,PP_CPU_NUMBER(r12)                   ; (TEST/DEBUG)
+#endif 
+
+;
+;                      Note: we need to do the atomic operation here because, even though
+;                      it is impossible with the current implementation, that we may take a
+;                      PTE miss between the load of the quickfret anchor and the subsequent
+;                      store.  The interrupt handler will dequeue everything on the list and
+;                      we could end up using stale data.  I do not like doing this...
+;
+
+cswfpudq:      lwarx   r3,0,r9                                                 ; Pick up the old chain head
+                       stw             r3,SAVprev(r10)                                 ; Move it to the current guy
+                       stwcx.  r5,0,r9                                                 ; Save it
+                       bne-    cswfpudq                                                ; Someone chaged the list...
+
+cswnofloat:    bne+    cr5,cswnovect                                   ; Vector is not ours...
+
+                       lwz             r10,VMXlevel(r2)                                ; Get the live level
+                       
+                       cmplw   r10,r11                                                 ; Is the level the same?
+                       lwz             r5,VMXcpu(r2)                                   ; Get the owning cpu
+                       bne+    cswnovect                                               ; Level not the same, this is not live...
+                       
+                       cmplw   r5,r0                                                   ; Still owned by this cpu?
+                       lwz             r10,VMXsave(r2)                                 ; Get the level
+                       bne+    cswnovect                                               ; CPU claimed by someone else...
+                       
+                       mr.             r10,r10                                                 ; Is there a savearea here?
+                       oris    r6,r6,hi16(MASK(MSR_VEC))               ; Enable vector
+                       
+                       beq-    cswnovect                                               ; No savearea to check...
+                       
+                       lwz             r3,SAVlevel(r10)                                ; Get the level
+                       lwz             r5,SAVprev(r10)                                 ; Get the previous of this savearea
+                       cmplw   r3,r11                                                  ; Is it for the current level?
+                       
+                       bne+    cswnovect                                               ; Nope...
+                       
+                       stw             r5,VMXsave(r2)                                  ; Pop off this savearea
+                       rlwinm  r5,r10,0,0,19                                   ; Move back to start of page
+                       lwz             r5,SACvrswap(r5)                                ; Get the virtual to real conversion
+                       la              r9,quickfret(r12)                               ; Point to the quickfret chain header                                   
+                       xor             r5,r10,r5                                               ; Convert savearea address to real
+
+#if FPVECDBG
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x4501                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
+#endif 
+
+;
+;                      Note: we need to do the atomic operation here because, even though
+;                      it is impossible with the current implementation, that we may take a
+;                      PTE miss between the load of the quickfret anchor and the subsequent
+;                      store.  The interrupt handler will dequeue everything on the list and
+;                      we could end up using stale data.  I do not like doing this...
+;
+
+cswvecdq:      lwarx   r3,0,r9                                                 ; Pick up the old chain head
+                       stw             r3,SAVprev(r10)                                 ; Move it to the current guy
+                       stwcx.  r5,0,r9                                                 ; Save it
+                       bne-    cswvecdq                                                ; Someone chaged the list...
+
+cswnovect:     lis             r9,hi16(EXT(switch_in))                 /* Get top of switch in routine */
+                       lwz             r5,savesrr0(r8)                                 /* Set up the new SRR0 */
+                       ori             r9,r9,lo16(EXT(switch_in))              /* Bottom half of switch in */
+                       lis             r0,hi16(SwitchContextCall)              /* Top part of switch context */
                        stw             r9,savesrr0(r8)                                 /* Make us jump to the switch in routine */
+                       
                        li              r10,MSR_SUPERVISOR_INT_OFF              /* Get the switcher's MSR */
                        lwz             r9,SAVflags(r8)                                 /* Get the flags */
                        stw             r10,savesrr1(r8)                                /* Set up for switch in */
                        rlwinm  r9,r9,0,15,13                                   /* Reset the syscall flag */
                        ori             r0,r0,lo16(SwitchContextCall)   /* Bottom part of switch context */
-                       rlwinm  r9,r9,0,1,31                                    /* Clear the attached flag */
                        xor             r3,r7,r8                                                /* Get the physical address of the new context save area */
                        stw             r9,SAVflags(r8)                                 /* Set the flags */
-/* if blocking on continuation avoid saving state */
-                       bne             cr1,1f
+
+                       bne             cr1,swtchtocont                                 ; Switch to the continuation
                        sc                                                                              /* Switch to the new context */
        
 /*                     We come back here in the new thread context     
@@ -221,10 +349,22 @@ cswNoTrc: mfmsr   r6                                                              /* Get the MSR because the switched to thread should i
  *                     R3 where it belongs.
  */
                        blr                                                                             /* Jump into the new thread */
+
+;
+;                      This is where we go when a continuation is set.  We are actually
+;                      killing off the old context of the new guy so we need to pop off
+;                      any float or vector states for the ditched level.
+;
+;                      Note that we do the same kind of thing a chkfac in hw_exceptions.s
+;
+
                
-1:             stw             r5,savesrr0(r8)                                 /* go to real pc */
-               stw             r4,saver3(r8)                                   /* must pass back old thread */
-               b               EXT(exception_exit)                             /* blocking on continuation, avoid state save */
+swtchtocont:
+                       stw             r5,savesrr0(r8)                                 ; Set the pc
+                       stw             r6,savesrr1(r8)                                 ; Set the next MSR to use
+                       stw             r4,saver3(r8)                                   ; Make sure we pass back the old thread
+                       
+                       b               EXT(exception_exit)                             ; Blocking on continuation, toss old context...
 
 
 
@@ -243,10 +383,13 @@ cswNoTrc: mfmsr   r6                                                              /* Get the MSR because the switched to thread should i
 
  */
  
-ENTRY(switch_in, TAG_NO_FRAME_USED)
+
+                       .align  5
+                       .globl  EXT(switch_in)
+
+LEXT(switch_in)
                        
                        lwz             r4,saver4(r3)                                   /* Get the old thread */
-                       li              r8,MSR_VM_OFF                                   /* Set to everything off */
                        lwz             r9,THREAD_TOP_ACT(r4)                   /* Get the switched from ACT */
                        lwz             r5,saver5(r3)                                   /* Get the srr0 value */
                        lwz             r10,ACT_MACT_PCB(r9)                    /* Get the top PCB on the old thread */
@@ -272,387 +415,158 @@ ENTRY(switch_in, TAG_NO_FRAME_USED)
 
                        
 /*
- * void fpu_save(void)
- *
- *             To do the floating point and VMX, we keep three thread pointers:  one
- *             to the current thread, one to the thread that has the floating point context
- *             loaded into the FPU registers, and one for the VMX owner.
- *
- *             Each of these threads has three PCB pointers.  The normal PCB, the FPU pcb,
- *             and the VMX pcb.  There is also a bit for each in the savearea flags.
- *             When we take an exception, or need to use the FPU/VMX in the kernel, we call
- *             this routine.  It checks to see if there is an owner thread for the facility.
- *             If so, it saves the facility's state information in the normal PCB. Then, it
- *             turns on the appropriate flag in the savearea to indicate that the state is
- *             in that particular savearea.  Also, the thread pointer for the owner in
- *             the per_processor block is cleared.  Note that we don't have to worry about the
- *             PCB pointers in the thread because whenever the state is loaded, the associated
- *             savearea is released and the pointer cleared.  This is done so that the facility
- *             context always migrates to the normal savearea/PCB.  This always insures that
- *             no more than 2 saveareas are used for a thread.
- *
- *             When the context is loaded into the facility, the associated PCB is released if
- *             its usage flags indicate that it is empty.  (Note that return from exception and
- *             context switch honor these flags and won't release a savearea if there is unrestored
- *             facility context.) The per_processor is set to point to the facility owner's
- *             thread and the associated PCB pointer within the thread is cleared because
- *             the PCB has been released.
+ * void fpu_save(facility_context ctx)
  *
- *             Part of loading a context is to release the savearea.  If the savearea contains
- *             other context, the savearea cannot be released.  So, what we're left with is 
- *             that there will be no normal context savearea, but one for the as-not-yet
- *             restored facility savearea.  Again, when that context is reloaded, the PCB
- *             is released, and when it is again stored, it goes into the "normal" savearea.
- *
- *             So, what do we do when there is no general context, and we have some FPU/VMX
- *             state to save?  Heck if I know, but it happens when we switch threads when
- *             we shortcut system calls.  The question is: does the target thread carry the
- *             FPU/VMX context with it or not? Actually, it don't matter, not one little bit.
- *             If we are asked to save it, we gotta.  It's a really lousy way to do it, but
- *             short of starting over with FPUs, it's what's what.  Therefore, we'll
- *             allocate an FPU context save and attach it.  
- *
- *             Actually, it's not quite that simple:  since we aren't in 
- *             in interrupt handler context (that's only in fpu_switch) we can't use 
- *             quickfret to merge FPU into general context.  So, if there is an FPU
- *             savearea, we need to use that.  So what we do is:  if there is FPU context
- *             use that.  If there is a general context, then use that.  If neither, 
- *             allocate a savearea and make that the FPU context.
- *
- *             The next thing we have to do is to allow the kernel to use both the 
- *             floating point and Altivec.  It is not recommended, but there may be a
- *             good reason to do so. So, what we need to do is to treat each of the
- *             three types of context the same, by keeping a LIFO chain of states.
- *             We do have a problem with that in that there can be multiple levels of
- *             kernel context. For example, we are using floating point and we take a
- *             page fault, and somehow start using the FPU, and take another page fault,
- *             etc. 
- *
- *             Anyway, we will hope that we only reasonably use floating point and vectors in
- *             the kernel. And try to pack the context in as few saveareas as possible.
- *
- *             The way we keep these "levels" of floating point or vector context straight is
- *             to remember the top of the normal savearea chain when we activate the 
- *             facility when it is first used.  Then, when we save that context, this value
- *             is saved in its level field.
- *
- *             What the level concept gives us is a way to distinguish between multiple
- *             independent contexts under the same thread activation. Any time we take
- *             any kind of interruption (trap, system call, I/O interruption), we are,
- *             in effect, running with a different context even though we are in the 
- *             same thread. The top savearea address is used only as a marker. It does not
- *             point to any context associated with the float or vector context. For example,
- *             the top savearea pointer will always be 0 for the user context, because there 
- *             it it always last on the list.
- *
- *             As normal context is unstacked, the first facility context is checked and
- *             if there is a match, the facility savearea is released.  This is because we
- *             are returning to a level before the facility saved there was used. In effect,
- *             this allows us to unwind the facility context saveareas at different rates.
- *
- *             In conjunction with the current activation, these markers are also used to 
- *             determine the state of the facility enablement. Whenever the facility context is
- *             "live," i.e., loaded in the hardware registers and belonging to the currently
- *             running context, the facility is enabled before dispatch.
- *
- *             There is nothing special about using floating point or vector facilities,
- *             no preliminary saving, enabling, or disabling. You just use them.  The only exception
- *             is during context switching on an SMP system.  In this case, the context must
- *             be saved as there is no guarantee that the thread will resume on the same 
- *             processor. This is not a good thing, not at all.  
- *
- *             Whenever we switch out a thread with a dirty context, we always need to save it
- *             because it can wake up on a different processor.  However, once the context has
- *             been saved, we don't need to save it again until it gets dirty, nor do we need
- *             to reload it unless someone else's context has been loaded. To handle this
- *             optimization, we need 3 things.  We need to know what processor the saved context
- *             was last loaded on, whether the loaded context could be dirty, and if we've already 
- *             saved it.
- *
- *             Whenever the facility is enabled, the processor ID is saved in the activation. This
- *             will show which processor has dirty data. When a context switch occurs, the facility 
- *             contexts are saved, but are still remembered as live. The next time we need to
- *             context switch, we first check if the state is live, and if not, do no state
- *             saving.  Then we check if the state has already been save and if not, save it.
- *             The facility is always disabled on a context switch. On a UP, this save function
- *             does not occur.
- *             
- *             Whenever a facility unavailable interruption occurs, the current state is saved
- *             if it is live and unsaved.  However, if the live state is the same as the new
- *             one to be loaded, the processor ID is checked and if it is the current processor
- *             the state does not need to be loaded or saved. The facility is simply enabled.
- *             
- *             Once allocated, facility saveareas are not released until a return is made to a
- *             previous level. Once a facility has been enabled, there is no way to tell if
- *             it will ever be used again, but it is likely.  Therefore, discarding a savearea
- *             when its context is made live is extra overhead.  So, we don't do it, but we
- *             do mark the savearea contents as invalid.
- *             
+ *                     Note that there are some oddities here when we save a context we are using.
+ *                     It is really not too cool to do this, but what the hey...  Anyway, 
+ *                     we turn fpus and vecs off before we leave., The oddity is that if you use fpus after this, the
+ *                     savearea containing the context just saved will go away.  So, bottom line is
+ *                     that don't use fpus until after you are done with the saved context.
  */
+                       .align  5
+                       .globl  EXT(fpu_save)
 
-/*
-;              The following is the actual way it is implemented.  It doesn't quite match
-;              the above text. I need to go and fix that.
-;
-;       Context download (operates on owner's data):
-;       
-;       0)     enable facility
-;       1)     if no owner exit to context restore
-;       2)     if context processor != current processor exit to context restore
-;       3)     if current activation == owner activation:
-;              1)      if curr level == active level:
-;                      1)      if top facility savearea exists:
-;                              invalidate savearea by setting level to 1
-;                      2)      enable facility for user
-;                      3)      exit
-;              
-;              2) else go to 5
-;       
-;       4)     if curr level == active level:
-;              1)      if top facility savearea exists:
-;                      1)      if top save level == active level exit to context restore               
-;       
-;       5)     allocate savearea
-;              1)      if there is a facility save and it is invalid, select it, and break
-;              2)      scan normal list for free facility area, select if found, and break
-;              3)      scan other facility for free save: select, if found, and break
-;              4)      allocate a new save area
-;       
-;       6)     save context
-;       7)     mark facility save with curr level
-;       8)     if reusing cached savearea (case #1) exit to context restore
-;       9)     set facility save backchain to facility top savearea
-;       10)    set facility top to savearea
-;       11)    exit to context restore
-;       
-;       
-;       Context restore/upload (operates on current activation's data):
-;       
-;       1)     set current to activation
-;       2)     set active level to current level
-;       3)     set context processor to current processor
-;       4)     if no facility savearea or top save level != curr level
-;                      initialize facility registers to empty value
-;       5)     else 
-;              1)      load registers from savearea
-;              2)      invalidate save area by setting level to 1
-;              
-;       6)     enable facility for user
-;       7)     exit to interrupt return
-;       
-;       
-;       Context save (operates on current activation's data; only used during context switch):
-;                               (context switch always disables the facility)
-;       
-;       1)     if no owner exit
-;       2)     if owner != current activation exit
-;       3)     if context processor != current processor 
-;              1)      clear owner
-;              2)      exit
-;              
-;       4)     if facility top savearea level exists and == active level exit
-;       5)     if curr level != active level exit
-;       6)     allocate savearea
-;              1)      if there is a facility save and it is invalid, select it, and break
-;              2)      scan normal list for free facility area, select if found, and break
-;              3)      scan other facility for free save: select, if found, and break
-;              4)      allocate a new save area
-;       7)     save context
-;       8)     mark facility savearea with curr level
-;       9)     if reusing cached savearea (case #1) exit
-;       10)    set facility save backchain to facility top savearea
-;       11)    set facility top to savearea
-;       12)    exit
-;       
-;       
-;       Exception exit (hw_exceptions):
-;       
-;       1)     disable return facility
-;       2)     if returning savearea != active level 
-;              1)      if owner != current activation exit
-;              2)      if context processor != current processor:
-;                      1)      clear owner
-;                      2)      exit
-;              
-;              3)      if new level != active level exit
-;              4)      enable return facility
-;              5)      exit
-;       
-;       3)     if no facility savearea exit
-;       4)     if top save level == active or top is invalid
-;              1)      dequeue top facility savearea
-;              2)      set active level to new top savearea's level
-;              3)      release savearea
-;              4)      if owner == current activation clear owner
-;       5)     exit
-;       
-;       
-;       
-;       
-;       if (owner == activation) && (curr level == active level)
-;              && (activation processor == current processor) ::= context live
-*/
-
-ENTRY(fpu_save, TAG_NO_FRAME_USED)
-
-                       mfmsr   r0                                              ; Get the MSR
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Turn off floating point forever
+LEXT(fpu_save)
+                       
+
+                       mfmsr   r0                                                              ; Get the MSR
+                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
                        rlwinm  r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1       ; But do interrupts only for now
-                       ori             r2,r2,MASK(MSR_FP)              ; Enable the floating point feature for now also
-                       mtmsr   r2                                              ; Set the MSR
+                       ori             r2,r2,MASK(MSR_FP)                              ; Enable the floating point feature for now also
+                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
+                       mtmsr   r2                                                              ; Set the MSR
                        isync
-               
-                       mfsprg  r6,0                                    ; Get the per_processor block 
-                       lwz             r12,PP_FPU_THREAD(r6)   ; Get the thread that owns the FPU
+
+                       mfsprg  r6,0                                                    ; Get the per_processor block 
+                       lwz             r12,FPUowner(r6)                                ; Get the context ID for owner
+
 #if FPVECDBG
-                       mr              r7,r0                                   ; (TEST/DEBUG)
-                       li              r4,0                                    ; (TEST/DEBUG)
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       mr.             r3,r12                                  ; (TEST/DEBUG)
-                       li              r2,0x6F00                               ; (TEST/DEBUG)
-                       li              r5,0                                    ; (TEST/DEBUG)
-                       beq-    noowneryet                              ; (TEST/DEBUG)
-                       lwz             r4,ACT_MACT_FPUlvl(r12) ; (TEST/DEBUG)
-                       lwz             r5,ACT_MACT_FPU(r12)    ; (TEST/DEBUG)
-
-noowneryet:    oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-                       mr              r0,r7                                   ; (TEST/DEBUG)
+                       mr              r7,r0                                                   ; (TEST/DEBUG)
+                       li              r4,0                                                    ; (TEST/DEBUG)
+                       mr              r10,r3                                                  ; (TEST/DEBUG)
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       mr.             r3,r12                                                  ; (TEST/DEBUG)
+                       li              r2,0x6F00                                               ; (TEST/DEBUG)
+                       li              r5,0                                                    ; (TEST/DEBUG)
+                       beq-    noowneryet                                              ; (TEST/DEBUG)
+                       lwz             r4,FPUlevel(r12)                                ; (TEST/DEBUG)
+                       lwz             r5,FPUsave(r12)                                 ; (TEST/DEBUG)
+
+noowneryet:    oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
+                       mr              r0,r7                                                   ; (TEST/DEBUG)
+                       mr              r3,r10                                                  ; (TEST/DEBUG)
 #endif 
-                       mflr    r2                                              ; Save the return address
-                       lwz             r10,PP_CPU_DATA(r6)             ; Get the CPU data pointer
-                       lhz             r11,PP_CPU_NUMBER(r6)   ; Get our CPU number
+                       mflr    r2                                                              ; Save the return address
+
+fsretry:       mr.             r12,r12                                                 ; Anyone own the FPU?
+                       lhz             r11,PP_CPU_NUMBER(r6)                   ; Get our CPU number
+                       beq-    fsret                                                   ; Nobody owns the FPU, no save required...
                        
-                       mr.             r12,r12                                 ; Anyone own the FPU?
+                       cmplw   cr1,r3,r12                                              ; Is the specified context live?
                        
-                       lwz             r10,CPU_ACTIVE_THREAD(r10)      ; Get the pointer to the active thread
+                       isync                                                                   ; Force owner check first
                        
-                       beq-    fsret                                   ; Nobody owns the FPU, no save required...
+                       lwz             r9,FPUcpu(r12)                                  ; Get the cpu that context was last on          
+                       bne-    cr1,fsret                                               ; No, it is not...
                        
-                       lwz             r10,THREAD_TOP_ACT(r10) ; Now get the activation that is running
-                       lwz             r9,ACT_MACT_FPUcpu(r12) ; Get the last CPU to use this context
+                       cmplw   cr1,r9,r11                                              ; Was the context for this processor? 
+                       beq-    cr1,fsgoodcpu                                   ; Facility last used on this processor...
+
+                       b               fsret                                                   ; Someone else claimed it...
                        
-                       cmplw   r12,r10                                 ; Do we own the FPU?
-                       cmplw   cr1,r9,r11                              ; Was the context for this processor? 
-                       bne+    fsret                                   ; Facility belongs to some other activation...
-                       li              r3,0                                    ; Assume we need a fix-me-up
-                       beq-    cr1,fsgoodcpu                   ; Facility last used on this processor...
-                       stw             r3,PP_FPU_THREAD(r6)    ; Clear owner because it was really on the other processor
-                       b               fsret                                   ; Bail now with no save...
+                       .align  5
                        
-fsgoodcpu:     lwz             r3,ACT_MACT_FPU(r12)    ; Get the current FPU savearea for the thread
-                       lwz             r9,ACT_MACT_FPUlvl(r12) ; Get our current level indicator
+fsgoodcpu:     lwz             r3,FPUsave(r12)                                 ; Get the current FPU savearea for the thread
+                       lwz             r9,FPUlevel(r12)                                ; Get our current level indicator
                        
-                       cmplwi  cr1,r3,0                                ; Have we ever saved this facility context?
-                       beq-    cr1,fsneedone                   ; Never saved it, so we need an area...
+                       cmplwi  cr1,r3,0                                                ; Have we ever saved this facility context?
+                       beq-    cr1,fsneedone                                   ; Never saved it, so go do it...
                        
-                       lwz             r8,SAVlvlfp(r3)                 ; Get the level this savearea is for
-                       cmplwi  r8,1                                    ; See if it is a spare
-                       cmplw   cr1,r9,r8                               ; Correct level?
-                       beq+    fsusespare                              ; We have a spare to use...
-                       beq-    cr1,fsret                               ; The current level is already saved, bail out...
+                       lwz             r8,SAVlevel(r3)                                 ; Get the level this savearea is for
+                       cmplw   cr1,r9,r8                                               ; Correct level?
+                       beq-    cr1,fsret                                               ; The current level is already saved, bail out...
 
-fsneedone:     li              r3,0                                    ; Tell the routine to allocate an area if none found
-                       bl              fpsrchsave                              ; Find a free savearea
-                       
-                       mfsprg  r6,0                                    ; Get back per_processor block
-                       oris    r7,r7,hi16(SAVfpuvalid) ; Set the allocated bit
-                       lwz             r12,PP_FPU_THREAD(r6)   ; Get back our thread
-                       mtlr    r2                                              ; Restore return
-                       lwz             r8,ACT_MACT_FPU(r12)    ; Get the current top floating point savearea
-                       lwz             r9,ACT_MACT_FPUlvl(r12) ; Get our current level indicator again         
-                       stw             r3,ACT_MACT_FPU(r12)    ; Set this as the latest FPU savearea for the thread
-                       stw             r8,SAVprefp(r3)                 ; And then chain this in front
-                       stw             r7,SAVflags(r3)                 ; Set the validity flags
-                       stw             r12,SAVact(r3)                  ; Make sure we point to the right guy
+fsneedone:     bl              EXT(save_get)                                   ; Get a savearea for the context
 
-fsusespare:    stw             r9,SAVlvlfp(r3)                 ; And set the level this savearea is for
+                       mfsprg  r6,0                                                    ; Get back per_processor block
+                       li              r4,SAVfloat                                             ; Get floating point tag                        
+                       lwz             r12,FPUowner(r6)                                ; Get back our thread
+                       stb             r4,SAVflags+2(r3)                               ; Mark this savearea as a float
+                       mr.             r12,r12                                                 ; See if we were disowned while away. Very, very small chance of it...
+                       beq-    fsbackout                                               ; If disowned, just toss savearea...
+                       lwz             r4,facAct(r12)                                  ; Get the activation associated with live context
+                       mtlr    r2                                                              ; Restore return
+                       lwz             r8,FPUsave(r12)                                 ; Get the current top floating point savearea
+                       stw             r4,SAVact(r3)                                   ; Indicate the right activation for this context
+                       lwz             r9,FPUlevel(r12)                                ; Get our current level indicator again         
+                       stw             r3,FPUsave(r12)                                 ; Set this as the most current floating point context
+                       stw             r8,SAVprev(r3)                                  ; And then chain this in front
+
+                       stw             r9,SAVlevel(r3)                                 ; Show level in savearea
 
 ;
 ;                      Save the current FPU state into the PCB of the thread that owns it.
 ; 
 
-                       la              r11,savefp0(r3)                 ; Point to the 1st line
-                       dcbz    0,r11                                   ; Allocate the first savearea line 
+                       la              r11,savefp0(r3)                                 ; Point to the 1st line
+                       dcbz    0,r11                                                   ; Allocate the first savearea line 
                        
-                       la              r11,savefp4(r3)                 /* Point to the 2nd line */
+                       la              r11,savefp4(r3)                                 ; Point to the 2nd line 
                        stfd    f0,savefp0(r3)
-                       dcbz    0,r11                                   /* allocate it */
+                       dcbz    0,r11                                                   ; Allocate it
                        stfd    f1,savefp1(r3)
                        stfd    f2,savefp2(r3)
-                       la              r11,savefp8(r3)                 /* Point to the 3rd line */
+                       la              r11,savefp8(r3)                                 ; Point to the 3rd line 
                        stfd    f3,savefp3(r3)
-                       dcbz    0,r11                                   /* allocate it */
+                       dcbz    0,r11                                                   ; Allocate it 
                        stfd    f4,savefp4(r3)
                        stfd    f5,savefp5(r3)
                        stfd    f6,savefp6(r3)
-                       la              r11,savefp12(r3)                /* Point to the 4th line */
+                       la              r11,savefp12(r3)                                ; Point to the 4th line 
                        stfd    f7,savefp7(r3)
-                       dcbz    0,r11                                   /* allocate it */
+                       dcbz    0,r11                                                   ; Allocate it 
                        stfd    f8,savefp8(r3)
                        stfd    f9,savefp9(r3)
                        stfd    f10,savefp10(r3)
-                       la              r11,savefp16(r3)                /* Point to the 5th line */
+                       la              r11,savefp16(r3)                                ; Point to the 5th line 
                        stfd    f11,savefp11(r3)
-                       dcbz    0,r11                                   /* allocate it */
+                       dcbz    0,r11                                                   ; Allocate it 
                        stfd    f12,savefp12(r3)
                        stfd    f13,savefp13(r3)
                        stfd    f14,savefp14(r3)
-                       la              r11,savefp20(r3)                /* Point to the 6th line */
+                       la              r11,savefp20(r3)                                ; Point to the 6th line 
                        stfd    f15,savefp15(r3)
                        stfd    f16,savefp16(r3)
                        stfd    f17,savefp17(r3)
                        stfd    f18,savefp18(r3)
-                       la              r11,savefp24(r3)                /* Point to the 7th line */
+                       la              r11,savefp24(r3)                                ; Point to the 7th line 
                        stfd    f19,savefp19(r3)
-                       dcbz    0,r11                                   /* allocate it */
+                       dcbz    0,r11                                                   ; Allocate it 
                        stfd    f20,savefp20(r3)
-                       lwz             r10,liveFPSCR(r6)               ; Get the previously saved FPSCR
                        stfd    f21,savefp21(r3)
                        stfd    f22,savefp22(r3)
-                       li              r9,0                                    ; Just clear this out 
-                       la              r11,savefp28(r3)                /* Point to the 8th line */
+                       la              r11,savefp28(r3)                                ; Point to the 8th line 
                        stfd    f23,savefp23(r3)
-                       dcbz    0,r11                                   /* allocate it */
+                       dcbz    0,r11                                                   ; Allocate it 
                        stfd    f24,savefp24(r3)
                        stfd    f25,savefp25(r3)
                        stfd    f26,savefp26(r3)
                        stfd    f27,savefp27(r3)
                        stfd    f28,savefp28(r3)
 
-;                      Note that we just save the FPSCR here for ease.  It is really already saved
-;                      in the "normal" context area of the savearea.
-
-                       stw             r9,savefpscrpad(r3)             ; Save the FPSCR pad
-                       stw             r10,savefpscr(r3)               ; Save the FPSCR
-                       
                        stfd    f29,savefp29(r3)
                        stfd    f30,savefp30(r3)
                        stfd    f31,savefp31(r3)
-                       lfd     f0,savefp0(r3)                  ; We need to restore F0 because we used it      
-                                                                                       ; to get the FPSCR
-                                                                                       
-#if 0
-                       la              r9,savefp0(r3)                  ; (TEST/DEBUG)
-                       la              r10,savefp31(r3)                ; (TEST/DEBUG)
-                       
-chkkillmedead:
-                       lha             r8,0(r9)                                ; (TEST/DEBUG)
-                       addi    r9,r9,8                                 ; (TEST/DEBUG)
-                       cmpwi   r8,-8                                   ; (TEST/DEBUG)
-                       cmplw   cr1,r9,r10                              ; (TEST/DEBUG)
-                       bne+    dontkillmedead                  ; (TEST/DEBUG)
-                       BREAKPOINT_TRAP                                 ; (TEST/DEBUG)
-
-dontkillmedead:                                                                ; (TEST/DEBUG)
-                       ble+    cr1,chkkillmedead               ; (TEST/DEBUG)
-#endif
-
-fsret:         mtmsr   r0                                              ; Put interrupts on if they were and floating point off
+
+fsret:         mtmsr   r0                                                              ; Put interrupts on if they were and floating point off
                        isync
 
                        blr
 
+fsbackout:     mr              r12,r0                                                  ; Save the original MSR
+                       b               EXT(save_ret_join)                              ; Toss savearea and return from there...
+
 /*
  * fpu_switch()
  *
@@ -671,328 +585,271 @@ fsret:          mtmsr   r0                                              ; Put interrupts on if they were and floating point off
  * 
  */
 
-ENTRY(fpu_switch, TAG_NO_FRAME_USED)
+                       .align  5
+                       .globl  EXT(fpu_switch)
+
+LEXT(fpu_switch)
+
 #if DEBUG
-#if GDDBG
-                       mr              r7,r4                                   ; Save input parameter
                        lis             r3,hi16(EXT(fpu_trap_count))    ; Get address of FP trap counter
                        ori             r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter
                        lwz             r1,0(r3)
-                       lis             r5,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       ori             r5,r5,lo16(EXT(GratefulDeb))    ; Put in bottom part
                        addi    r1,r1,1
-                       mtlr    r5                                              ; Set link register
                        stw             r1,0(r3)
-                       mr              r4,r1
-                       li              r3,0
-                       blrl                                                    ; Display count
-                       mr              r4,r7                                   ; Restore the parameter
-#else
-                       lis             r3,hi16(EXT(fpu_trap_count))    ; Get address of FP trap counter
-                       ori             r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter
-                       lwz             r1,0(r3)
-                       addi    r1,r1,1
-                       stw             r1,0(r3)
-#endif
 #endif /* DEBUG */
 
-                       mfsprg  r6,0                                    ; Get the per_processor block
-                       mfmsr   r19                                             ; Get the current MSR 
-                       
-                       lwz             r10,PP_CPU_DATA(r6)             ; Get the CPU data pointer
-                       lwz             r12,PP_FPU_THREAD(r6)   ; Get the thread that owns the FPU
-                       lwz             r10,CPU_ACTIVE_THREAD(r10)      ; Get the pointer to the active thread
-                       ori             r19,r19,lo16(MASK(MSR_FP))      ; Enable the floating point feature
-                       lwz             r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
-
-;                      R12 has the "old" activation
-;                      R17 has the "new" activation
-
-#if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x7F01                               ; (TEST/DEBUG)
-                       mr              r3,r12                                  ; (TEST/DEBUG)
-                       mr              r5,r17                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#endif 
-                       mr.             r12,r12                                 ; See if there is any live FP status
+                       mfsprg  r26,0                                                   ; Get the per_processor block
+                       mfmsr   r19                                                             ; Get the current MSR 
                        
-                       lhz             r18,PP_CPU_NUMBER(r6)   ; Get the current CPU, we will need it later
+                       mr              r25,r4                                                  ; Save the entry savearea
+                       lwz             r22,FPUowner(r26)                               ; Get the thread that owns the FPU
+                       lwz             r10,PP_ACTIVE_THREAD(r26)               ; Get the pointer to the active thread
+                       ori             r19,r19,lo16(MASK(MSR_FP))              ; Enable the floating point feature
+                       lwz             r17,THREAD_TOP_ACT(r10)                 ; Now get the activation that is running
                        
-                       mtmsr   r19                                             ; Enable floating point instructions
+                       mtmsr   r19                                                             ; Enable floating point instructions
                        isync
-                       
-                       beq-    fsnosave                                ; No live context, so nothing to save...
 
-                       lwz             r19,ACT_MACT_FPUcpu(r12)        ; Get the "old" active CPU
-                       lwz             r15,ACT_MACT_PCB(r12)   ; Get the current level of the "old" one
-                       cmplw   r18,r19                                 ; Check the CPU that the old context is live on
-                       lwz             r14,ACT_MACT_FPU(r12)   ; Point to the top of the old context stack
-                       bne-    fsnosave                                ; Context is not live if used on a different CPU...
-                       lwz             r13,ACT_MACT_FPUlvl(r12)        ; Get the "old" active level
-                       
-;
-;                      First, check to see if all we are doing is enabling because the
-;                      "new" context is live.
-;
+                       lwz             r27,ACT_MACT_PCB(r17)                   ; Get the current level
+                       lwz             r29,curctx(r17)                                 ; Grab the current context anchor of the current thread
+
+;                      R22 has the "old" context anchor
+;                      R29 has the "new" context anchor
+
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x7F02                               ; (TEST/DEBUG)
-                       mr              r1,r15                                  ; (TEST/DEBUG)
-                       mr              r3,r13                                  ; (TEST/DEBUG)
-                       mr              r5,r14                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x7F01                                               ; (TEST/DEBUG)
+                       mr              r3,r22                                                  ; (TEST/DEBUG)
+                       mr              r5,r29                                                  ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
+                                               
+                       lhz             r16,PP_CPU_NUMBER(r26)                  ; Get the current CPU number
 
-                       cmplw   cr1,r12,r17                             ; Are the "old" activation and the "new" the same?
-                       cmplwi  cr2,r14,0                               ; Is there any saved context on the "old" activation?
-                       bne+    cr1,fsmstsave                   ; The activations are different so "old" context must be saved...
+fswretry:      mr.             r22,r22                                                 ; See if there is any live FP status                    
 
-;
-;                      Here we know that both the "old" and "new" activations are the same.  We will
-;                      check the current level and active levels.  If they are the same, the context is
-;                      already live, so all we do is turn on the facility and invalidate the top
-;                      savearea. 
-;              
-;                      If the current level, the active level, and the top savearea level are the
-;                      same, then the context was saved as part of a thread context switch and neither
-;                      needs saving or restoration.
-;                      
-;                      In all other cases, the context must be saved unless we are just re-enabling
-;                      floating point.
-;
+                       beq-    fsnosave                                                ; No live context, so nothing to save...
 
-                       cmplw   r13,r15                                 ; Are the levels the same?
-                       cmplwi  cr2,r14,0                               ; Is there any saved context?
-                       bne-    fsmstsave                               ; Levels are different, we need to save...
-                       
-                       beq-    cr2,fsenable                    ; No saved context at all, enable and go...
-                       
-                       lwz             r20,SAVlvlfp(r14)               ; Get the level of the top savearea
+                       isync                                                                   ; Make sure we see this in the right order
 
-#if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x7F03                               ; (TEST/DEBUG)
-                       mr              r3,r15                                  ; (TEST/DEBUG)
-                       mr              r5,r20                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#endif 
-                       cmplw   r15,r20                                 ; Is the top level the same as the current?
-                       li              r0,1                                    ; Get the invalid flag
-                       bne-    fsenable                                ; Not the same, just enable and go...
-                       
-                       stw             r0,SAVlvlfp(r14)                ; Invalidate that top savearea
+                       lwz             r30,FPUsave(r22)                                ; Get the top savearea
+                       cmplw   cr2,r22,r29                                             ; Are both old and new the same context?
+                       lwz             r18,FPUcpu(r22)                                 ; Get the last CPU we ran on
+                       cmplwi  cr1,r30,0                                               ; Anything saved yet?
+                       cmplw   r18,r16                                                 ; Make sure we are on the right processor
+                       lwz             r31,FPUlevel(r22)                               ; Get the context level
 
-                       b               fsenable                                ; Then enable and go...
-                       
+                       bne-    fsnosave                                                ; No, not on the same processor...
+                                               
 ;
-;                      We need to save the "old" context here.  The LIFO queueing scheme works
-;                      out for all cases because if both the "new" and "old" activations are the
-;                      same, there can not be any saved state to load.  the "new" level is
-;                      truely new.
+;                      Check to see if the live context has already been saved.
+;                      Also check to see if all we are here just to re-enable the MSR
+;                      and handle specially if so.
 ;
-;                      When we save the context, we either use a new savearea, or the free
-;                      one that is cached at the head of the list.
+
+                       cmplw   r31,r27                                                 ; See if the current and active levels are the same
+                       crand   cr0_eq,cr2_eq,cr0_eq                    ; Remember if both the levels and contexts are the same
+                       li              r3,0                                                    ; Clear this
                        
-fsmstsave:     beq-    cr2,fsgetsave                   ; There is no possible cached save area
+                       beq-    fsthesame                                               ; New and old are the same, just go enable...
+
+                       beq-    cr1,fsmstsave                                   ; Not saved yet, go do it...
                        
-                       lwz             r5,SAVlvlfp(r14)                ; Get the level of first facility savearea
-#if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x7F04                               ; (TEST/DEBUG)
-                       mr              r3,r15                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#endif 
-                       mr              r3,r14                                  ; Assume we are invalid
-                       cmplwi  r5,1                                    ; Is it invalid?
-                       cmplw   cr1,r5,r13                              ; Is the SA level the active one?
-                       beq+    fsusecache                              ; Invalid, just use it...
-                       beq-    cr1,fsnosave                    ; The SA level is active, it is already saved...
+                       lwz             r11,SAVlevel(r30)                               ; Get the level of top saved context
                        
-fsgetsave:     mr              r3,r4                                   ; Use the interrupt save as the context savearea if none cached
+                       cmplw   r31,r11                                                 ; Are live and saved the same?
+
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x7F05                               ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x7F02                                               ; (TEST/DEBUG)
+                       mr              r3,r30                                                  ; (TEST/DEBUG)
+                       mr              r5,r31                                                  ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
+
+                       beq+    fsnosave                                                ; Same level, so already saved...
                        
-                       bl              fpsrchsave                              ; Find a free savearea
+                       
+fsmstsave:     stw             r3,FPUowner(r26)                                ; Kill the context now
+                       eieio                                                                   ; Make sure everyone sees it
+                       bl              EXT(save_get)                                   ; Go get a savearea
+
+                       la              r11,savefp0(r3)                                 ; Point to the 1st line in new savearea
+                       lwz             r12,facAct(r22)                                 ; Get the activation associated with the context
+                       dcbz    0,r11                                                   ; Allocate cache
+                       stw             r3,FPUsave(r22)                                 ; Set this as the latest context savearea for the thread
 
-                       stw             r3,ACT_MACT_FPU(r12)    ; Set this as the latest context savearea for the thread
-                       mfsprg  r6,0                                    ; Get back per_processor block
-                       stw             r14,SAVprefp(r3)                ; And then chain this in front
-                       oris    r7,r7,hi16(SAVfpuvalid) ; Set the allocated bit
-                       stw             r12,SAVact(r3)                  ; Make sure we point to the right guy
-                       stw             r7,SAVflags(r3)                 ; Set the allocation flags
+                       stw             r30,SAVprev(r3)                                 ; Point us to the old context
+                       stw             r31,SAVlevel(r3)                                ; Tag our level
+                       li              r7,SAVfloat                                             ; Get the floating point ID
+                       stw             r12,SAVact(r3)                                  ; Make sure we point to the right guy
+                       stb             r7,SAVflags+2(r3)                               ; Set that we have a floating point save area
 
-fsusecache:    la              r11,savefp0(r3)                 ; Point to the 1st line in area
-                       stw             r13,SAVlvlfp(r3)                ; Set this context level
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x7F06                               ; (TEST/DEBUG)
-                       mr              r5,r13                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x7F03                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
 
 ;
 ;                      Now we will actually save the old context
 ;
                        
-                       dcbz    0,r11                                   ; Allocate the output area
-
-                       la              r11,savefp4(r3)                 ; Point to the 2nd line
+                       la              r11,savefp4(r3)                                 ; Point to the 2nd line
                        stfd    f0,savefp0(r3)
-                       dcbz    0,r11                                   ; Allocate cache
+                       dcbz    0,r11                                                   ; Allocate cache
                        stfd    f1,savefp1(r3)
                        stfd    f2,savefp2(r3)
-                       la              r11,savefp8(r3)                 ; Point to the 3rd line
+                       la              r11,savefp8(r3)                                 ; Point to the 3rd line
                        stfd    f3,savefp3(r3)
-                       dcbz    0,r11                                   ; Allocate cache
+                       dcbz    0,r11                                                   ; Allocate cache
                        stfd    f4,savefp4(r3)
                        stfd    f5,savefp5(r3)
                        stfd    f6,savefp6(r3)
-                       la              r11,savefp12(r3)                ; Point to the 4th line
+                       la              r11,savefp12(r3)                                ; Point to the 4th line
                        stfd    f7,savefp7(r3)
-                       dcbz    0,r11                                   ; Allocate cache
+                       dcbz    0,r11                                                   ; Allocate cache
                        stfd    f8,savefp8(r3)
                        stfd    f9,savefp9(r3)
                        stfd    f10,savefp10(r3)
-                       la              r11,savefp16(r3)                ; Point to the 5th line
+                       la              r11,savefp16(r3)                                ; Point to the 5th line
                        stfd    f11,savefp11(r3)
-                       dcbz    0,r11                                   ; Allocate cache
+                       dcbz    0,r11                                                   ; Allocate cache
                        stfd    f12,savefp12(r3)
                        stfd    f13,savefp13(r3)
                        stfd    f14,savefp14(r3)
-                       la              r11,savefp20(r3)                ; Point to the 6th line 
+                       la              r11,savefp20(r3)                                ; Point to the 6th line 
                        stfd    f15,savefp15(r3)
-                       dcbz    0,r11                                   ; Allocate cache
+                       dcbz    0,r11                                                   ; Allocate cache
                        stfd    f16,savefp16(r3)
                        stfd    f17,savefp17(r3)
                        stfd    f18,savefp18(r3)
-                       la              r11,savefp24(r3)                ; Point to the 7th line
+                       la              r11,savefp24(r3)                                ; Point to the 7th line
                        stfd    f19,savefp19(r3)
-                       dcbz    0,r11                                   ; Allocate cache
+                       dcbz    0,r11                                                   ; Allocate cache
                        stfd    f20,savefp20(r3)
 
-                       li              r14,0                                   ; Clear this for now
-                       lwz             r15,liveFPSCR(r6)               ; Get the previously saved FPSCR
-
                        stfd    f21,savefp21(r3)
                        stfd    f22,savefp22(r3)
-                       la              r11,savefp28(r3)                ; Point to the 8th line
+                       la              r11,savefp28(r3)                                ; Point to the 8th line
                        stfd    f23,savefp23(r3)
-                       dcbz    0,r11                                   ; allocate it
+                       dcbz    0,r11                                                   ; allocate it
                        stfd    f24,savefp24(r3)
                        stfd    f25,savefp25(r3)
                        stfd    f26,savefp26(r3)
-                       la              r11,savefpscrpad(r3)    ; Point to the 9th line
                        stfd    f27,savefp27(r3)
-                       dcbz    0,r11                                   ; allocate it
+                       dcbz    0,r11                                                   ; allocate it
                        stfd    f28,savefp28(r3)
                        stfd    f29,savefp29(r3)
                        stfd    f30,savefp30(r3)
                        stfd    f31,savefp31(r3)
 
-;                      Note that we just save the FPSCR here for ease.  It is really already saved
-;                      in the "normal" context area of the savearea.
-
-                       stw             r14,savefpscrpad(r3)    ; Save the FPSCR pad
-                       stw             r15,savefpscr(r3)               ; Save the FPSCR
-
 ;
 ;                      The context is all saved now and the facility is free.
 ;
-;                      Now check out the "new" and see if we need to load up his context.
-;                      If we do (and this should be the normal case), do it and then invalidate the
-;                      savearea. (This will keep it cached for quick access next time around.)
-;                      
-;                      If we do not (remember, we already took care of the case where we just enable
-;                      the FPU), we need to fill the registers with junk, because this level has 
+;                      If we do not we need to fill the registers with junk, because this level has 
 ;                      never used them before and some thieving bastard could hack the old values
 ;                      of some thread!  Just imagine what would happen if they could!  Why, nothing
 ;                      would be safe! My God! It is terrifying!
 ;
 
-                       
-fsnosave:      lwz             r15,ACT_MACT_PCB(r17)   ; Get the current level of the "new" one
-                       lwz             r14,ACT_MACT_FPU(r17)   ; Point to the top of the "new" context stack
-                       lwz             r13,ACT_MACT_FPUlvl(r17)        ; Get the "new" active level
+
+fsnosave:      lwz             r15,ACT_MACT_PCB(r17)                   ; Get the current level of the "new" one
+                       lwz             r19,FPUcpu(r29)                                 ; Get the last CPU we ran on
+                       lwz             r14,FPUsave(r29)                                ; Point to the top of the "new" context stack
+
+                       stw             r16,FPUcpu(r29)                                 ; Claim context for us
+                       eieio
+
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x7F07                               ; (TEST/DEBUG)
-                       mr              r1,r15                                  ; (TEST/DEBUG)
-                       mr              r3,r14                                  ; (TEST/DEBUG)
-                       mr              r5,r13                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
+                       lwz             r13,FPUlevel(r29)                               ; (TEST/DEBUG)
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x7F04                                               ; (TEST/DEBUG)
+                       mr              r1,r15                                                  ; (TEST/DEBUG)
+                       mr              r3,r14                                                  ; (TEST/DEBUG)
+                       mr              r5,r13                                                  ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
-
-                       cmplwi  cr1,r14,0                               ; Do we possibly have some context to load?
-                       stw             r15,ACT_MACT_FPUlvl(r17)        ; Set the "new" active level
-                       stw             r18,ACT_MACT_FPUcpu(r17)        ; Set the active CPU
-                       la              r11,savefp0(r14)                ; Point to first line to bring in
-                       stw             r17,PP_FPU_THREAD(r6)   ; Store current thread address in fpu_thread to claim fpu for thread
+                       
+                       lis             r18,hi16(EXT(per_proc_info))    ; Set base per_proc
+                       mulli   r19,r19,ppSize                                  ; Find offset to the owner per_proc                     
+                       ori             r18,r18,lo16(EXT(per_proc_info))        ; Set base per_proc
+                       li              r16,FPUowner                                    ; Displacement to float owner
+                       add             r19,r18,r19                                             ; Point to the owner per_proc   
+                       li              r0,0
+                       
+fsinvothr:     lwarx   r18,r16,r19                                             ; Get the owner
+                       cmplw   r18,r29                                                 ; Does he still have this context?
+                       bne             fsinvoths                                               ; Nope...               
+                       stwcx.  r0,r16,r19                                              ; Try to invalidate it
+                       bne-    fsinvothr                                               ; Try again if there was a collision...
+               
+fsinvoths:     cmplwi  cr1,r14,0                                               ; Do we possibly have some context to load?
+                       la              r11,savefp0(r14)                                ; Point to first line to bring in
+                       stw             r15,FPUlevel(r29)                               ; Set the "new" active level
+                       eieio
+                       stw             r29,FPUowner(r26)                               ; Mark us as having the live context
                        
                        beq+    cr1,MakeSureThatNoTerroristsCanHurtUsByGod      ; No "new" context to load...
-                       lwz             r0,SAVlvlfp(r14)                ; Get the level of first facility savearea
-                       cmplw   r0,r15                                  ; Top level correct to load?
+                       
+                       dcbt    0,r11                                                   ; Touch line in
+
+                       lwz             r3,SAVprev(r14)                                 ; Get the previous context
+                       lwz             r0,SAVlevel(r14)                                ; Get the level of first facility savearea
+                       cmplw   r0,r15                                                  ; Top level correct to load?
                        bne-    MakeSureThatNoTerroristsCanHurtUsByGod  ; No, go initialize...
+
+                       stw             r3,FPUsave(r29)                                 ; Pop the context (we will toss the savearea later)
                        
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x7F08                               ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x7F05                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
 
-                       dcbt    0,r11                                   ; Touch line in
-                       li              r0,1                                    ; Get the level invalid indication
-                                               
-                       la              r11,savefp4(r14)                ; Point to next line
-                       dcbt    0,r11                                   ; Touch line in
+                       la              r11,savefp4(r14)                                ; Point to next line
+                       dcbt    0,r11                                                   ; Touch line in
                        lfd     f0, savefp0(r14)
                        lfd     f1,savefp1(r14)
-                       stw             r0,SAVlvlfp(r14)                ; Mark the savearea invalid because we are activating again
                        lfd     f2,savefp2(r14)
-                       la              r11,savefp8(r14)                ; Point to next line
+                       la              r11,savefp8(r14)                                ; Point to next line
                        lfd     f3,savefp3(r14)
-                       dcbt    0,r11                                   ; Touch line in
+                       dcbt    0,r11                                                   ; Touch line in
                        lfd     f4,savefp4(r14)
                        lfd     f5,savefp5(r14)
                        lfd     f6,savefp6(r14)
-                       la              r11,savefp12(r14)               ; Point to next line
+                       la              r11,savefp12(r14)                               ; Point to next line
                        lfd     f7,savefp7(r14)
-                       dcbt    0,r11                                   ; Touch line in
+                       dcbt    0,r11                                                   ; Touch line in
                        lfd     f8,savefp8(r14)
                        lfd     f9,savefp9(r14)
                        lfd     f10,savefp10(r14)
-                       la              r11,savefp16(r14)               ; Point to next line
+                       la              r11,savefp16(r14)                               ; Point to next line
                        lfd     f11,savefp11(r14)
-                       dcbt    0,r11                                   ; Touch line in
+                       dcbt    0,r11                                                   ; Touch line in
                        lfd     f12,savefp12(r14)
                        lfd     f13,savefp13(r14)
                        lfd     f14,savefp14(r14)
-                       la              r11,savefp20(r14)               ; Point to next line
+                       la              r11,savefp20(r14)                               ; Point to next line
                        lfd     f15,savefp15(r14)
-                       dcbt    0,r11                                   ; Touch line in
+                       dcbt    0,r11                                                   ; Touch line in
                        lfd     f16,savefp16(r14)
                        lfd     f17,savefp17(r14)
                        lfd     f18,savefp18(r14)
-                       la              r11,savefp24(r14)               ; Point to next line
+                       la              r11,savefp24(r14)                               ; Point to next line
                        lfd     f19,savefp19(r14)
-                       dcbt    0,r11                                   ; Touch line in
+                       dcbt    0,r11                                                   ; Touch line in
                        lfd     f20,savefp20(r14)
                        lfd     f21,savefp21(r14)
-                       la              r11,savefp28(r14)               ; Point to next line
+                       la              r11,savefp28(r14)                               ; Point to next line
                        lfd     f22,savefp22(r14)
                        lfd     f23,savefp23(r14)
-                       dcbt    0,r11                                   ; Touch line in
+                       dcbt    0,r11                                                   ; Touch line in
                        lfd     f24,savefp24(r14)
                        lfd     f25,savefp25(r14)
                        lfd     f26,savefp26(r14)
@@ -1002,49 +859,48 @@ fsnosave:        lwz             r15,ACT_MACT_PCB(r17)   ; Get the current level of the "new" one
                        lfd     f30,savefp30(r14)
                        lfd     f31,savefp31(r14)
                        
-fsenable:      lwz             r9,SAVflags(r4)                 /* Get the flags of the current savearea */
-                       lwz             r8,savesrr1(r4)                 ; Get the msr of the interrupted guy
-                       rlwinm  r5,r4,0,0,19                    /* Get the page address of the savearea */
-                       ori             r8,r8,MASK(MSR_FP)              ; Enable the floating point feature
-                       lwz             r10,ACT_MACT_SPF(r17)   ; Get the special flags
-                       lis             r7,hi16(SAVattach)              /* Get the attached flag */
-                       lwz             r5,SACvrswap(r5)                /* Get Virtual to Real translation */
+                       mr              r3,r14                                                  ; Get the old savearea (we popped it before)
+                       bl              EXT(save_ret)                                   ; Toss it
+                       
+fsenable:      lwz             r8,savesrr1(r25)                                ; Get the msr of the interrupted guy
+                       rlwinm  r5,r25,0,0,19                                   ; Get the page address of the savearea 
+                       ori             r8,r8,MASK(MSR_FP)                              ; Enable the floating point feature
+                       lwz             r10,ACT_MACT_SPF(r17)                   ; Get the special flags
+                       lwz             r5,SACvrswap(r5)                                ; Get Virtual to Real translation 
                        oris    r10,r10,hi16(floatUsed|floatCng)        ; Set that we used floating point
-                       mr.             r15,r15                                 ; See if we are doing this for user state
-                       stw             r8,savesrr1(r4)                 ; Set the msr of the interrupted guy
-                       andc    r9,r9,r7                                /* Clear the attached bit */
-                       xor             r3,r4,r5                                /* Get the real address of the savearea */
-                       bne-    fsnuser                                 ; We are not user state...
-                       stw             r10,ACT_MACT_SPF(r17)   ; Set the activation copy
-                       stw             r10,spcFlags(r6)                ; Set per_proc copy
+                       rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT   ; See if we are doing this for user state
+                       stw             r8,savesrr1(r25)                                ; Set the msr of the interrupted guy
+                       xor             r3,r25,r5                                               ; Get the real address of the savearea
+                       beq-    fsnuser                                                 ; We are not user state...
+                       stw             r10,ACT_MACT_SPF(r17)                   ; Set the activation copy
+                       stw             r10,spcFlags(r26)                               ; Set per_proc copy
 
 fsnuser:
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x7F0A                               ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x7F07                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
-                       stw             r9,SAVflags(r4)                 /* Set the flags of the current savearea */
                        
-                       b               EXT(exception_exit)             /* Exit from the fray... */
+                       b               EXT(exception_exit)                             ; Exit to the fray...
 
 /*
  *                     Initialize the registers to some bogus value
  */
 
 MakeSureThatNoTerroristsCanHurtUsByGod:
-                       
+
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x7F09                               ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x7F06                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
-                       lis             r5,hi16(EXT(FloatInit)) /* Get top secret floating point init value address */
-                       ori             r5,r5,lo16(EXT(FloatInit))      /* Slam bottom */
-                       lfd             f0,0(r5)                                /* Initialize FP0 */
-                       fmr             f1,f0                                   ; Do them all                                           
+                       lis             r5,hi16(EXT(FloatInit))                 ; Get top secret floating point init value address
+                       ori             r5,r5,lo16(EXT(FloatInit))              ; Slam bottom
+                       lfd             f0,0(r5)                                                ; Initialize FP0 
+                       fmr             f1,f0                                                   ; Do them all                                           
                        fmr             f2,f0                                                           
                        fmr             f3,f0                                                           
                        fmr             f4,f0                                                           
@@ -1061,11 +917,9 @@ MakeSureThatNoTerroristsCanHurtUsByGod:
                        fmr             f15,f0                                          
                        fmr             f16,f0                                          
                        fmr             f17,f0
-                       fsub    f31,f31,f31                             ; Get set to initialize the FPSCR
                        fmr             f18,f0                                          
                        fmr             f19,f0                                          
                        fmr             f20,f0                                          
-                       mtfsf   0xff,f31                                ; Clear all FPSCR exception eanbles
                        fmr             f21,f0                                          
                        fmr             f22,f0                                          
                        fmr             f23,f0                                          
@@ -1077,46 +931,93 @@ MakeSureThatNoTerroristsCanHurtUsByGod:
                        fmr             f29,f0                                          
                        fmr             f30,f0                                          
                        fmr             f31,f0                                          
-                       b               fsenable                                ; Finish setting it all up...                           
+                       b               fsenable                                                ; Finish setting it all up...                           
+
 
 ;
-;                      Finds an unused floating point area in the activation pointed
-;                      to by R12s saved contexts.  If none are found (unlikely but possible)
-;                      and R3 is 0, a new area is allocated.  If R3 is non-zero, it contains 
-;                      a pointer to an floating point savearea that is free.
+;                      We get here when we are switching to the same context at the same level and the context
+;                      is still live.  Essentially, all we are doing is turning on the faility.  It may have
+;                      gotten turned off due to doing a context save for the current level or a context switch
+;                      back to the live guy.
 ;
-fpsrchsave:
-                       lwz             r6,ACT_MACT_PCB(r12)            ; Get the first "normal" savearea
+
+                       .align  5
                        
-fpsrnorm:      mr.             r5,r6                                           ; Is there another?
-                       beq-    fpsrvect                                        ; No, search the vector saveareas...
-                       lwz             r7,SAVflags(r5)                         ; Get the flags for this guy
-                       lwz             r6,SAVprev(r5)                          ; Get the previous savearea, just in case
-                       andis.  r8,r7,hi16(SAVfpuvalid)         ; Have we found an empty FPU save in normal?
-                       beq+    fpsrgot                                         ; We found one...
-                       b               fpsrnorm                                        ; Search again...
+fsthesame:
 
-fpsrvect:      lwz             r6,ACT_MACT_VMX(r12)            ; Get the first "vector" savearea
+#if FPVECDBG
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x7F0A                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
+#endif 
+                       beq-    cr1,fsenable                                    ; Not saved yet, nothing to pop, go enable and exit...
                        
-fpsrvectx:     mr.             r5,r6                                           ; Is there another?
-                       beq-    fpsrget                                         ; No, try to allocate one...
-                       lwz             r7,SAVflags(r5)                         ; Get the flags for this guy
-                       lwz             r6,SAVprevec(r5)                        ; Get the previous savearea, just in case
-                       andis.  r8,r7,hi16(SAVfpuvalid)         ; Have we found an empty FPU save in vector?
-                       bne-    fpsrvectx                                       ; Search again...
+                       lwz             r11,SAVlevel(r30)                               ; Get the level of top saved context
+                       lwz             r14,SAVprev(r30)                                ; Get the previous savearea
                        
-fpsrgot:       mr              r3,r5                                           ; Get the savearea into the right register
-                       blr                                                                     ; Return...
+                       cmplw   r11,r31                                                 ; Are live and saved the same?
 
-fpsrget:       mr.             r5,r3                                           ; Do we allocate or use existing?
-                       beq+    fpsrallo                                        ; Allocate one...
+                       bne+    fsenable                                                ; Level not the same, nothing to pop, go enable and exit...
                        
-                       lwz             r7,SAVflags(r3)                         ; Get the passed in area flags
-                       blr                                                                     ; Return...
-;                      
-;                      NOTE: save_get will return directly and set R7 to 0...
+                       mr              r3,r30                                                  ; Get the old savearea (we popped it before)
+                       bl              EXT(save_ret)                                   ; Toss it
+                       b               fsenable                                                ; Go enable and exit...
+
+
+;
+;                      This function invalidates any live floating point context for the passed in facility_context.
+;                      This is intended to be called just before act_machine_sv_free tosses saveareas.
+;
+
+                       .align  5
+                       .globl  EXT(toss_live_fpu)
+
+LEXT(toss_live_fpu)
+                       
+                       
+                       mfmsr   r9                                                              ; Get the MSR
+                       rlwinm  r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1       ; Clear interuptions
+                       rlwinm. r8,r9,0,MSR_FP_BIT,MSR_FP_BIT   ; Are floats on right now?
+                       rlwinm  r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Make sure vectors are turned off
+                       rlwinm  r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Make sure floats are turned off
+                       mtmsr   r0                                                              ; No interruptions
+                       isync
+                       beq+    tlfnotours                                              ; Floats off, can not be live here...
+
+                       mfsprg  r8,0                                                    ; Get the per proc
+
+;
+;                      Note that at this point, since floats are on, we are the owner
+;                      of live state on this processor
 ;
-fpsrallo:      b               EXT(save_get)                           ; Get a fresh savearea 
+
+                       lwz             r6,FPUowner(r8)                                 ; Get the thread that owns the floats
+                       li              r0,0                                                    ; Clear this just in case we need it
+                       cmplw   r6,r3                                                   ; Are we tossing our own context?
+                       bne-    tlfnotours                                              ; Nope...
+                       
+                       fsub    f1,f1,f1                                                ; Make a 0                      
+                       mtfsf   0xFF,f1                                                 ; Clear it
+
+tlfnotours:    lwz             r11,FPUcpu(r3)                                  ; Get the cpu on which we last loaded context
+                       lis             r12,hi16(EXT(per_proc_info))    ; Set base per_proc
+                       mulli   r11,r11,ppSize                                  ; Find offset to the owner per_proc                     
+                       ori             r12,r12,lo16(EXT(per_proc_info))        ; Set base per_proc
+                       li              r10,FPUowner                                    ; Displacement to float owner
+                       add             r11,r12,r11                                             ; Point to the owner per_proc   
+                       li              r0,0                                                    ; Set a 0 to invalidate context
+                       
+tlfinvothr:    lwarx   r12,r10,r11                                             ; Get the owner
+                       cmplw   r12,r3                                                  ; Does he still have this context?
+                       bne+    tlfexit                                                 ; Nope, leave...                
+                       stwcx.  r0,r10,r11                                              ; Try to invalidate it
+                       bne-    tlfinvothr                                              ; Try again if there was a collision...
+
+tlfexit:       mtmsr   r9                                                              ; Restore interruptions
+                       isync                                                                   ; Could be turning off floats here
+                       blr                                                                             ; Leave...
+
 
 /*
  *                     Altivec stuff is here. The techniques used are pretty identical to
@@ -1132,98 +1033,132 @@ fpsrallo:      b               EXT(save_get)                           ; Get a fresh savearea
  *                     don't want to load any registers we don't have a copy of, we want to set them
  *                     to zero instead.
  *
+ *                     Note that there are some oddities here when we save a context we are using.
+ *                     It is really not too cool to do this, but what the hey...  Anyway, 
+ *                     we turn vectors and fpu off before we leave.
+ *                     The oddity is that if you use vectors after this, the
+ *                     savearea containing the context just saved will go away.  So, bottom line is
+ *                     that don't use vectors until after you are done with the saved context.
+ *
  */
 
-ENTRY(vec_save, TAG_NO_FRAME_USED)
+                       .align  5
+                       .globl  EXT(vec_save)
+
+LEXT(vec_save)
 
-                       mfmsr   r0                                              ; Get the MSR
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Turn off vector forever
+                       mfmsr   r0                                                              ; Get the MSR
+                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Make sure vectors are turned off when we leave
                        rlwinm  r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1       ; But do interrupts only for now
-                       oris    r2,r2,hi16(MASK(MSR_VEC))       ; Enable the vector facility for now also
-                       mtmsr   r2                                              ; Set the MSR
+                       oris    r2,r2,hi16(MASK(MSR_VEC))               ; Enable the vector facility for now also
+                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force off fp
+                       mtmsr   r2                                                              ; Set the MSR
                        isync
                
-                       mfsprg  r6,0                                    ; Get the per_processor block 
-                       lwz             r12,PP_VMX_THREAD(r6)   ; Get the thread that owns the vector
+                       mfsprg  r6,0                                                    ; Get the per_processor block 
+                       lwz             r12,VMXowner(r6)                                ; Get the context ID for owner
+
 #if FPVECDBG
-                       mr              r7,r0                                   ; (TEST/DEBUG)
-                       li              r4,0                                    ; (TEST/DEBUG)
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       mr.             r3,r12                                  ; (TEST/DEBUG)
-                       li              r2,0x5F00                               ; (TEST/DEBUG)
-                       li              r5,0                                    ; (TEST/DEBUG)
-                       beq-    noowneryeu                              ; (TEST/DEBUG)
-                       lwz             r4,ACT_MACT_VMXlvl(r12) ; (TEST/DEBUG)
-                       lwz             r5,ACT_MACT_VMX(r12)    ; (TEST/DEBUG)
-
-noowneryeu:    oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-                       mr              r0,r7                                   ; (TEST/DEBUG)
+                       mr              r7,r0                                                   ; (TEST/DEBUG)
+                       li              r4,0                                                    ; (TEST/DEBUG)
+                       mr              r10,r3                                                  ; (TEST/DEBUG)
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       mr.             r3,r12                                                  ; (TEST/DEBUG)
+                       li              r2,0x5F00                                               ; (TEST/DEBUG)
+                       li              r5,0                                                    ; (TEST/DEBUG)
+                       beq-    noowneryeu                                              ; (TEST/DEBUG)
+                       lwz             r4,VMXlevel(r12)                                ; (TEST/DEBUG)
+                       lwz             r5,VMXsave(r12)                                 ; (TEST/DEBUG)
+
+noowneryeu:    oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
+                       mr              r0,r7                                                   ; (TEST/DEBUG)
+                       mr              r3,r10                                                  ; (TEST/DEBUG)
 #endif 
-                       mflr    r2                                              ; Save the return address
-                       lwz             r10,PP_CPU_DATA(r6)             ; Get the CPU data pointer
-                       lhz             r11,PP_CPU_NUMBER(r6)   ; Get our CPU number
-                       
-                       mr.             r12,r12                                 ; Anyone own the vector?
-                       
-                       lwz             r10,CPU_ACTIVE_THREAD(r10)      ; Get the pointer to the active thread
-                       
-                       beq-    vsret                                   ; Nobody owns the vector, no save required...
-                       
-                       lwz             r10,THREAD_TOP_ACT(r10) ; Now get the activation that is running
-                       lwz             r9,ACT_MACT_VMXcpu(r12) ; Get the last CPU to use this context
-                       
-                       cmplw   r12,r10                                 ; Do we own the thread?
-                       cmplw   cr1,r9,r11                              ; Was the context for this processor? 
-                       bne+    vsret                                   ; Facility belongs to some other activation...
-                       li              r3,0                                    ; Assume we need a fix-me-up
-                       beq-    cr1,vsgoodcpu                   ; Facility last used on this processor...
-                       stw             r3,PP_VMX_THREAD(r6)    ; Clear owner because it was really on the other processor
-                       b               vsret                                   ; Bail now with no save...
-                       
-vsgoodcpu:     lwz             r3,ACT_MACT_VMX(r12)    ; Get the current vector savearea for the thread
-                       lwz             r9,ACT_MACT_VMXlvl(r12) ; Get our current level indicator
-                       
-                       cmplwi  cr1,r3,0                                ; Have we ever saved this facility context?
-                       beq-    cr1,vsneedone                   ; Never saved it, so we need an area...
-                       
-                       lwz             r8,SAVlvlvec(r3)                ; Get the level this savearea is for
-                       cmplwi  r8,1                                    ; See if this is a spare
-                       cmplw   cr1,r9,r8                               ; Correct level?
-                       beq+    vsusespare                              ; It is still live...
-                       beq-    cr1,vsret                               ; The current level is already saved, bail out...
-
-vsneedone:     li              r3,0                                    ; Tell the routine to allocate an area if none found
-                       bl              vsrchsave                               ; Find a free savearea
-                       
-                       mfsprg  r6,0                                    ; Get back per_processor block
-                       oris    r7,r7,hi16(SAVvmxvalid) ; Set the allocated bit
-                       lwz             r12,PP_VMX_THREAD(r6)   ; Get back our thread
-                       mtlr    r2                                              ; Restore return
-                       lwz             r8,ACT_MACT_VMX(r12)    ; Get the current top vector savearea
-                       lwz             r9,ACT_MACT_VMXlvl(r12) ; Get our current level indicator again         
-                       stw             r3,ACT_MACT_VMX(r12)    ; Set this as the latest vector savearea for the thread
-                       stw             r8,SAVprevec(r3)                ; And then chain this in front
-                       stw             r7,SAVflags(r3)                 ; Set the allocation flags
-                       stw             r12,SAVact(r3)                  ; Make sure we point to the right guy
-
-vsusespare:    stw             r9,SAVlvlvec(r3)                ; And set the level this savearea is for
+                       mflr    r2                                                              ; Save the return address
+
+vsretry:       mr.             r12,r12                                                 ; Anyone own the vector?
+                       lhz             r11,PP_CPU_NUMBER(r6)                   ; Get our CPU number
+                       beq-    vsret                                                   ; Nobody owns the vector, no save required...
+                       
+                       cmplw   cr1,r3,r12                                              ; Is the specified context live?
+                       
+                       isync                                                                   ; Force owner check first
+
+                       lwz             r9,VMXcpu(r12)                                  ; Get the cpu that context was last on          
+                       bne-    cr1,vsret                                               ; Specified context is not live
+                       
+                       cmplw   cr1,r9,r11                                              ; Was the context for this processor? 
+                       beq+    cr1,vsgoodcpu                                   ; Facility last used on this processor...
+
+                       b               vsret                                                   ; Someone else claimed this...
+                       
+                       .align  5
+                       
+vsgoodcpu:     lwz             r3,VMXsave(r12)                                 ; Get the current vector savearea for the thread
+                       lwz             r10,liveVRS(r6)                                 ; Get the right VRSave register
+                       lwz             r9,VMXlevel(r12)                                ; Get our current level indicator
+                       
+                       
+                       cmplwi  cr1,r3,0                                                ; Have we ever saved this facility context?
+                       beq-    cr1,vsneedone                                   ; Never saved it, so we need an area...
+                       
+                       lwz             r8,SAVlevel(r3)                                 ; Get the level this savearea is for
+                       mr.             r10,r10                                                 ; Is VRsave set to 0?
+                       cmplw   cr1,r9,r8                                               ; Correct level?
+                       bne-    cr1,vsneedone                                   ; Different level, so we need to save...
+                       
+                       bne+    vsret                                                   ; VRsave is non-zero so we need to keep what is saved...
+                                               
+                       lwz             r4,SAVprev(r3)                                  ; Pick up the previous area
+                       lwz             r5,SAVlevel(r4)                                 ; Get the level associated with save
+                       stw             r4,VMXsave(r12)                                 ; Dequeue this savearea
+                       stw             r5,VMXlevel(r12)                                ; Save the level
+       
+                       li              r3,0                                                    ; Clear
+                       stw             r3,VMXowner(r12)                                ; Show no live context here
+                       eieio
+
+vsbackout:     mr              r12,r0                                                  ; Set the saved MSR                     
+                       b               EXT(save_ret_join)                              ; Toss the savearea and return from there...
+
+                       .align  5
+
+vsneedone:     mr.             r10,r10                                                 ; Is VRsave set to 0?
+                       beq-    vsret                                                   ; Yeah, they do not care about any of them...
+
+                       bl              EXT(save_get)                                   ; Get a savearea for the context
+                       
+                       mfsprg  r6,0                                                    ; Get back per_processor block
+                       li              r4,SAVvector                                    ; Get vector tag                        
+                       lwz             r12,VMXowner(r6)                                ; Get back our context ID
+                       stb             r4,SAVflags+2(r3)                               ; Mark this savearea as a vector
+                       mr.             r12,r12                                                 ; See if we were disowned while away. Very, very small chance of it...
+                       beq-    vsbackout                                               ; If disowned, just toss savearea...
+                       lwz             r4,facAct(r12)                                  ; Get the activation associated with live context
+                       mtlr    r2                                                              ; Restore return
+                       lwz             r8,VMXsave(r12)                                 ; Get the current top vector savearea
+                       stw             r4,SAVact(r3)                                   ; Indicate the right activation for this context
+                       lwz             r9,VMXlevel(r12)                                ; Get our current level indicator again         
+                       stw             r3,VMXsave(r12)                                 ; Set this as the most current floating point context
+                       stw             r8,SAVprev(r3)                                  ; And then chain this in front
+
+                       stw             r9,SAVlevel(r3)                                 ; Set level in savearea
+
                        mfcr    r2                                              ; Save non-volatile CRs
                        lwz             r10,liveVRS(r6)                 ; Get the right VRSave register
                        lis             r9,0x5555                               ; Mask with odd bits set                
                        rlwinm  r11,r10,1,0,31                  ; Shift over 1
                        ori             r9,r9,0x5555                    ; Finish mask
-                       or              r12,r10,r11                             ; After this, even bits show which lines to zap
+                       or              r4,r10,r11                              ; After this, even bits show which lines to zap
                        
-                       andc    r11,r12,r9                              ; Clear out odd bits
+                       andc    r11,r4,r9                               ; Clear out odd bits
                        
                        la              r6,savevr0(r3)                  ; Point to line 0
                        rlwinm  r4,r11,15,0,15                  ; Move line 8-15 flags to high order odd bits
-                       la              r9,savevrvalid(r3)              ; Point to the saved register mask field
                        or              r4,r11,r4                               ; Set the odd bits
                                                                                        ; (bit 0 is line 0, bit 1 is line 8,
                                                                                        ; bit 2 is line 1, bit 3 is line 9, etc.
-                       dcba    br0,r9                                  ; Allocate the cache for it
                        rlwimi  r4,r10,16,16,31                 ; Put vrsave 0 - 15 into positions 16 - 31
                        la              r7,savevr2(r3)                  ; Point to line 1
                        mtcrf   255,r4                                  ; Load up the CRs
@@ -1470,30 +1405,15 @@ snovr28:
                        stvxl   v29,r11,r8                              ; Save VR29
                        
 snovr29:               
-                       mfvscr  v27                                             ; Get the VSCR
-                       la              r8,savevscr(r3)                 ; Point to the VSCR save area
                        bf              30,snovr30                              ; Do not save VR30...
                        stvxl   v30,br0,r7                              ; Save VR30
                        
 snovr30:
-                       dcba    br0,r8                                  ; Allocate VSCR savearea
                        bf              31,snovr31                              ; Do not save VR31...
                        stvxl   v31,r11,r7                              ; Save VR31
                        
 snovr31:
-                       add             r11,r11,r9                              ; Point to V27s saved value
-                       stvxl   v27,br0,r8                              ; Save the VSCR
-                       bt              27,v27ok                                ; V27 has been saved and is marked as wanted
-               
-                       lis             r11,hi16(EXT(QNaNbarbarian))    ; V27 is not wanted, so get empty value
-                       ori             r11,r11,lo16(EXT(QNaNbarbarian))
-
-v27ok:         mtcrf   255,r2                                  ; Restore all non-volatile CRs
-                       lvxl    v27,br0,r11                             ; Restore or load empty value into V27 because we used it       
-
-;
-;                      Save the current vector state into the savearea of the thread that owns it.
-; 
+                       mtcrf   255,r2                                  ; Restore all cr
 
 vsret:         mtmsr   r0                                              ; Put interrupts on if they were and vector off
                        isync
@@ -1518,1121 +1438,1082 @@ vsret:              mtmsr   r0                                              ; Put interrupts on if they were and vector off
  * 
  */
 
-ENTRY(vec_switch, TAG_NO_FRAME_USED)
+                       .align  5
+                       .globl  EXT(vec_switch)
+
+LEXT(vec_switch)
 
 #if DEBUG
-#if GDDBG
-                       mr              r7,r4                                   ; Save input parameter
-                       lis             r3,hi16(EXT(vec_trap_count))    ; Get address of vector trap counter
-                       ori             r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
-                       lwz             r1,0(r3)
-                       lis             r5,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       ori             r5,r5,lo16(EXT(GratefulDeb))    ; Put in bottom part
-                       addi    r1,r1,1
-                       mtlr    r5                                              ; Set link register
-                       stw             r1,0(r3)
-                       mr              r4,r1
-                       lis             r3,1
-                       blrl                                                    ; Display count
-                       mr              r4,r7                                   ; Restore the parameter
-#else
                        lis             r3,hi16(EXT(vec_trap_count))    ; Get address of vector trap counter
                        ori             r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
                        lwz             r1,0(r3)
                        addi    r1,r1,1
                        stw             r1,0(r3)
-#endif
 #endif /* DEBUG */
 
-                       mfsprg  r6,0                                    /* Get the per_processor block */
-                       mfmsr   r19                                             /* Get the current MSR */
+                       mfsprg  r26,0                                                   ; Get the per_processor block
+                       mfmsr   r19                                                             ; Get the current MSR 
                        
-                       lwz             r10,PP_CPU_DATA(r6)             /* Get the CPU data pointer */
-                       lwz             r12,PP_VMX_THREAD(r6)   /* Get the thread that owns the vector */
-                       lwz             r10,CPU_ACTIVE_THREAD(r10)      /* Get the pointer to the active thread */
-                       oris    r19,r19,hi16(MASK(MSR_VEC))     /* Enable the vector feature */
-                       lwz             r17,THREAD_TOP_ACT(r10) /* Now get the activation that is running */
-                       
-;                      R12 has the "old" activation
-;                      R17 has the "new" activation
-
-#if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x5F01                               ; (TEST/DEBUG)
-                       mr              r3,r12                                  ; (TEST/DEBUG)
-                       mr              r5,r17                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#if GDDBG
-                       lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       mr              r18,r4                                  ; Save this
-                       ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
-                       mr              r4,r2                                   ; Set value
-                       mtlr    r3                                              ; Set link register
-                       li              r3,1                                    ; Display address
-                       blrl                                                    ; Display it
-                       mr              r4,r18                                  ; Restore it
-                       mfsprg  r6,0                                    ; Get the per_processor block back
-#endif
-#endif 
-                       mr.             r12,r12                                 ; See if there is any live vector status
-                       
-                       lhz             r18,PP_CPU_NUMBER(r6)   ; Get our CPU number
-               
-                       mtmsr   r19                                             /* Set vector available */
+                       mr              r25,r4                                                  ; Save the entry savearea
+                       lwz             r22,VMXowner(r26)                               ; Get the thread that owns the vector
+                       lwz             r10,PP_ACTIVE_THREAD(r26)               ; Get the pointer to the active thread
+                       oris    r19,r19,hi16(MASK(MSR_VEC))             ; Enable the vector feature
+                       lwz             r17,THREAD_TOP_ACT(r10)                 ; Now get the activation that is running
+                               
+                       mtmsr   r19                                                             ; Enable vector instructions
                        isync
                        
-                       
-                       beq-    vsnosave                                ; No live context, so nothing to save...
-       
-                       lwz             r19,ACT_MACT_VMXcpu(r12)        ; Get the "old" active CPU
-                       lwz             r15,ACT_MACT_PCB(r12)   ; Get the current level of the "old" one
-                       cmplw   r18,r19                                 ; Check the CPU that the old context is live on
-                       lwz             r14,ACT_MACT_VMX(r12)   ; Point to the top of the old context stack
-                       bne-    vsnosave                                ; Context is not live if used on a different CPU...
-                       lwz             r13,ACT_MACT_VMXlvl(r12)        ; Get the "old" active level
-                       
-;
-;                      First, check to see if all we are doing is enabling because the
-;                      "new" context is live.
-;
-#if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x5F02                               ; (TEST/DEBUG)
-                       mr              r1,r15                                  ; (TEST/DEBUG)
-                       mr              r3,r13                                  ; (TEST/DEBUG)
-                       mr              r5,r14                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#if GDDBG
-                       lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       mr              r8,r4                                   ; Save this
-                       ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
-                       mr              r4,r2                                   ; Set value
-                       mtlr    r3                                              ; Set link register
-                       li              r3,1                                    ; Display address
-                       blrl                                                    ; Display it
-                       mr              r4,r8                                   ; Restore it
-#endif
-#endif 
+                       lwz             r27,ACT_MACT_PCB(r17)                   ; Get the current level
+                       lwz             r29,curctx(r17)                                 ; Grab the current context anchor of the current thread
 
-                       cmplw   cr1,r12,r17                             ; Is the "old" activation and the "new" the same?
-                       cmplwi  cr2,r14,0                               ; Is there any saved context on the "old" activation?
-                       bne+    cr1,vsmstsave                   ; The activations are different so "old" context must be saved...
+;                      R22 has the "old" context anchor
+;                      R29 has the "new" context anchor
 
-;
-;                      Here we know that both the "old" and "new" activations are the same.  We will
-;                      check the current level and active levels.  If they are the same, the context is
-;                      already live, so all we do is turn on the facility and invalidate the top
-;                      savearea. 
-;              
-;                      If the current level, the active level, and the top savearea level are the
-;                      same, then the context was saved as part of a thread context switch and neither
-;                      needs saving or restoration.
-;                      
-;                      In all other cases, the context must be saved unless we are just re-enabling
-;                      vector.
-;
+#if FPVECDBG
+                       lis             r0,HIGH_ADDR(CutTrace)                  ; (TEST/DEBUG)
+                       li              r2,0x5F01                                               ; (TEST/DEBUG)
+                       mr              r3,r22                                                  ; (TEST/DEBUG)
+                       mr              r5,r29                                                  ; (TEST/DEBUG)
+                       oris    r0,r0,LOW_ADDR(CutTrace)                ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
+#endif 
 
-                       cmplw   r13,r15                                 ; Are the levels the same?
-                       cmplwi  cr2,r14,0                               ; Is there any saved context?
-                       bne-    vsmstsave                               ; Levels are different, we need to save...
+                       lhz             r16,PP_CPU_NUMBER(r26)                  ; Get the current CPU number
                        
-                       beq-    cr2,vrenable                    ; No saved context at all, enable and go...
+vsvretry:      mr.             r22,r22                                                 ; See if there is any live vector status
                        
-                       lwz             r20,SAVlvlvec(r14)              ; Get the level of the top savearea
+                       beq-    vsnosave                                                ; No live context, so nothing to save...
 
-#if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x5F03                               ; (TEST/DEBUG)
-                       mr              r3,r15                                  ; (TEST/DEBUG)
-                       mr              r5,r20                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#if GDDBG
-                       lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       mr              r8,r4                                   ; Save this
-                       ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
-                       mr              r4,r2                                   ; Set value
-                       mtlr    r3                                              ; Set link register
-                       li              r3,1                                    ; Display address
-                       blrl                                                    ; Display it
-                       mr              r4,r8                                   ; Restore it
-#endif
-#endif 
-                       cmplw   r15,r20                                 ; Is the top level the same as the current?
-                       li              r0,1                                    ; Get the invalid flag
-                       bne-    vrenable                                ; Not the same, just enable and go...
-                       
-                       stw             r0,SAVlvlvec(r14)               ; Invalidate that top savearea
+                       isync                                                                   ; Make sure we see this in the right order
 
-                       b               vrenable                                ; Then enable and go...
+                       lwz             r30,VMXsave(r22)                                ; Get the top savearea
+                       cmplw   cr2,r22,r29                                             ; Are both old and new the same context?
+                       lwz             r18,VMXcpu(r22)                                 ; Get the last CPU we ran on
+                       cmplwi  cr1,r30,0                                               ; Anything saved yet?
+                       cmplw   r18,r16                                                 ; Make sure we are on the right processor
+                       lwz             r31,VMXlevel(r22)                               ; Get the context level
                        
+                       lwz             r10,liveVRS(r26)                                ; Get the right VRSave register
+
+                       bne-    vsnosave                                                ; No, not on the same processor...
+               
 ;
-;                      We need to save the "old" context here.  The LIFO queueing scheme works
-;                      out for all cases because if both the "new" and "old" activations are the
-;                      same, there can not be any saved state to load.  the "new" level is
-;                      truely new.
+;                      Check to see if the live context has already been saved.
+;                      Also check to see if all we are here just to re-enable the MSR
+;                      and handle specially if so.
 ;
-;                      When we save the context, we either use a new savearea, or the free
-;                      one that is cached at the head of the list.
+
+                       cmplw   r31,r27                                                 ; See if the current and active levels are the same
+                       crand   cr0_eq,cr2_eq,cr0_eq                    ; Remember if both the levels and contexts are the same
+                       li              r8,0                                                    ; Clear this
                        
-vsmstsave:     beq-    cr2,vsgetsave                   ; There is no possible cached save area
+                       beq-    vsthesame                                               ; New and old are the same, just go enable...
+
+                       cmplwi  cr2,r10,0                                               ; Check VRSave to see if we really need to save anything...
+                       beq-    cr1,vsmstsave                                   ; Not saved yet, go do it...
                        
-                       lwz             r5,SAVlvlvec(r14)               ; Get the level of first facility savearea
-#if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x5F04                               ; (TEST/DEBUG)
-                       mr              r3,r15                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#if GDDBG
-                       lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       mr              r8,r4                                   ; Save this
-                       mr              r7,r5                                   ; Save this
-                       ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
-                       mr              r4,r2                                   ; Set value
-                       mtlr    r3                                              ; Set link register
-                       li              r3,1                                    ; Display address
-                       blrl                                                    ; Display it
-                       mr              r4,r8                                   ; Restore it
-                       mr              r5,r7                                   ; Restore it
-#endif
-#endif 
-                       mr              r3,r14                                  ; Assume we are invalid
-                       cmplwi  r5,1                                    ; Is it invalid?
-                       cmplw   cr1,r5,r13                              ; Is the SA level the active one?
-                       beq+    vsusecache                              ; Invalid, just use it...
-                       beq-    cr1,vsnosave                    ; The SA level is active, it is already saved...
+                       lwz             r11,SAVlevel(r30)                               ; Get the level of top saved context
                        
-vsgetsave:     mr              r3,r4                                   ; Use the interrupt save as the context savearea if none cached
+                       cmplw   r31,r11                                                 ; Are live and saved the same?
+
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x5F05                               ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#if GDDBG
-                       lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       mr              r8,r4                                   ; Save this
-                       ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
-                       mr              r4,r2                                   ; Set value
-                       mtlr    r3                                              ; Set link register
-                       li              r3,1                                    ; Display address
-                       blrl                                                    ; Display it
-                       mr              r4,r8                                   ; Restore it
-                       mr              r3,r8                                   ; This too
-#endif
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x5F02                                               ; (TEST/DEBUG)
+                       mr              r3,r30                                                  ; (TEST/DEBUG)
+                       mr              r5,r31                                                  ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
+
+                       bne-    vsmstsave                                               ; Live context has not been saved yet...
+
+                       bne-    cr2,vsnosave                                    ; Live context saved and VRSave not 0, no save and keep context...
                        
-                       bl              vsrchsave                               ; Find a free savearea
+                       lwz             r4,SAVprev(r30)                                 ; Pick up the previous area
+                       li              r5,0                                                    ; Assume this is the only one (which should be the ususal case)
+                       mr.             r4,r4                                                   ; Was this the only one?
+                       stw             r4,VMXsave(r22)                                 ; Dequeue this savearea
+                       beq+    vsonlyone                                               ; This was the only one...
+                       lwz             r5,SAVlevel(r4)                                 ; Get the level associated with previous save
 
-                       stw             r3,ACT_MACT_VMX(r12)    ; Set this as the latest context savearea for the thread
-                       mfsprg  r6,0                                    ; Get back per_processor block
-                       stw             r14,SAVprevec(r3)               ; And then chain this in front
-                       oris    r7,r7,hi16(SAVvmxvalid) ; Set the allocated bit
-                       stw             r12,SAVact(r3)                  ; Make sure we point to the right guy
-                       stw             r7,SAVflags(r3)                 ; Set the allocation flags
+vsonlyone:     stw             r5,VMXlevel(r22)                                ; Save the level
+                       stw             r8,VMXowner(r26)                                ; Clear owner
+                       eieio
+                       mr              r3,r30                                                  ; Copy the savearea we are tossing
+                       bl              EXT(save_ret)                                   ; Toss the savearea
+                       b               vsnosave                                                ; Go load up the context...
+
+                       .align  5
+
+       
+vsmstsave:     stw             r8,VMXowner(r26)                                ; Clear owner
+                       eieio
+                       beq-    cr2,vsnosave                                    ; The VRSave was 0, so there is nothing to save...
+
+                       bl              EXT(save_get)                                   ; Go get a savearea
+
+                       lwz             r12,facAct(r22)                                 ; Get the activation associated with the context
+                       stw             r3,VMXsave(r22)                                 ; Set this as the latest context savearea for the thread
+
+                       stw             r30,SAVprev(r3)                                 ; Point us to the old context
+                       stw             r31,SAVlevel(r3)                                ; Tag our level
+                       li              r7,SAVvector                                    ; Get the vector ID
+                       stw             r12,SAVact(r3)                                  ; Make sure we point to the right guy
+                       stb             r7,SAVflags+2(r3)                               ; Set that we have a vector save area
 
-vsusecache:    la              r11,savevr0(r3)                 ; Point to the 1st line in area
-                       stw             r13,SAVlvlvec(r3)               ; Set this context level
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x5F06                               ; (TEST/DEBUG)
-                       mr              r5,r13                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#if GDDBG
-                       mr              r10,r3
-                       lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       mr              r8,r4                                   ; Save this
-                       ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
-                       mr              r4,r2                                   ; Set value
-                       mtlr    r3                                              ; Set link register
-                       li              r3,1                                    ; Display address
-                       blrl                                                    ; Display it
-                       mr              r4,r8                                   ; Restore it
-                       mr              r3,r10
-                       mfsprg  r6,0                                    ; Get back per_processor block
-#endif
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x5F03                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
 
-vsgotsave:     
-                       lwz             r10,liveVRS(r6)                 ; Get the right VRSave register
-                       lis             r9,0x5555                               ; Mask with odd bits set                
-                       rlwinm  r11,r10,1,0,31                  ; Shift over 1
-                       ori             r9,r9,0x5555                    ; Finish mask
-                       or              r12,r10,r11                             ; After this, even bits show which lines to zap
-                       
-                       stw             r13,SAVlvlvec(r3)               ; Set the savearea level
-                       andc    r13,r12,r9                              ; Clear out odd bits
-                       
-                       la              r20,savevr0(r3)                 ; Point to line 0
-                       rlwinm  r24,r13,15,0,15                 ; Move line 8-15 flags to high order odd bits
-                       la              r23,savevrvalid(r3)             ; Point to the saved register mask field
-                       or              r24,r13,r24                             ; Set the odd bits
-                                                                                       ; (bit 0 is line 0, bit 1 is line 8,
-                                                                                       ; bit 2 is line 1, bit 3 is line 9, etc.
-                       dcba    br0,r23                                 ; Allocate the cache for it
-                       rlwimi  r24,r10,16,16,31                ; Put vrsave 0 - 15 into positions 16 - 31
-                       la              r21,savevr2(r3)                 ; Point to line 1
-                       mtcrf   255,r24                                 ; Load up the CRs
-                       stw             r10,savevrvalid(r3)             ; Save the validity information
-                       mr              r22,r20                                 ; Start registers off
+                       lwz             r10,liveVRS(r26)                                ; Get the right VRSave register
+                       lis             r9,0x5555                                               ; Mask with odd bits set                
+                       rlwinm  r11,r10,1,0,31                                  ; Shift over 1
+                       ori             r9,r9,0x5555                                    ; Finish mask
+                       or              r21,r10,r11                                             ; After this, even bits show which lines to zap
+                       
+                       andc    r13,r21,r9                                              ; Clear out odd bits
+                       
+                       la              r11,savevr0(r3)                                 ; Point to line 0
+                       rlwinm  r24,r13,15,0,15                                 ; Move line 8-15 flags to high order odd bits
+                       or              r24,r13,r24                                             ; Set the odd bits
+                                                                                                       ; (bit 0 is line 0, bit 1 is line 8,
+                                                                                                       ; bit 2 is line 1, bit 3 is line 9, etc.
+                       rlwimi  r24,r10,16,16,31                                ; Put vrsave 0 - 15 into positions 16 - 31
+                       la              r21,savevr2(r3)                                 ; Point to line 1
+                       mtcrf   255,r24                                                 ; Load up the CRs
+                       stw             r10,savevrvalid(r3)                             ; Save the validity information
+                       mr              r12,r11                                                 ; Start registers off
 ;      
 ;                      Save the current vector state
 ;
                                                
-                       bf              0,nol0                                  ; No line 0 to do...
-                       dcba    br0,r20                                 ; Allocate cache line 0
+                       bf              0,nol0                                                  ; No line 0 to do...
+                       dcba    br0,r11                                                 ; Allocate cache line 0
                        
 nol0:          
-                       la              r20,savevr4(r3)                 ; Point to line 2
-                       bf              2,nol1                                  ; No line 1 to do...
-                       dcba    br0,r21                                 ; Allocate cache line 1
+                       la              r11,savevr4(r3)                                 ; Point to line 2
+                       bf              2,nol1                                                  ; No line 1 to do...
+                       dcba    br0,r21                                                 ; Allocate cache line 1
                        
 nol1:          
-                       la              r21,savevr6(r3)                 ; Point to line 3
-                       bf              4,nol2                                  ; No line 2 to do...
-                       dcba    br0,r20                                 ; Allocate cache line 2
+                       la              r21,savevr6(r3)                                 ; Point to line 3
+                       bf              4,nol2                                                  ; No line 2 to do...
+                       dcba    br0,r11                                                 ; Allocate cache line 2
                        
 nol2:          
-                       li              r30,16                                  ; Get offset for odd registers
-                       bf              16,novr0                                ; Do not save VR0...
-                       stvxl   v0,br0,r22                              ; Save VR0
+                       li              r14,16                                                  ; Get offset for odd registers
+                       bf              16,novr0                                                ; Do not save VR0...
+                       stvxl   v0,br0,r12                                              ; Save VR0
                        
 novr0:         
-                       la              r23,savevr2(r3)                 ; Point to V2/V3 pair
-                       bf              17,novr1                                ; Do not save VR1...
-                       stvxl   v1,r30,r22                              ; Save VR1
+                       la              r13,savevr2(r3)                                 ; Point to V2/V3 pair
+                       bf              17,novr1                                                ; Do not save VR1...
+                       stvxl   v1,r14,r12                                              ; Save VR1
                        
 novr1:
-                       la              r20,savevr8(r3)                 ; Point to line 4
-                       bf              6,nol3                                  ; No line 3 to do...
-                       dcba    br0,r21                                 ; Allocate cache line 3
+                       la              r11,savevr8(r3)                                 ; Point to line 4
+                       bf              6,nol3                                                  ; No line 3 to do...
+                       dcba    br0,r21                                                 ; Allocate cache line 3
                        
 nol3:          
-                       la              r22,savevr4(r3)                 ; Point to V4/V5 pair
-                       bf              18,novr2                                ; Do not save VR2...
-                       stvxl   v2,br0,r23                              ; Save VR2
+                       la              r12,savevr4(r3)                                 ; Point to V4/V5 pair
+                       bf              18,novr2                                                ; Do not save VR2...
+                       stvxl   v2,br0,r13                                              ; Save VR2
                        
 novr2:
-                       bf              19,novr3                                ; Do not save VR3...
-                       stvxl   v3,r30,r23                              ; Save VR3
+                       bf              19,novr3                                                ; Do not save VR3...
+                       stvxl   v3,r14,r13                                              ; Save VR3
                        
 novr3:
 ;
 ;                      Note: CR4 is now free
 ;
-                       la              r21,savevr10(r3)                ; Point to line 5
-                       bf              8,nol4                                  ; No line 4 to do...
-                       dcba    br0,r20                                 ; Allocate cache line 4
+                       la              r21,savevr10(r3)                                ; Point to line 5
+                       bf              8,nol4                                                  ; No line 4 to do...
+                       dcba    br0,r11                                                 ; Allocate cache line 4
                        
 nol4:          
-                       la              r23,savevr6(r3)                 ; Point to R6/R7 pair
-                       bf              20,novr4                                ; Do not save VR4...
-                       stvxl   v4,br0,r22                              ; Save VR4
+                       la              r13,savevr6(r3)                                 ; Point to R6/R7 pair
+                       bf              20,novr4                                                ; Do not save VR4...
+                       stvxl   v4,br0,r12                                              ; Save VR4
                        
 novr4:
-                       bf              21,novr5                                ; Do not save VR5...
-                       stvxl   v5,r30,r22                              ; Save VR5
+                       bf              21,novr5                                                ; Do not save VR5...
+                       stvxl   v5,r14,r12                                              ; Save VR5
                        
 novr5:
-                       mtcrf   0x08,r10                                ; Set CRs for registers 16-19
-                       la              r20,savevr12(r3)                ; Point to line 6
-                       bf              10,nol5                                 ; No line 5 to do...
-                       dcba    br0,r21                                 ; Allocate cache line 5
+                       mtcrf   0x08,r10                                                ; Set CRs for registers 16-19
+                       la              r11,savevr12(r3)                                ; Point to line 6
+                       bf              10,nol5                                                 ; No line 5 to do...
+                       dcba    br0,r21                                                 ; Allocate cache line 5
                        
 nol5:          
-                       la              r22,savevr8(r3)                 ; Point to V8/V9 pair
-                       bf              22,novr6                                ; Do not save VR6...
-                       stvxl   v6,br0,r23                              ; Save VR6
+                       la              r12,savevr8(r3)                                 ; Point to V8/V9 pair
+                       bf              22,novr6                                                ; Do not save VR6...
+                       stvxl   v6,br0,r13                                              ; Save VR6
                        
 novr6:
-                       bf              23,novr7                                ; Do not save VR7...
-                       stvxl   v7,r30,r23                              ; Save VR7
+                       bf              23,novr7                                                ; Do not save VR7...
+                       stvxl   v7,r14,r13                                              ; Save VR7
                        
 novr7:
 ;
 ;                      Note: CR5 is now free
 ;
-                       la              r21,savevr14(r3)                ; Point to line 7
-                       bf              12,nol6                                 ; No line 6 to do...
-                       dcba    br0,r20                                 ; Allocate cache line 6
+                       la              r21,savevr14(r3)                                ; Point to line 7
+                       bf              12,nol6                                                 ; No line 6 to do...
+                       dcba    br0,r11                                                 ; Allocate cache line 6
                        
 nol6:          
-                       la              r23,savevr10(r3)                ; Point to V10/V11 pair
-                       bf              24,novr8                                ; Do not save VR8...
-                       stvxl   v8,br0,r22                              ; Save VR8
+                       la              r13,savevr10(r3)                                ; Point to V10/V11 pair
+                       bf              24,novr8                                                ; Do not save VR8...
+                       stvxl   v8,br0,r12                                              ; Save VR8
                        
 novr8:
-                       bf              25,novr9                                ; Do not save VR9...
-                       stvxl   v9,r30,r22                              ; Save VR9
+                       bf              25,novr9                                                ; Do not save VR9...
+                       stvxl   v9,r14,r12                                              ; Save VR9
                        
 novr9:
-                       mtcrf   0x04,r10                                ; Set CRs for registers 20-23
-                       la              r20,savevr16(r3)                ; Point to line 8
-                       bf              14,nol7                                 ; No line 7 to do...
-                       dcba    br0,r21                                 ; Allocate cache line 7
+                       mtcrf   0x04,r10                                                ; Set CRs for registers 20-23
+                       la              r11,savevr16(r3)                                ; Point to line 8
+                       bf              14,nol7                                                 ; No line 7 to do...
+                       dcba    br0,r21                                                 ; Allocate cache line 7
                        
 nol7:          
-                       la              r22,savevr12(r3)                ; Point to V12/V13 pair
-                       bf              26,novr10                               ; Do not save VR10...
-                       stvxl   v10,br0,r23                             ; Save VR10
+                       la              r12,savevr12(r3)                                ; Point to V12/V13 pair
+                       bf              26,novr10                                               ; Do not save VR10...
+                       stvxl   v10,br0,r13                                             ; Save VR10
                        
 novr10:
-                       bf              27,novr11                               ; Do not save VR11...
-                       stvxl   v11,r30,r23                             ; Save VR11
+                       bf              27,novr11                                               ; Do not save VR11...
+                       stvxl   v11,r14,r13                                             ; Save VR11
                        
 novr11:
 
 ;
 ;                      Note: CR6 is now free
 ;
-                       la              r21,savevr18(r3)                ; Point to line 9
-                       bf              1,nol8                                  ; No line 8 to do...
-                       dcba    br0,r20                                 ; Allocate cache line 8
+                       la              r21,savevr18(r3)                                ; Point to line 9
+                       bf              1,nol8                                                  ; No line 8 to do...
+                       dcba    br0,r11                                                 ; Allocate cache line 8
                        
 nol8:          
-                       la              r23,savevr14(r3)                ; Point to V14/V15 pair
-                       bf              28,novr12                               ; Do not save VR12...
-                       stvxl   v12,br0,r22                             ; Save VR12
+                       la              r13,savevr14(r3)                                ; Point to V14/V15 pair
+                       bf              28,novr12                                               ; Do not save VR12...
+                       stvxl   v12,br0,r12                                             ; Save VR12
                        
 novr12:
-                       bf              29,novr13                               ; Do not save VR13...
-                       stvxl   v13,r30,r22                             ; Save VR13
+                       bf              29,novr13                                               ; Do not save VR13...
+                       stvxl   v13,r14,r12                                             ; Save VR13
                        
 novr13:
-                       mtcrf   0x02,r10                                ; Set CRs for registers 24-27
-                       la              r20,savevr20(r3)                ; Point to line 10
-                       bf              3,nol9                                  ; No line 9 to do...
-                       dcba    br0,r21                                 ; Allocate cache line 9
+                       mtcrf   0x02,r10                                                ; Set CRs for registers 24-27
+                       la              r11,savevr20(r3)                                ; Point to line 10
+                       bf              3,nol9                                                  ; No line 9 to do...
+                       dcba    br0,r21                                                 ; Allocate cache line 9
                        
 nol9:          
-                       la              r22,savevr16(r3)                ; Point to V16/V17 pair
-                       bf              30,novr14                               ; Do not save VR14...
-                       stvxl   v14,br0,r23                             ; Save VR14
+                       la              r12,savevr16(r3)                                ; Point to V16/V17 pair
+                       bf              30,novr14                                               ; Do not save VR14...
+                       stvxl   v14,br0,r13                                             ; Save VR14
                        
 novr14:
-                       bf              31,novr15                               ; Do not save VR15...
-                       stvxl   v15,r30,r23                             ; Save VR15
+                       bf              31,novr15                                               ; Do not save VR15...
+                       stvxl   v15,r14,r13                                             ; Save VR15
                        
 novr15:
 ;
 ;                      Note: CR7 is now free
 ;
-                       la              r21,savevr22(r3)                ; Point to line 11
-                       bf              5,nol10                                 ; No line 10 to do...
-                       dcba    br0,r20                                 ; Allocate cache line 10
+                       la              r21,savevr22(r3)                                ; Point to line 11
+                       bf              5,nol10                                                 ; No line 10 to do...
+                       dcba    br0,r11                                                 ; Allocate cache line 10
                        
 nol10:         
-                       la              r23,savevr18(r3)                ; Point to V18/V19 pair
-                       bf              16,novr16                               ; Do not save VR16...
-                       stvxl   v16,br0,r22                             ; Save VR16
+                       la              r13,savevr18(r3)                                ; Point to V18/V19 pair
+                       bf              16,novr16                                               ; Do not save VR16...
+                       stvxl   v16,br0,r12                                             ; Save VR16
                        
 novr16:
-                       bf              17,novr17                               ; Do not save VR17...
-                       stvxl   v17,r30,r22                             ; Save VR17
+                       bf              17,novr17                                               ; Do not save VR17...
+                       stvxl   v17,r14,r12                                             ; Save VR17
                        
 novr17:
-                       mtcrf   0x01,r10                                ; Set CRs for registers 28-31
+                       mtcrf   0x01,r10                                                ; Set CRs for registers 28-31
 ;
 ;                      Note: All registers have been or are accounted for in CRs
 ;
-                       la              r20,savevr24(r3)                ; Point to line 12
-                       bf              7,nol11                                 ; No line 11 to do...
-                       dcba    br0,r21                                 ; Allocate cache line 11
+                       la              r11,savevr24(r3)                                ; Point to line 12
+                       bf              7,nol11                                                 ; No line 11 to do...
+                       dcba    br0,r21                                                 ; Allocate cache line 11
                        
 nol11:         
-                       la              r22,savevr20(r3)                ; Point to V20/V21 pair
-                       bf              18,novr18                               ; Do not save VR18...
-                       stvxl   v18,br0,r23                             ; Save VR18
+                       la              r12,savevr20(r3)                                ; Point to V20/V21 pair
+                       bf              18,novr18                                               ; Do not save VR18...
+                       stvxl   v18,br0,r13                                             ; Save VR18
                        
 novr18:
-                       bf              19,novr19                               ; Do not save VR19...
-                       stvxl   v19,r30,r23                             ; Save VR19
+                       bf              19,novr19                                               ; Do not save VR19...
+                       stvxl   v19,r14,r13                                             ; Save VR19
                        
 novr19:
-                       la              r21,savevr26(r3)                ; Point to line 13
-                       bf              9,nol12                                 ; No line 12 to do...
-                       dcba    br0,r20                                 ; Allocate cache line 12
+                       la              r21,savevr26(r3)                                ; Point to line 13
+                       bf              9,nol12                                                 ; No line 12 to do...
+                       dcba    br0,r11                                                 ; Allocate cache line 12
                        
 nol12:         
-                       la              r23,savevr22(r3)                ; Point to V22/V23 pair
-                       bf              20,novr20                               ; Do not save VR20...
-                       stvxl   v20,br0,r22                             ; Save VR20
+                       la              r13,savevr22(r3)                                ; Point to V22/V23 pair
+                       bf              20,novr20                                               ; Do not save VR20...
+                       stvxl   v20,br0,r12                                             ; Save VR20
                        
 novr20:
-                       bf              21,novr21                               ; Do not save VR21...
-                       stvxl   v21,r30,r22                             ; Save VR21
+                       bf              21,novr21                                               ; Do not save VR21...
+                       stvxl   v21,r14,r12                                             ; Save VR21
                        
 novr21:
-                       la              r20,savevr28(r3)                ; Point to line 14
-                       bf              11,nol13                                ; No line 13 to do...
-                       dcba    br0,r21                                 ; Allocate cache line 13
+                       la              r11,savevr28(r3)                                ; Point to line 14
+                       bf              11,nol13                                                ; No line 13 to do...
+                       dcba    br0,r21                                                 ; Allocate cache line 13
                        
 nol13:         
-                       la              r22,savevr24(r3)                ; Point to V24/V25 pair
-                       bf              22,novr22                               ; Do not save VR22...
-                       stvxl   v22,br0,r23                             ; Save VR22
+                       la              r12,savevr24(r3)                                ; Point to V24/V25 pair
+                       bf              22,novr22                                               ; Do not save VR22...
+                       stvxl   v22,br0,r13                                             ; Save VR22
                        
 novr22:
-                       bf              23,novr23                               ; Do not save VR23...
-                       stvxl   v23,r30,r23                             ; Save VR23
+                       bf              23,novr23                                               ; Do not save VR23...
+                       stvxl   v23,r14,r13                                             ; Save VR23
                        
 novr23:
-                       la              r21,savevr30(r3)                ; Point to line 15
-                       bf              13,nol14                                ; No line 14 to do...
-                       dcba    br0,r20                                 ; Allocate cache line 14
+                       la              r21,savevr30(r3)                                ; Point to line 15
+                       bf              13,nol14                                                ; No line 14 to do...
+                       dcba    br0,r11                                                 ; Allocate cache line 14
                        
 nol14:         
-                       la              r23,savevr26(r3)                ; Point to V26/V27 pair
-                       bf              24,novr24                               ; Do not save VR24...
-                       stvxl   v24,br0,r22                             ; Save VR24
+                       la              r13,savevr26(r3)                                ; Point to V26/V27 pair
+                       bf              24,novr24                                               ; Do not save VR24...
+                       stvxl   v24,br0,r12                                             ; Save VR24
                        
 novr24:
-                       bf              25,novr25                               ; Do not save VR25...
-                       stvxl   v25,r30,r22                             ; Save VR25
+                       bf              25,novr25                                               ; Do not save VR25...
+                       stvxl   v25,r14,r12                                             ; Save VR25
                        
 novr25:
-                       bf              15,nol15                                ; No line 15 to do...
-                       dcba    br0,r21                                 ; Allocate cache line 15
+                       bf              15,nol15                                                ; No line 15 to do...
+                       dcba    br0,r21                                                 ; Allocate cache line 15
                        
 nol15:         
 ;
 ;                      Note: All cache lines allocated now
 ;
-                       la              r22,savevr28(r3)                ; Point to V28/V29 pair
-                       bf              26,novr26                               ; Do not save VR26...
-                       stvxl   v26,br0,r23                             ; Save VR26
+                       la              r12,savevr28(r3)                                ; Point to V28/V29 pair
+                       bf              26,novr26                                               ; Do not save VR26...
+                       stvxl   v26,br0,r13                                             ; Save VR26
                        
 novr26:
-                       bf              27,novr27                               ; Do not save VR27...
-                       stvxl   v27,r30,r23                             ; Save VR27
+                       bf              27,novr27                                               ; Do not save VR27...
+                       stvxl   v27,r14,r13                                             ; Save VR27
                        
 novr27:
-                       la              r23,savevr30(r3)                ; Point to V30/V31 pair
-                       bf              28,novr28                               ; Do not save VR28...
-                       stvxl   v28,br0,r22                             ; Save VR28
+                       la              r13,savevr30(r3)                                ; Point to V30/V31 pair
+                       bf              28,novr28                                               ; Do not save VR28...
+                       stvxl   v28,br0,r12                                             ; Save VR28
                        
 novr28:                
-                       mfvscr  v27                                             ; Get the VSCR
-                       bf              29,novr29                               ; Do not save VR29...
-                       stvxl   v29,r30,r22                             ; Save VR29
+                       bf              29,novr29                                               ; Do not save VR29...
+                       stvxl   v29,r14,r12                                             ; Save VR29
                        
 novr29:                
-                       la              r22,savevscr(r3)                ; Point to the VSCR save area
-                       bf              30,novr30                               ; Do not save VR30...
-                       stvxl   v30,br0,r23                             ; Save VR30
+                       bf              30,novr30                                               ; Do not save VR30...
+                       stvxl   v30,br0,r13                                             ; Save VR30
                        
 novr30:
-                       dcba    br0,r22                                 ; Allocate VSCR savearea
-                       bf              31,novr31                               ; Do not save VR31...
-                       stvxl   v31,r30,r23                             ; Save VR31
+                       bf              31,novr31                                               ; Do not save VR31...
+                       stvxl   v31,r14,r13                                             ; Save VR31
                        
 novr31:
-                       stvxl   v27,br0,r22                             ; Save the VSCR
 
                        
 
-/*
- *                     Now check out the current thread and see if we need to load up his context.
- *                     If we do (and this should be the normal case), do it and then release the
- *                     savearea.
- *                     
- *                     If we don't (remember, we already took care of the case where we just enable
- *                     the vector), we need to fill the registers with garbage, because this thread has 
- *                     never used them before and some thieving bastard could hack the old values
- *                     of some thread!  Just imagine what would happen if they could!  Why, nothing
- *                     would be safe! My Gosh! It's terrifying!
- */
+;
+;                      The context is all saved now and the facility is free.
+;
+;                      If we do not we need to fill the registers with junk, because this level has 
+;                      never used them before and some thieving bastard could hack the old values
+;                      of some thread!  Just imagine what would happen if they could!  Why, nothing
+;                      would be safe! My God! It is terrifying!
+;
+;                      Also, along the way, thanks to Ian Ollmann, we generate the 0x7FFFDEAD (QNaNbarbarian)
+;                      constant that we may need to fill unused vector registers.
+;
+
+
 
-vsnosave:      lwz             r15,ACT_MACT_PCB(r17)   ; Get the current level of the "new" one
-                       lwz             r14,ACT_MACT_VMX(r17)   ; Point to the top of the "new" context stack
-                       lwz             r13,ACT_MACT_VMXlvl(r17)        ; Get the "new" active level
+
+vsnosave:      vspltisb v31,-10                                                ; Get 0xF6F6F6F6        
+                       lwz             r15,ACT_MACT_PCB(r17)                   ; Get the current level of the "new" one
+                       vspltisb v30,5                                                  ; Get 0x05050505        
+                       lwz             r19,VMXcpu(r29)                                 ; Get the last CPU we ran on
+                       vspltish v29,4                                                  ; Get 0x00040004
+                       lwz             r14,VMXsave(r29)                                ; Point to the top of the "new" context stack
+                       vrlb    v31,v31,v30                                             ; Get 0xDEDEDEDE
+
+                       stw             r16,VMXcpu(r29)                                 ; Claim context for us
+                       eieio
 
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x5F07                               ; (TEST/DEBUG)
-                       mr              r1,r15                                  ; (TEST/DEBUG)
-                       mr              r3,r14                                  ; (TEST/DEBUG)
-                       mr              r5,r13                                  ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
+                       lwz             r13,VMXlevel(r29)                               ; (TEST/DEBUG)
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x5F04                                               ; (TEST/DEBUG)
+                       mr              r1,r15                                                  ; (TEST/DEBUG)
+                       mr              r3,r14                                                  ; (TEST/DEBUG)
+                       mr              r5,r13                                                  ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
+                       
+                       lis             r18,hi16(EXT(per_proc_info))    ; Set base per_proc
+                       vspltisb v28,-2                                                 ; Get 0xFEFEFEFE                   
+                       mulli   r19,r19,ppSize                                  ; Find offset to the owner per_proc                     
+                       vsubuhm v31,v31,v29                                             ; Get 0xDEDADEDA
+                       ori             r18,r18,lo16(EXT(per_proc_info))        ; Set base per_proc
+                       vpkpx   v30,v28,v3                                              ; Get 0x7FFF7FFF
+                       li              r16,VMXowner                                    ; Displacement to vector owner
+                       add             r19,r18,r19                                             ; Point to the owner per_proc   
+                       vrlb    v31,v31,v29                                             ; Get 0xDEADDEAD        
+                       li              r0,0
+                       
+vsinvothr:     lwarx   r18,r16,r19                                             ; Get the owner
+                       cmplw   r18,r29                                                 ; Does he still have this context?
+                       bne             vsinvoths                                               ; Nope...               
+                       stwcx.  r0,r16,r19                                              ; Try to invalidate it
+                       bne-    vsinvothr                                               ; Try again if there was a collision...
+               
+       
+vsinvoths:     cmplwi  cr1,r14,0                                               ; Do we possibly have some context to load?
+                       vmrghh  v31,v30,v31                                             ; Get 0x7FFFDEAD.  V31 keeps this value until the bitter end
+                       stw             r15,VMXlevel(r29)                               ; Set the "new" active level
+                       eieio
+                       stw             r29,VMXowner(r26)                               ; Mark us as having the live context
 
-                       cmplwi  cr1,r14,0                               ; Do we possibly have some context to load?
-                       stw             r15,ACT_MACT_VMXlvl(r17)        ; Set the "new" active level
-                       la              r23,savevscr(r14)               ; Point to the VSCR
-                       stw             r18,ACT_MACT_VMXcpu(r17)        ; Set the active CPU
-                       la              r20,savevr0(r14)                ; Point to first line to bring in
-                       stw             r17,PP_VMX_THREAD(r6)   ; Store current thread address in vmx_thread to claim vector for thread
-                       beq-    cr1,ProtectTheAmericanWay       ; Nothing to restore, first time use...
-                       lwz             r0,SAVlvlvec(r14)               ; Get the level of first facility savearea
-                       cmplw   r0,r15                                  ; Top level correct to load?
-                       bne-    ProtectTheAmericanWay   ; No, go initialize...
+                       beq-    cr1,ProtectTheAmericanWay               ; Nothing to restore, first time use...
+               
+                       lwz             r3,SAVprev(r14)                                 ; Get the previous context
+                       lwz             r0,SAVlevel(r14)                                ; Get the level of first facility savearea
+                       cmplw   r0,r15                                                  ; Top level correct to load?
+                       bne-    ProtectTheAmericanWay                   ; No, go initialize...
                        
+                       stw             r3,VMXsave(r29)                                 ; Pop the context (we will toss the savearea later)
+
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x5F08                               ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#if GDDBG
-                       mr              r8,r3
-                       lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       mr              r22,r4                                  ; Save this
-                       ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
-                       mr              r4,r2                                   ; Set value
-                       mtlr    r3                                              ; Set link register
-                       li              r3,1                                    ; Display address
-                       blrl                                                    ; Display it
-                       mr              r4,r22                                  ; Restore it
-                       mr              r3,r8
-#endif
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x5F05                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
 
-                       li              r0,1                                    ; Get the level invalid indication
-                       lwz             r22,savevrsave(r4)              ; Get the most current VRSAVE
-                       lwz             r10,savevrvalid(r14)    ; Get the valid VRs in the savearea
-                       lis             r9,0x5555                               ; Mask with odd bits set
-                       and             r10,r10,r22                             ; Figure out just what registers need to be loaded
-                       ori             r9,r9,0x5555                    ; Finish mask
-                       rlwinm  r11,r10,1,0,31                  ; Shift over 1
-                       stw             r0,SAVlvlvec(r14)               ; Mark the savearea invalid because we are activating again
-                       or              r12,r10,r11                             ; After this, even bits show which lines to touch
-                       dcbt    br0,r23                                 ; Touch in the VSCR
-                       andc    r13,r12,r9                              ; Clear out odd bits
-                       
-                       la              r20,savevr0(r14)                ; Point to line 0
-                       rlwinm  r3,r13,15,0,15                  ; Move line 8-15 flags to high order odd bits
-                       la              r21,savevr2(r3)                 ; Point to line 1
-                       or              r3,r13,r3                               ; Set the odd bits
-                                                                                       ; (bit 0 is line 0, bit 1 is line 8,
-                                                                                       ; bit 2 is line 1, bit 3 is line 9, etc.
-                       lvxl    v31,br0,r23                             ; Get the VSCR
-                       rlwimi  r3,r10,16,16,31                 ; Put vrsave 0 - 15 into positions 16 - 31
-                       mtvscr  v31                                             ; Slam the VSCR value
-                       mtcrf   255,r3                                  ; Load up the CRs
-                       mr              r22,r20                                 ; Start registers off
+                       lwz             r22,savevrsave(r25)                             ; Get the most current VRSAVE
+                       lwz             r10,savevrvalid(r14)                    ; Get the valid VRs in the savearea
+                       lis             r9,0x5555                                               ; Mask with odd bits set
+                       and             r10,r10,r22                                             ; Figure out just what registers need to be loaded
+                       ori             r9,r9,0x5555                                    ; Finish mask
+                       rlwinm  r11,r10,1,0,31                                  ; Shift over 1
+                       or              r12,r10,r11                                             ; After this, even bits show which lines to touch
+                       andc    r13,r12,r9                                              ; Clear out odd bits
+                       
+                       la              r20,savevr0(r14)                                ; Point to line 0
+                       rlwinm  r3,r13,15,0,15                                  ; Move line 8-15 flags to high order odd bits
+                       la              r21,savevr2(r3)                                 ; Point to line 1
+                       or              r3,r13,r3                                               ; Set the odd bits
+                                                                                                       ; (bit 0 is line 0, bit 1 is line 8,
+                                                                                                       ; bit 2 is line 1, bit 3 is line 9, etc.
+                       rlwimi  r3,r10,16,16,31                                 ; Put vrsave 0 - 15 into positions 16 - 31
+                       mtcrf   255,r3                                                  ; Load up the CRs
+                       mr              r22,r20                                                 ; Start registers off
 ;      
 ;                      Load the new vector state
 ;
                                                
-                       bf              0,lnol0                                 ; No line 0 to do...
-                       dcbt    br0,r20                                 ; Touch cache line 0
+                       bf              0,lnol0                                                 ; No line 0 to do...
+                       dcbt    br0,r20                                                 ; Touch cache line 0
                        
 lnol0:         
-                       la              r20,savevr4(r14)                ; Point to line 2
-                       bf              2,lnol1                                 ; No line 1 to do...
-                       dcbt    br0,r21                                 ; Touch cache line 1
+                       la              r20,savevr4(r14)                                ; Point to line 2
+                       bf              2,lnol1                                                 ; No line 1 to do...
+                       dcbt    br0,r21                                                 ; Touch cache line 1
                        
 lnol1:         
-                       la              r21,savevr6(r14)                ; Point to line 3
-                       bf              4,lnol2                                 ; No line 2 to do...
-                       dcbt    br0,r20                                 ; Touch cache line 2
+                       la              r21,savevr6(r14)                                ; Point to line 3
+                       bf              4,lnol2                                                 ; No line 2 to do...
+                       dcbt    br0,r20                                                 ; Touch cache line 2
                        
 lnol2:         
-                       li              r30,16                                  ; Get offset for odd registers
-                       bf              16,lnovr0                               ; Do not restore VR0...
-                       lvxl    v0,br0,r22                              ; Restore VR0
+                       li              r30,16                                                  ; Get offset for odd registers
+                       bf              16,lnovr0                                               ; Do not restore VR0...
+                       lvxl    v0,br0,r22                                              ; Restore VR0
                        
 lnovr0:                
-                       la              r23,savevr2(r14)                ; Point to V2/V3 pair
-                       bf              17,lnovr1                               ; Do not restore VR1...
-                       lvxl    v1,r30,r22                              ; Restore VR1
+                       la              r23,savevr2(r14)                                ; Point to V2/V3 pair
+                       bf              17,lnovr1                                               ; Do not restore VR1...
+                       lvxl    v1,r30,r22                                              ; Restore VR1
                        
 lnovr1:
-                       la              r20,savevr8(r14)                ; Point to line 4
-                       bf              6,lnol3                                 ; No line 3 to do...
-                       dcbt    br0,r21                                 ; Touch cache line 3
+                       la              r20,savevr8(r14)                                ; Point to line 4
+                       bf              6,lnol3                                                 ; No line 3 to do...
+                       dcbt    br0,r21                                                 ; Touch cache line 3
                        
 lnol3:         
-                       la              r22,savevr4(r14)                ; Point to V4/V5 pair
-                       bf              18,lnovr2                               ; Do not restore VR2...
-                       lvxl    v2,br0,r23                              ; Restore VR2
+                       la              r22,savevr4(r14)                                ; Point to V4/V5 pair
+                       bf              18,lnovr2                                               ; Do not restore VR2...
+                       lvxl    v2,br0,r23                                              ; Restore VR2
                        
 lnovr2:
-                       bf              19,lnovr3                               ; Do not restore VR3...
-                       lvxl    v3,r30,r23                              ; Restore VR3
+                       bf              19,lnovr3                                               ; Do not restore VR3...
+                       lvxl    v3,r30,r23                                              ; Restore VR3
                        
 lnovr3:
 ;
 ;                      Note: CR4 is now free
 ;
-                       la              r21,savevr10(r14)               ; Point to line 5
-                       bf              8,lnol4                                 ; No line 4 to do...
-                       dcbt    br0,r20                                 ; Touch cache line 4
+                       la              r21,savevr10(r14)                               ; Point to line 5
+                       bf              8,lnol4                                                 ; No line 4 to do...
+                       dcbt    br0,r20                                                 ; Touch cache line 4
                        
 lnol4:         
-                       la              r23,savevr6(r14)                ; Point to R6/R7 pair
-                       bf              20,lnovr4                               ; Do not restore VR4...
-                       lvxl    v4,br0,r22                              ; Restore VR4
+                       la              r23,savevr6(r14)                                ; Point to R6/R7 pair
+                       bf              20,lnovr4                                               ; Do not restore VR4...
+                       lvxl    v4,br0,r22                                              ; Restore VR4
                        
 lnovr4:
-                       bf              21,lnovr5                               ; Do not restore VR5...
-                       lvxl    v5,r30,r22                              ; Restore VR5
+                       bf              21,lnovr5                                               ; Do not restore VR5...
+                       lvxl    v5,r30,r22                                              ; Restore VR5
                        
 lnovr5:
-                       mtcrf   0x08,r10                                ; Set CRs for registers 16-19
-                       la              r20,savevr12(r14)               ; Point to line 6
-                       bf              10,lnol5                                ; No line 5 to do...
-                       dcbt    br0,r21                                 ; Touch cache line 5
+                       mtcrf   0x08,r10                                                ; Set CRs for registers 16-19
+                       la              r20,savevr12(r14)                               ; Point to line 6
+                       bf              10,lnol5                                                ; No line 5 to do...
+                       dcbt    br0,r21                                                 ; Touch cache line 5
                        
 lnol5:         
-                       la              r22,savevr8(r14)                ; Point to V8/V9 pair
-                       bf              22,lnovr6                               ; Do not restore VR6...
-                       lvxl    v6,br0,r23                              ; Restore VR6
+                       la              r22,savevr8(r14)                                ; Point to V8/V9 pair
+                       bf              22,lnovr6                                               ; Do not restore VR6...
+                       lvxl    v6,br0,r23                                              ; Restore VR6
                        
 lnovr6:
-                       bf              23,lnovr7                               ; Do not restore VR7...
-                       lvxl    v7,r30,r23                              ; Restore VR7
+                       bf              23,lnovr7                                               ; Do not restore VR7...
+                       lvxl    v7,r30,r23                                              ; Restore VR7
                        
 lnovr7:
 ;
 ;                      Note: CR5 is now free
 ;
-                       la              r21,savevr14(r14)               ; Point to line 7
-                       bf              12,lnol6                                ; No line 6 to do...
-                       dcbt    br0,r20                                 ; Touch cache line 6
+                       la              r21,savevr14(r14)                               ; Point to line 7
+                       bf              12,lnol6                                                ; No line 6 to do...
+                       dcbt    br0,r20                                                 ; Touch cache line 6
                        
 lnol6:         
-                       la              r23,savevr10(r14)               ; Point to V10/V11 pair
-                       bf              24,lnovr8                               ; Do not restore VR8...
-                       lvxl    v8,br0,r22                              ; Restore VR8
+                       la              r23,savevr10(r14)                               ; Point to V10/V11 pair
+                       bf              24,lnovr8                                               ; Do not restore VR8...
+                       lvxl    v8,br0,r22                                              ; Restore VR8
                        
 lnovr8:
-                       bf              25,lnovr9                               ; Do not save VR9...
-                       lvxl    v9,r30,r22                              ; Restore VR9
+                       bf              25,lnovr9                                               ; Do not save VR9...
+                       lvxl    v9,r30,r22                                              ; Restore VR9
                        
 lnovr9:
-                       mtcrf   0x04,r10                                ; Set CRs for registers 20-23
-                       la              r20,savevr16(r14)               ; Point to line 8
-                       bf              14,lnol7                                ; No line 7 to do...
-                       dcbt    br0,r21                                 ; Touch cache line 7
+                       mtcrf   0x04,r10                                                ; Set CRs for registers 20-23
+                       la              r20,savevr16(r14)                               ; Point to line 8
+                       bf              14,lnol7                                                ; No line 7 to do...
+                       dcbt    br0,r21                                                 ; Touch cache line 7
                        
 lnol7:         
-                       la              r22,savevr12(r14)               ; Point to V12/V13 pair
-                       bf              26,lnovr10                              ; Do not restore VR10...
-                       lvxl    v10,br0,r23                             ; Restore VR10
+                       la              r22,savevr12(r14)                               ; Point to V12/V13 pair
+                       bf              26,lnovr10                                              ; Do not restore VR10...
+                       lvxl    v10,br0,r23                                             ; Restore VR10
                        
 lnovr10:
-                       bf              27,lnovr11                              ; Do not restore VR11...
-                       lvxl    v11,r30,r23                             ; Restore VR11
+                       bf              27,lnovr11                                              ; Do not restore VR11...
+                       lvxl    v11,r30,r23                                             ; Restore VR11
                        
 lnovr11:
 
 ;
 ;                      Note: CR6 is now free
 ;
-                       la              r21,savevr18(r14)               ; Point to line 9
-                       bf              1,lnol8                                 ; No line 8 to do...
-                       dcbt    br0,r20                                 ; Touch cache line 8
+                       la              r21,savevr18(r14)                               ; Point to line 9
+                       bf              1,lnol8                                                 ; No line 8 to do...
+                       dcbt    br0,r20                                                 ; Touch cache line 8
                        
 lnol8:         
-                       la              r23,savevr14(r14)               ; Point to V14/V15 pair
-                       bf              28,lnovr12                              ; Do not restore VR12...
-                       lvxl    v12,br0,r22                             ; Restore VR12
+                       la              r23,savevr14(r14)                               ; Point to V14/V15 pair
+                       bf              28,lnovr12                                              ; Do not restore VR12...
+                       lvxl    v12,br0,r22                                             ; Restore VR12
                        
 lnovr12:
-                       bf              29,lnovr13                              ; Do not restore VR13...
-                       lvxl    v13,r30,r22                             ; Restore VR13
+                       bf              29,lnovr13                                              ; Do not restore VR13...
+                       lvxl    v13,r30,r22                                             ; Restore VR13
                        
 lnovr13:
-                       mtcrf   0x02,r10                                ; Set CRs for registers 24-27
-                       la              r20,savevr20(r14)               ; Point to line 10
-                       bf              3,lnol9                                 ; No line 9 to do...
-                       dcbt    br0,r21                                 ; Touch cache line 9
+                       mtcrf   0x02,r10                                                ; Set CRs for registers 24-27
+                       la              r20,savevr20(r14)                               ; Point to line 10
+                       bf              3,lnol9                                                 ; No line 9 to do...
+                       dcbt    br0,r21                                                 ; Touch cache line 9
                        
 lnol9:         
-                       la              r22,savevr16(r14)               ; Point to V16/V17 pair
-                       bf              30,lnovr14                              ; Do not restore VR14...
-                       lvxl    v14,br0,r23                             ; Restore VR14
+                       la              r22,savevr16(r14)                               ; Point to V16/V17 pair
+                       bf              30,lnovr14                                              ; Do not restore VR14...
+                       lvxl    v14,br0,r23                                             ; Restore VR14
                        
 lnovr14:
-                       bf              31,lnovr15                              ; Do not restore VR15...
-                       lvxl    v15,r30,r23                             ; Restore VR15
+                       bf              31,lnovr15                                              ; Do not restore VR15...
+                       lvxl    v15,r30,r23                                             ; Restore VR15
                        
 lnovr15:
 ;
 ;                      Note: CR7 is now free
 ;
-                       la              r21,savevr22(r14)               ; Point to line 11
-                       bf              5,lnol10                                ; No line 10 to do...
-                       dcbt    br0,r20                                 ; Touch cache line 10
+                       la              r21,savevr22(r14)                               ; Point to line 11
+                       bf              5,lnol10                                                ; No line 10 to do...
+                       dcbt    br0,r20                                                 ; Touch cache line 10
                        
 lnol10:                
-                       la              r23,savevr18(r14)               ; Point to V18/V19 pair
-                       bf              16,lnovr16                              ; Do not restore VR16...
-                       lvxl    v16,br0,r22                             ; Restore VR16
+                       la              r23,savevr18(r14)                               ; Point to V18/V19 pair
+                       bf              16,lnovr16                                              ; Do not restore VR16...
+                       lvxl    v16,br0,r22                                             ; Restore VR16
                        
 lnovr16:
-                       bf              17,lnovr17                              ; Do not restore VR17...
-                       lvxl    v17,r30,r22                             ; Restore VR17
+                       bf              17,lnovr17                                              ; Do not restore VR17...
+                       lvxl    v17,r30,r22                                             ; Restore VR17
                        
 lnovr17:
-                       mtcrf   0x01,r10                                ; Set CRs for registers 28-31
+                       mtcrf   0x01,r10                                                ; Set CRs for registers 28-31
 ;
 ;                      Note: All registers have been or are accounted for in CRs
 ;
-                       la              r20,savevr24(r14)               ; Point to line 12
-                       bf              7,lnol11                                ; No line 11 to do...
-                       dcbt    br0,r21                                 ; Touch cache line 11
+                       la              r20,savevr24(r14)                               ; Point to line 12
+                       bf              7,lnol11                                                ; No line 11 to do...
+                       dcbt    br0,r21                                                 ; Touch cache line 11
                        
 lnol11:                
-                       la              r22,savevr20(r14)               ; Point to V20/V21 pair
-                       bf              18,lnovr18                              ; Do not restore VR18...
-                       lvxl    v18,br0,r23                             ; Restore VR18
+                       la              r22,savevr20(r14)                               ; Point to V20/V21 pair
+                       bf              18,lnovr18                                              ; Do not restore VR18...
+                       lvxl    v18,br0,r23                                             ; Restore VR18
                        
 lnovr18:
-                       bf              19,lnovr19                              ; Do not restore VR19...
-                       lvxl    v19,r30,r23                             ; Restore VR19
+                       bf              19,lnovr19                                              ; Do not restore VR19...
+                       lvxl    v19,r30,r23                                             ; Restore VR19
                        
 lnovr19:
-                       la              r21,savevr26(r14)               ; Point to line 13
-                       bf              9,lnol12                                ; No line 12 to do...
-                       dcbt    br0,r20                                 ; Touch cache line 12
+                       la              r21,savevr26(r14)                               ; Point to line 13
+                       bf              9,lnol12                                                ; No line 12 to do...
+                       dcbt    br0,r20                                                 ; Touch cache line 12
                        
 lnol12:                
-                       la              r23,savevr22(r14)               ; Point to V22/V23 pair
-                       bf              20,lnovr20                              ; Do not restore VR20...
-                       lvxl    v20,br0,r22                             ; Restore VR20
+                       la              r23,savevr22(r14)                               ; Point to V22/V23 pair
+                       bf              20,lnovr20                                              ; Do not restore VR20...
+                       lvxl    v20,br0,r22                                             ; Restore VR20
                        
 lnovr20:
-                       bf              21,lnovr21                              ; Do not restore VR21...
-                       lvxl    v21,r30,r22                             ; Restore VR21
+                       bf              21,lnovr21                                              ; Do not restore VR21...
+                       lvxl    v21,r30,r22                                             ; Restore VR21
                        
 lnovr21:
-                       la              r20,savevr28(r14)               ; Point to line 14
-                       bf              11,lnol13                               ; No line 13 to do...
-                       dcbt    br0,r21                                 ; Touch cache line 13
+                       la              r20,savevr28(r14)                               ; Point to line 14
+                       bf              11,lnol13                                               ; No line 13 to do...
+                       dcbt    br0,r21                                                 ; Touch cache line 13
                        
 lnol13:                
-                       la              r22,savevr24(r14)               ; Point to V24/V25 pair
-                       bf              22,lnovr22                              ; Do not restore VR22...
-                       lvxl    v22,br0,r23                             ; Restore VR22
+                       la              r22,savevr24(r14)                               ; Point to V24/V25 pair
+                       bf              22,lnovr22                                              ; Do not restore VR22...
+                       lvxl    v22,br0,r23                                             ; Restore VR22
                        
 lnovr22:
-                       bf              23,lnovr23                              ; Do not restore VR23...
-                       lvxl    v23,r30,r23                             ; Restore VR23
+                       bf              23,lnovr23                                              ; Do not restore VR23...
+                       lvxl    v23,r30,r23                                             ; Restore VR23
                        
 lnovr23:
-                       la              r21,savevr30(r14)               ; Point to line 15
-                       bf              13,lnol14                               ; No line 14 to do...
-                       dcbt    br0,r20                                 ; Touch cache line 14
+                       la              r21,savevr30(r14)                               ; Point to line 15
+                       bf              13,lnol14                                               ; No line 14 to do...
+                       dcbt    br0,r20                                                 ; Touch cache line 14
                        
 lnol14:                
-                       la              r23,savevr26(r14)               ; Point to V26/V27 pair
-                       bf              24,lnovr24                              ; Do not restore VR24...
-                       lvxl    v24,br0,r22                             ; Restore VR24
+                       la              r23,savevr26(r14)                               ; Point to V26/V27 pair
+                       bf              24,lnovr24                                              ; Do not restore VR24...
+                       lvxl    v24,br0,r22                                             ; Restore VR24
                        
 lnovr24:
-                       bf              25,lnovr25                              ; Do not restore VR25...
-                       lvxl    v25,r30,r22                             ; Restore VR25
+                       bf              25,lnovr25                                              ; Do not restore VR25...
+                       lvxl    v25,r30,r22                                             ; Restore VR25
                        
 lnovr25:
-                       bf              15,lnol15                               ; No line 15 to do...
-                       dcbt    br0,r21                                 ; Touch cache line 15
+                       bf              15,lnol15                                               ; No line 15 to do...
+                       dcbt    br0,r21                                                 ; Touch cache line 15
                        
 lnol15:                
 ;
 ;                      Note: All needed cache lines have been touched now
 ;
-                       la              r22,savevr28(r14)               ; Point to V28/V29 pair
-                       bf              26,lnovr26                              ; Do not restore VR26...
-                       lvxl    v26,br0,r23                             ; Restore VR26
+                       la              r22,savevr28(r14)                               ; Point to V28/V29 pair
+                       bf              26,lnovr26                                              ; Do not restore VR26...
+                       lvxl    v26,br0,r23                                             ; Restore VR26
                        
 lnovr26:
-                       bf              27,lnovr27                              ; Do not restore VR27...
-                       lvxl    v27,r30,r23                             ; Restore VR27
+                       bf              27,lnovr27                                              ; Do not restore VR27...
+                       lvxl    v27,r30,r23                                             ; Restore VR27
                        
 lnovr27:
-                       la              r23,savevr30(r14)               ; Point to V30/V31 pair
-                       bf              28,lnovr28                              ; Do not restore VR28...
-                       lvxl    v28,br0,r22                             ; Restore VR28
+                       la              r23,savevr30(r14)                               ; Point to V30/V31 pair
+                       bf              28,lnovr28                                              ; Do not restore VR28...
+                       lvxl    v28,br0,r22                                             ; Restore VR28
                        
 lnovr28:               
-                       bf              29,lnovr29                              ; Do not restore VR29...
-                       lvxl    v29,r30,r22                             ; Restore VR29
+                       bf              29,lnovr29                                              ; Do not restore VR29...
+                       lvxl    v29,r30,r22                                             ; Restore VR29
                        
 lnovr29:               
-                       bf              30,lnovr30                              ; Do not restore VR30...
-                       lvxl    v30,br0,r23                             ; Restore VR30
+                       bf              30,lnovr30                                              ; Do not restore VR30...
+                       lvxl    v30,br0,r23                                             ; Restore VR30
                        
 lnovr30:
 ;
 ;                      Everything is restored now except for VR31.  We need it to get
-;                      the QNaNBarbarian value to put into idle vector registers
+;                      the QNaNBarbarian value to put into idle vector registers. 
+;                      Note: V31 was set above to QNaNbarbarian
 ;
                        
-                       lis             r5,hi16(EXT(QNaNbarbarian))     ; Get address of empty value
-                       cmpwi   r10,-1                                  ; Handle the quick case of all registers in use
-                       ori             r5,r5,lo16(EXT(QNaNbarbarian))  ; Get low address of empty value
-                       beq-    mstlvr31                                ; Not likely, but all are in use...
-                       mtcrf   255,r10                                 ; Get mask of valid registers
-                       lvxl    v31,br0,r5                              ; Initialize VR31 to the empty value
+                       cmpwi   r10,-1                                                  ; Handle the quick case of all registers in use
+                       beq-    mstlvr31                                                ; Not likely, but all are in use...
+                       mtcrf   255,r10                                                 ; Get mask of valid registers
 
-                       bt              0,ni0                                   ; Register is ok already...
-                       vor             v0,v31,v31                              ; Copy into the next register
+                       bt              0,ni0                                                   ; Register is ok already...
+                       vor             v0,v31,v31                                              ; Copy into the next register
 ni0:
-                       bt              1,ni1                                   ; Register is ok already...
-                       vor             v1,v31,v31                              ; Copy into the next register
+                       bt              1,ni1                                                   ; Register is ok already...
+                       vor             v1,v31,v31                                              ; Copy into the next register
 ni1:
-                       bt              2,ni2                                   ; Register is ok already...
-                       vor             v2,v31,v31                              ; Copy into the next register
+                       bt              2,ni2                                                   ; Register is ok already...
+                       vor             v2,v31,v31                                              ; Copy into the next register
 ni2:
-                       bt              3,ni3                                   ; Register is ok already...
-                       vor             v3,v31,v31                              ; Copy into the next register
+                       bt              3,ni3                                                   ; Register is ok already...
+                       vor             v3,v31,v31                                              ; Copy into the next register
 ni3:
-                       bt              4,ni4                                   ; Register is ok already...
-                       vor             v4,v31,v31                              ; Copy into the next register
+                       bt              4,ni4                                                   ; Register is ok already...
+                       vor             v4,v31,v31                                              ; Copy into the next register
 ni4:
-                       bt              5,ni5                                   ; Register is ok already...
-                       vor             v5,v31,v31                              ; Copy into the next register
+                       bt              5,ni5                                                   ; Register is ok already...
+                       vor             v5,v31,v31                                              ; Copy into the next register
 ni5:
-                       bt              6,ni6                                   ; Register is ok already...
-                       vor             v6,v31,v31                              ; Copy into the next register
+                       bt              6,ni6                                                   ; Register is ok already...
+                       vor             v6,v31,v31                                              ; Copy into the next register
 ni6:
-                       bt              7,ni7                                   ; Register is ok already...
-                       vor             v7,v31,v31                              ; Copy into the next register
+                       bt              7,ni7                                                   ; Register is ok already...
+                       vor             v7,v31,v31                                              ; Copy into the next register
 ni7:
-                       bt              8,ni8                                   ; Register is ok already...
-                       vor             v8,v31,v31                              ; Copy into the next register
+                       bt              8,ni8                                                   ; Register is ok already...
+                       vor             v8,v31,v31                                              ; Copy into the next register
 ni8:
-                       bt              9,ni9                                   ; Register is ok already...
-                       vor             v9,v31,v31                              ; Copy into the next register
+                       bt              9,ni9                                                   ; Register is ok already...
+                       vor             v9,v31,v31                                              ; Copy into the next register
 ni9:
-                       bt              10,ni10                                 ; Register is ok already...
-                       vor             v10,v31,v31                             ; Copy into the next register
+                       bt              10,ni10                                                 ; Register is ok already...
+                       vor             v10,v31,v31                                             ; Copy into the next register
 ni10:
-                       bt              11,ni11                                 ; Register is ok already...
-                       vor             v11,v31,v31                             ; Copy into the next register
+                       bt              11,ni11                                                 ; Register is ok already...
+                       vor             v11,v31,v31                                             ; Copy into the next register
 ni11:
-                       bt              12,ni12                                 ; Register is ok already...
-                       vor             v12,v31,v31                             ; Copy into the next register
+                       bt              12,ni12                                                 ; Register is ok already...
+                       vor             v12,v31,v31                                             ; Copy into the next register
 ni12:
-                       bt              13,ni13                                 ; Register is ok already...
-                       vor             v13,v31,v31                             ; Copy into the next register
+                       bt              13,ni13                                                 ; Register is ok already...
+                       vor             v13,v31,v31                                             ; Copy into the next register
 ni13:
-                       bt              14,ni14                                 ; Register is ok already...
-                       vor             v14,v31,v31                             ; Copy into the next register
+                       bt              14,ni14                                                 ; Register is ok already...
+                       vor             v14,v31,v31                                             ; Copy into the next register
 ni14:
-                       bt              15,ni15                                 ; Register is ok already...
-                       vor             v15,v31,v31                             ; Copy into the next register
+                       bt              15,ni15                                                 ; Register is ok already...
+                       vor             v15,v31,v31                                             ; Copy into the next register
 ni15:
-                       bt              16,ni16                                 ; Register is ok already...
-                       vor             v16,v31,v31                             ; Copy into the next register
+                       bt              16,ni16                                                 ; Register is ok already...
+                       vor             v16,v31,v31                                             ; Copy into the next register
 ni16:
-                       bt              17,ni17                                 ; Register is ok already...
-                       vor             v17,v31,v31                             ; Copy into the next register
+                       bt              17,ni17                                                 ; Register is ok already...
+                       vor             v17,v31,v31                                             ; Copy into the next register
 ni17:
-                       bt              18,ni18                                 ; Register is ok already...
-                       vor             v18,v31,v31                             ; Copy into the next register
+                       bt              18,ni18                                                 ; Register is ok already...
+                       vor             v18,v31,v31                                             ; Copy into the next register
 ni18:
-                       bt              19,ni19                                 ; Register is ok already...
-                       vor             v19,v31,v31                             ; Copy into the next register
+                       bt              19,ni19                                                 ; Register is ok already...
+                       vor             v19,v31,v31                                             ; Copy into the next register
 ni19:
-                       bt              20,ni20                                 ; Register is ok already...
-                       vor             v20,v31,v31                             ; Copy into the next register
+                       bt              20,ni20                                                 ; Register is ok already...
+                       vor             v20,v31,v31                                             ; Copy into the next register
 ni20:
-                       bt              21,ni21                                 ; Register is ok already...
-                       vor             v21,v31,v31                             ; Copy into the next register
+                       bt              21,ni21                                                 ; Register is ok already...
+                       vor             v21,v31,v31                                             ; Copy into the next register
 ni21:
-                       bt              22,ni22                                 ; Register is ok already...
-                       vor             v22,v31,v31                             ; Copy into the next register
+                       bt              22,ni22                                                 ; Register is ok already...
+                       vor             v22,v31,v31                                             ; Copy into the next register
 ni22:
-                       bt              23,ni23                                 ; Register is ok already...
-                       vor             v23,v31,v31                             ; Copy into the next register
+                       bt              23,ni23                                                 ; Register is ok already...
+                       vor             v23,v31,v31                                             ; Copy into the next register
 ni23:
-                       bt              24,ni24                                 ; Register is ok already...
-                       vor             v24,v31,v31                             ; Copy into the next register
+                       bt              24,ni24                                                 ; Register is ok already...
+                       vor             v24,v31,v31                                             ; Copy into the next register
 ni24:
-                       bt              25,ni25                                 ; Register is ok already...
-                       vor             v25,v31,v31                             ; Copy into the next register
+                       bt              25,ni25                                                 ; Register is ok already...
+                       vor             v25,v31,v31                                             ; Copy into the next register
 ni25:
-                       bt              26,ni26                                 ; Register is ok already...
-                       vor             v26,v31,v31                             ; Copy into the next register
+                       bt              26,ni26                                                 ; Register is ok already...
+                       vor             v26,v31,v31                                             ; Copy into the next register
 ni26:
-                       bt              27,ni27                                 ; Register is ok already...
-                       vor             v27,v31,v31                             ; Copy into the next register
+                       bt              27,ni27                                                 ; Register is ok already...
+                       vor             v27,v31,v31                                             ; Copy into the next register
 ni27:
-                       bt              28,ni28                                 ; Register is ok already...
-                       vor             v28,v31,v31                             ; Copy into the next register
+                       bt              28,ni28                                                 ; Register is ok already...
+                       vor             v28,v31,v31                                             ; Copy into the next register
 ni28:
-                       bt              29,ni29                                 ; Register is ok already...
-                       vor             v29,v31,v31                             ; Copy into the next register
+                       bt              29,ni29                                                 ; Register is ok already...
+                       vor             v29,v31,v31                                             ; Copy into the next register
 ni29:
-                       bt              30,ni30                                 ; Register is ok already...
-                       vor             v30,v31,v31                             ; Copy into the next register
+                       bt              30,ni30                                                 ; Register is ok already...
+                       vor             v30,v31,v31                                             ; Copy into the next register
 ni30:
-                       bf              31,lnovr31                              ; R31 is empty, no need to restore...
+                       bf              31,lnovr31                                              ; V31 is empty, no need to restore...
 
-mstlvr31:      lvxl    v31,r30,r23                             ; Restore VR31
+mstlvr31:      lvxl    v31,r30,r23                                             ; Restore VR31
                        
-lnovr31:
+lnovr31:       mr              r3,r14                                                  ; Get the old savearea (we popped it before)
+                       bl              EXT(save_ret)                                   ; Toss it
                        
-vrenable:      
-                       lwz             r9,SAVflags(r4)                 /* Get the flags of the current savearea */
-                       lwz             r8,savesrr1(r4)                 ; Get the msr of the interrupted guy
-                       rlwinm  r5,r4,0,0,19                    /* Get the page address of the savearea */
-                       oris    r8,r8,hi16(MASK(MSR_VEC))       ; Enable the vector facility
-                       lwz             r10,ACT_MACT_SPF(r17)   ; Get the special flags
-                       lis             r7,hi16(SAVattach)              /* Get the attached flag */
-                       lwz             r5,SACvrswap(r5)                /* Get Virtual to Real translation */
+vrenable:      lwz             r8,savesrr1(r25)                                ; Get the msr of the interrupted guy
+                       rlwinm  r5,r25,0,0,19                                   ; Get the page address of the savearea 
+                       oris    r8,r8,hi16(MASK(MSR_VEC))               ; Enable the vector facility
+                       lwz             r10,ACT_MACT_SPF(r17)                   ; Get the special flags
+                       lwz             r5,SACvrswap(r5)                                ; Get Virtual to Real translation 
                        oris    r10,r10,hi16(vectorUsed|vectorCng)      ; Set that we used vectors
-                       mr.             r15,r15                                 ; See if we are doing this for user state
-                       stw             r8,savesrr1(r4)                 ; Set the msr of the interrupted guy
-                       andc    r9,r9,r7                                /* Clear the attached bit */
-                       xor             r3,r4,r5                                /* Get the real address of the savearea */
-                       stw             r9,SAVflags(r4)                 /* Set the flags of the current savearea */
-                       bne-    vrnuser                                 ; We are not user state...
-                       stw             r10,ACT_MACT_SPF(r17)   ; Set the activation copy
-                       stw             r10,spcFlags(r6)                ; Set per_proc copy
+                       rlwinm. r0,r8,0,MSR_PR_BIT,MSR_PR_BIT   ; See if we are doing this for user state
+                       stw             r8,savesrr1(r25)                                ; Set the msr of the interrupted guy
+                       xor             r3,r25,r5                                               ; Get the real address of the savearea
+                       beq-    vrnuser                                                 ; We are not user state...
+                       stw             r10,ACT_MACT_SPF(r17)                   ; Set the activation copy
+                       stw             r10,spcFlags(r26)                               ; Set per_proc copy
 
 vrnuser:
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x5F0A                               ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#if GDDBG
-                       mr              r8,r3                                   ; Save this
-                       lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
-                       mr              r4,r2                                   ; Set value
-                       mtlr    r3                                              ; Set link register
-                       li              r3,1                                    ; Display address
-                       blrl                                                    ; Display it
-                       mr              r3,r8                                   ; Restore it
-#endif
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x5F07                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
-                       b               EXT(exception_exit)             /* Exit from the fray... */
+                       b               EXT(exception_exit)                             ; Exit to the fray...
 
 /*
  *                     Initialize the registers to some bogus value
- *                     We make sure that non-Java mode is the default here
  */
 
 ProtectTheAmericanWay:
                        
 #if FPVECDBG
-                       lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
-                       li              r2,0x5F09                               ; (TEST/DEBUG)
-                       oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
-                       sc                                                              ; (TEST/DEBUG)
-#if GDDBG
-                       lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
-                       mr              r8,r4                                   ; Save this
-                       ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
-                       mr              r4,r2                                   ; Set value
-                       mtlr    r3                                              ; Set link register
-                       li              r3,1                                    ; Display address
-                       blrl                                                    ; Display it
-                       mr              r4,r8                                   ; Restore it
-#endif
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x5F06                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
 #endif 
-                       lis             r5,hi16(EXT(QNaNbarbarian))     ; Get address of empty value
-                       vspltish v1,1                                   ; Turn on the non-Java bit and saturate
-                       ori             r5,r5,lo16(EXT(QNaNbarbarian))  ; Get low address of empty value
-                       vspltisw v2,1                                   ; Turn on the saturate bit
-                       lvxl    v0,br0,r5                               ; Initialize VR0
-                       vxor    v1,v1,v2                                ; Turn off saturate     
-                       
-                       vor             v2,v0,v0                                ; Copy into the next register
-                       mtvscr  v1                                              ; Clear the vector status register
-                       vor             v3,v0,v0                                ; Copy into the next register
-                       vor             v1,v0,v0                                ; Copy into the next register
-                       vor             v4,v0,v0                                ; Copy into the next register
-                       vor             v5,v0,v0                                ; Copy into the next register
-                       vor             v6,v0,v0                                ; Copy into the next register
-                       vor             v7,v0,v0                                ; Copy into the next register
-                       vor             v8,v0,v0                                ; Copy into the next register
-                       vor             v9,v0,v0                                ; Copy into the next register
-                       vor             v10,v0,v0                               ; Copy into the next register
-                       vor             v11,v0,v0                               ; Copy into the next register
-                       vor             v12,v0,v0                               ; Copy into the next register
-                       vor             v13,v0,v0                               ; Copy into the next register
-                       vor             v14,v0,v0                               ; Copy into the next register
-                       vor             v15,v0,v0                               ; Copy into the next register
-                       vor             v16,v0,v0                               ; Copy into the next register
-                       vor             v17,v0,v0                               ; Copy into the next register
-                       vor             v18,v0,v0                               ; Copy into the next register
-                       vor             v19,v0,v0                               ; Copy into the next register
-                       vor             v20,v0,v0                               ; Copy into the next register
-                       vor             v21,v0,v0                               ; Copy into the next register
-                       vor             v22,v0,v0                               ; Copy into the next register
-                       vor             v23,v0,v0                               ; Copy into the next register
-                       vor             v24,v0,v0                               ; Copy into the next register
-                       vor             v25,v0,v0                               ; Copy into the next register
-                       vor             v26,v0,v0                               ; Copy into the next register
-                       vor             v27,v0,v0                               ; Copy into the next register
-                       vor             v28,v0,v0                               ; Copy into the next register
-                       vor             v29,v0,v0                               ; Copy into the next register
-                       vor             v30,v0,v0                               ; Copy into the next register
-                       vor             v31,v0,v0                               ; Copy into the next register
-                       b               vrenable                                ; Finish setting it all up...                           
-
-;
-;                      Finds a unused vector area in the activation pointed
-;                      to by R12s saved contexts.  If none are found (unlikely but possible)
-;                      and R3 is 0, a new area is allocated.  If R3 is non-zero, it contains 
-;                      a pointer to a vector savearea that is free.
-;
-
-vsrchsave:     lwz             r6,ACT_MACT_PCB(r12)            ; Get the first "normal" savearea
-                       
-vsrnorm:       mr.             r5,r6                                           ; Is there another?
-                       beq-    vsrvect                                         ; No, search the floating point saveareas...
-                       lwz             r7,SAVflags(r5)                         ; Get the flags for this guy
-                       lwz             r6,SAVprev(r5)                          ; Get the previous savearea, just in case
-                       andis.  r8,r7,hi16(SAVvmxvalid)         ; Have we found an empty vector save in normal?
-                       beq+    vsrgot                                          ; We found one...
-                       b               vsrnorm                                         ; Search again...
-
-vsrvect:       lwz             r6,ACT_MACT_FPU(r12)            ; Get the first "floating point" savearea
-                       
-vsrvectx:      mr.             r5,r6                                           ; Is there another?
-                       beq-    vsrget                                          ; No, try to allocate one...
-                       lwz             r7,SAVflags(r5)                         ; Get the flags for this guy
-                       lwz             r6,SAVprefp(r5)                         ; Get the previous savearea, just in case
-                       andis.  r8,r7,hi16(SAVvmxvalid)         ; Have we found an empty vector save in float?
-                       bne-    vsrvectx                                        ; Search again...
-                       
-vsrgot:                mr              r3,r5                                           ; Get the savearea into the right register
-                       blr                                                                     ; Return...
-
-vsrget:                mr.             r5,r3                                           ; Do we allocate or use existing?
-                       beq+    vsrallo                                         ; Allocate one...
-                       
-                       lwz             r7,SAVflags(r3)                         ; Get the passed in area flags
-                       blr                                                                     ; Return...
-;                      
-;                      NOTE: save_get will return directly and set R7 to 0...
+                       
+                       vor             v0,v31,v31                                              ; Copy into the next register
+                       vor             v1,v31,v31                                              ; Copy into the next register
+                       vor             v2,v31,v31                                              ; Copy into the next register
+                       vor             v3,v31,v31                                              ; Copy into the next register
+                       vor             v4,v31,v31                                              ; Copy into the next register
+                       vor             v5,v31,v31                                              ; Copy into the next register
+                       vor             v6,v31,v31                                              ; Copy into the next register
+                       vor             v7,v31,v31                                              ; Copy into the next register
+                       vor             v8,v31,v31                                              ; Copy into the next register
+                       vor             v9,v31,v31                                              ; Copy into the next register
+                       vor             v10,v31,v31                                             ; Copy into the next register
+                       vor             v11,v31,v31                                             ; Copy into the next register
+                       vor             v12,v31,v31                                             ; Copy into the next register
+                       vor             v13,v31,v31                                             ; Copy into the next register
+                       vor             v14,v31,v31                                             ; Copy into the next register
+                       vor             v15,v31,v31                                             ; Copy into the next register
+                       vor             v16,v31,v31                                             ; Copy into the next register
+                       vor             v17,v31,v31                                             ; Copy into the next register
+                       vor             v18,v31,v31                                             ; Copy into the next register
+                       vor             v19,v31,v31                                             ; Copy into the next register
+                       vor             v20,v31,v31                                             ; Copy into the next register
+                       vor             v21,v31,v31                                             ; Copy into the next register
+                       vor             v22,v31,v31                                             ; Copy into the next register
+                       vor             v23,v31,v31                                             ; Copy into the next register
+                       vor             v24,v31,v31                                             ; Copy into the next register
+                       vor             v25,v31,v31                                             ; Copy into the next register
+                       vor             v26,v31,v31                                             ; Copy into the next register
+                       vor             v27,v31,v31                                             ; Copy into the next register
+                       vor             v28,v31,v31                                             ; Copy into the next register
+                       vor             v29,v31,v31                                             ; Copy into the next register
+                       vor             v30,v31,v31                                             ; Copy into the next register
+                       b               vrenable                                                ; Finish setting it all up...                           
+
+
+
+;
+;                      We get here when we are switching to the same context at the same level and the context
+;                      is still live.  Essentially, all we are doing is turning on the faility.  It may have
+;                      gotten turned off due to doing a context save for the current level or a context switch
+;                      back to the live guy.
+;
+
+                       .align  5
+                       
+vsthesame:
+
+#if FPVECDBG
+                       lis             r0,hi16(CutTrace)                               ; (TEST/DEBUG)
+                       li              r2,0x5F0A                                               ; (TEST/DEBUG)
+                       oris    r0,r0,lo16(CutTrace)                    ; (TEST/DEBUG)
+                       sc                                                                              ; (TEST/DEBUG)
+#endif 
+                       beq-    cr1,vrenable                                    ; Not saved yet, nothing to pop, go enable and exit...
+                       
+                       lwz             r11,SAVlevel(r30)                               ; Get the level of top saved context
+                       lwz             r14,SAVprev(r30)                                ; Get the previous savearea
+                       
+                       cmplw   r11,r31                                                 ; Are live and saved the same?
+
+                       bne+    vrenable                                                ; Level not the same, nothing to pop, go enable and exit...
+                       
+                       mr              r3,r30                                                  ; Get the old savearea (we popped it before)
+                       bl              EXT(save_ret)                                   ; Toss it
+                       b               vrenable                                                ; Go enable and exit...
+
+
+;
+;                      This function invalidates any live vector context for the passed in facility_context.
+;                      This is intended to be called just before act_machine_sv_free tosses saveareas.
 ;
-vsrallo:       b               EXT(save_get)                           ; Get a fresh savearea 
 
+                       .align  5
+                       .globl  EXT(toss_live_vec)
 
-/*
- * void lfs(fpsp,fpdp)
- *
- * load the single precision float to the double
- *
- * This routine is used by the alignment handler.
- *
- */
-ENTRY(lfs, TAG_NO_FRAME_USED)
-        lfs     f1,    0(r3)
-       stfd    f1,     0(r4)
-       blr
+LEXT(toss_live_vec)
+                       
+                       mfmsr   r9                                                              ; Get the MSR
+                       rlwinm  r0,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1       ; Clear interuptions
+                       rlwinm. r8,r9,0,MSR_VEC_BIT,MSR_VEC_BIT ; Is vector on right now?
+                       rlwinm  r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Make sure vector is turned off
+                       rlwinm  r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Make sure fpu is turned off
+                       mtmsr   r0                                                              ; No interruptions
+                       isync
+                       beq+    tlvnotours                                              ; Vector off, can not be live here...
 
-/*
- * fpsp stfs(fpdp,fpsp)
- *
- * store the double precision float to the single
- *
- * This routine is used by the alignment handler.
- *
- */
-ENTRY(stfs, TAG_NO_FRAME_USED)
-       lfd     f1,     0(r3)
-        stfs   f1,     0(r4)
-       blr
+                       mfsprg  r8,0                                                    ; Get the per proc
+
+;
+;                      Note that at this point, since vecs are on, we are the owner
+;                      of live state on this processor
+;
+
+                       lwz             r6,VMXowner(r8)                                 ; Get the thread that owns the vector
+                       li              r0,0                                                    ; Clear this just in case we need it
+                       cmplw   r6,r3                                                   ; Are we tossing our own context?
+                       bne-    tlvnotours                                              ; Nope...
+                       
+                       vspltish v1,1                                                   ; Turn on the non-Java bit and saturate
+                       vspltisw v0,1                                                   ; Turn on the saturate bit
+                       vxor    v1,v1,v0                                                ; Turn off saturate     
+                       mtspr   vrsave,r0                                               ; Clear VRSAVE 
+                       mtvscr  v1                                                              ; Set the non-java, no saturate status
+
+tlvnotours:    lwz             r11,VMXcpu(r3)                                  ; Get the cpu on which we last loaded context
+                       lis             r12,hi16(EXT(per_proc_info))    ; Set base per_proc
+                       mulli   r11,r11,ppSize                                  ; Find offset to the owner per_proc                     
+                       ori             r12,r12,lo16(EXT(per_proc_info))        ; Set base per_proc
+                       li              r10,VMXowner                                    ; Displacement to vector owner
+                       add             r11,r12,r11                                             ; Point to the owner per_proc   
+                       li              r0,0                                                    ; Set a 0 to invalidate context
+                       
+tlvinvothr:    lwarx   r12,r10,r11                                             ; Get the owner
+                       cmplw   r12,r3                                                  ; Does he still have this context?
+                       bne+    tlvexit                                                 ; Nope, leave...                
+                       stwcx.  r0,r10,r11                                              ; Try to invalidate it
+                       bne-    tlvinvothr                                              ; Try again if there was a collision...
+
+tlvexit:       mtmsr   r9                                                              ; Restore interruptions
+                       isync                                                                   ; Could be turning off vectors here
+                       blr                                                                             ; Leave....
+
+#if 0
+;
+;                      This function invalidates any live vector context for the passed in facility_context
+;                      if the level is current.  It also tosses the corresponding savearea if there is one.
+;                      This function is primarily used whenever we detect a VRSave that is all zeros.
+;
+
+                       .align  5
+                       .globl  EXT(vec_trash)
+
+LEXT(vec_trash)
+                       
+                       lwz             r12,facAct(r3)                                  ; Get the activation
+                       lwz             r11,VMXlevel(r3)                                ; Get the context level
+                       lwz             r10,ACT_MACT_PCB(r12)                   ; Grab the current level for the thread
+                       lwz             r9,VMXsave(r3)                                  ; Get the savearea, if any
+                       cmplw   r10,r11                                                 ; Are we at the right level?
+                       cmplwi  cr1,r9,0                                                ; Remember if there is a savearea
+                       bnelr+                                                                  ; No, we do nothing...                  
+                       
+                       lwz             r11,VMXcpu(r3)                                  ; Get the cpu on which we last loaded context
+                       lis             r12,hi16(EXT(per_proc_info))    ; Set base per_proc
+                       mulli   r11,r11,ppSize                                  ; Find offset to the owner per_proc                     
+                       ori             r12,r12,lo16(EXT(per_proc_info))        ; Set base per_proc
+                       li              r10,VMXowner                                    ; Displacement to vector owner
+                       add             r11,r12,r11                                             ; Point to the owner per_proc   
+                       li              r0,0                                                    ; Set a 0 to invalidate context
+                       
+vtinvothr:     lwarx   r12,r10,r11                                             ; Get the owner
+                       cmplw   r12,r3                                                  ; Does he still have this context?
+                       bne             vtnotlive                                               ; Nope, not live anywhere...    
+                       stwcx.  r0,r10,r11                                              ; Try to invalidate it
+                       bne-    vtinvothr                                               ; Try again if there was a collision...
+
+vtnotlive:     beqlr+  cr1                                                             ; Leave if there is no savearea
+                       lwz             r8,SAVlevel(r9)                                 ; Get the level of the savearea
+                       cmplw   r8,r11                                                  ; Savearea for the current level?
+                       bnelr+                                                                  ; No, nothing to release...
+                       
+                       lwz             r8,SAVprev(r9)                                  ; Pick up the previous area
+                       mr.             r8,r8                                                   ; Is there a previous?
+                       beq-    vtnoprev                                                ; Nope...
+                       lwz             r7,SAVlevel(r8)                                 ; Get the level associated with save
+
+vtnoprev:      stw             r8,VMXsave(r3)                                  ; Dequeue this savearea
+                       stw             r7,VMXlevel(r3)                                 ; Pop the level
+                       
+                       mr              r3,r9                                                   ; Get the savearea to release
+                       b               EXT(save_ret)                                   ; Go and toss the save area (note, we will return from there)...
+#endif 
+                       
+;
+;                      Just some test code to force vector and/or floating point in the kernel
+;                      
+
+                       .align  5
+                       .globl  EXT(fctx_test)
 
+LEXT(fctx_test)
+                       
+                       mfsprg  r3,0                                                    ; Get the per_proc block
+                       lwz             r3,PP_ACTIVE_THREAD(r3)                 ; Get the thread pointer
+                       mr.             r3,r3                                                   ; Are we actually up and running?
+                       beqlr-                                                                  ; No...
+                       
+                       fmr             f0,f0                                                   ; Use floating point
+                       mftb    r4                                                              ; Get time base for a random number
+                       li              r5,1                                                    ; Get a potential vrsave to use
+                       andi.   r4,r4,0x3F                                              ; Get a number from 0 - 63
+                       slw             r5,r5,r4                                                ; Choose a register to save (should be 0 half the time)
+                       mtspr   vrsave,r5                                               ; Set VRSave
+                       vor             v0,v0,v0                                                ; Use vectors
+                       blr