Annotation of XNU/osfmk/ppc/cswtch.s, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * @OSF_COPYRIGHT@
        !            24:  */
        !            25: 
        !            26: #include <ppc/asm.h>
        !            27: #include <ppc/proc_reg.h>
        !            28: #include <cpus.h>
        !            29: #include <assym.s>
        !            30: #include <debug.h>
        !            31: #include <mach/ppc/vm_param.h>
        !            32: #include <ppc/exception.h>
        !            33: 
        !            34: #define FPVECDBG 0
        !            35: #define GDDBG 0
        !            36: 
        !            37:        .text
        !            38:        
        !            39: /*
        !            40:  * void     load_context(thread_t        thread)
        !            41:  *
        !            42:  * Load the context for the first kernel thread, and go.
        !            43:  *
        !            44:  * NOTE - if DEBUG is set, the former routine is a piece
        !            45:  * of C capable of printing out debug info before calling the latter,
        !            46:  * otherwise both entry points are identical.
        !            47:  */
        !            48: 
        !            49: ENTRY2(load_context, Load_context, TAG_NO_FRAME_USED)
        !            50: 
        !            51: /*
        !            52:  * Since this is the first thread, we came in on the interrupt
        !            53:  * stack. The first thread never returns, so there is no need to
        !            54:  * worry about saving its frame, hence we can reset the istackptr
        !            55:  * back to the saved_state structure at it's top
        !            56:  */
        !            57:                        
        !            58: 
        !            59: /*
        !            60:  * get new thread pointer and set it into the active_threads pointer
        !            61:  *
        !            62:  */
        !            63:        
        !            64:                        mfsprg  r6,0
        !            65:                        lwz             r0,PP_INTSTACK_TOP_SS(r6)
        !            66:                        lwz             r11,PP_CPU_DATA(r6)
        !            67:                        stw             r0,PP_ISTACKPTR(r6)
        !            68:                        stw             r3,CPU_ACTIVE_THREAD(r11)
        !            69: 
        !            70: /* Find the new stack and store it in active_stacks */
        !            71:        
        !            72:                        lwz             r12,PP_ACTIVE_STACKS(r6)
        !            73:                        lwz             r1,THREAD_KERNEL_STACK(r3)
        !            74:                        lwz             r9,THREAD_TOP_ACT(r3)                   /* Point to the active activation */
        !            75:                        stw             r1,0(r12)
        !            76:                        li              r0,0                                                    /* Clear a register */
        !            77:                        lwz             r8,ACT_MACT_PCB(r9)                             /* Get the savearea used */
        !            78:                        lwz             r10,SAVflags(r8)                                /* Get the savearea flags */
        !            79:                        rlwinm  r7,r8,0,0,19                                    /* Switch to savearea base */
        !            80:                        lwz             r11,SAVprev(r8)                                 /* Get the previous savearea */
        !            81:                        mfmsr   r5                                                              /* Since we are passing control, get our MSR values */
        !            82:                        lwz             r1,saver1(r8)                                   /* Load new stack pointer */
        !            83:                        rlwinm  r10,r10,0,1,31                                  /* Remove the attached flag */
        !            84:                        stw             r0,saver3(r8)                                   /* Make sure we pass in a 0 for the continuation */
        !            85:                        lwz             r7,SACvrswap(r7)                                /* Get the translation from virtual to real */
        !            86:                        stw             r0,FM_BACKPTR(r1)                               /* zero backptr */
        !            87:                        stw             r5,savesrr1(r8)                                 /* Pass our MSR to the new guy */
        !            88:                        stw             r10,SAVflags(r8)                                /* Pass back the flags */
        !            89:                        xor             r3,r7,r8                                                /* Get the physical address of the new context save area */
        !            90:                        stw             r11,ACT_MACT_PCB(r9)                    /* Unstack our savearea */
        !            91:                        b               EXT(exception_exit)                             /* Go end it all... */
        !            92:        
        !            93: /* struct thread_shuttle *Switch_context(struct thread_shuttle   *old,
        !            94:  *                                      void                    (*cont)(void),
        !            95:  *                                      struct thread_shuttle   *new)
        !            96:  *
        !            97:  * Switch from one thread to another. If a continuation is supplied, then
        !            98:  * we do not need to save callee save registers.
        !            99:  *
        !           100:  */
        !           101: 
        !           102: /* void Call_continuation( void (*continuation)(void),  vm_offset_t stack_ptr)
        !           103:  */
        !           104: 
        !           105: ENTRY(Call_continuation, TAG_NO_FRAME_USED)
        !           106:        mtlr    r3
        !           107:        mr      r1, r4          /* Load new stack pointer */
        !           108:        blr                     /* Jump to the continuation */
        !           109: 
        !           110: /*
        !           111:  * Get the old kernel stack, and store into the thread structure.
        !           112:  * See if a continuation is supplied, and skip state save if so.
        !           113:  * NB. Continuations are no longer used, so this test is omitted,
        !           114:  * as should the second argument, but it is in generic code.
        !           115:  * We always save state. This does not hurt even if continuations
        !           116:  * are put back in.
        !           117:  */
        !           118: 
        !           119: /*                     Context switches are double jumps.  We pass the following to the
        !           120:  *                     context switch firmware call:
        !           121:  *
        !           122:  *                     R3  = switchee's savearea
        !           123:  *                     R4  = old thread
        !           124:  *                     R5  = new SRR0
        !           125:  *                     R6  = new SRR1
        !           126:  *
        !           127:  *                     savesrr0 is set to go to switch_in
        !           128:  *                     savesrr1 is set to uninterruptible with translation on
        !           129:  */
        !           130: 
        !           131: 
        !           132: ENTRY(Switch_context, TAG_NO_FRAME_USED)
        !           133: 
        !           134:                        mfsprg  r6,0                                                    /* Get the per_proc block */
        !           135:                        lwz             r12,PP_ACTIVE_STACKS(r6)
        !           136: #if DEBUG
        !           137:                        lwz             r11,PP_ISTACKPTR(r6)                    ; (DEBUG/TRACE) make sure we are not
        !           138:                        mr.             r11,r11                                                 ; (DEBUG/TRACE) on the interrupt
        !           139:                        bne+    notonintstack                                   ; (DEBUG/TRACE) stack
        !           140:                        BREAKPOINT_TRAP
        !           141: notonintstack:
        !           142: #endif 
        !           143:                        stw             r4,THREAD_CONTINUATION(r3)
        !           144:                        cmpwi   cr1,r4,0                                                /* used waaaay down below */
        !           145:                        lwz             r11,0(r12)
        !           146:                        stw             r11,THREAD_KERNEL_STACK(r3)
        !           147: /*
        !           148:  * Make the new thread the current thread.
        !           149:  */
        !           150:        
        !           151:                        lwz             r11,PP_CPU_DATA(r6)
        !           152:                        stw             r5,     CPU_ACTIVE_THREAD(r11)
        !           153:                        
        !           154:                        lwz             r11,THREAD_KERNEL_STACK(r5)
        !           155:                
        !           156:                        lwz             r5,THREAD_TOP_ACT(r5)
        !           157:                        lwz             r10,PP_ACTIVE_STACKS(r6)
        !           158:                        lwz             r7,CTHREAD_SELF(r5)                             ; Pick up the user assist word
        !           159:                        lwz             r8,ACT_MACT_PCB(r5)                             /* Get the PCB for the new guy */
        !           160:                
        !           161:                        stw             r11,0(r10)                                              ; Save the kernel stack address
        !           162:                        stw             r7,UAW(r6)                                              ; Save the assist word for the "ultra fast path"
        !           163:                
        !           164:                        lwz             r7,ACT_MACT_SPF(r5)                             ; Get the special flags
        !           165:                        
        !           166:                        lwz             r10,ACT_KLOADED(r5)
        !           167:                        li              r0,0
        !           168:                        cmpwi   cr0,r10,0
        !           169:                        lwz             r10,PP_ACTIVE_KLOADED(r6)
        !           170:                        stw             r7,spcFlags(r6)                                 ; Set per_proc copy of the special flags
        !           171:                        beq             cr0,.L_sw_ctx_not_kld
        !           172:                
        !           173:                        stw             r5,0(r10)
        !           174:                        b               .L_sw_ctx_cont
        !           175: 
        !           176: .L_sw_ctx_not_kld:     
        !           177:                        stw             r0,0(r10)                                               /* act_kloaded = 0 */
        !           178: 
        !           179: .L_sw_ctx_cont:        
        !           180:                        rlwinm  r7,r8,0,0,19                                    /* Switch to savearea base */
        !           181:                        lwz             r11,SAVprev(r8)                                 /* Get the previous of the switchee's savearea */
        !           182: #if 1                  
        !           183:                        lis             r0,hi16(CutTrace)                               /* (TEST/DEBUG) */
        !           184:                        ori             r0,r0,lo16(CutTrace)                    /* (TEST/DEBUG) */
        !           185:                        lwz             r2,THREAD_TOP_ACT(r3)                   ; (TEST/DEBUG) Get the old activation
        !           186:                        mr              r10,r3                                                  /* (TEST/DEBUG) */
        !           187:                        mr              r3,r11                                                  /* (TEST/DEBUG) */
        !           188:                        sc                                                                              /* (TEST/DEBUG) */
        !           189:                        mr              r3,r10                                                  /* (TEST/DEBUG) */
        !           190: #endif
        !           191:                        
        !           192:                        mfmsr   r6                                                              /* Get the MSR because the switched to thread should inherit it */
        !           193:                        lwz             r7,SACvrswap(r7)                                /* Get the translation from virtual to real */
        !           194:                        lis             r0,hi16(SwitchContextCall)              /* Top part of switch context */
        !           195:                        lis             r9,hi16(EXT(switch_in))                 /* Get top of switch in routine */
        !           196:                        stw             r11,ACT_MACT_PCB(r5)                    /* Dequeue the savearea we're switching to */
        !           197: 
        !           198:                        rlwinm  r6,r6,0,MSR_FP_BIT+1,MSR_FP_BIT-1       /* Turn off the FP */
        !           199:                        ori             r9,r9,lo16(EXT(switch_in))              /* Bottom half of switch in */
        !           200:                        lwz             r5,savesrr0(r8)                                 /* Set up the new SRR0 */
        !           201:                        rlwinm  r6,r6,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     /* Turn off the vector */
        !           202:                        mr              r4,r3                                                   /* Save our old thread to pass back */
        !           203:                        stw             r9,savesrr0(r8)                                 /* Make us jump to the switch in routine */
        !           204:                        li              r10,MSR_SUPERVISOR_INT_OFF              /* Get the switcher's MSR */
        !           205:                        lwz             r9,SAVflags(r8)                                 /* Get the flags */
        !           206:                        stw             r10,savesrr1(r8)                                /* Set up for switch in */
        !           207:                        rlwinm  r9,r9,0,15,13                                   /* Reset the syscall flag */
        !           208:                        ori             r0,r0,lo16(SwitchContextCall)   /* Bottom part of switch context */
        !           209:                        rlwinm  r9,r9,0,1,31                                    /* Clear the attached flag */
        !           210:                        xor             r3,r7,r8                                                /* Get the physical address of the new context save area */
        !           211:                        stw             r9,SAVflags(r8)                                 /* Set the flags */
        !           212: /* if blocking on continuation avoid saving state */
        !           213:                        bne             cr1,1f
        !           214:                        sc                                                                              /* Switch to the new context */
        !           215:        
        !           216: /*                     We come back here in the new thread context     
        !           217:  *                     R4 was set to hold the old thread pointer, but switch_in will put it into
        !           218:  *                     R3 where it belongs.
        !           219:  */
        !           220:                        blr                                                                             /* Jump into the new thread */
        !           221:                
        !           222: 1:             stw             r5,savesrr0(r8)                                 /* go to real pc */
        !           223:                stw             r4,saver3(r8)                                   /* must pass back old thread */
        !           224:                b               EXT(exception_exit)                             /* blocking on continuation, avoid state save */
        !           225: 
        !           226: 
        !           227: 
        !           228: /*
        !           229:  *                     All switched to threads come here first to clean up the old thread.
        !           230:  *                     We need to do the following contortions because we need to keep
        !           231:  *                     the LR clean. And because we need to manipulate the savearea chain
        !           232:  *                     with translation on.  If we could, this should be done in lowmem_vectors
        !           233:  *                     before translation is turned on.  But we can't, dang it!
        !           234:  *
        !           235:  *                     R3  = switcher's savearea
        !           236:  *                     saver4  = old thread in switcher's save
        !           237:  *                     saver5  = new SRR0 in switcher's save
        !           238:  *                     saver6  = new SRR1 in switcher's save
        !           239: 
        !           240: 
        !           241:  */
        !           242:  
        !           243: ENTRY(switch_in, TAG_NO_FRAME_USED)
        !           244:                        
        !           245:                        lwz             r4,saver4(r3)                                   /* Get the old thread */
        !           246:                        li              r8,MSR_VM_OFF                                   /* Set to everything off */
        !           247:                        lwz             r9,THREAD_TOP_ACT(r4)                   /* Get the switched from ACT */
        !           248:                        lwz             r5,saver5(r3)                                   /* Get the srr0 value */
        !           249:                        lwz             r10,ACT_MACT_PCB(r9)                    /* Get the top PCB on the old thread */
        !           250:                        lwz             r6,saver6(r3)                                   /* Get the srr1 value */
        !           251: 
        !           252:                        stw             r3,ACT_MACT_PCB(r9)                             /* Put the new one on top */
        !           253:                        stw             r10,SAVprev(r3)                                 /* Chain on the old one */
        !           254: 
        !           255:                        mr              r3,r4                                                   /* Pass back the old thread */
        !           256: /*
        !           257:  *                     Note: we can't instruction trace the next few instructions
        !           258:  *                     because we blast the MSR
        !           259:  */
        !           260: 
        !           261:                        mtmsr   r8                                                              /* Turn off everything */
        !           262:                        isync
        !           263:                        mtsrr0  r5                                                              /* Set return point */
        !           264:                        mtsrr1  r6                                                              /* Set return MSR */
        !           265:                        rfi                                                                             /* Jam... */
        !           266:                        .long   0
        !           267:                        .long   0
        !           268:                        .long   0
        !           269:                        .long   0
        !           270:                        .long   0
        !           271:                        .long   0
        !           272:                        .long   0
        !           273:                        .long   0
        !           274: 
        !           275: 
        !           276:                        
        !           277: /*
        !           278:  * void fpu_save(void)
        !           279:  *
        !           280:  *             To do the floating point and VMX, we keep three thread pointers:  one
        !           281:  *             to the current thread, one to the thread that has the floating point context
        !           282:  *             loaded into the FPU registers, and one for the VMX owner.
        !           283:  *
        !           284:  *             Each of these threads has three PCB pointers.  The normal PCB, the FPU pcb,
        !           285:  *             and the VMX pcb.  There is also a bit for each in the savearea flags.
        !           286:  *             When we take an exception, or need to use the FPU/VMX in the kernel, we call
        !           287:  *             this routine.  It checks to see if there is an owner thread for the facility.
        !           288:  *             If so, it saves the facility's state information in the normal PCB. Then, it
        !           289:  *             turns on the appropriate flag in the savearea to indicate that the state is
        !           290:  *             in that particular savearea.  Also, the thread pointer for the owner in
        !           291:  *             the per_processor block is cleared.  Note that we don't have to worry about the
        !           292:  *             PCB pointers in the thread because whenever the state is loaded, the associated
        !           293:  *             savearea is released and the pointer cleared.  This is done so that the facility
        !           294:  *             context always migrates to the normal savearea/PCB.  This always insures that
        !           295:  *             no more than 2 saveareas are used for a thread.
        !           296:  *
        !           297:  *             When the context is loaded into the facility, the associated PCB is released if
        !           298:  *             its usage flags indicate that it is empty.  (Note that return from exception and
        !           299:  *             context switch honor these flags and won't release a savearea if there is unrestored
        !           300:  *             facility context.) The per_processor is set to point to the facility owner's
        !           301:  *             thread and the associated PCB pointer within the thread is cleared because
        !           302:  *             the PCB has been released.
        !           303:  *
        !           304:  *             Part of loading a context is to release the savearea.  If the savearea contains
        !           305:  *             other context, the savearea cannot be released.  So, what we're left with is 
        !           306:  *             that there will be no normal context savearea, but one for the as-not-yet
        !           307:  *             restored facility savearea.  Again, when that context is reloaded, the PCB
        !           308:  *             is released, and when it is again stored, it goes into the "normal" savearea.
        !           309:  *
        !           310:  *             So, what do we do when there is no general context, and we have some FPU/VMX
        !           311:  *             state to save?  Heck if I know, but it happens when we switch threads when
        !           312:  *             we shortcut system calls.  The question is: does the target thread carry the
        !           313:  *             FPU/VMX context with it or not? Actually, it don't matter, not one little bit.
        !           314:  *             If we are asked to save it, we gotta.  It's a really lousy way to do it, but
        !           315:  *             short of starting over with FPUs, it's what's what.  Therefore, we'll
        !           316:  *             allocate an FPU context save and attach it.  
        !           317:  *
        !           318:  *             Actually, it's not quite that simple:  since we aren't in 
        !           319:  *             in interrupt handler context (that's only in fpu_switch) we can't use 
        !           320:  *             quickfret to merge FPU into general context.  So, if there is an FPU
        !           321:  *             savearea, we need to use that.  So what we do is:  if there is FPU context
        !           322:  *             use that.  If there is a general context, then use that.  If neither, 
        !           323:  *             allocate a savearea and make that the FPU context.
        !           324:  *
        !           325:  *             The next thing we have to do is to allow the kernel to use both the 
        !           326:  *             floating point and Altivec.  It is not recommended, but there may be a
        !           327:  *             good reason to do so. So, what we need to do is to treat each of the
        !           328:  *             three types of context the same, by keeping a LIFO chain of states.
        !           329:  *             We do have a problem with that in that there can be multiple levels of
        !           330:  *             kernel context. For example, we are using floating point and we take a
        !           331:  *             page fault, and somehow start using the FPU, and take another page fault,
        !           332:  *             etc. 
        !           333:  *
        !           334:  *             Anyway, we will hope that we only reasonably use floating point and vectors in
        !           335:  *             the kernel. And try to pack the context in as few saveareas as possible.
        !           336:  *
        !           337:  *             The way we keep these "levels" of floating point or vector context straight is
        !           338:  *             to remember the top of the normal savearea chain when we activate the 
        !           339:  *             facility when it is first used.  Then, when we save that context, this value
        !           340:  *             is saved in its level field.
        !           341:  *
        !           342:  *             What the level concept gives us is a way to distinguish between multiple
        !           343:  *             independent contexts under the same thread activation. Any time we take
        !           344:  *             any kind of interruption (trap, system call, I/O interruption), we are,
        !           345:  *             in effect, running with a different context even though we are in the 
        !           346:  *             same thread. The top savearea address is used only as a marker. It does not
        !           347:  *             point to any context associated with the float or vector context. For example,
        !           348:  *             the top savearea pointer will always be 0 for the user context, because there 
        !           349:  *             it it always last on the list.
        !           350:  *
        !           351:  *             As normal context is unstacked, the first facility context is checked and
        !           352:  *             if there is a match, the facility savearea is released.  This is because we
        !           353:  *             are returning to a level before the facility saved there was used. In effect,
        !           354:  *             this allows us to unwind the facility context saveareas at different rates.
        !           355:  *
        !           356:  *             In conjunction with the current activation, these markers are also used to 
        !           357:  *             determine the state of the facility enablement. Whenever the facility context is
        !           358:  *             "live," i.e., loaded in the hardware registers and belonging to the currently
        !           359:  *             running context, the facility is enabled before dispatch.
        !           360:  *
        !           361:  *             There is nothing special about using floating point or vector facilities,
        !           362:  *             no preliminary saving, enabling, or disabling. You just use them.  The only exception
        !           363:  *             is during context switching on an SMP system.  In this case, the context must
        !           364:  *             be saved as there is no guarantee that the thread will resume on the same 
        !           365:  *             processor. This is not a good thing, not at all.  
        !           366:  *
        !           367:  *             Whenever we switch out a thread with a dirty context, we always need to save it
        !           368:  *             because it can wake up on a different processor.  However, once the context has
        !           369:  *             been saved, we don't need to save it again until it gets dirty, nor do we need
        !           370:  *             to reload it unless someone else's context has been loaded. To handle this
        !           371:  *             optimization, we need 3 things.  We need to know what processor the saved context
        !           372:  *             was last loaded on, whether the loaded context could be dirty, and if we've already 
        !           373:  *             saved it.
        !           374:  *
        !           375:  *             Whenever the facility is enabled, the processor ID is saved in the activation. This
        !           376:  *             will show which processor has dirty data. When a context switch occurs, the facility 
        !           377:  *             contexts are saved, but are still remembered as live. The next time we need to
        !           378:  *             context switch, we first check if the state is live, and if not, do no state
        !           379:  *             saving.  Then we check if the state has already been save and if not, save it.
        !           380:  *             The facility is always disabled on a context switch. On a UP, this save function
        !           381:  *             does not occur.
        !           382:  *             
        !           383:  *             Whenever a facility unavailable interruption occurs, the current state is saved
        !           384:  *             if it is live and unsaved.  However, if the live state is the same as the new
        !           385:  *             one to be loaded, the processor ID is checked and if it is the current processor
        !           386:  *             the state does not need to be loaded or saved. The facility is simply enabled.
        !           387:  *             
        !           388:  *             Once allocated, facility saveareas are not released until a return is made to a
        !           389:  *             previous level. Once a facility has been enabled, there is no way to tell if
        !           390:  *             it will ever be used again, but it is likely.  Therefore, discarding a savearea
        !           391:  *             when its context is made live is extra overhead.  So, we don't do it, but we
        !           392:  *             do mark the savearea contents as invalid.
        !           393:  *             
        !           394:  */
        !           395: 
        !           396: /*
        !           397: ;              The following is the actual way it is implemented.  It doesn't quite match
        !           398: ;              the above text. I need to go and fix that.
        !           399: ;
        !           400: ;       Context download (operates on owner's data):
        !           401: ;       
        !           402: ;       0)     enable facility
        !           403: ;       1)     if no owner exit to context restore
        !           404: ;       2)     if context processor != current processor exit to context restore
        !           405: ;       3)     if current activation == owner activation:
        !           406: ;              1)      if curr level == active level:
        !           407: ;                      1)      if top facility savearea exists:
        !           408: ;                              invalidate savearea by setting level to 1
        !           409: ;                      2)      enable facility for user
        !           410: ;                      3)      exit
        !           411: ;              
        !           412: ;              2) else go to 5
        !           413: ;       
        !           414: ;       4)     if curr level == active level:
        !           415: ;              1)      if top facility savearea exists:
        !           416: ;                      1)      if top save level == active level exit to context restore               
        !           417: ;       
        !           418: ;       5)     allocate savearea
        !           419: ;              1)      if there is a facility save and it is invalid, select it, and break
        !           420: ;              2)      scan normal list for free facility area, select if found, and break
        !           421: ;              3)      scan other facility for free save: select, if found, and break
        !           422: ;              4)      allocate a new save area
        !           423: ;       
        !           424: ;       6)     save context
        !           425: ;       7)     mark facility save with curr level
        !           426: ;       8)     if reusing cached savearea (case #1) exit to context restore
        !           427: ;       9)     set facility save backchain to facility top savearea
        !           428: ;       10)    set facility top to savearea
        !           429: ;       11)    exit to context restore
        !           430: ;       
        !           431: ;       
        !           432: ;       Context restore/upload (operates on current activation's data):
        !           433: ;       
        !           434: ;       1)     set current to activation
        !           435: ;       2)     set active level to current level
        !           436: ;       3)     set context processor to current processor
        !           437: ;       4)     if no facility savearea or top save level != curr level
        !           438: ;                      initialize facility registers to empty value
        !           439: ;       5)     else 
        !           440: ;              1)      load registers from savearea
        !           441: ;              2)      invalidate save area by setting level to 1
        !           442: ;              
        !           443: ;       6)     enable facility for user
        !           444: ;       7)     exit to interrupt return
        !           445: ;       
        !           446: ;       
        !           447: ;       Context save (operates on current activation's data; only used during context switch):
        !           448: ;                               (context switch always disables the facility)
        !           449: ;       
        !           450: ;       1)     if no owner exit
        !           451: ;       2)     if owner != current activation exit
        !           452: ;       3)     if context processor != current processor 
        !           453: ;              1)      clear owner
        !           454: ;              2)      exit
        !           455: ;              
        !           456: ;       4)     if facility top savearea level exists and == active level exit
        !           457: ;       5)     if curr level != active level exit
        !           458: ;       6)     allocate savearea
        !           459: ;              1)      if there is a facility save and it is invalid, select it, and break
        !           460: ;              2)      scan normal list for free facility area, select if found, and break
        !           461: ;              3)      scan other facility for free save: select, if found, and break
        !           462: ;              4)      allocate a new save area
        !           463: ;       7)     save context
        !           464: ;       8)     mark facility savearea with curr level
        !           465: ;       9)     if reusing cached savearea (case #1) exit
        !           466: ;       10)    set facility save backchain to facility top savearea
        !           467: ;       11)    set facility top to savearea
        !           468: ;       12)    exit
        !           469: ;       
        !           470: ;       
        !           471: ;       Exception exit (hw_exceptions):
        !           472: ;       
        !           473: ;       1)     disable return facility
        !           474: ;       2)     if returning savearea != active level 
        !           475: ;              1)      if owner != current activation exit
        !           476: ;              2)      if context processor != current processor:
        !           477: ;                      1)      clear owner
        !           478: ;                      2)      exit
        !           479: ;              
        !           480: ;              3)      if new level != active level exit
        !           481: ;              4)      enable return facility
        !           482: ;              5)      exit
        !           483: ;       
        !           484: ;       3)     if no facility savearea exit
        !           485: ;       4)     if top save level == active or top is invalid
        !           486: ;              1)      dequeue top facility savearea
        !           487: ;              2)      set active level to new top savearea's level
        !           488: ;              3)      release savearea
        !           489: ;              4)      if owner == current activation clear owner
        !           490: ;       5)     exit
        !           491: ;       
        !           492: ;       
        !           493: ;       
        !           494: ;       
        !           495: ;       if (owner == activation) && (curr level == active level)
        !           496: ;              && (activation processor == current processor) ::= context live
        !           497: */
        !           498: 
        !           499: ENTRY(fpu_save, TAG_NO_FRAME_USED)
        !           500: 
        !           501:                        mfmsr   r0                                              ; Get the MSR
        !           502:                        rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Turn off floating point forever
        !           503:                        rlwinm  r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1       ; But do interrupts only for now
        !           504:                        ori             r2,r2,MASK(MSR_FP)              ; Enable the floating point feature for now also
        !           505:                        mtmsr   r2                                              ; Set the MSR
        !           506:                        isync
        !           507:                
        !           508:                        mfsprg  r6,0                                    ; Get the per_processor block 
        !           509:                        lwz             r12,PP_FPU_THREAD(r6)   ; Get the thread that owns the FPU
        !           510: #if FPVECDBG
        !           511:                        mr              r7,r0                                   ; (TEST/DEBUG)
        !           512:                        li              r4,0                                    ; (TEST/DEBUG)
        !           513:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !           514:                        mr.             r3,r12                                  ; (TEST/DEBUG)
        !           515:                        li              r2,0x6F00                               ; (TEST/DEBUG)
        !           516:                        li              r5,0                                    ; (TEST/DEBUG)
        !           517:                        beq-    noowneryet                              ; (TEST/DEBUG)
        !           518:                        lwz             r4,ACT_MACT_FPUlvl(r12) ; (TEST/DEBUG)
        !           519:                        lwz             r5,ACT_MACT_FPU(r12)    ; (TEST/DEBUG)
        !           520: 
        !           521: noowneryet:    oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !           522:                        sc                                                              ; (TEST/DEBUG)
        !           523:                        mr              r0,r7                                   ; (TEST/DEBUG)
        !           524: #endif 
        !           525:                        mflr    r2                                              ; Save the return address
        !           526:                        lwz             r10,PP_CPU_DATA(r6)             ; Get the CPU data pointer
        !           527:                        lhz             r11,PP_CPU_NUMBER(r6)   ; Get our CPU number
        !           528:                        
        !           529:                        mr.             r12,r12                                 ; Anyone own the FPU?
        !           530:                        
        !           531:                        lwz             r10,CPU_ACTIVE_THREAD(r10)      ; Get the pointer to the active thread
        !           532:                        
        !           533:                        beq-    fsret                                   ; Nobody owns the FPU, no save required...
        !           534:                        
        !           535:                        lwz             r10,THREAD_TOP_ACT(r10) ; Now get the activation that is running
        !           536:                        lwz             r9,ACT_MACT_FPUcpu(r12) ; Get the last CPU to use this context
        !           537:                        
        !           538:                        cmplw   r12,r10                                 ; Do we own the FPU?
        !           539:                        cmplw   cr1,r9,r11                              ; Was the context for this processor? 
        !           540:                        bne+    fsret                                   ; Facility belongs to some other activation...
        !           541:                        li              r3,0                                    ; Assume we need a fix-me-up
        !           542:                        beq-    cr1,fsgoodcpu                   ; Facility last used on this processor...
        !           543:                        stw             r3,PP_FPU_THREAD(r6)    ; Clear owner because it was really on the other processor
        !           544:                        b               fsret                                   ; Bail now with no save...
        !           545:                        
        !           546: fsgoodcpu:     lwz             r3,ACT_MACT_FPU(r12)    ; Get the current FPU savearea for the thread
        !           547:                        lwz             r9,ACT_MACT_FPUlvl(r12) ; Get our current level indicator
        !           548:                        
        !           549:                        cmplwi  cr1,r3,0                                ; Have we ever saved this facility context?
        !           550:                        beq-    cr1,fsneedone                   ; Never saved it, so we need an area...
        !           551:                        
        !           552:                        lwz             r8,SAVlvlfp(r3)                 ; Get the level this savearea is for
        !           553:                        cmplwi  r8,1                                    ; See if it is a spare
        !           554:                        cmplw   cr1,r9,r8                               ; Correct level?
        !           555:                        beq+    fsusespare                              ; We have a spare to use...
        !           556:                        beq-    cr1,fsret                               ; The current level is already saved, bail out...
        !           557: 
        !           558: fsneedone:     li              r3,0                                    ; Tell the routine to allocate an area if none found
        !           559:                        bl              fpsrchsave                              ; Find a free savearea
        !           560:                        
        !           561:                        mfsprg  r6,0                                    ; Get back per_processor block
        !           562:                        oris    r7,r7,hi16(SAVfpuvalid) ; Set the allocated bit
        !           563:                        lwz             r12,PP_FPU_THREAD(r6)   ; Get back our thread
        !           564:                        mtlr    r2                                              ; Restore return
        !           565:                        lwz             r8,ACT_MACT_FPU(r12)    ; Get the current top floating point savearea
        !           566:                        lwz             r9,ACT_MACT_FPUlvl(r12) ; Get our current level indicator again         
        !           567:                        stw             r3,ACT_MACT_FPU(r12)    ; Set this as the latest FPU savearea for the thread
        !           568:                        stw             r8,SAVprefp(r3)                 ; And then chain this in front
        !           569:                        stw             r7,SAVflags(r3)                 ; Set the validity flags
        !           570:                        stw             r12,SAVact(r3)                  ; Make sure we point to the right guy
        !           571: 
        !           572: fsusespare:    stw             r9,SAVlvlfp(r3)                 ; And set the level this savearea is for
        !           573: 
        !           574: ;
        !           575: ;                      Save the current FPU state into the PCB of the thread that owns it.
        !           576: ; 
        !           577: 
        !           578:                        la              r11,savefp0(r3)                 ; Point to the 1st line
        !           579:                        dcbz    0,r11                                   ; Allocate the first savearea line 
        !           580:                        
        !           581:                        la              r11,savefp4(r3)                 /* Point to the 2nd line */
        !           582:                        stfd    f0,savefp0(r3)
        !           583:                        dcbz    0,r11                                   /* allocate it */
        !           584:                        stfd    f1,savefp1(r3)
        !           585:                        stfd    f2,savefp2(r3)
        !           586:                        la              r11,savefp8(r3)                 /* Point to the 3rd line */
        !           587:                        stfd    f3,savefp3(r3)
        !           588:                        dcbz    0,r11                                   /* allocate it */
        !           589:                        stfd    f4,savefp4(r3)
        !           590:                        stfd    f5,savefp5(r3)
        !           591:                        stfd    f6,savefp6(r3)
        !           592:                        la              r11,savefp12(r3)                /* Point to the 4th line */
        !           593:                        stfd    f7,savefp7(r3)
        !           594:                        dcbz    0,r11                                   /* allocate it */
        !           595:                        stfd    f8,savefp8(r3)
        !           596:                        stfd    f9,savefp9(r3)
        !           597:                        stfd    f10,savefp10(r3)
        !           598:                        la              r11,savefp16(r3)                /* Point to the 5th line */
        !           599:                        stfd    f11,savefp11(r3)
        !           600:                        dcbz    0,r11                                   /* allocate it */
        !           601:                        stfd    f12,savefp12(r3)
        !           602:                        stfd    f13,savefp13(r3)
        !           603:                        stfd    f14,savefp14(r3)
        !           604:                        la              r11,savefp20(r3)                /* Point to the 6th line */
        !           605:                        stfd    f15,savefp15(r3)
        !           606:                        stfd    f16,savefp16(r3)
        !           607:                        stfd    f17,savefp17(r3)
        !           608:                        stfd    f18,savefp18(r3)
        !           609:                        la              r11,savefp24(r3)                /* Point to the 7th line */
        !           610:                        stfd    f19,savefp19(r3)
        !           611:                        dcbz    0,r11                                   /* allocate it */
        !           612:                        stfd    f20,savefp20(r3)
        !           613:                        mffs    f0                                              /* fpscr in f0 low 32 bits */
        !           614:                        stfd    f21,savefp21(r3)
        !           615:                        stfd    f22,savefp22(r3)
        !           616:                        la              r11,savefp28(r3)                /* Point to the 8th line */
        !           617:                        stfd    f23,savefp23(r3)
        !           618:                        dcbz    0,r11                                   /* allocate it */
        !           619:                        stfd    f24,savefp24(r3)
        !           620:                        stfd    f25,savefp25(r3)
        !           621:                        stfd    f26,savefp26(r3)
        !           622:                        stfd    f27,savefp27(r3)
        !           623:                        stfd    f28,savefp28(r3)
        !           624:                        stfd    f0,savefpscrpad(r3)             ; Save the FPSCR
        !           625:                        stfd    f29,savefp29(r3)
        !           626:                        stfd    f30,savefp30(r3)
        !           627:                        stfd    f31,savefp31(r3)
        !           628:                        lfd     f0,savefp0(r3)                  ; We need to restore F0 because we used it      
        !           629:                                                                                        ; to get the FPSCR
        !           630:                                                                                        
        !           631: #if 0
        !           632:                        la              r9,savefp0(r3)                  ; (TEST/DEBUG)
        !           633:                        la              r10,savefp31(r3)                ; (TEST/DEBUG)
        !           634:                        
        !           635: chkkillmedead:
        !           636:                        lha             r8,0(r9)                                ; (TEST/DEBUG)
        !           637:                        addi    r9,r9,8                                 ; (TEST/DEBUG)
        !           638:                        cmpwi   r8,-8                                   ; (TEST/DEBUG)
        !           639:                        cmplw   cr1,r9,r10                              ; (TEST/DEBUG)
        !           640:                        bne+    dontkillmedead                  ; (TEST/DEBUG)
        !           641:                        BREAKPOINT_TRAP                                 ; (TEST/DEBUG)
        !           642: 
        !           643: dontkillmedead:                                                                ; (TEST/DEBUG)
        !           644:                        ble+    cr1,chkkillmedead               ; (TEST/DEBUG)
        !           645: #endif
        !           646: 
        !           647: fsret:         mtmsr   r0                                              ; Put interrupts on if they were and floating point off
        !           648:                        isync
        !           649: 
        !           650:                        blr
        !           651: 
        !           652: /*
        !           653:  * fpu_switch()
        !           654:  *
        !           655:  * Entered to handle the floating-point unavailable exception and
        !           656:  * switch fpu context
        !           657:  *
        !           658:  * This code is run in virtual address mode on with interrupts off.
        !           659:  *
        !           660:  * Upon exit, the code returns to the users context with the floating
        !           661:  * point facility turned on.
        !           662:  *
        !           663:  * ENTRY:      VM switched ON
        !           664:  *             Interrupts  OFF
        !           665:  *              State is saved in savearea pointed to by R4.
        !           666:  *                             All other registers are free.
        !           667:  * 
        !           668:  */
        !           669: 
        !           670: ENTRY(fpu_switch, TAG_NO_FRAME_USED)
        !           671: #if DEBUG
        !           672: #if GDDBG
        !           673:                        mr              r7,r4                                   ; Save input parameter
        !           674:                        lis             r3,hi16(EXT(fpu_trap_count))    ; Get address of FP trap counter
        !           675:                        ori             r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter
        !           676:                        lwz             r1,0(r3)
        !           677:                        lis             r5,hi16(EXT(GratefulDeb))       ; Point to top of display
        !           678:                        ori             r5,r5,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !           679:                        addi    r1,r1,1
        !           680:                        mtlr    r5                                              ; Set link register
        !           681:                        stw             r1,0(r3)
        !           682:                        mr              r4,r1
        !           683:                        li              r3,0
        !           684:                        blrl                                                    ; Display count
        !           685:                        mr              r4,r7                                   ; Restore the parameter
        !           686: #else
        !           687:                        lis             r3,hi16(EXT(fpu_trap_count))    ; Get address of FP trap counter
        !           688:                        ori             r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter
        !           689:                        lwz             r1,0(r3)
        !           690:                        addi    r1,r1,1
        !           691:                        stw             r1,0(r3)
        !           692: #endif
        !           693: #endif /* DEBUG */
        !           694: 
        !           695:                        mfsprg  r6,0                                    ; Get the per_processor block
        !           696:                        mfmsr   r19                                             ; Get the current MSR 
        !           697:                        
        !           698:                        lwz             r10,PP_CPU_DATA(r6)             ; Get the CPU data pointer
        !           699:                        lwz             r12,PP_FPU_THREAD(r6)   ; Get the thread that owns the FPU
        !           700:                        lwz             r10,CPU_ACTIVE_THREAD(r10)      ; Get the pointer to the active thread
        !           701:                        ori             r19,r19,lo16(MASK(MSR_FP))      ; Enable the floating point feature
        !           702:                        lwz             r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
        !           703: 
        !           704: ;                      R12 has the "old" activation
        !           705: ;                      R17 has the "new" activation
        !           706: 
        !           707: #if FPVECDBG
        !           708:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !           709:                        li              r2,0x7F01                               ; (TEST/DEBUG)
        !           710:                        mr              r3,r12                                  ; (TEST/DEBUG)
        !           711:                        mr              r5,r17                                  ; (TEST/DEBUG)
        !           712:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !           713:                        sc                                                              ; (TEST/DEBUG)
        !           714: #endif 
        !           715:                        mr.             r12,r12                                 ; See if there is any live FP status
        !           716:                        
        !           717:                        lhz             r18,PP_CPU_NUMBER(r6)   ; Get the current CPU, we will need it later
        !           718:                        
        !           719:                        mtmsr   r19                                             ; Enable floating point instructions
        !           720:                        isync
        !           721:                        
        !           722:                        beq-    fsnosave                                ; No live context, so nothing to save...
        !           723: 
        !           724:                        lwz             r19,ACT_MACT_FPUcpu(r12)        ; Get the "old" active CPU
        !           725:                        lwz             r15,ACT_MACT_PCB(r12)   ; Get the current level of the "old" one
        !           726:                        cmplw   r18,r19                                 ; Check the CPU that the old context is live on
        !           727:                        lwz             r14,ACT_MACT_FPU(r12)   ; Point to the top of the old context stack
        !           728:                        bne-    fsnosave                                ; Context is not live if used on a different CPU...
        !           729:                        lwz             r13,ACT_MACT_FPUlvl(r12)        ; Get the "old" active level
        !           730:                        
        !           731: ;
        !           732: ;                      First, check to see if all we are doing is enabling because the
        !           733: ;                      "new" context is live.
        !           734: ;
        !           735: #if FPVECDBG
        !           736:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !           737:                        li              r2,0x7F02                               ; (TEST/DEBUG)
        !           738:                        mr              r1,r15                                  ; (TEST/DEBUG)
        !           739:                        mr              r3,r13                                  ; (TEST/DEBUG)
        !           740:                        mr              r5,r14                                  ; (TEST/DEBUG)
        !           741:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !           742:                        sc                                                              ; (TEST/DEBUG)
        !           743: #endif 
        !           744: 
        !           745:                        cmplw   cr1,r12,r17                             ; Are the "old" activation and the "new" the same?
        !           746:                        cmplwi  cr2,r14,0                               ; Is there any saved context on the "old" activation?
        !           747:                        bne+    cr1,fsmstsave                   ; The activations are different so "old" context must be saved...
        !           748: 
        !           749: ;
        !           750: ;                      Here we know that both the "old" and "new" activations are the same.  We will
        !           751: ;                      check the current level and active levels.  If they are the same, the context is
        !           752: ;                      already live, so all we do is turn on the facility and invalidate the top
        !           753: ;                      savearea. 
        !           754: ;              
        !           755: ;                      If the current level, the active level, and the top savearea level are the
        !           756: ;                      same, then the context was saved as part of a thread context switch and neither
        !           757: ;                      needs saving or restoration.
        !           758: ;                      
        !           759: ;                      In all other cases, the context must be saved unless we are just re-enabling
        !           760: ;                      floating point.
        !           761: ;
        !           762: 
        !           763:                        cmplw   r13,r15                                 ; Are the levels the same?
        !           764:                        cmplwi  cr2,r14,0                               ; Is there any saved context?
        !           765:                        bne-    fsmstsave                               ; Levels are different, we need to save...
        !           766:                        
        !           767:                        beq-    cr2,fsenable                    ; No saved context at all, enable and go...
        !           768:                        
        !           769:                        lwz             r20,SAVlvlfp(r14)               ; Get the level of the top savearea
        !           770: 
        !           771: #if FPVECDBG
        !           772:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !           773:                        li              r2,0x7F03                               ; (TEST/DEBUG)
        !           774:                        mr              r3,r15                                  ; (TEST/DEBUG)
        !           775:                        mr              r5,r20                                  ; (TEST/DEBUG)
        !           776:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !           777:                        sc                                                              ; (TEST/DEBUG)
        !           778: #endif 
        !           779:                        cmplw   r15,r20                                 ; Is the top level the same as the current?
        !           780:                        li              r0,1                                    ; Get the invalid flag
        !           781:                        bne-    fsenable                                ; Not the same, just enable and go...
        !           782:                        
        !           783:                        stw             r0,SAVlvlfp(r14)                ; Invalidate that top savearea
        !           784: 
        !           785:                        b               fsenable                                ; Then enable and go...
        !           786:                        
        !           787: ;
        !           788: ;                      We need to save the "old" context here.  The LIFO queueing scheme works
        !           789: ;                      out for all cases because if both the "new" and "old" activations are the
        !           790: ;                      same, there can not be any saved state to load.  the "new" level is
        !           791: ;                      truely new.
        !           792: ;
        !           793: ;                      When we save the context, we either use a new savearea, or the free
        !           794: ;                      one that is cached at the head of the list.
        !           795:                        
        !           796: fsmstsave:     beq-    cr2,fsgetsave                   ; There is no possible cached save area
        !           797:                        
        !           798:                        lwz             r5,SAVlvlfp(r14)                ; Get the level of first facility savearea
        !           799: #if FPVECDBG
        !           800:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !           801:                        li              r2,0x7F04                               ; (TEST/DEBUG)
        !           802:                        mr              r3,r15                                  ; (TEST/DEBUG)
        !           803:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !           804:                        sc                                                              ; (TEST/DEBUG)
        !           805: #endif 
        !           806:                        mr              r3,r14                                  ; Assume we are invalid
        !           807:                        cmplwi  r5,1                                    ; Is it invalid?
        !           808:                        cmplw   cr1,r5,r13                              ; Is the SA level the active one?
        !           809:                        beq+    fsusecache                              ; Invalid, just use it...
        !           810:                        beq-    cr1,fsnosave                    ; The SA level is active, it is already saved...
        !           811:                        
        !           812: fsgetsave:     mr              r3,r4                                   ; Use the interrupt save as the context savearea if none cached
        !           813: #if FPVECDBG
        !           814:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !           815:                        li              r2,0x7F05                               ; (TEST/DEBUG)
        !           816:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !           817:                        sc                                                              ; (TEST/DEBUG)
        !           818: #endif 
        !           819:                        
        !           820:                        bl              fpsrchsave                              ; Find a free savearea
        !           821: 
        !           822:                        stw             r3,ACT_MACT_FPU(r12)    ; Set this as the latest context savearea for the thread
        !           823:                        mfsprg  r6,0                                    ; Get back per_processor block
        !           824:                        stw             r14,SAVprefp(r3)                ; And then chain this in front
        !           825:                        oris    r7,r7,hi16(SAVfpuvalid) ; Set the allocated bit
        !           826:                        stw             r12,SAVact(r3)                  ; Make sure we point to the right guy
        !           827:                        stw             r7,SAVflags(r3)                 ; Set the allocation flags
        !           828: 
        !           829: fsusecache:    la              r11,savefp0(r3)                 ; Point to the 1st line in area
        !           830:                        stw             r13,SAVlvlfp(r3)                ; Set this context level
        !           831: #if FPVECDBG
        !           832:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !           833:                        li              r2,0x7F06                               ; (TEST/DEBUG)
        !           834:                        mr              r5,r13                                  ; (TEST/DEBUG)
        !           835:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !           836:                        sc                                                              ; (TEST/DEBUG)
        !           837: #endif 
        !           838: 
        !           839: ;
        !           840: ;                      Now we will actually save the old context
        !           841: ;
        !           842:                        
        !           843:                        dcbz    0,r11                                   ; Allocate the output area
        !           844: 
        !           845:                        la              r11,savefp4(r3)                 ; Point to the 2nd line
        !           846:                        stfd    f0,savefp0(r3)
        !           847:                        dcbz    0,r11                                   ; Allocate cache
        !           848:                        stfd    f1,savefp1(r3)
        !           849:                        stfd    f2,savefp2(r3)
        !           850:                        la              r11,savefp8(r3)                 ; Point to the 3rd line
        !           851:                        stfd    f3,savefp3(r3)
        !           852:                        dcbz    0,r11                                   ; Allocate cache
        !           853:                        stfd    f4,savefp4(r3)
        !           854:                        stfd    f5,savefp5(r3)
        !           855:                        stfd    f6,savefp6(r3)
        !           856:                        la              r11,savefp12(r3)                ; Point to the 4th line
        !           857:                        stfd    f7,savefp7(r3)
        !           858:                        dcbz    0,r11                                   ; Allocate cache
        !           859:                        stfd    f8,savefp8(r3)
        !           860:                        stfd    f9,savefp9(r3)
        !           861:                        stfd    f10,savefp10(r3)
        !           862:                        la              r11,savefp16(r3)                ; Point to the 5th line
        !           863:                        stfd    f11,savefp11(r3)
        !           864:                        dcbz    0,r11                                   ; Allocate cache
        !           865:                        stfd    f12,savefp12(r3)
        !           866:                        stfd    f13,savefp13(r3)
        !           867:                        stfd    f14,savefp14(r3)
        !           868:                        la              r11,savefp20(r3)                ; Point to the 6th line 
        !           869:                        stfd    f15,savefp15(r3)
        !           870:                        dcbz    0,r11                                   ; Allocate cache
        !           871:                        stfd    f16,savefp16(r3)
        !           872:                        stfd    f17,savefp17(r3)
        !           873:                        stfd    f18,savefp18(r3)
        !           874:                        la              r11,savefp24(r3)                ; Point to the 7th line
        !           875:                        stfd    f19,savefp19(r3)
        !           876:                        dcbz    0,r11                                   ; Allocate cache
        !           877:                        stfd    f20,savefp20(r3)
        !           878:                        mffs    f0                                              ; Get the FPSCR
        !           879:                        stfd    f21,savefp21(r3)
        !           880:                        stfd    f22,savefp22(r3)
        !           881:                        la              r11,savefp28(r3)                ; Point to the 8th line
        !           882:                        stfd    f23,savefp23(r3)
        !           883:                        dcbz    0,r11                                   ; allocate it
        !           884:                        stfd    f24,savefp24(r3)
        !           885:                        stfd    f25,savefp25(r3)
        !           886:                        stfd    f26,savefp26(r3)
        !           887:                        la              r11,savefpscrpad(r3)    ; Point to the 9th line
        !           888:                        stfd    f27,savefp27(r3)
        !           889:                        dcbz    0,r11                                   ; allocate it
        !           890:                        stfd    f28,savefp28(r3)
        !           891:                        stfd    f29,savefp29(r3)
        !           892:                        stfd    f30,savefp30(r3)
        !           893:                        stfd    f31,savefp31(r3)
        !           894:                        stfd    f0,savefpscrpad(r3)
        !           895: 
        !           896: ;
        !           897: ;                      The context is all saved now and the facility is free.
        !           898: ;
        !           899: ;                      Now check out the "new" and see if we need to load up his context.
        !           900: ;                      If we do (and this should be the normal case), do it and then invalidate the
        !           901: ;                      savearea. (This will keep it cached for quick access next time around.)
        !           902: ;                      
        !           903: ;                      If we do not (remember, we already took care of the case where we just enable
        !           904: ;                      the FPU), we need to fill the registers with junk, because this level has 
        !           905: ;                      never used them before and some thieving bastard could hack the old values
        !           906: ;                      of some thread!  Just imagine what would happen if they could!  Why, nothing
        !           907: ;                      would be safe! My God! It is terrifying!
        !           908: ;
        !           909: 
        !           910:                        
        !           911: fsnosave:      lwz             r15,ACT_MACT_PCB(r17)   ; Get the current level of the "new" one
        !           912:                        lwz             r14,ACT_MACT_FPU(r17)   ; Point to the top of the "new" context stack
        !           913:                        lwz             r13,ACT_MACT_FPUlvl(r17)        ; Get the "new" active level
        !           914: #if FPVECDBG
        !           915:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !           916:                        li              r2,0x7F07                               ; (TEST/DEBUG)
        !           917:                        mr              r1,r15                                  ; (TEST/DEBUG)
        !           918:                        mr              r3,r14                                  ; (TEST/DEBUG)
        !           919:                        mr              r5,r13                                  ; (TEST/DEBUG)
        !           920:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !           921:                        sc                                                              ; (TEST/DEBUG)
        !           922: #endif 
        !           923: 
        !           924:                        cmplwi  cr1,r14,0                               ; Do we possibly have some context to load?
        !           925:                        stw             r15,ACT_MACT_FPUlvl(r17)        ; Set the "new" active level
        !           926:                        stw             r18,ACT_MACT_FPUcpu(r17)        ; Set the active CPU
        !           927:                        la              r11,savefp0(r14)                ; Point to first line to bring in
        !           928:                        stw             r17,PP_FPU_THREAD(r6)   ; Store current thread address in fpu_thread to claim fpu for thread
        !           929:                        
        !           930:                        beq+    cr1,MakeSureThatNoTerroristsCanHurtUsByGod      ; No "new" context to load...
        !           931:                        lwz             r0,SAVlvlfp(r14)                ; Get the level of first facility savearea
        !           932:                        cmplw   r0,r15                                  ; Top level correct to load?
        !           933:                        bne-    MakeSureThatNoTerroristsCanHurtUsByGod  ; No, go initialize...
        !           934:                        
        !           935: #if FPVECDBG
        !           936:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !           937:                        li              r2,0x7F08                               ; (TEST/DEBUG)
        !           938:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !           939:                        sc                                                              ; (TEST/DEBUG)
        !           940: #endif 
        !           941: 
        !           942:                        dcbt    0,r11                                   ; Touch line in
        !           943:                        li              r0,1                                    ; Get the level invalid indication
        !           944:                                                
        !           945:                        la              r11,savefp4(r14)                ; Point to next line
        !           946:                        dcbt    0,r11                                   ; Touch line in
        !           947:                        lfd             f31,savefpscrpad(r14)   ; Load junk 32 bits+fpscr
        !           948:                        lfd     f0, savefp0(r14)
        !           949:                        lfd     f1,savefp1(r14)
        !           950:                        stw             r0,SAVlvlfp(r14)                ; Mark the savearea invalid because we are activating again
        !           951:                        lfd     f2,savefp2(r14)
        !           952:                        la              r11,savefp8(r14)                ; Point to next line
        !           953:                        lfd     f3,savefp3(r14)
        !           954:                        dcbt    0,r11                                   ; Touch line in
        !           955:                        lfd     f4,savefp4(r14)
        !           956:                        lfd     f5,savefp5(r14)
        !           957:                        lfd     f6,savefp6(r14)
        !           958:                        la              r11,savefp12(r14)               ; Point to next line
        !           959:                        lfd     f7,savefp7(r14)
        !           960:                        dcbt    0,r11                                   ; Touch line in
        !           961:                        mtfsf   0xff,f31                                ; fpscr in f0 low 32 bits
        !           962:                        lfd     f8,savefp8(r14)
        !           963:                        lfd     f9,savefp9(r14)
        !           964:                        lfd     f10,savefp10(r14)
        !           965:                        la              r11,savefp16(r14)               ; Point to next line
        !           966:                        lfd     f11,savefp11(r14)
        !           967:                        dcbt    0,r11                                   ; Touch line in
        !           968:                        lfd     f12,savefp12(r14)
        !           969:                        lfd     f13,savefp13(r14)
        !           970:                        lfd     f14,savefp14(r14)
        !           971:                        la              r11,savefp20(r14)               ; Point to next line
        !           972:                        lfd     f15,savefp15(r14)
        !           973:                        dcbt    0,r11                                   ; Touch line in
        !           974:                        lfd     f16,savefp16(r14)
        !           975:                        lfd     f17,savefp17(r14)
        !           976:                        lfd     f18,savefp18(r14)
        !           977:                        la              r11,savefp24(r14)               ; Point to next line
        !           978:                        lfd     f19,savefp19(r14)
        !           979:                        dcbt    0,r11                                   ; Touch line in
        !           980:                        lfd     f20,savefp20(r14)
        !           981:                        lfd     f21,savefp21(r14)
        !           982:                        la              r11,savefp28(r14)               ; Point to next line
        !           983:                        lfd     f22,savefp22(r14)
        !           984:                        lfd     f23,savefp23(r14)
        !           985:                        dcbt    0,r11                                   ; Touch line in
        !           986:                        lfd     f24,savefp24(r14)
        !           987:                        lfd     f25,savefp25(r14)
        !           988:                        lfd     f26,savefp26(r14)
        !           989:                        lfd     f27,savefp27(r14)
        !           990:                        lfd     f28,savefp28(r14)
        !           991:                        lfd     f29,savefp29(r14)
        !           992:                        lfd     f30,savefp30(r14)
        !           993:                        lfd     f31,savefp31(r14)
        !           994:                        
        !           995: fsenable:      lwz             r9,SAVflags(r4)                 /* Get the flags of the current savearea */
        !           996:                        lwz             r8,savesrr1(r4)                 ; Get the msr of the interrupted guy
        !           997:                        rlwinm  r5,r4,0,0,19                    /* Get the page address of the savearea */
        !           998:                        ori             r8,r8,MASK(MSR_FP)              ; Enable the floating point feature
        !           999:                        lwz             r10,ACT_MACT_SPF(r17)   ; Get the special flags
        !          1000:                        lis             r7,hi16(SAVattach)              /* Get the attached flag */
        !          1001:                        lwz             r5,SACvrswap(r5)                /* Get Virtual to Real translation */
        !          1002:                        oris    r10,r10,hi16(floatUsed) ; Set that we used floating point
        !          1003:                        mr.             r15,r15                                 ; See if we are doing this for user state
        !          1004:                        stw             r8,savesrr1(r4)                 ; Set the msr of the interrupted guy
        !          1005:                        andc    r9,r9,r7                                /* Clear the attached bit */
        !          1006:                        xor             r3,r4,r5                                /* Get the real address of the savearea */
        !          1007:                        bne-    fsnuser                                 ; We are not user state...
        !          1008:                        stw             r10,ACT_MACT_SPF(r17)   ; Set the activation copy
        !          1009:                        stw             r10,spcFlags(r6)                ; Set per_proc copy
        !          1010: 
        !          1011: fsnuser:
        !          1012: #if FPVECDBG
        !          1013:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          1014:                        li              r2,0x7F0A                               ; (TEST/DEBUG)
        !          1015:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1016:                        sc                                                              ; (TEST/DEBUG)
        !          1017: #endif 
        !          1018:                        stw             r9,SAVflags(r4)                 /* Set the flags of the current savearea */
        !          1019:                        
        !          1020:                        b               EXT(exception_exit)             /* Exit from the fray... */
        !          1021: 
        !          1022: /*
        !          1023:  *                     Initialize the registers to some bogus value
        !          1024:  */
        !          1025: 
        !          1026: MakeSureThatNoTerroristsCanHurtUsByGod:
        !          1027:                        
        !          1028: #if FPVECDBG
        !          1029:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          1030:                        li              r2,0x7F09                               ; (TEST/DEBUG)
        !          1031:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1032:                        sc                                                              ; (TEST/DEBUG)
        !          1033: #endif 
        !          1034:                        lis             r5,hi16(EXT(FloatInit)) /* Get top secret floating point init value address */
        !          1035:                        ori             r5,r5,lo16(EXT(FloatInit))      /* Slam bottom */
        !          1036:                        lfd             f0,0(r5)                                /* Initialize FP0 */
        !          1037:                        fmr             f1,f0                                   ; Do them all                                           
        !          1038:                        fmr             f2,f0                                                           
        !          1039:                        fmr             f3,f0                                                           
        !          1040:                        fmr             f4,f0                                                           
        !          1041:                        fmr             f5,f0                                           
        !          1042:                        fmr             f6,f0                                           
        !          1043:                        fmr             f7,f0                                           
        !          1044:                        fmr             f8,f0                                           
        !          1045:                        fmr             f9,f0                                           
        !          1046:                        fmr             f10,f0                                          
        !          1047:                        fmr             f11,f0                                          
        !          1048:                        fmr             f12,f0                                          
        !          1049:                        fmr             f13,f0                                          
        !          1050:                        fmr             f14,f0                                          
        !          1051:                        fmr             f15,f0                                          
        !          1052:                        fmr             f16,f0                                          
        !          1053:                        fmr             f17,f0
        !          1054:                        fsub    f31,f31,f31                             ; Get set to initialize the FPSCR
        !          1055:                        fmr             f18,f0                                          
        !          1056:                        fmr             f19,f0                                          
        !          1057:                        fmr             f20,f0                                          
        !          1058:                        mtfsf   0xff,f31                                ; Clear all FPSCR exception eanbles
        !          1059:                        fmr             f21,f0                                          
        !          1060:                        fmr             f22,f0                                          
        !          1061:                        fmr             f23,f0                                          
        !          1062:                        fmr             f24,f0                                          
        !          1063:                        fmr             f25,f0                                          
        !          1064:                        fmr             f26,f0                                          
        !          1065:                        fmr             f27,f0                                          
        !          1066:                        fmr             f28,f0                                          
        !          1067:                        fmr             f29,f0                                          
        !          1068:                        fmr             f30,f0                                          
        !          1069:                        fmr             f31,f0                                          
        !          1070:                        b               fsenable                                ; Finish setting it all up...                           
        !          1071: 
        !          1072: ;
        !          1073: ;                      Finds an unused floating point area in the activation pointed
        !          1074: ;                      to by R12s saved contexts.  If none are found (unlikely but possible)
        !          1075: ;                      and R3 is 0, a new area is allocated.  If R3 is non-zero, it contains 
        !          1076: ;                      a pointer to an floating point savearea that is free.
        !          1077: ;
        !          1078: fpsrchsave:
        !          1079:                        lwz             r6,ACT_MACT_PCB(r12)            ; Get the first "normal" savearea
        !          1080:                        
        !          1081: fpsrnorm:      mr.             r5,r6                                           ; Is there another?
        !          1082:                        beq-    fpsrvect                                        ; No, search the vector saveareas...
        !          1083:                        lwz             r7,SAVflags(r5)                         ; Get the flags for this guy
        !          1084:                        lwz             r6,SAVprev(r5)                          ; Get the previous savearea, just in case
        !          1085:                        andis.  r8,r7,hi16(SAVfpuvalid)         ; Have we found an empty FPU save in normal?
        !          1086:                        beq+    fpsrgot                                         ; We found one...
        !          1087:                        b               fpsrnorm                                        ; Search again...
        !          1088: 
        !          1089: fpsrvect:      lwz             r6,ACT_MACT_VMX(r12)            ; Get the first "vector" savearea
        !          1090:                        
        !          1091: fpsrvectx:     mr.             r5,r6                                           ; Is there another?
        !          1092:                        beq-    fpsrget                                         ; No, try to allocate one...
        !          1093:                        lwz             r7,SAVflags(r5)                         ; Get the flags for this guy
        !          1094:                        lwz             r6,SAVprevec(r5)                        ; Get the previous savearea, just in case
        !          1095:                        andis.  r8,r7,hi16(SAVfpuvalid)         ; Have we found an empty FPU save in vector?
        !          1096:                        bne-    fpsrvectx                                       ; Search again...
        !          1097:                        
        !          1098: fpsrgot:       mr              r3,r5                                           ; Get the savearea into the right register
        !          1099:                        blr                                                                     ; Return...
        !          1100: 
        !          1101: fpsrget:       mr.             r5,r3                                           ; Do we allocate or use existing?
        !          1102:                        beq+    fpsrallo                                        ; Allocate one...
        !          1103:                        
        !          1104:                        lwz             r7,SAVflags(r3)                         ; Get the passed in area flags
        !          1105:                        blr                                                                     ; Return...
        !          1106: ;                      
        !          1107: ;                      NOTE: save_get will return directly and set R7 to 0...
        !          1108: ;
        !          1109: fpsrallo:      b               EXT(save_get)                           ; Get a fresh savearea 
        !          1110: 
        !          1111: /*
        !          1112:  *                     Altivec stuff is here. The techniques used are pretty identical to
        !          1113:  *                     the floating point. Except that we will honor the VRSAVE register
        !          1114:  *                     settings when loading and restoring registers.
        !          1115:  *
        !          1116:  *                     There are two indications of saved VRs: the VRSAVE register and the vrvalid
        !          1117:  *                     mask. VRSAVE is set by the vector user and represents the VRs that they
        !          1118:  *                     say that they are using. The vrvalid mask indicates which vector registers
        !          1119:  *                     are saved in the savearea. Whenever context is saved, it is saved according
        !          1120:  *                     to the VRSAVE register.  It is loaded based on VRSAVE anded with
        !          1121:  *                     vrvalid (all other registers are splatted with 0s). This is done because we
        !          1122:  *                     don't want to load any registers we don't have a copy of, we want to set them
        !          1123:  *                     to zero instead.
        !          1124:  *
        !          1125:  */
        !          1126: 
        !          1127: ENTRY(vec_save, TAG_NO_FRAME_USED)
        !          1128: 
        !          1129:                        mfmsr   r0                                              ; Get the MSR
        !          1130:                        rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Turn off vector forever
        !          1131:                        rlwinm  r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1       ; But do interrupts only for now
        !          1132:                        oris    r2,r2,hi16(MASK(MSR_VEC))       ; Enable the vector facility for now also
        !          1133:                        mtmsr   r2                                              ; Set the MSR
        !          1134:                        isync
        !          1135:                
        !          1136:                        mfsprg  r6,0                                    ; Get the per_processor block 
        !          1137:                        lwz             r12,PP_VMX_THREAD(r6)   ; Get the thread that owns the vector
        !          1138: #if FPVECDBG
        !          1139:                        mr              r7,r0                                   ; (TEST/DEBUG)
        !          1140:                        li              r4,0                                    ; (TEST/DEBUG)
        !          1141:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          1142:                        mr.             r3,r12                                  ; (TEST/DEBUG)
        !          1143:                        li              r2,0x5F00                               ; (TEST/DEBUG)
        !          1144:                        li              r5,0                                    ; (TEST/DEBUG)
        !          1145:                        beq-    noowneryeu                              ; (TEST/DEBUG)
        !          1146:                        lwz             r4,ACT_MACT_VMXlvl(r12) ; (TEST/DEBUG)
        !          1147:                        lwz             r5,ACT_MACT_VMX(r12)    ; (TEST/DEBUG)
        !          1148: 
        !          1149: noowneryeu:    oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1150:                        sc                                                              ; (TEST/DEBUG)
        !          1151:                        mr              r0,r7                                   ; (TEST/DEBUG)
        !          1152: #endif 
        !          1153:                        mflr    r2                                              ; Save the return address
        !          1154:                        lwz             r10,PP_CPU_DATA(r6)             ; Get the CPU data pointer
        !          1155:                        lhz             r11,PP_CPU_NUMBER(r6)   ; Get our CPU number
        !          1156:                        
        !          1157:                        mr.             r12,r12                                 ; Anyone own the vector?
        !          1158:                        
        !          1159:                        lwz             r10,CPU_ACTIVE_THREAD(r10)      ; Get the pointer to the active thread
        !          1160:                        
        !          1161:                        beq-    vsret                                   ; Nobody owns the vector, no save required...
        !          1162:                        
        !          1163:                        lwz             r10,THREAD_TOP_ACT(r10) ; Now get the activation that is running
        !          1164:                        lwz             r9,ACT_MACT_VMXcpu(r12) ; Get the last CPU to use this context
        !          1165:                        
        !          1166:                        cmplw   r12,r10                                 ; Do we own the thread?
        !          1167:                        cmplw   cr1,r9,r11                              ; Was the context for this processor? 
        !          1168:                        bne+    vsret                                   ; Facility belongs to some other activation...
        !          1169:                        li              r3,0                                    ; Assume we need a fix-me-up
        !          1170:                        beq-    cr1,vsgoodcpu                   ; Facility last used on this processor...
        !          1171:                        stw             r3,PP_VMX_THREAD(r6)    ; Clear owner because it was really on the other processor
        !          1172:                        b               vsret                                   ; Bail now with no save...
        !          1173:                        
        !          1174: vsgoodcpu:     lwz             r3,ACT_MACT_VMX(r12)    ; Get the current vector savearea for the thread
        !          1175:                        lwz             r9,ACT_MACT_VMXlvl(r12) ; Get our current level indicator
        !          1176:                        
        !          1177:                        cmplwi  cr1,r3,0                                ; Have we ever saved this facility context?
        !          1178:                        beq-    cr1,vsneedone                   ; Never saved it, so we need an area...
        !          1179:                        
        !          1180:                        lwz             r8,SAVlvlvec(r3)                ; Get the level this savearea is for
        !          1181:                        cmplwi  r8,1                                    ; See if this is a spare
        !          1182:                        cmplw   cr1,r9,r8                               ; Correct level?
        !          1183:                        beq+    vsusespare                              ; It is still live...
        !          1184:                        beq-    cr1,vsret                               ; The current level is already saved, bail out...
        !          1185: 
        !          1186: vsneedone:     li              r3,0                                    ; Tell the routine to allocate an area if none found
        !          1187:                        bl              vsrchsave                               ; Find a free savearea
        !          1188:                        
        !          1189:                        mfsprg  r6,0                                    ; Get back per_processor block
        !          1190:                        oris    r7,r7,hi16(SAVvmxvalid) ; Set the allocated bit
        !          1191:                        lwz             r12,PP_VMX_THREAD(r6)   ; Get back our thread
        !          1192:                        mtlr    r2                                              ; Restore return
        !          1193:                        lwz             r8,ACT_MACT_VMX(r12)    ; Get the current top vector savearea
        !          1194:                        lwz             r9,ACT_MACT_VMXlvl(r12) ; Get our current level indicator again         
        !          1195:                        stw             r3,ACT_MACT_VMX(r12)    ; Set this as the latest vector savearea for the thread
        !          1196:                        stw             r8,SAVprevec(r3)                ; And then chain this in front
        !          1197:                        stw             r7,SAVflags(r3)                 ; Set the allocation flags
        !          1198:                        stw             r12,SAVact(r3)                  ; Make sure we point to the right guy
        !          1199: 
        !          1200: vsusespare:    stw             r9,SAVlvlvec(r3)                ; And set the level this savearea is for
        !          1201:                        mfcr    r2                                              ; Save non-volatile CRs
        !          1202:                        lwz             r10,liveVRS(r6)                 ; Get the right VRSave register
        !          1203:                        lis             r9,0x5555                               ; Mask with odd bits set                
        !          1204:                        rlwinm  r11,r10,1,0,31                  ; Shift over 1
        !          1205:                        ori             r9,r9,0x5555                    ; Finish mask
        !          1206:                        or              r12,r10,r11                             ; After this, even bits show which lines to zap
        !          1207:                        
        !          1208:                        andc    r11,r12,r9                              ; Clear out odd bits
        !          1209:                        
        !          1210:                        la              r6,savevr0(r3)                  ; Point to line 0
        !          1211:                        rlwinm  r4,r11,15,0,15                  ; Move line 8-15 flags to high order odd bits
        !          1212:                        la              r9,savevrvalid(r3)              ; Point to the saved register mask field
        !          1213:                        or              r4,r11,r4                               ; Set the odd bits
        !          1214:                                                                                        ; (bit 0 is line 0, bit 1 is line 8,
        !          1215:                                                                                        ; bit 2 is line 1, bit 3 is line 9, etc.
        !          1216:                        dcba    br0,r9                                  ; Allocate the cache for it
        !          1217:                        rlwimi  r4,r10,16,16,31                 ; Put vrsave 0 - 15 into positions 16 - 31
        !          1218:                        la              r7,savevr2(r3)                  ; Point to line 1
        !          1219:                        mtcrf   255,r4                                  ; Load up the CRs
        !          1220:                        stw             r10,savevrvalid(r3)             ; Save the validity information
        !          1221:                        mr              r8,r6                                   ; Start registers off
        !          1222: ;      
        !          1223: ;                      Save the current vector state
        !          1224: ;
        !          1225:                                                
        !          1226:                        bf              0,snol0                                 ; No line 0 to do...
        !          1227:                        dcba    br0,r6                                  ; Allocate cache line 0
        !          1228:                        
        !          1229: snol0:         
        !          1230:                        la              r6,savevr4(r3)                  ; Point to line 2
        !          1231:                        bf              2,snol1                                 ; No line 1 to do...
        !          1232:                        dcba    br0,r7                                  ; Allocate cache line 1
        !          1233:                        
        !          1234: snol1:         
        !          1235:                        la              r7,savevr6(r3)                  ; Point to line 3
        !          1236:                        bf              4,snol2                                 ; No line 2 to do...
        !          1237:                        dcba    br0,r6                                  ; Allocate cache line 2
        !          1238:                        
        !          1239: snol2:         
        !          1240:                        li              r11,16                                  ; Get offset for odd registers
        !          1241:                        bf              16,snovr0                               ; Do not save VR0...
        !          1242:                        stvxl   v0,br0,r8                               ; Save VR0
        !          1243:                        
        !          1244: snovr0:                
        !          1245:                        la              r9,savevr2(r3)                  ; Point to V2/V3 pair
        !          1246:                        bf              17,snovr1                               ; Do not save VR1...
        !          1247:                        stvxl   v1,r11,r8                               ; Save VR1
        !          1248:                        
        !          1249: snovr1:
        !          1250:                        la              r6,savevr8(r3)                  ; Point to line 4
        !          1251:                        bf              6,snol3                                 ; No line 3 to do...
        !          1252:                        dcba    br0,r7                                  ; Allocate cache line 3
        !          1253:                        
        !          1254: snol3:         
        !          1255:                        la              r8,savevr4(r3)                  ; Point to V4/V5 pair
        !          1256:                        bf              18,snovr2                               ; Do not save VR2...
        !          1257:                        stvxl   v2,br0,r9                               ; Save VR2
        !          1258:                        
        !          1259: snovr2:
        !          1260:                        bf              19,snovr3                               ; Do not save VR3...
        !          1261:                        stvxl   v3,r11,r9                               ; Save VR3
        !          1262:                        
        !          1263: snovr3:
        !          1264: ;
        !          1265: ;                      Note: CR4 is now free
        !          1266: ;
        !          1267:                        la              r7,savevr10(r3)                 ; Point to line 5
        !          1268:                        bf              8,snol4                                 ; No line 4 to do...
        !          1269:                        dcba    br0,r6                                  ; Allocate cache line 4
        !          1270:                        
        !          1271: snol4:         
        !          1272:                        la              r9,savevr6(r3)                  ; Point to R6/R7 pair
        !          1273:                        bf              20,snovr4                               ; Do not save VR4...
        !          1274:                        stvxl   v4,br0,r8                               ; Save VR4
        !          1275:                        
        !          1276: snovr4:
        !          1277:                        bf              21,snovr5                               ; Do not save VR5...
        !          1278:                        stvxl   v5,r11,r8                               ; Save VR5
        !          1279:                        
        !          1280: snovr5:
        !          1281:                        mtcrf   0x08,r10                                ; Set CRs for registers 16-19
        !          1282:                        la              r6,savevr12(r3)                 ; Point to line 6
        !          1283:                        bf              10,snol5                                ; No line 5 to do...
        !          1284:                        dcba    br0,r7                                  ; Allocate cache line 5
        !          1285:                        
        !          1286: snol5:         
        !          1287:                        la              r8,savevr8(r3)                  ; Point to V8/V9 pair
        !          1288:                        bf              22,snovr6                               ; Do not save VR6...
        !          1289:                        stvxl   v6,br0,r9                               ; Save VR6
        !          1290:                        
        !          1291: snovr6:
        !          1292:                        bf              23,snovr7                               ; Do not save VR7...
        !          1293:                        stvxl   v7,r11,r9                               ; Save VR7
        !          1294:                        
        !          1295: snovr7:
        !          1296: ;
        !          1297: ;                      Note: CR5 is now free
        !          1298: ;
        !          1299:                        la              r7,savevr14(r3)                 ; Point to line 7
        !          1300:                        bf              12,snol6                                ; No line 6 to do...
        !          1301:                        dcba    br0,r6                                  ; Allocate cache line 6
        !          1302:                        
        !          1303: snol6:         
        !          1304:                        la              r9,savevr10(r3)                 ; Point to V10/V11 pair
        !          1305:                        bf              24,snovr8                               ; Do not save VR8...
        !          1306:                        stvxl   v8,br0,r8                               ; Save VR8
        !          1307:                        
        !          1308: snovr8:
        !          1309:                        bf              25,snovr9                               ; Do not save VR9...
        !          1310:                        stvxl   v9,r11,r8                               ; Save VR9
        !          1311:                        
        !          1312: snovr9:
        !          1313:                        mtcrf   0x04,r10                                ; Set CRs for registers 20-23
        !          1314:                        la              r6,savevr16(r3)                 ; Point to line 8
        !          1315:                        bf              14,snol7                                ; No line 7 to do...
        !          1316:                        dcba    br0,r7                                  ; Allocate cache line 7
        !          1317:                        
        !          1318: snol7:         
        !          1319:                        la              r8,savevr12(r3)                 ; Point to V12/V13 pair
        !          1320:                        bf              26,snovr10                              ; Do not save VR10...
        !          1321:                        stvxl   v10,br0,r9                              ; Save VR10
        !          1322:                        
        !          1323: snovr10:
        !          1324:                        bf              27,snovr11                              ; Do not save VR11...
        !          1325:                        stvxl   v11,r11,r9                              ; Save VR11
        !          1326:                        
        !          1327: snovr11:
        !          1328: 
        !          1329: ;
        !          1330: ;                      Note: CR6 is now free
        !          1331: ;
        !          1332:                        la              r7,savevr18(r3)                 ; Point to line 9
        !          1333:                        bf              1,snol8                                 ; No line 8 to do...
        !          1334:                        dcba    br0,r6                                  ; Allocate cache line 8
        !          1335:                        
        !          1336: snol8:         
        !          1337:                        la              r9,savevr14(r3)                 ; Point to V14/V15 pair
        !          1338:                        bf              28,snovr12                              ; Do not save VR12...
        !          1339:                        stvxl   v12,br0,r8                              ; Save VR12
        !          1340:                        
        !          1341: snovr12:
        !          1342:                        bf              29,snovr13                              ; Do not save VR13...
        !          1343:                        stvxl   v13,r11,r8                              ; Save VR13
        !          1344:                        
        !          1345: snovr13:
        !          1346:                        mtcrf   0x02,r10                                ; Set CRs for registers 24-27
        !          1347:                        la              r6,savevr20(r3)                 ; Point to line 10
        !          1348:                        bf              3,snol9                                 ; No line 9 to do...
        !          1349:                        dcba    br0,r7                                  ; Allocate cache line 9
        !          1350:                        
        !          1351: snol9:         
        !          1352:                        la              r8,savevr16(r3)                 ; Point to V16/V17 pair
        !          1353:                        bf              30,snovr14                              ; Do not save VR14...
        !          1354:                        stvxl   v14,br0,r9                              ; Save VR14
        !          1355:                        
        !          1356: snovr14:
        !          1357:                        bf              31,snovr15                              ; Do not save VR15...
        !          1358:                        stvxl   v15,r11,r9                              ; Save VR15
        !          1359:                        
        !          1360: snovr15:
        !          1361: ;
        !          1362: ;                      Note: CR7 is now free
        !          1363: ;
        !          1364:                        la              r7,savevr22(r3)                 ; Point to line 11
        !          1365:                        bf              5,snol10                                ; No line 10 to do...
        !          1366:                        dcba    br0,r6                                  ; Allocate cache line 10
        !          1367:                        
        !          1368: snol10:                
        !          1369:                        la              r9,savevr18(r3)                 ; Point to V18/V19 pair
        !          1370:                        bf              16,snovr16                              ; Do not save VR16...
        !          1371:                        stvxl   v16,br0,r8                              ; Save VR16
        !          1372:                        
        !          1373: snovr16:
        !          1374:                        bf              17,snovr17                              ; Do not save VR17...
        !          1375:                        stvxl   v17,r11,r8                              ; Save VR17
        !          1376:                        
        !          1377: snovr17:
        !          1378:                        mtcrf   0x01,r10                                ; Set CRs for registers 28-31
        !          1379: ;
        !          1380: ;                      Note: All registers have been or are accounted for in CRs
        !          1381: ;
        !          1382:                        la              r6,savevr24(r3)                 ; Point to line 12
        !          1383:                        bf              7,snol11                                ; No line 11 to do...
        !          1384:                        dcba    br0,r7                                  ; Allocate cache line 11
        !          1385:                        
        !          1386: snol11:                
        !          1387:                        la              r8,savevr20(r3)                 ; Point to V20/V21 pair
        !          1388:                        bf              18,snovr18                              ; Do not save VR18...
        !          1389:                        stvxl   v18,br0,r9                              ; Save VR18
        !          1390:                        
        !          1391: snovr18:
        !          1392:                        bf              19,snovr19                              ; Do not save VR19...
        !          1393:                        stvxl   v19,r11,r9                              ; Save VR19
        !          1394:                        
        !          1395: snovr19:
        !          1396:                        la              r7,savevr26(r3)                 ; Point to line 13
        !          1397:                        bf              9,snol12                                ; No line 12 to do...
        !          1398:                        dcba    br0,r6                                  ; Allocate cache line 12
        !          1399:                        
        !          1400: snol12:                
        !          1401:                        la              r9,savevr22(r3)                 ; Point to V22/V23 pair
        !          1402:                        bf              20,snovr20                              ; Do not save VR20...
        !          1403:                        stvxl   v20,br0,r8                              ; Save VR20
        !          1404:                        
        !          1405: snovr20:
        !          1406:                        bf              21,snovr21                              ; Do not save VR21...
        !          1407:                        stvxl   v21,r11,r8                              ; Save VR21
        !          1408:                        
        !          1409: snovr21:
        !          1410:                        la              r6,savevr28(r3)                 ; Point to line 14
        !          1411:                        bf              11,snol13                               ; No line 13 to do...
        !          1412:                        dcba    br0,r7                                  ; Allocate cache line 13
        !          1413:                        
        !          1414: snol13:                
        !          1415:                        la              r8,savevr24(r3)                 ; Point to V24/V25 pair
        !          1416:                        bf              22,snovr22                              ; Do not save VR22...
        !          1417:                        stvxl   v22,br0,r9                              ; Save VR22
        !          1418:                        
        !          1419: snovr22:
        !          1420:                        bf              23,snovr23                              ; Do not save VR23...
        !          1421:                        stvxl   v23,r11,r9                              ; Save VR23
        !          1422:                        
        !          1423: snovr23:
        !          1424:                        la              r7,savevr30(r3)                 ; Point to line 15
        !          1425:                        bf              13,snol14                               ; No line 14 to do...
        !          1426:                        dcba    br0,r6                                  ; Allocate cache line 14
        !          1427:                        
        !          1428: snol14:                
        !          1429:                        la              r9,savevr26(r3)                 ; Point to V26/V27 pair
        !          1430:                        bf              24,snovr24                              ; Do not save VR24...
        !          1431:                        stvxl   v24,br0,r8                              ; Save VR24
        !          1432:                        
        !          1433: snovr24:
        !          1434:                        bf              25,snovr25                              ; Do not save VR25...
        !          1435:                        stvxl   v25,r11,r8                              ; Save VR25
        !          1436:                        
        !          1437: snovr25:
        !          1438:                        bf              15,snol15                               ; No line 15 to do...
        !          1439:                        dcba    br0,r7                                  ; Allocate cache line 15
        !          1440:                        
        !          1441: snol15:                
        !          1442: ;
        !          1443: ;                      Note: All cache lines allocated now
        !          1444: ;
        !          1445:                        la              r8,savevr28(r3)                 ; Point to V28/V29 pair
        !          1446:                        bf              26,snovr26                              ; Do not save VR26...
        !          1447:                        stvxl   v26,br0,r9                              ; Save VR26
        !          1448: 
        !          1449: snovr26:
        !          1450:                        bf              27,snovr27                              ; Do not save VR27...
        !          1451:                        stvxl   v27,r11,r9                              ; Save VR27
        !          1452:                        
        !          1453: snovr27:
        !          1454:                        la              r7,savevr30(r3)                 ; Point to V30/V31 pair
        !          1455:                        bf              28,snovr28                              ; Do not save VR28...
        !          1456:                        stvxl   v28,br0,r8                              ; Save VR28
        !          1457:                        
        !          1458: snovr28:               
        !          1459:                        bf              29,snovr29                              ; Do not save VR29...
        !          1460:                        stvxl   v29,r11,r8                              ; Save VR29
        !          1461:                        
        !          1462: snovr29:               
        !          1463:                        mfvscr  v27                                             ; Get the VSCR
        !          1464:                        la              r8,savevscr(r3)                 ; Point to the VSCR save area
        !          1465:                        bf              30,snovr30                              ; Do not save VR30...
        !          1466:                        stvxl   v30,br0,r7                              ; Save VR30
        !          1467:                        
        !          1468: snovr30:
        !          1469:                        dcba    br0,r8                                  ; Allocate VSCR savearea
        !          1470:                        bf              31,snovr31                              ; Do not save VR31...
        !          1471:                        stvxl   v31,r11,r7                              ; Save VR31
        !          1472:                        
        !          1473: snovr31:
        !          1474:                        add             r11,r11,r9                              ; Point to V27s saved value
        !          1475:                        stvxl   v27,br0,r8                              ; Save the VSCR
        !          1476:                        bt              27,v27ok                                ; V27 has been saved and is marked as wanted
        !          1477:                
        !          1478:                        lis             r11,hi16(EXT(QNaNbarbarian))    ; V27 is not wanted, so get empty value
        !          1479:                        ori             r11,r11,lo16(EXT(QNaNbarbarian))
        !          1480: 
        !          1481: v27ok:         mtcrf   255,r2                                  ; Restore all non-volatile CRs
        !          1482:                        lvxl    v27,br0,r11                             ; Restore or load empty value into V27 because we used it       
        !          1483: 
        !          1484: ;
        !          1485: ;                      Save the current vector state into the savearea of the thread that owns it.
        !          1486: ; 
        !          1487: 
        !          1488: vsret:         mtmsr   r0                                              ; Put interrupts on if they were and vector off
        !          1489:                        isync
        !          1490: 
        !          1491:                        blr
        !          1492: 
        !          1493: /*
        !          1494:  * vec_switch()
        !          1495:  *
        !          1496:  * Entered to handle the vector unavailable exception and
        !          1497:  * switch vector context
        !          1498:  *
        !          1499:  * This code is run with virtual address mode on and interrupts off.
        !          1500:  *
        !          1501:  * Upon exit, the code returns to the users context with the vector
        !          1502:  * facility turned on.
        !          1503:  *
        !          1504:  * ENTRY:      VM switched ON
        !          1505:  *             Interrupts  OFF
        !          1506:  *              State is saved in savearea pointed to by R4.
        !          1507:  *                             All other registers are free.
        !          1508:  * 
        !          1509:  */
        !          1510: 
        !          1511: ENTRY(vec_switch, TAG_NO_FRAME_USED)
        !          1512: 
        !          1513: #if DEBUG
        !          1514: #if GDDBG
        !          1515:                        mr              r7,r4                                   ; Save input parameter
        !          1516:                        lis             r3,hi16(EXT(vec_trap_count))    ; Get address of vector trap counter
        !          1517:                        ori             r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
        !          1518:                        lwz             r1,0(r3)
        !          1519:                        lis             r5,hi16(EXT(GratefulDeb))       ; Point to top of display
        !          1520:                        ori             r5,r5,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !          1521:                        addi    r1,r1,1
        !          1522:                        mtlr    r5                                              ; Set link register
        !          1523:                        stw             r1,0(r3)
        !          1524:                        mr              r4,r1
        !          1525:                        lis             r3,1
        !          1526:                        blrl                                                    ; Display count
        !          1527:                        mr              r4,r7                                   ; Restore the parameter
        !          1528: #else
        !          1529:                        lis             r3,hi16(EXT(vec_trap_count))    ; Get address of vector trap counter
        !          1530:                        ori             r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
        !          1531:                        lwz             r1,0(r3)
        !          1532:                        addi    r1,r1,1
        !          1533:                        stw             r1,0(r3)
        !          1534: #endif
        !          1535: #endif /* DEBUG */
        !          1536: 
        !          1537:                        mfsprg  r6,0                                    /* Get the per_processor block */
        !          1538:                        mfmsr   r19                                             /* Get the current MSR */
        !          1539:                        
        !          1540:                        lwz             r10,PP_CPU_DATA(r6)             /* Get the CPU data pointer */
        !          1541:                        lwz             r12,PP_VMX_THREAD(r6)   /* Get the thread that owns the vector */
        !          1542:                        lwz             r10,CPU_ACTIVE_THREAD(r10)      /* Get the pointer to the active thread */
        !          1543:                        oris    r19,r19,hi16(MASK(MSR_VEC))     /* Enable the vector feature */
        !          1544:                        lwz             r17,THREAD_TOP_ACT(r10) /* Now get the activation that is running */
        !          1545:                        
        !          1546: ;                      R12 has the "old" activation
        !          1547: ;                      R17 has the "new" activation
        !          1548: 
        !          1549: #if FPVECDBG
        !          1550:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          1551:                        li              r2,0x5F01                               ; (TEST/DEBUG)
        !          1552:                        mr              r3,r12                                  ; (TEST/DEBUG)
        !          1553:                        mr              r5,r17                                  ; (TEST/DEBUG)
        !          1554:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1555:                        sc                                                              ; (TEST/DEBUG)
        !          1556: #if GDDBG
        !          1557:                        lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
        !          1558:                        mr              r18,r4                                  ; Save this
        !          1559:                        ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !          1560:                        mr              r4,r2                                   ; Set value
        !          1561:                        mtlr    r3                                              ; Set link register
        !          1562:                        li              r3,1                                    ; Display address
        !          1563:                        blrl                                                    ; Display it
        !          1564:                        mr              r4,r18                                  ; Restore it
        !          1565:                        mfsprg  r6,0                                    ; Get the per_processor block back
        !          1566: #endif
        !          1567: #endif 
        !          1568:                        mr.             r12,r12                                 ; See if there is any live vector status
        !          1569:                        
        !          1570:                        lhz             r18,PP_CPU_NUMBER(r6)   ; Get our CPU number
        !          1571:                
        !          1572:                        mtmsr   r19                                             /* Set vector available */
        !          1573:                        isync
        !          1574:                        
        !          1575:                        
        !          1576:                        beq-    vsnosave                                ; No live context, so nothing to save...
        !          1577:        
        !          1578:                        lwz             r19,ACT_MACT_VMXcpu(r12)        ; Get the "old" active CPU
        !          1579:                        lwz             r15,ACT_MACT_PCB(r12)   ; Get the current level of the "old" one
        !          1580:                        cmplw   r18,r19                                 ; Check the CPU that the old context is live on
        !          1581:                        lwz             r14,ACT_MACT_VMX(r12)   ; Point to the top of the old context stack
        !          1582:                        bne-    vsnosave                                ; Context is not live if used on a different CPU...
        !          1583:                        lwz             r13,ACT_MACT_VMXlvl(r12)        ; Get the "old" active level
        !          1584:                        
        !          1585: ;
        !          1586: ;                      First, check to see if all we are doing is enabling because the
        !          1587: ;                      "new" context is live.
        !          1588: ;
        !          1589: #if FPVECDBG
        !          1590:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          1591:                        li              r2,0x5F02                               ; (TEST/DEBUG)
        !          1592:                        mr              r1,r15                                  ; (TEST/DEBUG)
        !          1593:                        mr              r3,r13                                  ; (TEST/DEBUG)
        !          1594:                        mr              r5,r14                                  ; (TEST/DEBUG)
        !          1595:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1596:                        sc                                                              ; (TEST/DEBUG)
        !          1597: #if GDDBG
        !          1598:                        lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
        !          1599:                        mr              r8,r4                                   ; Save this
        !          1600:                        ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !          1601:                        mr              r4,r2                                   ; Set value
        !          1602:                        mtlr    r3                                              ; Set link register
        !          1603:                        li              r3,1                                    ; Display address
        !          1604:                        blrl                                                    ; Display it
        !          1605:                        mr              r4,r8                                   ; Restore it
        !          1606: #endif
        !          1607: #endif 
        !          1608: 
        !          1609:                        cmplw   cr1,r12,r17                             ; Is the "old" activation and the "new" the same?
        !          1610:                        cmplwi  cr2,r14,0                               ; Is there any saved context on the "old" activation?
        !          1611:                        bne+    cr1,vsmstsave                   ; The activations are different so "old" context must be saved...
        !          1612: 
        !          1613: ;
        !          1614: ;                      Here we know that both the "old" and "new" activations are the same.  We will
        !          1615: ;                      check the current level and active levels.  If they are the same, the context is
        !          1616: ;                      already live, so all we do is turn on the facility and invalidate the top
        !          1617: ;                      savearea. 
        !          1618: ;              
        !          1619: ;                      If the current level, the active level, and the top savearea level are the
        !          1620: ;                      same, then the context was saved as part of a thread context switch and neither
        !          1621: ;                      needs saving or restoration.
        !          1622: ;                      
        !          1623: ;                      In all other cases, the context must be saved unless we are just re-enabling
        !          1624: ;                      vector.
        !          1625: ;
        !          1626: 
        !          1627:                        cmplw   r13,r15                                 ; Are the levels the same?
        !          1628:                        cmplwi  cr2,r14,0                               ; Is there any saved context?
        !          1629:                        bne-    vsmstsave                               ; Levels are different, we need to save...
        !          1630:                        
        !          1631:                        beq-    cr2,vrenable                    ; No saved context at all, enable and go...
        !          1632:                        
        !          1633:                        lwz             r20,SAVlvlvec(r14)              ; Get the level of the top savearea
        !          1634: 
        !          1635: #if FPVECDBG
        !          1636:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          1637:                        li              r2,0x5F03                               ; (TEST/DEBUG)
        !          1638:                        mr              r3,r15                                  ; (TEST/DEBUG)
        !          1639:                        mr              r5,r20                                  ; (TEST/DEBUG)
        !          1640:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1641:                        sc                                                              ; (TEST/DEBUG)
        !          1642: #if GDDBG
        !          1643:                        lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
        !          1644:                        mr              r8,r4                                   ; Save this
        !          1645:                        ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !          1646:                        mr              r4,r2                                   ; Set value
        !          1647:                        mtlr    r3                                              ; Set link register
        !          1648:                        li              r3,1                                    ; Display address
        !          1649:                        blrl                                                    ; Display it
        !          1650:                        mr              r4,r8                                   ; Restore it
        !          1651: #endif
        !          1652: #endif 
        !          1653:                        cmplw   r15,r20                                 ; Is the top level the same as the current?
        !          1654:                        li              r0,1                                    ; Get the invalid flag
        !          1655:                        bne-    vrenable                                ; Not the same, just enable and go...
        !          1656:                        
        !          1657:                        stw             r0,SAVlvlvec(r14)               ; Invalidate that top savearea
        !          1658: 
        !          1659:                        b               vrenable                                ; Then enable and go...
        !          1660:                        
        !          1661: ;
        !          1662: ;                      We need to save the "old" context here.  The LIFO queueing scheme works
        !          1663: ;                      out for all cases because if both the "new" and "old" activations are the
        !          1664: ;                      same, there can not be any saved state to load.  the "new" level is
        !          1665: ;                      truely new.
        !          1666: ;
        !          1667: ;                      When we save the context, we either use a new savearea, or the free
        !          1668: ;                      one that is cached at the head of the list.
        !          1669:                        
        !          1670: vsmstsave:     beq-    cr2,vsgetsave                   ; There is no possible cached save area
        !          1671:                        
        !          1672:                        lwz             r5,SAVlvlvec(r14)               ; Get the level of first facility savearea
        !          1673: #if FPVECDBG
        !          1674:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          1675:                        li              r2,0x5F04                               ; (TEST/DEBUG)
        !          1676:                        mr              r3,r15                                  ; (TEST/DEBUG)
        !          1677:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1678:                        sc                                                              ; (TEST/DEBUG)
        !          1679: #if GDDBG
        !          1680:                        lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
        !          1681:                        mr              r8,r4                                   ; Save this
        !          1682:                        mr              r7,r5                                   ; Save this
        !          1683:                        ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !          1684:                        mr              r4,r2                                   ; Set value
        !          1685:                        mtlr    r3                                              ; Set link register
        !          1686:                        li              r3,1                                    ; Display address
        !          1687:                        blrl                                                    ; Display it
        !          1688:                        mr              r4,r8                                   ; Restore it
        !          1689:                        mr              r5,r7                                   ; Restore it
        !          1690: #endif
        !          1691: #endif 
        !          1692:                        mr              r3,r14                                  ; Assume we are invalid
        !          1693:                        cmplwi  r5,1                                    ; Is it invalid?
        !          1694:                        cmplw   cr1,r5,r13                              ; Is the SA level the active one?
        !          1695:                        beq+    vsusecache                              ; Invalid, just use it...
        !          1696:                        beq-    cr1,vsnosave                    ; The SA level is active, it is already saved...
        !          1697:                        
        !          1698: vsgetsave:     mr              r3,r4                                   ; Use the interrupt save as the context savearea if none cached
        !          1699: #if FPVECDBG
        !          1700:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          1701:                        li              r2,0x5F05                               ; (TEST/DEBUG)
        !          1702:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1703:                        sc                                                              ; (TEST/DEBUG)
        !          1704: #if GDDBG
        !          1705:                        lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
        !          1706:                        mr              r8,r4                                   ; Save this
        !          1707:                        ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !          1708:                        mr              r4,r2                                   ; Set value
        !          1709:                        mtlr    r3                                              ; Set link register
        !          1710:                        li              r3,1                                    ; Display address
        !          1711:                        blrl                                                    ; Display it
        !          1712:                        mr              r4,r8                                   ; Restore it
        !          1713:                        mr              r3,r8                                   ; This too
        !          1714: #endif
        !          1715: #endif 
        !          1716:                        
        !          1717:                        bl              vsrchsave                               ; Find a free savearea
        !          1718: 
        !          1719:                        stw             r3,ACT_MACT_VMX(r12)    ; Set this as the latest context savearea for the thread
        !          1720:                        mfsprg  r6,0                                    ; Get back per_processor block
        !          1721:                        stw             r14,SAVprevec(r3)               ; And then chain this in front
        !          1722:                        oris    r7,r7,hi16(SAVvmxvalid) ; Set the allocated bit
        !          1723:                        stw             r12,SAVact(r3)                  ; Make sure we point to the right guy
        !          1724:                        stw             r7,SAVflags(r3)                 ; Set the allocation flags
        !          1725: 
        !          1726: vsusecache:    la              r11,savevr0(r3)                 ; Point to the 1st line in area
        !          1727:                        stw             r13,SAVlvlvec(r3)               ; Set this context level
        !          1728: #if FPVECDBG
        !          1729:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          1730:                        li              r2,0x5F06                               ; (TEST/DEBUG)
        !          1731:                        mr              r5,r13                                  ; (TEST/DEBUG)
        !          1732:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1733:                        sc                                                              ; (TEST/DEBUG)
        !          1734: #if GDDBG
        !          1735:                        mr              r10,r3
        !          1736:                        lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
        !          1737:                        mr              r8,r4                                   ; Save this
        !          1738:                        ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !          1739:                        mr              r4,r2                                   ; Set value
        !          1740:                        mtlr    r3                                              ; Set link register
        !          1741:                        li              r3,1                                    ; Display address
        !          1742:                        blrl                                                    ; Display it
        !          1743:                        mr              r4,r8                                   ; Restore it
        !          1744:                        mr              r3,r10
        !          1745:                        mfsprg  r6,0                                    ; Get back per_processor block
        !          1746: #endif
        !          1747: #endif 
        !          1748: 
        !          1749: vsgotsave:     
        !          1750:                        lwz             r10,liveVRS(r6)                 ; Get the right VRSave register
        !          1751:                        lis             r9,0x5555                               ; Mask with odd bits set                
        !          1752:                        rlwinm  r11,r10,1,0,31                  ; Shift over 1
        !          1753:                        ori             r9,r9,0x5555                    ; Finish mask
        !          1754:                        or              r12,r10,r11                             ; After this, even bits show which lines to zap
        !          1755:                        
        !          1756:                        stw             r13,SAVlvlvec(r3)               ; Set the savearea level
        !          1757:                        andc    r13,r12,r9                              ; Clear out odd bits
        !          1758:                        
        !          1759:                        la              r20,savevr0(r3)                 ; Point to line 0
        !          1760:                        rlwinm  r24,r13,15,0,15                 ; Move line 8-15 flags to high order odd bits
        !          1761:                        la              r23,savevrvalid(r3)             ; Point to the saved register mask field
        !          1762:                        or              r24,r13,r24                             ; Set the odd bits
        !          1763:                                                                                        ; (bit 0 is line 0, bit 1 is line 8,
        !          1764:                                                                                        ; bit 2 is line 1, bit 3 is line 9, etc.
        !          1765:                        dcba    br0,r23                                 ; Allocate the cache for it
        !          1766:                        rlwimi  r24,r10,16,16,31                ; Put vrsave 0 - 15 into positions 16 - 31
        !          1767:                        la              r21,savevr2(r3)                 ; Point to line 1
        !          1768:                        mtcrf   255,r24                                 ; Load up the CRs
        !          1769:                        stw             r10,savevrvalid(r3)             ; Save the validity information
        !          1770:                        mr              r22,r20                                 ; Start registers off
        !          1771: ;      
        !          1772: ;                      Save the current vector state
        !          1773: ;
        !          1774:                                                
        !          1775:                        bf              0,nol0                                  ; No line 0 to do...
        !          1776:                        dcba    br0,r20                                 ; Allocate cache line 0
        !          1777:                        
        !          1778: nol0:          
        !          1779:                        la              r20,savevr4(r3)                 ; Point to line 2
        !          1780:                        bf              2,nol1                                  ; No line 1 to do...
        !          1781:                        dcba    br0,r21                                 ; Allocate cache line 1
        !          1782:                        
        !          1783: nol1:          
        !          1784:                        la              r21,savevr6(r3)                 ; Point to line 3
        !          1785:                        bf              4,nol2                                  ; No line 2 to do...
        !          1786:                        dcba    br0,r20                                 ; Allocate cache line 2
        !          1787:                        
        !          1788: nol2:          
        !          1789:                        li              r30,16                                  ; Get offset for odd registers
        !          1790:                        bf              16,novr0                                ; Do not save VR0...
        !          1791:                        stvxl   v0,br0,r22                              ; Save VR0
        !          1792:                        
        !          1793: novr0:         
        !          1794:                        la              r23,savevr2(r3)                 ; Point to V2/V3 pair
        !          1795:                        bf              17,novr1                                ; Do not save VR1...
        !          1796:                        stvxl   v1,r30,r22                              ; Save VR1
        !          1797:                        
        !          1798: novr1:
        !          1799:                        la              r20,savevr8(r3)                 ; Point to line 4
        !          1800:                        bf              6,nol3                                  ; No line 3 to do...
        !          1801:                        dcba    br0,r21                                 ; Allocate cache line 3
        !          1802:                        
        !          1803: nol3:          
        !          1804:                        la              r22,savevr4(r3)                 ; Point to V4/V5 pair
        !          1805:                        bf              18,novr2                                ; Do not save VR2...
        !          1806:                        stvxl   v2,br0,r23                              ; Save VR2
        !          1807:                        
        !          1808: novr2:
        !          1809:                        bf              19,novr3                                ; Do not save VR3...
        !          1810:                        stvxl   v3,r30,r23                              ; Save VR3
        !          1811:                        
        !          1812: novr3:
        !          1813: ;
        !          1814: ;                      Note: CR4 is now free
        !          1815: ;
        !          1816:                        la              r21,savevr10(r3)                ; Point to line 5
        !          1817:                        bf              8,nol4                                  ; No line 4 to do...
        !          1818:                        dcba    br0,r20                                 ; Allocate cache line 4
        !          1819:                        
        !          1820: nol4:          
        !          1821:                        la              r23,savevr6(r3)                 ; Point to R6/R7 pair
        !          1822:                        bf              20,novr4                                ; Do not save VR4...
        !          1823:                        stvxl   v4,br0,r22                              ; Save VR4
        !          1824:                        
        !          1825: novr4:
        !          1826:                        bf              21,novr5                                ; Do not save VR5...
        !          1827:                        stvxl   v5,r30,r22                              ; Save VR5
        !          1828:                        
        !          1829: novr5:
        !          1830:                        mtcrf   0x08,r10                                ; Set CRs for registers 16-19
        !          1831:                        la              r20,savevr12(r3)                ; Point to line 6
        !          1832:                        bf              10,nol5                                 ; No line 5 to do...
        !          1833:                        dcba    br0,r21                                 ; Allocate cache line 5
        !          1834:                        
        !          1835: nol5:          
        !          1836:                        la              r22,savevr8(r3)                 ; Point to V8/V9 pair
        !          1837:                        bf              22,novr6                                ; Do not save VR6...
        !          1838:                        stvxl   v6,br0,r23                              ; Save VR6
        !          1839:                        
        !          1840: novr6:
        !          1841:                        bf              23,novr7                                ; Do not save VR7...
        !          1842:                        stvxl   v7,r30,r23                              ; Save VR7
        !          1843:                        
        !          1844: novr7:
        !          1845: ;
        !          1846: ;                      Note: CR5 is now free
        !          1847: ;
        !          1848:                        la              r21,savevr14(r3)                ; Point to line 7
        !          1849:                        bf              12,nol6                                 ; No line 6 to do...
        !          1850:                        dcba    br0,r20                                 ; Allocate cache line 6
        !          1851:                        
        !          1852: nol6:          
        !          1853:                        la              r23,savevr10(r3)                ; Point to V10/V11 pair
        !          1854:                        bf              24,novr8                                ; Do not save VR8...
        !          1855:                        stvxl   v8,br0,r22                              ; Save VR8
        !          1856:                        
        !          1857: novr8:
        !          1858:                        bf              25,novr9                                ; Do not save VR9...
        !          1859:                        stvxl   v9,r30,r22                              ; Save VR9
        !          1860:                        
        !          1861: novr9:
        !          1862:                        mtcrf   0x04,r10                                ; Set CRs for registers 20-23
        !          1863:                        la              r20,savevr16(r3)                ; Point to line 8
        !          1864:                        bf              14,nol7                                 ; No line 7 to do...
        !          1865:                        dcba    br0,r21                                 ; Allocate cache line 7
        !          1866:                        
        !          1867: nol7:          
        !          1868:                        la              r22,savevr12(r3)                ; Point to V12/V13 pair
        !          1869:                        bf              26,novr10                               ; Do not save VR10...
        !          1870:                        stvxl   v10,br0,r23                             ; Save VR10
        !          1871:                        
        !          1872: novr10:
        !          1873:                        bf              27,novr11                               ; Do not save VR11...
        !          1874:                        stvxl   v11,r30,r23                             ; Save VR11
        !          1875:                        
        !          1876: novr11:
        !          1877: 
        !          1878: ;
        !          1879: ;                      Note: CR6 is now free
        !          1880: ;
        !          1881:                        la              r21,savevr18(r3)                ; Point to line 9
        !          1882:                        bf              1,nol8                                  ; No line 8 to do...
        !          1883:                        dcba    br0,r20                                 ; Allocate cache line 8
        !          1884:                        
        !          1885: nol8:          
        !          1886:                        la              r23,savevr14(r3)                ; Point to V14/V15 pair
        !          1887:                        bf              28,novr12                               ; Do not save VR12...
        !          1888:                        stvxl   v12,br0,r22                             ; Save VR12
        !          1889:                        
        !          1890: novr12:
        !          1891:                        bf              29,novr13                               ; Do not save VR13...
        !          1892:                        stvxl   v13,r30,r22                             ; Save VR13
        !          1893:                        
        !          1894: novr13:
        !          1895:                        mtcrf   0x02,r10                                ; Set CRs for registers 24-27
        !          1896:                        la              r20,savevr20(r3)                ; Point to line 10
        !          1897:                        bf              3,nol9                                  ; No line 9 to do...
        !          1898:                        dcba    br0,r21                                 ; Allocate cache line 9
        !          1899:                        
        !          1900: nol9:          
        !          1901:                        la              r22,savevr16(r3)                ; Point to V16/V17 pair
        !          1902:                        bf              30,novr14                               ; Do not save VR14...
        !          1903:                        stvxl   v14,br0,r23                             ; Save VR14
        !          1904:                        
        !          1905: novr14:
        !          1906:                        bf              31,novr15                               ; Do not save VR15...
        !          1907:                        stvxl   v15,r30,r23                             ; Save VR15
        !          1908:                        
        !          1909: novr15:
        !          1910: ;
        !          1911: ;                      Note: CR7 is now free
        !          1912: ;
        !          1913:                        la              r21,savevr22(r3)                ; Point to line 11
        !          1914:                        bf              5,nol10                                 ; No line 10 to do...
        !          1915:                        dcba    br0,r20                                 ; Allocate cache line 10
        !          1916:                        
        !          1917: nol10:         
        !          1918:                        la              r23,savevr18(r3)                ; Point to V18/V19 pair
        !          1919:                        bf              16,novr16                               ; Do not save VR16...
        !          1920:                        stvxl   v16,br0,r22                             ; Save VR16
        !          1921:                        
        !          1922: novr16:
        !          1923:                        bf              17,novr17                               ; Do not save VR17...
        !          1924:                        stvxl   v17,r30,r22                             ; Save VR17
        !          1925:                        
        !          1926: novr17:
        !          1927:                        mtcrf   0x01,r10                                ; Set CRs for registers 28-31
        !          1928: ;
        !          1929: ;                      Note: All registers have been or are accounted for in CRs
        !          1930: ;
        !          1931:                        la              r20,savevr24(r3)                ; Point to line 12
        !          1932:                        bf              7,nol11                                 ; No line 11 to do...
        !          1933:                        dcba    br0,r21                                 ; Allocate cache line 11
        !          1934:                        
        !          1935: nol11:         
        !          1936:                        la              r22,savevr20(r3)                ; Point to V20/V21 pair
        !          1937:                        bf              18,novr18                               ; Do not save VR18...
        !          1938:                        stvxl   v18,br0,r23                             ; Save VR18
        !          1939:                        
        !          1940: novr18:
        !          1941:                        bf              19,novr19                               ; Do not save VR19...
        !          1942:                        stvxl   v19,r30,r23                             ; Save VR19
        !          1943:                        
        !          1944: novr19:
        !          1945:                        la              r21,savevr26(r3)                ; Point to line 13
        !          1946:                        bf              9,nol12                                 ; No line 12 to do...
        !          1947:                        dcba    br0,r20                                 ; Allocate cache line 12
        !          1948:                        
        !          1949: nol12:         
        !          1950:                        la              r23,savevr22(r3)                ; Point to V22/V23 pair
        !          1951:                        bf              20,novr20                               ; Do not save VR20...
        !          1952:                        stvxl   v20,br0,r22                             ; Save VR20
        !          1953:                        
        !          1954: novr20:
        !          1955:                        bf              21,novr21                               ; Do not save VR21...
        !          1956:                        stvxl   v21,r30,r22                             ; Save VR21
        !          1957:                        
        !          1958: novr21:
        !          1959:                        la              r20,savevr28(r3)                ; Point to line 14
        !          1960:                        bf              11,nol13                                ; No line 13 to do...
        !          1961:                        dcba    br0,r21                                 ; Allocate cache line 13
        !          1962:                        
        !          1963: nol13:         
        !          1964:                        la              r22,savevr24(r3)                ; Point to V24/V25 pair
        !          1965:                        bf              22,novr22                               ; Do not save VR22...
        !          1966:                        stvxl   v22,br0,r23                             ; Save VR22
        !          1967:                        
        !          1968: novr22:
        !          1969:                        bf              23,novr23                               ; Do not save VR23...
        !          1970:                        stvxl   v23,r30,r23                             ; Save VR23
        !          1971:                        
        !          1972: novr23:
        !          1973:                        la              r21,savevr30(r3)                ; Point to line 15
        !          1974:                        bf              13,nol14                                ; No line 14 to do...
        !          1975:                        dcba    br0,r20                                 ; Allocate cache line 14
        !          1976:                        
        !          1977: nol14:         
        !          1978:                        la              r23,savevr26(r3)                ; Point to V26/V27 pair
        !          1979:                        bf              24,novr24                               ; Do not save VR24...
        !          1980:                        stvxl   v24,br0,r22                             ; Save VR24
        !          1981:                        
        !          1982: novr24:
        !          1983:                        bf              25,novr25                               ; Do not save VR25...
        !          1984:                        stvxl   v25,r30,r22                             ; Save VR25
        !          1985:                        
        !          1986: novr25:
        !          1987:                        bf              15,nol15                                ; No line 15 to do...
        !          1988:                        dcba    br0,r21                                 ; Allocate cache line 15
        !          1989:                        
        !          1990: nol15:         
        !          1991: ;
        !          1992: ;                      Note: All cache lines allocated now
        !          1993: ;
        !          1994:                        la              r22,savevr28(r3)                ; Point to V28/V29 pair
        !          1995:                        bf              26,novr26                               ; Do not save VR26...
        !          1996:                        stvxl   v26,br0,r23                             ; Save VR26
        !          1997:                        
        !          1998: novr26:
        !          1999:                        bf              27,novr27                               ; Do not save VR27...
        !          2000:                        stvxl   v27,r30,r23                             ; Save VR27
        !          2001:                        
        !          2002: novr27:
        !          2003:                        la              r23,savevr30(r3)                ; Point to V30/V31 pair
        !          2004:                        bf              28,novr28                               ; Do not save VR28...
        !          2005:                        stvxl   v28,br0,r22                             ; Save VR28
        !          2006:                        
        !          2007: novr28:                
        !          2008:                        mfvscr  v27                                             ; Get the VSCR
        !          2009:                        bf              29,novr29                               ; Do not save VR29...
        !          2010:                        stvxl   v29,r30,r22                             ; Save VR29
        !          2011:                        
        !          2012: novr29:                
        !          2013:                        la              r22,savevscr(r3)                ; Point to the VSCR save area
        !          2014:                        bf              30,novr30                               ; Do not save VR30...
        !          2015:                        stvxl   v30,br0,r23                             ; Save VR30
        !          2016:                        
        !          2017: novr30:
        !          2018:                        dcba    br0,r22                                 ; Allocate VSCR savearea
        !          2019:                        bf              31,novr31                               ; Do not save VR31...
        !          2020:                        stvxl   v31,r30,r23                             ; Save VR31
        !          2021:                        
        !          2022: novr31:
        !          2023:                        stvxl   v27,br0,r22                             ; Save the VSCR
        !          2024: 
        !          2025:                        
        !          2026: 
        !          2027: /*
        !          2028:  *                     Now check out the current thread and see if we need to load up his context.
        !          2029:  *                     If we do (and this should be the normal case), do it and then release the
        !          2030:  *                     savearea.
        !          2031:  *                     
        !          2032:  *                     If we don't (remember, we already took care of the case where we just enable
        !          2033:  *                     the vector), we need to fill the registers with garbage, because this thread has 
        !          2034:  *                     never used them before and some thieving bastard could hack the old values
        !          2035:  *                     of some thread!  Just imagine what would happen if they could!  Why, nothing
        !          2036:  *                     would be safe! My Gosh! It's terrifying!
        !          2037:  */
        !          2038: 
        !          2039: vsnosave:      lwz             r15,ACT_MACT_PCB(r17)   ; Get the current level of the "new" one
        !          2040:                        lwz             r14,ACT_MACT_VMX(r17)   ; Point to the top of the "new" context stack
        !          2041:                        lwz             r13,ACT_MACT_VMXlvl(r17)        ; Get the "new" active level
        !          2042: 
        !          2043: #if FPVECDBG
        !          2044:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          2045:                        li              r2,0x5F07                               ; (TEST/DEBUG)
        !          2046:                        mr              r1,r15                                  ; (TEST/DEBUG)
        !          2047:                        mr              r3,r14                                  ; (TEST/DEBUG)
        !          2048:                        mr              r5,r13                                  ; (TEST/DEBUG)
        !          2049:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          2050:                        sc                                                              ; (TEST/DEBUG)
        !          2051: #endif 
        !          2052: 
        !          2053:                        cmplwi  cr1,r14,0                               ; Do we possibly have some context to load?
        !          2054:                        stw             r15,ACT_MACT_VMXlvl(r17)        ; Set the "new" active level
        !          2055:                        la              r23,savevscr(r14)               ; Point to the VSCR
        !          2056:                        stw             r18,ACT_MACT_VMXcpu(r17)        ; Set the active CPU
        !          2057:                        la              r20,savevr0(r14)                ; Point to first line to bring in
        !          2058:                        stw             r17,PP_VMX_THREAD(r6)   ; Store current thread address in vmx_thread to claim vector for thread
        !          2059:                        beq-    cr1,ProtectTheAmericanWay       ; Nothing to restore, first time use...
        !          2060:                        lwz             r0,SAVlvlvec(r14)               ; Get the level of first facility savearea
        !          2061:                        cmplw   r0,r15                                  ; Top level correct to load?
        !          2062:                        bne-    ProtectTheAmericanWay   ; No, go initialize...
        !          2063:                        
        !          2064: #if FPVECDBG
        !          2065:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          2066:                        li              r2,0x5F08                               ; (TEST/DEBUG)
        !          2067:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          2068:                        sc                                                              ; (TEST/DEBUG)
        !          2069: #if GDDBG
        !          2070:                        mr              r8,r3
        !          2071:                        lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
        !          2072:                        mr              r22,r4                                  ; Save this
        !          2073:                        ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !          2074:                        mr              r4,r2                                   ; Set value
        !          2075:                        mtlr    r3                                              ; Set link register
        !          2076:                        li              r3,1                                    ; Display address
        !          2077:                        blrl                                                    ; Display it
        !          2078:                        mr              r4,r22                                  ; Restore it
        !          2079:                        mr              r3,r8
        !          2080: #endif
        !          2081: #endif 
        !          2082: 
        !          2083:                        li              r0,1                                    ; Get the level invalid indication
        !          2084:                        lwz             r22,savevrsave(r4)              ; Get the most current VRSAVE
        !          2085:                        lwz             r10,savevrvalid(r14)    ; Get the valid VRs in the savearea
        !          2086:                        lis             r9,0x5555                               ; Mask with odd bits set
        !          2087:                        and             r10,r10,r22                             ; Figure out just what registers need to be loaded
        !          2088:                        ori             r9,r9,0x5555                    ; Finish mask
        !          2089:                        rlwinm  r11,r10,1,0,31                  ; Shift over 1
        !          2090:                        stw             r0,SAVlvlvec(r14)               ; Mark the savearea invalid because we are activating again
        !          2091:                        or              r12,r10,r11                             ; After this, even bits show which lines to touch
        !          2092:                        dcbt    br0,r23                                 ; Touch in the VSCR
        !          2093:                        andc    r13,r12,r9                              ; Clear out odd bits
        !          2094:                        
        !          2095:                        la              r20,savevr0(r14)                ; Point to line 0
        !          2096:                        rlwinm  r3,r13,15,0,15                  ; Move line 8-15 flags to high order odd bits
        !          2097:                        la              r21,savevr2(r3)                 ; Point to line 1
        !          2098:                        or              r3,r13,r3                               ; Set the odd bits
        !          2099:                                                                                        ; (bit 0 is line 0, bit 1 is line 8,
        !          2100:                                                                                        ; bit 2 is line 1, bit 3 is line 9, etc.
        !          2101:                        lvxl    v31,br0,r23                             ; Get the VSCR
        !          2102:                        rlwimi  r3,r10,16,16,31                 ; Put vrsave 0 - 15 into positions 16 - 31
        !          2103:                        mtvscr  v31                                             ; Slam the VSCR value
        !          2104:                        mtcrf   255,r3                                  ; Load up the CRs
        !          2105:                        mr              r22,r20                                 ; Start registers off
        !          2106: ;      
        !          2107: ;                      Load the new vector state
        !          2108: ;
        !          2109:                                                
        !          2110:                        bf              0,lnol0                                 ; No line 0 to do...
        !          2111:                        dcbt    br0,r20                                 ; Touch cache line 0
        !          2112:                        
        !          2113: lnol0:         
        !          2114:                        la              r20,savevr4(r14)                ; Point to line 2
        !          2115:                        bf              2,lnol1                                 ; No line 1 to do...
        !          2116:                        dcbt    br0,r21                                 ; Touch cache line 1
        !          2117:                        
        !          2118: lnol1:         
        !          2119:                        la              r21,savevr6(r14)                ; Point to line 3
        !          2120:                        bf              4,lnol2                                 ; No line 2 to do...
        !          2121:                        dcbt    br0,r20                                 ; Touch cache line 2
        !          2122:                        
        !          2123: lnol2:         
        !          2124:                        li              r30,16                                  ; Get offset for odd registers
        !          2125:                        bf              16,lnovr0                               ; Do not restore VR0...
        !          2126:                        lvxl    v0,br0,r22                              ; Restore VR0
        !          2127:                        
        !          2128: lnovr0:                
        !          2129:                        la              r23,savevr2(r14)                ; Point to V2/V3 pair
        !          2130:                        bf              17,lnovr1                               ; Do not restore VR1...
        !          2131:                        lvxl    v1,r30,r22                              ; Restore VR1
        !          2132:                        
        !          2133: lnovr1:
        !          2134:                        la              r20,savevr8(r14)                ; Point to line 4
        !          2135:                        bf              6,lnol3                                 ; No line 3 to do...
        !          2136:                        dcbt    br0,r21                                 ; Touch cache line 3
        !          2137:                        
        !          2138: lnol3:         
        !          2139:                        la              r22,savevr4(r14)                ; Point to V4/V5 pair
        !          2140:                        bf              18,lnovr2                               ; Do not restore VR2...
        !          2141:                        lvxl    v2,br0,r23                              ; Restore VR2
        !          2142:                        
        !          2143: lnovr2:
        !          2144:                        bf              19,lnovr3                               ; Do not restore VR3...
        !          2145:                        lvxl    v3,r30,r23                              ; Restore VR3
        !          2146:                        
        !          2147: lnovr3:
        !          2148: ;
        !          2149: ;                      Note: CR4 is now free
        !          2150: ;
        !          2151:                        la              r21,savevr10(r14)               ; Point to line 5
        !          2152:                        bf              8,lnol4                                 ; No line 4 to do...
        !          2153:                        dcbt    br0,r20                                 ; Touch cache line 4
        !          2154:                        
        !          2155: lnol4:         
        !          2156:                        la              r23,savevr6(r14)                ; Point to R6/R7 pair
        !          2157:                        bf              20,lnovr4                               ; Do not restore VR4...
        !          2158:                        lvxl    v4,br0,r22                              ; Restore VR4
        !          2159:                        
        !          2160: lnovr4:
        !          2161:                        bf              21,lnovr5                               ; Do not restore VR5...
        !          2162:                        lvxl    v5,r30,r22                              ; Restore VR5
        !          2163:                        
        !          2164: lnovr5:
        !          2165:                        mtcrf   0x08,r10                                ; Set CRs for registers 16-19
        !          2166:                        la              r20,savevr12(r14)               ; Point to line 6
        !          2167:                        bf              10,lnol5                                ; No line 5 to do...
        !          2168:                        dcbt    br0,r21                                 ; Touch cache line 5
        !          2169:                        
        !          2170: lnol5:         
        !          2171:                        la              r22,savevr8(r14)                ; Point to V8/V9 pair
        !          2172:                        bf              22,lnovr6                               ; Do not restore VR6...
        !          2173:                        lvxl    v6,br0,r23                              ; Restore VR6
        !          2174:                        
        !          2175: lnovr6:
        !          2176:                        bf              23,lnovr7                               ; Do not restore VR7...
        !          2177:                        lvxl    v7,r30,r23                              ; Restore VR7
        !          2178:                        
        !          2179: lnovr7:
        !          2180: ;
        !          2181: ;                      Note: CR5 is now free
        !          2182: ;
        !          2183:                        la              r21,savevr14(r14)               ; Point to line 7
        !          2184:                        bf              12,lnol6                                ; No line 6 to do...
        !          2185:                        dcbt    br0,r20                                 ; Touch cache line 6
        !          2186:                        
        !          2187: lnol6:         
        !          2188:                        la              r23,savevr10(r14)               ; Point to V10/V11 pair
        !          2189:                        bf              24,lnovr8                               ; Do not restore VR8...
        !          2190:                        lvxl    v8,br0,r22                              ; Restore VR8
        !          2191:                        
        !          2192: lnovr8:
        !          2193:                        bf              25,lnovr9                               ; Do not save VR9...
        !          2194:                        lvxl    v9,r30,r22                              ; Restore VR9
        !          2195:                        
        !          2196: lnovr9:
        !          2197:                        mtcrf   0x04,r10                                ; Set CRs for registers 20-23
        !          2198:                        la              r20,savevr16(r14)               ; Point to line 8
        !          2199:                        bf              14,lnol7                                ; No line 7 to do...
        !          2200:                        dcbt    br0,r21                                 ; Touch cache line 7
        !          2201:                        
        !          2202: lnol7:         
        !          2203:                        la              r22,savevr12(r14)               ; Point to V12/V13 pair
        !          2204:                        bf              26,lnovr10                              ; Do not restore VR10...
        !          2205:                        lvxl    v10,br0,r23                             ; Restore VR10
        !          2206:                        
        !          2207: lnovr10:
        !          2208:                        bf              27,lnovr11                              ; Do not restore VR11...
        !          2209:                        lvxl    v11,r30,r23                             ; Restore VR11
        !          2210:                        
        !          2211: lnovr11:
        !          2212: 
        !          2213: ;
        !          2214: ;                      Note: CR6 is now free
        !          2215: ;
        !          2216:                        la              r21,savevr18(r14)               ; Point to line 9
        !          2217:                        bf              1,lnol8                                 ; No line 8 to do...
        !          2218:                        dcbt    br0,r20                                 ; Touch cache line 8
        !          2219:                        
        !          2220: lnol8:         
        !          2221:                        la              r23,savevr14(r14)               ; Point to V14/V15 pair
        !          2222:                        bf              28,lnovr12                              ; Do not restore VR12...
        !          2223:                        lvxl    v12,br0,r22                             ; Restore VR12
        !          2224:                        
        !          2225: lnovr12:
        !          2226:                        bf              29,lnovr13                              ; Do not restore VR13...
        !          2227:                        lvxl    v13,r30,r22                             ; Restore VR13
        !          2228:                        
        !          2229: lnovr13:
        !          2230:                        mtcrf   0x02,r10                                ; Set CRs for registers 24-27
        !          2231:                        la              r20,savevr20(r14)               ; Point to line 10
        !          2232:                        bf              3,lnol9                                 ; No line 9 to do...
        !          2233:                        dcbt    br0,r21                                 ; Touch cache line 9
        !          2234:                        
        !          2235: lnol9:         
        !          2236:                        la              r22,savevr16(r14)               ; Point to V16/V17 pair
        !          2237:                        bf              30,lnovr14                              ; Do not restore VR14...
        !          2238:                        lvxl    v14,br0,r23                             ; Restore VR14
        !          2239:                        
        !          2240: lnovr14:
        !          2241:                        bf              31,lnovr15                              ; Do not restore VR15...
        !          2242:                        lvxl    v15,r30,r23                             ; Restore VR15
        !          2243:                        
        !          2244: lnovr15:
        !          2245: ;
        !          2246: ;                      Note: CR7 is now free
        !          2247: ;
        !          2248:                        la              r21,savevr22(r14)               ; Point to line 11
        !          2249:                        bf              5,lnol10                                ; No line 10 to do...
        !          2250:                        dcbt    br0,r20                                 ; Touch cache line 10
        !          2251:                        
        !          2252: lnol10:                
        !          2253:                        la              r23,savevr18(r14)               ; Point to V18/V19 pair
        !          2254:                        bf              16,lnovr16                              ; Do not restore VR16...
        !          2255:                        lvxl    v16,br0,r22                             ; Restore VR16
        !          2256:                        
        !          2257: lnovr16:
        !          2258:                        bf              17,lnovr17                              ; Do not restore VR17...
        !          2259:                        lvxl    v17,r30,r22                             ; Restore VR17
        !          2260:                        
        !          2261: lnovr17:
        !          2262:                        mtcrf   0x01,r10                                ; Set CRs for registers 28-31
        !          2263: ;
        !          2264: ;                      Note: All registers have been or are accounted for in CRs
        !          2265: ;
        !          2266:                        la              r20,savevr24(r14)               ; Point to line 12
        !          2267:                        bf              7,lnol11                                ; No line 11 to do...
        !          2268:                        dcbt    br0,r21                                 ; Touch cache line 11
        !          2269:                        
        !          2270: lnol11:                
        !          2271:                        la              r22,savevr20(r14)               ; Point to V20/V21 pair
        !          2272:                        bf              18,lnovr18                              ; Do not restore VR18...
        !          2273:                        lvxl    v18,br0,r23                             ; Restore VR18
        !          2274:                        
        !          2275: lnovr18:
        !          2276:                        bf              19,lnovr19                              ; Do not restore VR19...
        !          2277:                        lvxl    v19,r30,r23                             ; Restore VR19
        !          2278:                        
        !          2279: lnovr19:
        !          2280:                        la              r21,savevr26(r14)               ; Point to line 13
        !          2281:                        bf              9,lnol12                                ; No line 12 to do...
        !          2282:                        dcbt    br0,r20                                 ; Touch cache line 12
        !          2283:                        
        !          2284: lnol12:                
        !          2285:                        la              r23,savevr22(r14)               ; Point to V22/V23 pair
        !          2286:                        bf              20,lnovr20                              ; Do not restore VR20...
        !          2287:                        lvxl    v20,br0,r22                             ; Restore VR20
        !          2288:                        
        !          2289: lnovr20:
        !          2290:                        bf              21,lnovr21                              ; Do not restore VR21...
        !          2291:                        lvxl    v21,r30,r22                             ; Restore VR21
        !          2292:                        
        !          2293: lnovr21:
        !          2294:                        la              r20,savevr28(r14)               ; Point to line 14
        !          2295:                        bf              11,lnol13                               ; No line 13 to do...
        !          2296:                        dcbt    br0,r21                                 ; Touch cache line 13
        !          2297:                        
        !          2298: lnol13:                
        !          2299:                        la              r22,savevr24(r14)               ; Point to V24/V25 pair
        !          2300:                        bf              22,lnovr22                              ; Do not restore VR22...
        !          2301:                        lvxl    v22,br0,r23                             ; Restore VR22
        !          2302:                        
        !          2303: lnovr22:
        !          2304:                        bf              23,lnovr23                              ; Do not restore VR23...
        !          2305:                        lvxl    v23,r30,r23                             ; Restore VR23
        !          2306:                        
        !          2307: lnovr23:
        !          2308:                        la              r21,savevr30(r14)               ; Point to line 15
        !          2309:                        bf              13,lnol14                               ; No line 14 to do...
        !          2310:                        dcbt    br0,r20                                 ; Touch cache line 14
        !          2311:                        
        !          2312: lnol14:                
        !          2313:                        la              r23,savevr26(r14)               ; Point to V26/V27 pair
        !          2314:                        bf              24,lnovr24                              ; Do not restore VR24...
        !          2315:                        lvxl    v24,br0,r22                             ; Restore VR24
        !          2316:                        
        !          2317: lnovr24:
        !          2318:                        bf              25,lnovr25                              ; Do not restore VR25...
        !          2319:                        lvxl    v25,r30,r22                             ; Restore VR25
        !          2320:                        
        !          2321: lnovr25:
        !          2322:                        bf              15,lnol15                               ; No line 15 to do...
        !          2323:                        dcbt    br0,r21                                 ; Touch cache line 15
        !          2324:                        
        !          2325: lnol15:                
        !          2326: ;
        !          2327: ;                      Note: All needed cache lines have been touched now
        !          2328: ;
        !          2329:                        la              r22,savevr28(r14)               ; Point to V28/V29 pair
        !          2330:                        bf              26,lnovr26                              ; Do not restore VR26...
        !          2331:                        lvxl    v26,br0,r23                             ; Restore VR26
        !          2332:                        
        !          2333: lnovr26:
        !          2334:                        bf              27,lnovr27                              ; Do not restore VR27...
        !          2335:                        lvxl    v27,r30,r23                             ; Restore VR27
        !          2336:                        
        !          2337: lnovr27:
        !          2338:                        la              r23,savevr30(r14)               ; Point to V30/V31 pair
        !          2339:                        bf              28,lnovr28                              ; Do not restore VR28...
        !          2340:                        lvxl    v28,br0,r22                             ; Restore VR28
        !          2341:                        
        !          2342: lnovr28:               
        !          2343:                        bf              29,lnovr29                              ; Do not restore VR29...
        !          2344:                        lvxl    v29,r30,r22                             ; Restore VR29
        !          2345:                        
        !          2346: lnovr29:               
        !          2347:                        bf              30,lnovr30                              ; Do not restore VR30...
        !          2348:                        lvxl    v30,br0,r23                             ; Restore VR30
        !          2349:                        
        !          2350: lnovr30:
        !          2351: ;
        !          2352: ;                      Everything is restored now except for VR31.  We need it to get
        !          2353: ;                      the QNaNBarbarian value to put into idle vector registers
        !          2354: ;
        !          2355:                        
        !          2356:                        lis             r5,hi16(EXT(QNaNbarbarian))     ; Get address of empty value
        !          2357:                        cmpwi   r10,-1                                  ; Handle the quick case of all registers in use
        !          2358:                        ori             r5,r5,lo16(EXT(QNaNbarbarian))  ; Get low address of empty value
        !          2359:                        beq-    mstlvr31                                ; Not likely, but all are in use...
        !          2360:                        mtcrf   255,r10                                 ; Get mask of valid registers
        !          2361:                        lvxl    v31,br0,r5                              ; Initialize VR31 to the empty value
        !          2362: 
        !          2363:                        bt              0,ni0                                   ; Register is ok already...
        !          2364:                        vor             v0,v31,v31                              ; Copy into the next register
        !          2365: ni0:
        !          2366:                        bt              1,ni1                                   ; Register is ok already...
        !          2367:                        vor             v1,v31,v31                              ; Copy into the next register
        !          2368: ni1:
        !          2369:                        bt              2,ni2                                   ; Register is ok already...
        !          2370:                        vor             v2,v31,v31                              ; Copy into the next register
        !          2371: ni2:
        !          2372:                        bt              3,ni3                                   ; Register is ok already...
        !          2373:                        vor             v3,v31,v31                              ; Copy into the next register
        !          2374: ni3:
        !          2375:                        bt              4,ni4                                   ; Register is ok already...
        !          2376:                        vor             v4,v31,v31                              ; Copy into the next register
        !          2377: ni4:
        !          2378:                        bt              5,ni5                                   ; Register is ok already...
        !          2379:                        vor             v5,v31,v31                              ; Copy into the next register
        !          2380: ni5:
        !          2381:                        bt              6,ni6                                   ; Register is ok already...
        !          2382:                        vor             v6,v31,v31                              ; Copy into the next register
        !          2383: ni6:
        !          2384:                        bt              7,ni7                                   ; Register is ok already...
        !          2385:                        vor             v7,v31,v31                              ; Copy into the next register
        !          2386: ni7:
        !          2387:                        bt              8,ni8                                   ; Register is ok already...
        !          2388:                        vor             v8,v31,v31                              ; Copy into the next register
        !          2389: ni8:
        !          2390:                        bt              9,ni9                                   ; Register is ok already...
        !          2391:                        vor             v9,v31,v31                              ; Copy into the next register
        !          2392: ni9:
        !          2393:                        bt              10,ni10                                 ; Register is ok already...
        !          2394:                        vor             v10,v31,v31                             ; Copy into the next register
        !          2395: ni10:
        !          2396:                        bt              11,ni11                                 ; Register is ok already...
        !          2397:                        vor             v11,v31,v31                             ; Copy into the next register
        !          2398: ni11:
        !          2399:                        bt              12,ni12                                 ; Register is ok already...
        !          2400:                        vor             v12,v31,v31                             ; Copy into the next register
        !          2401: ni12:
        !          2402:                        bt              13,ni13                                 ; Register is ok already...
        !          2403:                        vor             v13,v31,v31                             ; Copy into the next register
        !          2404: ni13:
        !          2405:                        bt              14,ni14                                 ; Register is ok already...
        !          2406:                        vor             v14,v31,v31                             ; Copy into the next register
        !          2407: ni14:
        !          2408:                        bt              15,ni15                                 ; Register is ok already...
        !          2409:                        vor             v15,v31,v31                             ; Copy into the next register
        !          2410: ni15:
        !          2411:                        bt              16,ni16                                 ; Register is ok already...
        !          2412:                        vor             v16,v31,v31                             ; Copy into the next register
        !          2413: ni16:
        !          2414:                        bt              17,ni17                                 ; Register is ok already...
        !          2415:                        vor             v17,v31,v31                             ; Copy into the next register
        !          2416: ni17:
        !          2417:                        bt              18,ni18                                 ; Register is ok already...
        !          2418:                        vor             v18,v31,v31                             ; Copy into the next register
        !          2419: ni18:
        !          2420:                        bt              19,ni19                                 ; Register is ok already...
        !          2421:                        vor             v19,v31,v31                             ; Copy into the next register
        !          2422: ni19:
        !          2423:                        bt              20,ni20                                 ; Register is ok already...
        !          2424:                        vor             v20,v31,v31                             ; Copy into the next register
        !          2425: ni20:
        !          2426:                        bt              21,ni21                                 ; Register is ok already...
        !          2427:                        vor             v21,v31,v31                             ; Copy into the next register
        !          2428: ni21:
        !          2429:                        bt              22,ni22                                 ; Register is ok already...
        !          2430:                        vor             v22,v31,v31                             ; Copy into the next register
        !          2431: ni22:
        !          2432:                        bt              23,ni23                                 ; Register is ok already...
        !          2433:                        vor             v23,v31,v31                             ; Copy into the next register
        !          2434: ni23:
        !          2435:                        bt              24,ni24                                 ; Register is ok already...
        !          2436:                        vor             v24,v31,v31                             ; Copy into the next register
        !          2437: ni24:
        !          2438:                        bt              25,ni25                                 ; Register is ok already...
        !          2439:                        vor             v25,v31,v31                             ; Copy into the next register
        !          2440: ni25:
        !          2441:                        bt              26,ni26                                 ; Register is ok already...
        !          2442:                        vor             v26,v31,v31                             ; Copy into the next register
        !          2443: ni26:
        !          2444:                        bt              27,ni27                                 ; Register is ok already...
        !          2445:                        vor             v27,v31,v31                             ; Copy into the next register
        !          2446: ni27:
        !          2447:                        bt              28,ni28                                 ; Register is ok already...
        !          2448:                        vor             v28,v31,v31                             ; Copy into the next register
        !          2449: ni28:
        !          2450:                        bt              29,ni29                                 ; Register is ok already...
        !          2451:                        vor             v29,v31,v31                             ; Copy into the next register
        !          2452: ni29:
        !          2453:                        bt              30,ni30                                 ; Register is ok already...
        !          2454:                        vor             v30,v31,v31                             ; Copy into the next register
        !          2455: ni30:
        !          2456:                        bf              31,lnovr31                              ; R31 is empty, no need to restore...
        !          2457: 
        !          2458: mstlvr31:      lvxl    v31,r30,r23                             ; Restore VR31
        !          2459:                        
        !          2460: lnovr31:
        !          2461:                        
        !          2462: vrenable:      
        !          2463:                        lwz             r9,SAVflags(r4)                 /* Get the flags of the current savearea */
        !          2464:                        lwz             r8,savesrr1(r4)                 ; Get the msr of the interrupted guy
        !          2465:                        rlwinm  r5,r4,0,0,19                    /* Get the page address of the savearea */
        !          2466:                        oris    r8,r8,hi16(MASK(MSR_VEC))       ; Enable the vector facility
        !          2467:                        lwz             r10,ACT_MACT_SPF(r17)   ; Get the special flags
        !          2468:                        lis             r7,hi16(SAVattach)              /* Get the attached flag */
        !          2469:                        lwz             r5,SACvrswap(r5)                /* Get Virtual to Real translation */
        !          2470:                        oris    r10,r10,hi16(vectorUsed)        ; Set that we used vectors
        !          2471:                        mr.             r15,r15                                 ; See if we are doing this for user state
        !          2472:                        stw             r8,savesrr1(r4)                 ; Set the msr of the interrupted guy
        !          2473:                        andc    r9,r9,r7                                /* Clear the attached bit */
        !          2474:                        xor             r3,r4,r5                                /* Get the real address of the savearea */
        !          2475:                        stw             r9,SAVflags(r4)                 /* Set the flags of the current savearea */
        !          2476:                        bne-    vrnuser                                 ; We are not user state...
        !          2477:                        stw             r10,ACT_MACT_SPF(r17)   ; Set the activation copy
        !          2478:                        stw             r10,spcFlags(r6)                ; Set per_proc copy
        !          2479: 
        !          2480: vrnuser:
        !          2481: #if FPVECDBG
        !          2482:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          2483:                        li              r2,0x5F0A                               ; (TEST/DEBUG)
        !          2484:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          2485:                        sc                                                              ; (TEST/DEBUG)
        !          2486: #if GDDBG
        !          2487:                        mr              r8,r3                                   ; Save this
        !          2488:                        lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
        !          2489:                        ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !          2490:                        mr              r4,r2                                   ; Set value
        !          2491:                        mtlr    r3                                              ; Set link register
        !          2492:                        li              r3,1                                    ; Display address
        !          2493:                        blrl                                                    ; Display it
        !          2494:                        mr              r3,r8                                   ; Restore it
        !          2495: #endif
        !          2496: #endif 
        !          2497:                        b               EXT(exception_exit)             /* Exit from the fray... */
        !          2498: 
        !          2499: /*
        !          2500:  *                     Initialize the registers to some bogus value
        !          2501:  *                     We make sure that non-Java mode is the default here
        !          2502:  */
        !          2503: 
        !          2504: ProtectTheAmericanWay:
        !          2505:                        
        !          2506: #if FPVECDBG
        !          2507:                        lis             r0,HIGH_ADDR(CutTrace)  ; (TEST/DEBUG)
        !          2508:                        li              r2,0x5F09                               ; (TEST/DEBUG)
        !          2509:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          2510:                        sc                                                              ; (TEST/DEBUG)
        !          2511: #if GDDBG
        !          2512:                        lis             r3,hi16(EXT(GratefulDeb))       ; Point to top of display
        !          2513:                        mr              r8,r4                                   ; Save this
        !          2514:                        ori             r3,r3,lo16(EXT(GratefulDeb))    ; Put in bottom part
        !          2515:                        mr              r4,r2                                   ; Set value
        !          2516:                        mtlr    r3                                              ; Set link register
        !          2517:                        li              r3,1                                    ; Display address
        !          2518:                        blrl                                                    ; Display it
        !          2519:                        mr              r4,r8                                   ; Restore it
        !          2520: #endif
        !          2521: #endif 
        !          2522:                        lis             r5,hi16(EXT(QNaNbarbarian))     ; Get address of empty value
        !          2523:                        vspltish v1,1                                   ; Turn on the non-Java bit and saturate
        !          2524:                        ori             r5,r5,lo16(EXT(QNaNbarbarian))  ; Get low address of empty value
        !          2525:                        vspltisw v2,1                                   ; Turn on the saturate bit
        !          2526:                        lvxl    v0,br0,r5                               ; Initialize VR0
        !          2527:                        vxor    v1,v1,v2                                ; Turn off saturate     
        !          2528:                        
        !          2529:                        vor             v2,v0,v0                                ; Copy into the next register
        !          2530:                        mtvscr  v1                                              ; Clear the vector status register
        !          2531:                        vor             v3,v0,v0                                ; Copy into the next register
        !          2532:                        vor             v1,v0,v0                                ; Copy into the next register
        !          2533:                        vor             v4,v0,v0                                ; Copy into the next register
        !          2534:                        vor             v5,v0,v0                                ; Copy into the next register
        !          2535:                        vor             v6,v0,v0                                ; Copy into the next register
        !          2536:                        vor             v7,v0,v0                                ; Copy into the next register
        !          2537:                        vor             v8,v0,v0                                ; Copy into the next register
        !          2538:                        vor             v9,v0,v0                                ; Copy into the next register
        !          2539:                        vor             v10,v0,v0                               ; Copy into the next register
        !          2540:                        vor             v11,v0,v0                               ; Copy into the next register
        !          2541:                        vor             v12,v0,v0                               ; Copy into the next register
        !          2542:                        vor             v13,v0,v0                               ; Copy into the next register
        !          2543:                        vor             v14,v0,v0                               ; Copy into the next register
        !          2544:                        vor             v15,v0,v0                               ; Copy into the next register
        !          2545:                        vor             v16,v0,v0                               ; Copy into the next register
        !          2546:                        vor             v17,v0,v0                               ; Copy into the next register
        !          2547:                        vor             v18,v0,v0                               ; Copy into the next register
        !          2548:                        vor             v19,v0,v0                               ; Copy into the next register
        !          2549:                        vor             v20,v0,v0                               ; Copy into the next register
        !          2550:                        vor             v21,v0,v0                               ; Copy into the next register
        !          2551:                        vor             v22,v0,v0                               ; Copy into the next register
        !          2552:                        vor             v23,v0,v0                               ; Copy into the next register
        !          2553:                        vor             v24,v0,v0                               ; Copy into the next register
        !          2554:                        vor             v25,v0,v0                               ; Copy into the next register
        !          2555:                        vor             v26,v0,v0                               ; Copy into the next register
        !          2556:                        vor             v27,v0,v0                               ; Copy into the next register
        !          2557:                        vor             v28,v0,v0                               ; Copy into the next register
        !          2558:                        vor             v29,v0,v0                               ; Copy into the next register
        !          2559:                        vor             v30,v0,v0                               ; Copy into the next register
        !          2560:                        vor             v31,v0,v0                               ; Copy into the next register
        !          2561:                        b               vrenable                                ; Finish setting it all up...                           
        !          2562: 
        !          2563: ;
        !          2564: ;                      Finds a unused vector area in the activation pointed
        !          2565: ;                      to by R12s saved contexts.  If none are found (unlikely but possible)
        !          2566: ;                      and R3 is 0, a new area is allocated.  If R3 is non-zero, it contains 
        !          2567: ;                      a pointer to a vector savearea that is free.
        !          2568: ;
        !          2569: 
        !          2570: vsrchsave:     lwz             r6,ACT_MACT_PCB(r12)            ; Get the first "normal" savearea
        !          2571:                        
        !          2572: vsrnorm:       mr.             r5,r6                                           ; Is there another?
        !          2573:                        beq-    vsrvect                                         ; No, search the floating point saveareas...
        !          2574:                        lwz             r7,SAVflags(r5)                         ; Get the flags for this guy
        !          2575:                        lwz             r6,SAVprev(r5)                          ; Get the previous savearea, just in case
        !          2576:                        andis.  r8,r7,hi16(SAVvmxvalid)         ; Have we found an empty vector save in normal?
        !          2577:                        beq+    vsrgot                                          ; We found one...
        !          2578:                        b               vsrnorm                                         ; Search again...
        !          2579: 
        !          2580: vsrvect:       lwz             r6,ACT_MACT_FPU(r12)            ; Get the first "floating point" savearea
        !          2581:                        
        !          2582: vsrvectx:      mr.             r5,r6                                           ; Is there another?
        !          2583:                        beq-    vsrget                                          ; No, try to allocate one...
        !          2584:                        lwz             r7,SAVflags(r5)                         ; Get the flags for this guy
        !          2585:                        lwz             r6,SAVprefp(r5)                         ; Get the previous savearea, just in case
        !          2586:                        andis.  r8,r7,hi16(SAVvmxvalid)         ; Have we found an empty vector save in float?
        !          2587:                        bne-    vsrvectx                                        ; Search again...
        !          2588:                        
        !          2589: vsrgot:                mr              r3,r5                                           ; Get the savearea into the right register
        !          2590:                        blr                                                                     ; Return...
        !          2591: 
        !          2592: vsrget:                mr.             r5,r3                                           ; Do we allocate or use existing?
        !          2593:                        beq+    vsrallo                                         ; Allocate one...
        !          2594:                        
        !          2595:                        lwz             r7,SAVflags(r3)                         ; Get the passed in area flags
        !          2596:                        blr                                                                     ; Return...
        !          2597: ;                      
        !          2598: ;                      NOTE: save_get will return directly and set R7 to 0...
        !          2599: ;
        !          2600: vsrallo:       b               EXT(save_get)                           ; Get a fresh savearea 
        !          2601: 
        !          2602: 
        !          2603: /*
        !          2604:  * void lfs(fpsp,fpdp)
        !          2605:  *
        !          2606:  * load the single precision float to the double
        !          2607:  *
        !          2608:  * This routine is used by the alignment handler.
        !          2609:  *
        !          2610:  */
        !          2611: ENTRY(lfs, TAG_NO_FRAME_USED)
        !          2612:         lfs     f1,    0(r3)
        !          2613:        stfd    f1,     0(r4)
        !          2614:        blr
        !          2615: 
        !          2616: /*
        !          2617:  * fpsp stfs(fpdp,fpsp)
        !          2618:  *
        !          2619:  * store the double precision float to the single
        !          2620:  *
        !          2621:  * This routine is used by the alignment handler.
        !          2622:  *
        !          2623:  */
        !          2624: ENTRY(stfs, TAG_NO_FRAME_USED)
        !          2625:        lfd     f1,     0(r3)
        !          2626:         stfs   f1,     0(r4)
        !          2627:        blr
        !          2628: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.