Annotation of XNU/osfmk/ppc/cswtch.s, revision 1.1.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.