2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
27 #include <ppc/proc_reg.h>
31 #include <mach/ppc/vm_param.h>
32 #include <ppc/exception.h>
40 * void load_context(thread_t thread)
42 * Load the context for the first kernel thread, and go.
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.
49 ENTRY2(load_context, Load_context, TAG_NO_FRAME_USED)
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
60 * get new thread pointer and set it into the active_threads pointer
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)
70 /* Find the new stack and store it in active_stacks */
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 */
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... */
93 /* struct thread_shuttle *Switch_context(struct thread_shuttle *old,
95 * struct thread_shuttle *new)
97 * Switch from one thread to another. If a continuation is supplied, then
98 * we do not need to save callee save registers.
102 /* void Call_continuation( void (*continuation)(void), vm_offset_t stack_ptr)
105 ENTRY(Call_continuation, TAG_NO_FRAME_USED)
107 mr r1, r4 /* Load new stack pointer */
108 blr /* Jump to the continuation */
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
119 /* Context switches are double jumps. We pass the following to the
120 * context switch firmware call:
122 * R3 = switchee's savearea
127 * savesrr0 is set to go to switch_in
128 * savesrr1 is set to uninterruptible with translation on
132 ENTRY(Switch_context, TAG_NO_FRAME_USED)
134 mfsprg r6,0 /* Get the per_proc block */
135 lwz r12,PP_ACTIVE_STACKS(r6)
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
143 stw r4,THREAD_CONTINUATION(r3)
144 cmpwi cr1,r4,0 /* used waaaay down below */
146 stw r11,THREAD_KERNEL_STACK(r3)
148 * Make the new thread the current thread.
151 lwz r11,PP_CPU_DATA(r6)
152 stw r5, CPU_ACTIVE_THREAD(r11)
154 lwz r11,THREAD_KERNEL_STACK(r5)
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 */
161 stw r11,0(r10) ; Save the kernel stack address
162 stw r7,UAW(r6) ; Save the assist word for the "ultra fast path"
164 lwz r7,ACT_MACT_SPF(r5) ; Get the special flags
166 lwz r10,ACT_KLOADED(r5)
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
177 stw r0,0(r10) /* act_kloaded = 0 */
180 lis r10,hi16(EXT(trcWork)) ; Get top of trace mask
181 rlwinm r7,r8,0,0,19 /* Switch to savearea base */
182 ori r10,r10,lo16(EXT(trcWork)) ; Get bottom of mask
183 lwz r11,SAVprev(r8) /* Get the previous of the switchee's savearea */
184 lwz r10,traceMask(r10) ; Get the enabled traces
185 lis r0,hi16(CutTrace) ; Trace FW call
186 mr. r10,r10 ; Any tracing going on?
187 ori r0,r0,lo16(CutTrace) ; Trace FW call
188 beq+ cswNoTrc ; No trace today, dude...
189 mr r10,r3 ; Save across trace
190 lwz r2,THREAD_TOP_ACT(r3) ; Trace old activation
191 mr r3,r11 ; Trace prev savearea
192 sc ; Cut trace entry of context switch
195 cswNoTrc: mfmsr r6 /* Get the MSR because the switched to thread should inherit it */
196 lwz r7,SACvrswap(r7) /* Get the translation from virtual to real */
197 lis r0,hi16(SwitchContextCall) /* Top part of switch context */
198 lis r9,hi16(EXT(switch_in)) /* Get top of switch in routine */
199 stw r11,ACT_MACT_PCB(r5) /* Dequeue the savearea we're switching to */
201 rlwinm r6,r6,0,MSR_FP_BIT+1,MSR_FP_BIT-1 /* Turn off the FP */
202 ori r9,r9,lo16(EXT(switch_in)) /* Bottom half of switch in */
203 lwz r5,savesrr0(r8) /* Set up the new SRR0 */
204 rlwinm r6,r6,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 /* Turn off the vector */
205 mr r4,r3 /* Save our old thread to pass back */
206 stw r9,savesrr0(r8) /* Make us jump to the switch in routine */
207 li r10,MSR_SUPERVISOR_INT_OFF /* Get the switcher's MSR */
208 lwz r9,SAVflags(r8) /* Get the flags */
209 stw r10,savesrr1(r8) /* Set up for switch in */
210 rlwinm r9,r9,0,15,13 /* Reset the syscall flag */
211 ori r0,r0,lo16(SwitchContextCall) /* Bottom part of switch context */
212 rlwinm r9,r9,0,1,31 /* Clear the attached flag */
213 xor r3,r7,r8 /* Get the physical address of the new context save area */
214 stw r9,SAVflags(r8) /* Set the flags */
215 /* if blocking on continuation avoid saving state */
217 sc /* Switch to the new context */
219 /* We come back here in the new thread context
220 * R4 was set to hold the old thread pointer, but switch_in will put it into
221 * R3 where it belongs.
223 blr /* Jump into the new thread */
225 1: stw r5,savesrr0(r8) /* go to real pc */
226 stw r4,saver3(r8) /* must pass back old thread */
227 b EXT(exception_exit) /* blocking on continuation, avoid state save */
232 * All switched to threads come here first to clean up the old thread.
233 * We need to do the following contortions because we need to keep
234 * the LR clean. And because we need to manipulate the savearea chain
235 * with translation on. If we could, this should be done in lowmem_vectors
236 * before translation is turned on. But we can't, dang it!
238 * R3 = switcher's savearea
239 * saver4 = old thread in switcher's save
240 * saver5 = new SRR0 in switcher's save
241 * saver6 = new SRR1 in switcher's save
246 ENTRY(switch_in, TAG_NO_FRAME_USED)
248 lwz r4,saver4(r3) /* Get the old thread */
249 li r8,MSR_VM_OFF /* Set to everything off */
250 lwz r9,THREAD_TOP_ACT(r4) /* Get the switched from ACT */
251 lwz r5,saver5(r3) /* Get the srr0 value */
252 lwz r10,ACT_MACT_PCB(r9) /* Get the top PCB on the old thread */
253 lwz r6,saver6(r3) /* Get the srr1 value */
255 stw r3,ACT_MACT_PCB(r9) /* Put the new one on top */
256 stw r10,SAVprev(r3) /* Chain on the old one */
258 mr r3,r4 /* Pass back the old thread */
260 mtsrr0 r5 /* Set return point */
261 mtsrr1 r6 /* Set return MSR */
275 * void fpu_save(void)
277 * To do the floating point and VMX, we keep three thread pointers: one
278 * to the current thread, one to the thread that has the floating point context
279 * loaded into the FPU registers, and one for the VMX owner.
281 * Each of these threads has three PCB pointers. The normal PCB, the FPU pcb,
282 * and the VMX pcb. There is also a bit for each in the savearea flags.
283 * When we take an exception, or need to use the FPU/VMX in the kernel, we call
284 * this routine. It checks to see if there is an owner thread for the facility.
285 * If so, it saves the facility's state information in the normal PCB. Then, it
286 * turns on the appropriate flag in the savearea to indicate that the state is
287 * in that particular savearea. Also, the thread pointer for the owner in
288 * the per_processor block is cleared. Note that we don't have to worry about the
289 * PCB pointers in the thread because whenever the state is loaded, the associated
290 * savearea is released and the pointer cleared. This is done so that the facility
291 * context always migrates to the normal savearea/PCB. This always insures that
292 * no more than 2 saveareas are used for a thread.
294 * When the context is loaded into the facility, the associated PCB is released if
295 * its usage flags indicate that it is empty. (Note that return from exception and
296 * context switch honor these flags and won't release a savearea if there is unrestored
297 * facility context.) The per_processor is set to point to the facility owner's
298 * thread and the associated PCB pointer within the thread is cleared because
299 * the PCB has been released.
301 * Part of loading a context is to release the savearea. If the savearea contains
302 * other context, the savearea cannot be released. So, what we're left with is
303 * that there will be no normal context savearea, but one for the as-not-yet
304 * restored facility savearea. Again, when that context is reloaded, the PCB
305 * is released, and when it is again stored, it goes into the "normal" savearea.
307 * So, what do we do when there is no general context, and we have some FPU/VMX
308 * state to save? Heck if I know, but it happens when we switch threads when
309 * we shortcut system calls. The question is: does the target thread carry the
310 * FPU/VMX context with it or not? Actually, it don't matter, not one little bit.
311 * If we are asked to save it, we gotta. It's a really lousy way to do it, but
312 * short of starting over with FPUs, it's what's what. Therefore, we'll
313 * allocate an FPU context save and attach it.
315 * Actually, it's not quite that simple: since we aren't in
316 * in interrupt handler context (that's only in fpu_switch) we can't use
317 * quickfret to merge FPU into general context. So, if there is an FPU
318 * savearea, we need to use that. So what we do is: if there is FPU context
319 * use that. If there is a general context, then use that. If neither,
320 * allocate a savearea and make that the FPU context.
322 * The next thing we have to do is to allow the kernel to use both the
323 * floating point and Altivec. It is not recommended, but there may be a
324 * good reason to do so. So, what we need to do is to treat each of the
325 * three types of context the same, by keeping a LIFO chain of states.
326 * We do have a problem with that in that there can be multiple levels of
327 * kernel context. For example, we are using floating point and we take a
328 * page fault, and somehow start using the FPU, and take another page fault,
331 * Anyway, we will hope that we only reasonably use floating point and vectors in
332 * the kernel. And try to pack the context in as few saveareas as possible.
334 * The way we keep these "levels" of floating point or vector context straight is
335 * to remember the top of the normal savearea chain when we activate the
336 * facility when it is first used. Then, when we save that context, this value
337 * is saved in its level field.
339 * What the level concept gives us is a way to distinguish between multiple
340 * independent contexts under the same thread activation. Any time we take
341 * any kind of interruption (trap, system call, I/O interruption), we are,
342 * in effect, running with a different context even though we are in the
343 * same thread. The top savearea address is used only as a marker. It does not
344 * point to any context associated with the float or vector context. For example,
345 * the top savearea pointer will always be 0 for the user context, because there
346 * it it always last on the list.
348 * As normal context is unstacked, the first facility context is checked and
349 * if there is a match, the facility savearea is released. This is because we
350 * are returning to a level before the facility saved there was used. In effect,
351 * this allows us to unwind the facility context saveareas at different rates.
353 * In conjunction with the current activation, these markers are also used to
354 * determine the state of the facility enablement. Whenever the facility context is
355 * "live," i.e., loaded in the hardware registers and belonging to the currently
356 * running context, the facility is enabled before dispatch.
358 * There is nothing special about using floating point or vector facilities,
359 * no preliminary saving, enabling, or disabling. You just use them. The only exception
360 * is during context switching on an SMP system. In this case, the context must
361 * be saved as there is no guarantee that the thread will resume on the same
362 * processor. This is not a good thing, not at all.
364 * Whenever we switch out a thread with a dirty context, we always need to save it
365 * because it can wake up on a different processor. However, once the context has
366 * been saved, we don't need to save it again until it gets dirty, nor do we need
367 * to reload it unless someone else's context has been loaded. To handle this
368 * optimization, we need 3 things. We need to know what processor the saved context
369 * was last loaded on, whether the loaded context could be dirty, and if we've already
372 * Whenever the facility is enabled, the processor ID is saved in the activation. This
373 * will show which processor has dirty data. When a context switch occurs, the facility
374 * contexts are saved, but are still remembered as live. The next time we need to
375 * context switch, we first check if the state is live, and if not, do no state
376 * saving. Then we check if the state has already been save and if not, save it.
377 * The facility is always disabled on a context switch. On a UP, this save function
380 * Whenever a facility unavailable interruption occurs, the current state is saved
381 * if it is live and unsaved. However, if the live state is the same as the new
382 * one to be loaded, the processor ID is checked and if it is the current processor
383 * the state does not need to be loaded or saved. The facility is simply enabled.
385 * Once allocated, facility saveareas are not released until a return is made to a
386 * previous level. Once a facility has been enabled, there is no way to tell if
387 * it will ever be used again, but it is likely. Therefore, discarding a savearea
388 * when its context is made live is extra overhead. So, we don't do it, but we
389 * do mark the savearea contents as invalid.
394 ; The following is the actual way it is implemented. It doesn't quite match
395 ; the above text. I need to go and fix that.
397 ; Context download (operates on owner's data):
400 ; 1) if no owner exit to context restore
401 ; 2) if context processor != current processor exit to context restore
402 ; 3) if current activation == owner activation:
403 ; 1) if curr level == active level:
404 ; 1) if top facility savearea exists:
405 ; invalidate savearea by setting level to 1
406 ; 2) enable facility for user
411 ; 4) if curr level == active level:
412 ; 1) if top facility savearea exists:
413 ; 1) if top save level == active level exit to context restore
415 ; 5) allocate savearea
416 ; 1) if there is a facility save and it is invalid, select it, and break
417 ; 2) scan normal list for free facility area, select if found, and break
418 ; 3) scan other facility for free save: select, if found, and break
419 ; 4) allocate a new save area
422 ; 7) mark facility save with curr level
423 ; 8) if reusing cached savearea (case #1) exit to context restore
424 ; 9) set facility save backchain to facility top savearea
425 ; 10) set facility top to savearea
426 ; 11) exit to context restore
429 ; Context restore/upload (operates on current activation's data):
431 ; 1) set current to activation
432 ; 2) set active level to current level
433 ; 3) set context processor to current processor
434 ; 4) if no facility savearea or top save level != curr level
435 ; initialize facility registers to empty value
437 ; 1) load registers from savearea
438 ; 2) invalidate save area by setting level to 1
440 ; 6) enable facility for user
441 ; 7) exit to interrupt return
444 ; Context save (operates on current activation's data; only used during context switch):
445 ; (context switch always disables the facility)
447 ; 1) if no owner exit
448 ; 2) if owner != current activation exit
449 ; 3) if context processor != current processor
453 ; 4) if facility top savearea level exists and == active level exit
454 ; 5) if curr level != active level exit
455 ; 6) allocate savearea
456 ; 1) if there is a facility save and it is invalid, select it, and break
457 ; 2) scan normal list for free facility area, select if found, and break
458 ; 3) scan other facility for free save: select, if found, and break
459 ; 4) allocate a new save area
461 ; 8) mark facility savearea with curr level
462 ; 9) if reusing cached savearea (case #1) exit
463 ; 10) set facility save backchain to facility top savearea
464 ; 11) set facility top to savearea
468 ; Exception exit (hw_exceptions):
470 ; 1) disable return facility
471 ; 2) if returning savearea != active level
472 ; 1) if owner != current activation exit
473 ; 2) if context processor != current processor:
477 ; 3) if new level != active level exit
478 ; 4) enable return facility
481 ; 3) if no facility savearea exit
482 ; 4) if top save level == active or top is invalid
483 ; 1) dequeue top facility savearea
484 ; 2) set active level to new top savearea's level
485 ; 3) release savearea
486 ; 4) if owner == current activation clear owner
492 ; if (owner == activation) && (curr level == active level)
493 ; && (activation processor == current processor) ::= context live
496 ENTRY(fpu_save, TAG_NO_FRAME_USED)
498 mfmsr r0 ; Get the MSR
499 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Turn off floating point forever
500 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
501 ori r2,r2,MASK(MSR_FP) ; Enable the floating point feature for now also
502 mtmsr r2 ; Set the MSR
505 mfsprg r6,0 ; Get the per_processor block
506 lwz r12,PP_FPU_THREAD(r6) ; Get the thread that owns the FPU
508 mr r7,r0 ; (TEST/DEBUG)
509 li r4,0 ; (TEST/DEBUG)
510 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
511 mr. r3,r12 ; (TEST/DEBUG)
512 li r2,0x6F00 ; (TEST/DEBUG)
513 li r5,0 ; (TEST/DEBUG)
514 beq- noowneryet ; (TEST/DEBUG)
515 lwz r4,ACT_MACT_FPUlvl(r12) ; (TEST/DEBUG)
516 lwz r5,ACT_MACT_FPU(r12) ; (TEST/DEBUG)
518 noowneryet: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
520 mr r0,r7 ; (TEST/DEBUG)
522 mflr r2 ; Save the return address
523 lwz r10,PP_CPU_DATA(r6) ; Get the CPU data pointer
524 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
526 mr. r12,r12 ; Anyone own the FPU?
528 lwz r10,CPU_ACTIVE_THREAD(r10) ; Get the pointer to the active thread
530 beq- fsret ; Nobody owns the FPU, no save required...
532 lwz r10,THREAD_TOP_ACT(r10) ; Now get the activation that is running
533 lwz r9,ACT_MACT_FPUcpu(r12) ; Get the last CPU to use this context
535 cmplw r12,r10 ; Do we own the FPU?
536 cmplw cr1,r9,r11 ; Was the context for this processor?
537 bne+ fsret ; Facility belongs to some other activation...
538 li r3,0 ; Assume we need a fix-me-up
539 beq- cr1,fsgoodcpu ; Facility last used on this processor...
540 stw r3,PP_FPU_THREAD(r6) ; Clear owner because it was really on the other processor
541 b fsret ; Bail now with no save...
543 fsgoodcpu: lwz r3,ACT_MACT_FPU(r12) ; Get the current FPU savearea for the thread
544 lwz r9,ACT_MACT_FPUlvl(r12) ; Get our current level indicator
546 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
547 beq- cr1,fsneedone ; Never saved it, so we need an area...
549 lwz r8,SAVlvlfp(r3) ; Get the level this savearea is for
550 cmplwi r8,1 ; See if it is a spare
551 cmplw cr1,r9,r8 ; Correct level?
552 beq+ fsusespare ; We have a spare to use...
553 beq- cr1,fsret ; The current level is already saved, bail out...
555 fsneedone: li r3,0 ; Tell the routine to allocate an area if none found
556 bl fpsrchsave ; Find a free savearea
558 mfsprg r6,0 ; Get back per_processor block
559 oris r7,r7,hi16(SAVfpuvalid) ; Set the allocated bit
560 lwz r12,PP_FPU_THREAD(r6) ; Get back our thread
561 mtlr r2 ; Restore return
562 lwz r8,ACT_MACT_FPU(r12) ; Get the current top floating point savearea
563 lwz r9,ACT_MACT_FPUlvl(r12) ; Get our current level indicator again
564 stw r3,ACT_MACT_FPU(r12) ; Set this as the latest FPU savearea for the thread
565 stw r8,SAVprefp(r3) ; And then chain this in front
566 stw r7,SAVflags(r3) ; Set the validity flags
567 stw r12,SAVact(r3) ; Make sure we point to the right guy
569 fsusespare: stw r9,SAVlvlfp(r3) ; And set the level this savearea is for
572 ; Save the current FPU state into the PCB of the thread that owns it.
575 la r11,savefp0(r3) ; Point to the 1st line
576 dcbz 0,r11 ; Allocate the first savearea line
578 la r11,savefp4(r3) /* Point to the 2nd line */
580 dcbz 0,r11 /* allocate it */
583 la r11,savefp8(r3) /* Point to the 3rd line */
585 dcbz 0,r11 /* allocate it */
589 la r11,savefp12(r3) /* Point to the 4th line */
591 dcbz 0,r11 /* allocate it */
594 stfd f10,savefp10(r3)
595 la r11,savefp16(r3) /* Point to the 5th line */
596 stfd f11,savefp11(r3)
597 dcbz 0,r11 /* allocate it */
598 stfd f12,savefp12(r3)
599 stfd f13,savefp13(r3)
600 stfd f14,savefp14(r3)
601 la r11,savefp20(r3) /* Point to the 6th line */
602 stfd f15,savefp15(r3)
603 stfd f16,savefp16(r3)
604 stfd f17,savefp17(r3)
605 stfd f18,savefp18(r3)
606 la r11,savefp24(r3) /* Point to the 7th line */
607 stfd f19,savefp19(r3)
608 dcbz 0,r11 /* allocate it */
609 stfd f20,savefp20(r3)
610 lwz r10,liveFPSCR(r6) ; Get the previously saved FPSCR
611 stfd f21,savefp21(r3)
612 stfd f22,savefp22(r3)
613 li r9,0 ; Just clear this out
614 la r11,savefp28(r3) /* Point to the 8th line */
615 stfd f23,savefp23(r3)
616 dcbz 0,r11 /* allocate it */
617 stfd f24,savefp24(r3)
618 stfd f25,savefp25(r3)
619 stfd f26,savefp26(r3)
620 stfd f27,savefp27(r3)
621 stfd f28,savefp28(r3)
623 ; Note that we just save the FPSCR here for ease. It is really already saved
624 ; in the "normal" context area of the savearea.
626 stw r9,savefpscrpad(r3) ; Save the FPSCR pad
627 stw r10,savefpscr(r3) ; Save the FPSCR
629 stfd f29,savefp29(r3)
630 stfd f30,savefp30(r3)
631 stfd f31,savefp31(r3)
632 lfd f0,savefp0(r3) ; We need to restore F0 because we used it
636 la r9,savefp0(r3) ; (TEST/DEBUG)
637 la r10,savefp31(r3) ; (TEST/DEBUG)
640 lha r8,0(r9) ; (TEST/DEBUG)
641 addi r9,r9,8 ; (TEST/DEBUG)
642 cmpwi r8,-8 ; (TEST/DEBUG)
643 cmplw cr1,r9,r10 ; (TEST/DEBUG)
644 bne+ dontkillmedead ; (TEST/DEBUG)
645 BREAKPOINT_TRAP ; (TEST/DEBUG)
647 dontkillmedead: ; (TEST/DEBUG)
648 ble+ cr1,chkkillmedead ; (TEST/DEBUG)
651 fsret: mtmsr r0 ; Put interrupts on if they were and floating point off
659 * Entered to handle the floating-point unavailable exception and
662 * This code is run in virtual address mode on with interrupts off.
664 * Upon exit, the code returns to the users context with the floating
665 * point facility turned on.
667 * ENTRY: VM switched ON
669 * State is saved in savearea pointed to by R4.
670 * All other registers are free.
674 ENTRY(fpu_switch, TAG_NO_FRAME_USED)
677 mr r7,r4 ; Save input parameter
678 lis r3,hi16(EXT(fpu_trap_count)) ; Get address of FP trap counter
679 ori r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter
681 lis r5,hi16(EXT(GratefulDeb)) ; Point to top of display
682 ori r5,r5,lo16(EXT(GratefulDeb)) ; Put in bottom part
684 mtlr r5 ; Set link register
689 mr r4,r7 ; Restore the parameter
691 lis r3,hi16(EXT(fpu_trap_count)) ; Get address of FP trap counter
692 ori r3,r3,lo16(EXT(fpu_trap_count)) ; Get address of FP trap counter
699 mfsprg r6,0 ; Get the per_processor block
700 mfmsr r19 ; Get the current MSR
702 lwz r10,PP_CPU_DATA(r6) ; Get the CPU data pointer
703 lwz r12,PP_FPU_THREAD(r6) ; Get the thread that owns the FPU
704 lwz r10,CPU_ACTIVE_THREAD(r10) ; Get the pointer to the active thread
705 ori r19,r19,lo16(MASK(MSR_FP)) ; Enable the floating point feature
706 lwz r17,THREAD_TOP_ACT(r10) ; Now get the activation that is running
708 ; R12 has the "old" activation
709 ; R17 has the "new" activation
712 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
713 li r2,0x7F01 ; (TEST/DEBUG)
714 mr r3,r12 ; (TEST/DEBUG)
715 mr r5,r17 ; (TEST/DEBUG)
716 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
719 mr. r12,r12 ; See if there is any live FP status
721 lhz r18,PP_CPU_NUMBER(r6) ; Get the current CPU, we will need it later
723 mtmsr r19 ; Enable floating point instructions
726 beq- fsnosave ; No live context, so nothing to save...
728 lwz r19,ACT_MACT_FPUcpu(r12) ; Get the "old" active CPU
729 lwz r15,ACT_MACT_PCB(r12) ; Get the current level of the "old" one
730 cmplw r18,r19 ; Check the CPU that the old context is live on
731 lwz r14,ACT_MACT_FPU(r12) ; Point to the top of the old context stack
732 bne- fsnosave ; Context is not live if used on a different CPU...
733 lwz r13,ACT_MACT_FPUlvl(r12) ; Get the "old" active level
736 ; First, check to see if all we are doing is enabling because the
737 ; "new" context is live.
740 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
741 li r2,0x7F02 ; (TEST/DEBUG)
742 mr r1,r15 ; (TEST/DEBUG)
743 mr r3,r13 ; (TEST/DEBUG)
744 mr r5,r14 ; (TEST/DEBUG)
745 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
749 cmplw cr1,r12,r17 ; Are the "old" activation and the "new" the same?
750 cmplwi cr2,r14,0 ; Is there any saved context on the "old" activation?
751 bne+ cr1,fsmstsave ; The activations are different so "old" context must be saved...
754 ; Here we know that both the "old" and "new" activations are the same. We will
755 ; check the current level and active levels. If they are the same, the context is
756 ; already live, so all we do is turn on the facility and invalidate the top
759 ; If the current level, the active level, and the top savearea level are the
760 ; same, then the context was saved as part of a thread context switch and neither
761 ; needs saving or restoration.
763 ; In all other cases, the context must be saved unless we are just re-enabling
767 cmplw r13,r15 ; Are the levels the same?
768 cmplwi cr2,r14,0 ; Is there any saved context?
769 bne- fsmstsave ; Levels are different, we need to save...
771 beq- cr2,fsenable ; No saved context at all, enable and go...
773 lwz r20,SAVlvlfp(r14) ; Get the level of the top savearea
776 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
777 li r2,0x7F03 ; (TEST/DEBUG)
778 mr r3,r15 ; (TEST/DEBUG)
779 mr r5,r20 ; (TEST/DEBUG)
780 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
783 cmplw r15,r20 ; Is the top level the same as the current?
784 li r0,1 ; Get the invalid flag
785 bne- fsenable ; Not the same, just enable and go...
787 stw r0,SAVlvlfp(r14) ; Invalidate that top savearea
789 b fsenable ; Then enable and go...
792 ; We need to save the "old" context here. The LIFO queueing scheme works
793 ; out for all cases because if both the "new" and "old" activations are the
794 ; same, there can not be any saved state to load. the "new" level is
797 ; When we save the context, we either use a new savearea, or the free
798 ; one that is cached at the head of the list.
800 fsmstsave: beq- cr2,fsgetsave ; There is no possible cached save area
802 lwz r5,SAVlvlfp(r14) ; Get the level of first facility savearea
804 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
805 li r2,0x7F04 ; (TEST/DEBUG)
806 mr r3,r15 ; (TEST/DEBUG)
807 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
810 mr r3,r14 ; Assume we are invalid
811 cmplwi r5,1 ; Is it invalid?
812 cmplw cr1,r5,r13 ; Is the SA level the active one?
813 beq+ fsusecache ; Invalid, just use it...
814 beq- cr1,fsnosave ; The SA level is active, it is already saved...
816 fsgetsave: mr r3,r4 ; Use the interrupt save as the context savearea if none cached
818 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
819 li r2,0x7F05 ; (TEST/DEBUG)
820 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
824 bl fpsrchsave ; Find a free savearea
826 stw r3,ACT_MACT_FPU(r12) ; Set this as the latest context savearea for the thread
827 mfsprg r6,0 ; Get back per_processor block
828 stw r14,SAVprefp(r3) ; And then chain this in front
829 oris r7,r7,hi16(SAVfpuvalid) ; Set the allocated bit
830 stw r12,SAVact(r3) ; Make sure we point to the right guy
831 stw r7,SAVflags(r3) ; Set the allocation flags
833 fsusecache: la r11,savefp0(r3) ; Point to the 1st line in area
834 stw r13,SAVlvlfp(r3) ; Set this context level
836 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
837 li r2,0x7F06 ; (TEST/DEBUG)
838 mr r5,r13 ; (TEST/DEBUG)
839 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
844 ; Now we will actually save the old context
847 dcbz 0,r11 ; Allocate the output area
849 la r11,savefp4(r3) ; Point to the 2nd line
851 dcbz 0,r11 ; Allocate cache
854 la r11,savefp8(r3) ; Point to the 3rd line
856 dcbz 0,r11 ; Allocate cache
860 la r11,savefp12(r3) ; Point to the 4th line
862 dcbz 0,r11 ; Allocate cache
865 stfd f10,savefp10(r3)
866 la r11,savefp16(r3) ; Point to the 5th line
867 stfd f11,savefp11(r3)
868 dcbz 0,r11 ; Allocate cache
869 stfd f12,savefp12(r3)
870 stfd f13,savefp13(r3)
871 stfd f14,savefp14(r3)
872 la r11,savefp20(r3) ; Point to the 6th line
873 stfd f15,savefp15(r3)
874 dcbz 0,r11 ; Allocate cache
875 stfd f16,savefp16(r3)
876 stfd f17,savefp17(r3)
877 stfd f18,savefp18(r3)
878 la r11,savefp24(r3) ; Point to the 7th line
879 stfd f19,savefp19(r3)
880 dcbz 0,r11 ; Allocate cache
881 stfd f20,savefp20(r3)
883 li r14,0 ; Clear this for now
884 lwz r15,liveFPSCR(r6) ; Get the previously saved FPSCR
886 stfd f21,savefp21(r3)
887 stfd f22,savefp22(r3)
888 la r11,savefp28(r3) ; Point to the 8th line
889 stfd f23,savefp23(r3)
890 dcbz 0,r11 ; allocate it
891 stfd f24,savefp24(r3)
892 stfd f25,savefp25(r3)
893 stfd f26,savefp26(r3)
894 la r11,savefpscrpad(r3) ; Point to the 9th line
895 stfd f27,savefp27(r3)
896 dcbz 0,r11 ; allocate it
897 stfd f28,savefp28(r3)
898 stfd f29,savefp29(r3)
899 stfd f30,savefp30(r3)
900 stfd f31,savefp31(r3)
902 ; Note that we just save the FPSCR here for ease. It is really already saved
903 ; in the "normal" context area of the savearea.
905 stw r14,savefpscrpad(r3) ; Save the FPSCR pad
906 stw r15,savefpscr(r3) ; Save the FPSCR
909 ; The context is all saved now and the facility is free.
911 ; Now check out the "new" and see if we need to load up his context.
912 ; If we do (and this should be the normal case), do it and then invalidate the
913 ; savearea. (This will keep it cached for quick access next time around.)
915 ; If we do not (remember, we already took care of the case where we just enable
916 ; the FPU), we need to fill the registers with junk, because this level has
917 ; never used them before and some thieving bastard could hack the old values
918 ; of some thread! Just imagine what would happen if they could! Why, nothing
919 ; would be safe! My God! It is terrifying!
923 fsnosave: lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
924 lwz r14,ACT_MACT_FPU(r17) ; Point to the top of the "new" context stack
925 lwz r13,ACT_MACT_FPUlvl(r17) ; Get the "new" active level
927 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
928 li r2,0x7F07 ; (TEST/DEBUG)
929 mr r1,r15 ; (TEST/DEBUG)
930 mr r3,r14 ; (TEST/DEBUG)
931 mr r5,r13 ; (TEST/DEBUG)
932 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
936 cmplwi cr1,r14,0 ; Do we possibly have some context to load?
937 stw r15,ACT_MACT_FPUlvl(r17) ; Set the "new" active level
938 stw r18,ACT_MACT_FPUcpu(r17) ; Set the active CPU
939 la r11,savefp0(r14) ; Point to first line to bring in
940 stw r17,PP_FPU_THREAD(r6) ; Store current thread address in fpu_thread to claim fpu for thread
942 beq+ cr1,MakeSureThatNoTerroristsCanHurtUsByGod ; No "new" context to load...
943 lwz r0,SAVlvlfp(r14) ; Get the level of first facility savearea
944 cmplw r0,r15 ; Top level correct to load?
945 bne- MakeSureThatNoTerroristsCanHurtUsByGod ; No, go initialize...
948 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
949 li r2,0x7F08 ; (TEST/DEBUG)
950 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
954 dcbt 0,r11 ; Touch line in
955 li r0,1 ; Get the level invalid indication
957 la r11,savefp4(r14) ; Point to next line
958 dcbt 0,r11 ; Touch line in
961 stw r0,SAVlvlfp(r14) ; Mark the savearea invalid because we are activating again
963 la r11,savefp8(r14) ; Point to next line
965 dcbt 0,r11 ; Touch line in
969 la r11,savefp12(r14) ; Point to next line
971 dcbt 0,r11 ; Touch line in
974 lfd f10,savefp10(r14)
975 la r11,savefp16(r14) ; Point to next line
976 lfd f11,savefp11(r14)
977 dcbt 0,r11 ; Touch line in
978 lfd f12,savefp12(r14)
979 lfd f13,savefp13(r14)
980 lfd f14,savefp14(r14)
981 la r11,savefp20(r14) ; Point to next line
982 lfd f15,savefp15(r14)
983 dcbt 0,r11 ; Touch line in
984 lfd f16,savefp16(r14)
985 lfd f17,savefp17(r14)
986 lfd f18,savefp18(r14)
987 la r11,savefp24(r14) ; Point to next line
988 lfd f19,savefp19(r14)
989 dcbt 0,r11 ; Touch line in
990 lfd f20,savefp20(r14)
991 lfd f21,savefp21(r14)
992 la r11,savefp28(r14) ; Point to next line
993 lfd f22,savefp22(r14)
994 lfd f23,savefp23(r14)
995 dcbt 0,r11 ; Touch line in
996 lfd f24,savefp24(r14)
997 lfd f25,savefp25(r14)
998 lfd f26,savefp26(r14)
999 lfd f27,savefp27(r14)
1000 lfd f28,savefp28(r14)
1001 lfd f29,savefp29(r14)
1002 lfd f30,savefp30(r14)
1003 lfd f31,savefp31(r14)
1005 fsenable: lwz r9,SAVflags(r4) /* Get the flags of the current savearea */
1006 lwz r8,savesrr1(r4) ; Get the msr of the interrupted guy
1007 rlwinm r5,r4,0,0,19 /* Get the page address of the savearea */
1008 ori r8,r8,MASK(MSR_FP) ; Enable the floating point feature
1009 lwz r10,ACT_MACT_SPF(r17) ; Get the special flags
1010 lis r7,hi16(SAVattach) /* Get the attached flag */
1011 lwz r5,SACvrswap(r5) /* Get Virtual to Real translation */
1012 oris r10,r10,hi16(floatUsed|floatCng) ; Set that we used floating point
1013 mr. r15,r15 ; See if we are doing this for user state
1014 stw r8,savesrr1(r4) ; Set the msr of the interrupted guy
1015 andc r9,r9,r7 /* Clear the attached bit */
1016 xor r3,r4,r5 /* Get the real address of the savearea */
1017 bne- fsnuser ; We are not user state...
1018 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
1019 stw r10,spcFlags(r6) ; Set per_proc copy
1023 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1024 li r2,0x7F0A ; (TEST/DEBUG)
1025 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1028 stw r9,SAVflags(r4) /* Set the flags of the current savearea */
1030 b EXT(exception_exit) /* Exit from the fray... */
1033 * Initialize the registers to some bogus value
1036 MakeSureThatNoTerroristsCanHurtUsByGod:
1039 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1040 li r2,0x7F09 ; (TEST/DEBUG)
1041 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1044 lis r5,hi16(EXT(FloatInit)) /* Get top secret floating point init value address */
1045 ori r5,r5,lo16(EXT(FloatInit)) /* Slam bottom */
1046 lfd f0,0(r5) /* Initialize FP0 */
1047 fmr f1,f0 ; Do them all
1064 fsub f31,f31,f31 ; Get set to initialize the FPSCR
1068 mtfsf 0xff,f31 ; Clear all FPSCR exception eanbles
1080 b fsenable ; Finish setting it all up...
1083 ; Finds an unused floating point area in the activation pointed
1084 ; to by R12s saved contexts. If none are found (unlikely but possible)
1085 ; and R3 is 0, a new area is allocated. If R3 is non-zero, it contains
1086 ; a pointer to an floating point savearea that is free.
1089 lwz r6,ACT_MACT_PCB(r12) ; Get the first "normal" savearea
1091 fpsrnorm: mr. r5,r6 ; Is there another?
1092 beq- fpsrvect ; No, search the vector saveareas...
1093 lwz r7,SAVflags(r5) ; Get the flags for this guy
1094 lwz r6,SAVprev(r5) ; Get the previous savearea, just in case
1095 andis. r8,r7,hi16(SAVfpuvalid) ; Have we found an empty FPU save in normal?
1096 beq+ fpsrgot ; We found one...
1097 b fpsrnorm ; Search again...
1099 fpsrvect: lwz r6,ACT_MACT_VMX(r12) ; Get the first "vector" savearea
1101 fpsrvectx: mr. r5,r6 ; Is there another?
1102 beq- fpsrget ; No, try to allocate one...
1103 lwz r7,SAVflags(r5) ; Get the flags for this guy
1104 lwz r6,SAVprevec(r5) ; Get the previous savearea, just in case
1105 andis. r8,r7,hi16(SAVfpuvalid) ; Have we found an empty FPU save in vector?
1106 bne- fpsrvectx ; Search again...
1108 fpsrgot: mr r3,r5 ; Get the savearea into the right register
1111 fpsrget: mr. r5,r3 ; Do we allocate or use existing?
1112 beq+ fpsrallo ; Allocate one...
1114 lwz r7,SAVflags(r3) ; Get the passed in area flags
1117 ; NOTE: save_get will return directly and set R7 to 0...
1119 fpsrallo: b EXT(save_get) ; Get a fresh savearea
1122 * Altivec stuff is here. The techniques used are pretty identical to
1123 * the floating point. Except that we will honor the VRSAVE register
1124 * settings when loading and restoring registers.
1126 * There are two indications of saved VRs: the VRSAVE register and the vrvalid
1127 * mask. VRSAVE is set by the vector user and represents the VRs that they
1128 * say that they are using. The vrvalid mask indicates which vector registers
1129 * are saved in the savearea. Whenever context is saved, it is saved according
1130 * to the VRSAVE register. It is loaded based on VRSAVE anded with
1131 * vrvalid (all other registers are splatted with 0s). This is done because we
1132 * don't want to load any registers we don't have a copy of, we want to set them
1137 ENTRY(vec_save, TAG_NO_FRAME_USED)
1139 mfmsr r0 ; Get the MSR
1140 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Turn off vector forever
1141 rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; But do interrupts only for now
1142 oris r2,r2,hi16(MASK(MSR_VEC)) ; Enable the vector facility for now also
1143 mtmsr r2 ; Set the MSR
1146 mfsprg r6,0 ; Get the per_processor block
1147 lwz r12,PP_VMX_THREAD(r6) ; Get the thread that owns the vector
1149 mr r7,r0 ; (TEST/DEBUG)
1150 li r4,0 ; (TEST/DEBUG)
1151 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1152 mr. r3,r12 ; (TEST/DEBUG)
1153 li r2,0x5F00 ; (TEST/DEBUG)
1154 li r5,0 ; (TEST/DEBUG)
1155 beq- noowneryeu ; (TEST/DEBUG)
1156 lwz r4,ACT_MACT_VMXlvl(r12) ; (TEST/DEBUG)
1157 lwz r5,ACT_MACT_VMX(r12) ; (TEST/DEBUG)
1159 noowneryeu: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1161 mr r0,r7 ; (TEST/DEBUG)
1163 mflr r2 ; Save the return address
1164 lwz r10,PP_CPU_DATA(r6) ; Get the CPU data pointer
1165 lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number
1167 mr. r12,r12 ; Anyone own the vector?
1169 lwz r10,CPU_ACTIVE_THREAD(r10) ; Get the pointer to the active thread
1171 beq- vsret ; Nobody owns the vector, no save required...
1173 lwz r10,THREAD_TOP_ACT(r10) ; Now get the activation that is running
1174 lwz r9,ACT_MACT_VMXcpu(r12) ; Get the last CPU to use this context
1176 cmplw r12,r10 ; Do we own the thread?
1177 cmplw cr1,r9,r11 ; Was the context for this processor?
1178 bne+ vsret ; Facility belongs to some other activation...
1179 li r3,0 ; Assume we need a fix-me-up
1180 beq- cr1,vsgoodcpu ; Facility last used on this processor...
1181 stw r3,PP_VMX_THREAD(r6) ; Clear owner because it was really on the other processor
1182 b vsret ; Bail now with no save...
1184 vsgoodcpu: lwz r3,ACT_MACT_VMX(r12) ; Get the current vector savearea for the thread
1185 lwz r9,ACT_MACT_VMXlvl(r12) ; Get our current level indicator
1187 cmplwi cr1,r3,0 ; Have we ever saved this facility context?
1188 beq- cr1,vsneedone ; Never saved it, so we need an area...
1190 lwz r8,SAVlvlvec(r3) ; Get the level this savearea is for
1191 cmplwi r8,1 ; See if this is a spare
1192 cmplw cr1,r9,r8 ; Correct level?
1193 beq+ vsusespare ; It is still live...
1194 beq- cr1,vsret ; The current level is already saved, bail out...
1196 vsneedone: li r3,0 ; Tell the routine to allocate an area if none found
1197 bl vsrchsave ; Find a free savearea
1199 mfsprg r6,0 ; Get back per_processor block
1200 oris r7,r7,hi16(SAVvmxvalid) ; Set the allocated bit
1201 lwz r12,PP_VMX_THREAD(r6) ; Get back our thread
1202 mtlr r2 ; Restore return
1203 lwz r8,ACT_MACT_VMX(r12) ; Get the current top vector savearea
1204 lwz r9,ACT_MACT_VMXlvl(r12) ; Get our current level indicator again
1205 stw r3,ACT_MACT_VMX(r12) ; Set this as the latest vector savearea for the thread
1206 stw r8,SAVprevec(r3) ; And then chain this in front
1207 stw r7,SAVflags(r3) ; Set the allocation flags
1208 stw r12,SAVact(r3) ; Make sure we point to the right guy
1210 vsusespare: stw r9,SAVlvlvec(r3) ; And set the level this savearea is for
1211 mfcr r2 ; Save non-volatile CRs
1212 lwz r10,liveVRS(r6) ; Get the right VRSave register
1213 lis r9,0x5555 ; Mask with odd bits set
1214 rlwinm r11,r10,1,0,31 ; Shift over 1
1215 ori r9,r9,0x5555 ; Finish mask
1216 or r12,r10,r11 ; After this, even bits show which lines to zap
1218 andc r11,r12,r9 ; Clear out odd bits
1220 la r6,savevr0(r3) ; Point to line 0
1221 rlwinm r4,r11,15,0,15 ; Move line 8-15 flags to high order odd bits
1222 la r9,savevrvalid(r3) ; Point to the saved register mask field
1223 or r4,r11,r4 ; Set the odd bits
1224 ; (bit 0 is line 0, bit 1 is line 8,
1225 ; bit 2 is line 1, bit 3 is line 9, etc.
1226 dcba br0,r9 ; Allocate the cache for it
1227 rlwimi r4,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1228 la r7,savevr2(r3) ; Point to line 1
1229 mtcrf 255,r4 ; Load up the CRs
1230 stw r10,savevrvalid(r3) ; Save the validity information
1231 mr r8,r6 ; Start registers off
1233 ; Save the current vector state
1236 bf 0,snol0 ; No line 0 to do...
1237 dcba br0,r6 ; Allocate cache line 0
1240 la r6,savevr4(r3) ; Point to line 2
1241 bf 2,snol1 ; No line 1 to do...
1242 dcba br0,r7 ; Allocate cache line 1
1245 la r7,savevr6(r3) ; Point to line 3
1246 bf 4,snol2 ; No line 2 to do...
1247 dcba br0,r6 ; Allocate cache line 2
1250 li r11,16 ; Get offset for odd registers
1251 bf 16,snovr0 ; Do not save VR0...
1252 stvxl v0,br0,r8 ; Save VR0
1255 la r9,savevr2(r3) ; Point to V2/V3 pair
1256 bf 17,snovr1 ; Do not save VR1...
1257 stvxl v1,r11,r8 ; Save VR1
1260 la r6,savevr8(r3) ; Point to line 4
1261 bf 6,snol3 ; No line 3 to do...
1262 dcba br0,r7 ; Allocate cache line 3
1265 la r8,savevr4(r3) ; Point to V4/V5 pair
1266 bf 18,snovr2 ; Do not save VR2...
1267 stvxl v2,br0,r9 ; Save VR2
1270 bf 19,snovr3 ; Do not save VR3...
1271 stvxl v3,r11,r9 ; Save VR3
1275 ; Note: CR4 is now free
1277 la r7,savevr10(r3) ; Point to line 5
1278 bf 8,snol4 ; No line 4 to do...
1279 dcba br0,r6 ; Allocate cache line 4
1282 la r9,savevr6(r3) ; Point to R6/R7 pair
1283 bf 20,snovr4 ; Do not save VR4...
1284 stvxl v4,br0,r8 ; Save VR4
1287 bf 21,snovr5 ; Do not save VR5...
1288 stvxl v5,r11,r8 ; Save VR5
1291 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1292 la r6,savevr12(r3) ; Point to line 6
1293 bf 10,snol5 ; No line 5 to do...
1294 dcba br0,r7 ; Allocate cache line 5
1297 la r8,savevr8(r3) ; Point to V8/V9 pair
1298 bf 22,snovr6 ; Do not save VR6...
1299 stvxl v6,br0,r9 ; Save VR6
1302 bf 23,snovr7 ; Do not save VR7...
1303 stvxl v7,r11,r9 ; Save VR7
1307 ; Note: CR5 is now free
1309 la r7,savevr14(r3) ; Point to line 7
1310 bf 12,snol6 ; No line 6 to do...
1311 dcba br0,r6 ; Allocate cache line 6
1314 la r9,savevr10(r3) ; Point to V10/V11 pair
1315 bf 24,snovr8 ; Do not save VR8...
1316 stvxl v8,br0,r8 ; Save VR8
1319 bf 25,snovr9 ; Do not save VR9...
1320 stvxl v9,r11,r8 ; Save VR9
1323 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1324 la r6,savevr16(r3) ; Point to line 8
1325 bf 14,snol7 ; No line 7 to do...
1326 dcba br0,r7 ; Allocate cache line 7
1329 la r8,savevr12(r3) ; Point to V12/V13 pair
1330 bf 26,snovr10 ; Do not save VR10...
1331 stvxl v10,br0,r9 ; Save VR10
1334 bf 27,snovr11 ; Do not save VR11...
1335 stvxl v11,r11,r9 ; Save VR11
1340 ; Note: CR6 is now free
1342 la r7,savevr18(r3) ; Point to line 9
1343 bf 1,snol8 ; No line 8 to do...
1344 dcba br0,r6 ; Allocate cache line 8
1347 la r9,savevr14(r3) ; Point to V14/V15 pair
1348 bf 28,snovr12 ; Do not save VR12...
1349 stvxl v12,br0,r8 ; Save VR12
1352 bf 29,snovr13 ; Do not save VR13...
1353 stvxl v13,r11,r8 ; Save VR13
1356 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1357 la r6,savevr20(r3) ; Point to line 10
1358 bf 3,snol9 ; No line 9 to do...
1359 dcba br0,r7 ; Allocate cache line 9
1362 la r8,savevr16(r3) ; Point to V16/V17 pair
1363 bf 30,snovr14 ; Do not save VR14...
1364 stvxl v14,br0,r9 ; Save VR14
1367 bf 31,snovr15 ; Do not save VR15...
1368 stvxl v15,r11,r9 ; Save VR15
1372 ; Note: CR7 is now free
1374 la r7,savevr22(r3) ; Point to line 11
1375 bf 5,snol10 ; No line 10 to do...
1376 dcba br0,r6 ; Allocate cache line 10
1379 la r9,savevr18(r3) ; Point to V18/V19 pair
1380 bf 16,snovr16 ; Do not save VR16...
1381 stvxl v16,br0,r8 ; Save VR16
1384 bf 17,snovr17 ; Do not save VR17...
1385 stvxl v17,r11,r8 ; Save VR17
1388 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1390 ; Note: All registers have been or are accounted for in CRs
1392 la r6,savevr24(r3) ; Point to line 12
1393 bf 7,snol11 ; No line 11 to do...
1394 dcba br0,r7 ; Allocate cache line 11
1397 la r8,savevr20(r3) ; Point to V20/V21 pair
1398 bf 18,snovr18 ; Do not save VR18...
1399 stvxl v18,br0,r9 ; Save VR18
1402 bf 19,snovr19 ; Do not save VR19...
1403 stvxl v19,r11,r9 ; Save VR19
1406 la r7,savevr26(r3) ; Point to line 13
1407 bf 9,snol12 ; No line 12 to do...
1408 dcba br0,r6 ; Allocate cache line 12
1411 la r9,savevr22(r3) ; Point to V22/V23 pair
1412 bf 20,snovr20 ; Do not save VR20...
1413 stvxl v20,br0,r8 ; Save VR20
1416 bf 21,snovr21 ; Do not save VR21...
1417 stvxl v21,r11,r8 ; Save VR21
1420 la r6,savevr28(r3) ; Point to line 14
1421 bf 11,snol13 ; No line 13 to do...
1422 dcba br0,r7 ; Allocate cache line 13
1425 la r8,savevr24(r3) ; Point to V24/V25 pair
1426 bf 22,snovr22 ; Do not save VR22...
1427 stvxl v22,br0,r9 ; Save VR22
1430 bf 23,snovr23 ; Do not save VR23...
1431 stvxl v23,r11,r9 ; Save VR23
1434 la r7,savevr30(r3) ; Point to line 15
1435 bf 13,snol14 ; No line 14 to do...
1436 dcba br0,r6 ; Allocate cache line 14
1439 la r9,savevr26(r3) ; Point to V26/V27 pair
1440 bf 24,snovr24 ; Do not save VR24...
1441 stvxl v24,br0,r8 ; Save VR24
1444 bf 25,snovr25 ; Do not save VR25...
1445 stvxl v25,r11,r8 ; Save VR25
1448 bf 15,snol15 ; No line 15 to do...
1449 dcba br0,r7 ; Allocate cache line 15
1453 ; Note: All cache lines allocated now
1455 la r8,savevr28(r3) ; Point to V28/V29 pair
1456 bf 26,snovr26 ; Do not save VR26...
1457 stvxl v26,br0,r9 ; Save VR26
1460 bf 27,snovr27 ; Do not save VR27...
1461 stvxl v27,r11,r9 ; Save VR27
1464 la r7,savevr30(r3) ; Point to V30/V31 pair
1465 bf 28,snovr28 ; Do not save VR28...
1466 stvxl v28,br0,r8 ; Save VR28
1469 bf 29,snovr29 ; Do not save VR29...
1470 stvxl v29,r11,r8 ; Save VR29
1473 mfvscr v27 ; Get the VSCR
1474 la r8,savevscr(r3) ; Point to the VSCR save area
1475 bf 30,snovr30 ; Do not save VR30...
1476 stvxl v30,br0,r7 ; Save VR30
1479 dcba br0,r8 ; Allocate VSCR savearea
1480 bf 31,snovr31 ; Do not save VR31...
1481 stvxl v31,r11,r7 ; Save VR31
1484 add r11,r11,r9 ; Point to V27s saved value
1485 stvxl v27,br0,r8 ; Save the VSCR
1486 bt 27,v27ok ; V27 has been saved and is marked as wanted
1488 lis r11,hi16(EXT(QNaNbarbarian)) ; V27 is not wanted, so get empty value
1489 ori r11,r11,lo16(EXT(QNaNbarbarian))
1491 v27ok: mtcrf 255,r2 ; Restore all non-volatile CRs
1492 lvxl v27,br0,r11 ; Restore or load empty value into V27 because we used it
1495 ; Save the current vector state into the savearea of the thread that owns it.
1498 vsret: mtmsr r0 ; Put interrupts on if they were and vector off
1506 * Entered to handle the vector unavailable exception and
1507 * switch vector context
1509 * This code is run with virtual address mode on and interrupts off.
1511 * Upon exit, the code returns to the users context with the vector
1512 * facility turned on.
1514 * ENTRY: VM switched ON
1516 * State is saved in savearea pointed to by R4.
1517 * All other registers are free.
1521 ENTRY(vec_switch, TAG_NO_FRAME_USED)
1525 mr r7,r4 ; Save input parameter
1526 lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter
1527 ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
1529 lis r5,hi16(EXT(GratefulDeb)) ; Point to top of display
1530 ori r5,r5,lo16(EXT(GratefulDeb)) ; Put in bottom part
1532 mtlr r5 ; Set link register
1536 blrl ; Display count
1537 mr r4,r7 ; Restore the parameter
1539 lis r3,hi16(EXT(vec_trap_count)) ; Get address of vector trap counter
1540 ori r3,r3,lo16(EXT(vec_trap_count)) ; Get address of vector trap counter
1547 mfsprg r6,0 /* Get the per_processor block */
1548 mfmsr r19 /* Get the current MSR */
1550 lwz r10,PP_CPU_DATA(r6) /* Get the CPU data pointer */
1551 lwz r12,PP_VMX_THREAD(r6) /* Get the thread that owns the vector */
1552 lwz r10,CPU_ACTIVE_THREAD(r10) /* Get the pointer to the active thread */
1553 oris r19,r19,hi16(MASK(MSR_VEC)) /* Enable the vector feature */
1554 lwz r17,THREAD_TOP_ACT(r10) /* Now get the activation that is running */
1556 ; R12 has the "old" activation
1557 ; R17 has the "new" activation
1560 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1561 li r2,0x5F01 ; (TEST/DEBUG)
1562 mr r3,r12 ; (TEST/DEBUG)
1563 mr r5,r17 ; (TEST/DEBUG)
1564 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1567 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1568 mr r18,r4 ; Save this
1569 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1570 mr r4,r2 ; Set value
1571 mtlr r3 ; Set link register
1572 li r3,1 ; Display address
1574 mr r4,r18 ; Restore it
1575 mfsprg r6,0 ; Get the per_processor block back
1578 mr. r12,r12 ; See if there is any live vector status
1580 lhz r18,PP_CPU_NUMBER(r6) ; Get our CPU number
1582 mtmsr r19 /* Set vector available */
1586 beq- vsnosave ; No live context, so nothing to save...
1588 lwz r19,ACT_MACT_VMXcpu(r12) ; Get the "old" active CPU
1589 lwz r15,ACT_MACT_PCB(r12) ; Get the current level of the "old" one
1590 cmplw r18,r19 ; Check the CPU that the old context is live on
1591 lwz r14,ACT_MACT_VMX(r12) ; Point to the top of the old context stack
1592 bne- vsnosave ; Context is not live if used on a different CPU...
1593 lwz r13,ACT_MACT_VMXlvl(r12) ; Get the "old" active level
1596 ; First, check to see if all we are doing is enabling because the
1597 ; "new" context is live.
1600 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1601 li r2,0x5F02 ; (TEST/DEBUG)
1602 mr r1,r15 ; (TEST/DEBUG)
1603 mr r3,r13 ; (TEST/DEBUG)
1604 mr r5,r14 ; (TEST/DEBUG)
1605 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1608 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1609 mr r8,r4 ; Save this
1610 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1611 mr r4,r2 ; Set value
1612 mtlr r3 ; Set link register
1613 li r3,1 ; Display address
1615 mr r4,r8 ; Restore it
1619 cmplw cr1,r12,r17 ; Is the "old" activation and the "new" the same?
1620 cmplwi cr2,r14,0 ; Is there any saved context on the "old" activation?
1621 bne+ cr1,vsmstsave ; The activations are different so "old" context must be saved...
1624 ; Here we know that both the "old" and "new" activations are the same. We will
1625 ; check the current level and active levels. If they are the same, the context is
1626 ; already live, so all we do is turn on the facility and invalidate the top
1629 ; If the current level, the active level, and the top savearea level are the
1630 ; same, then the context was saved as part of a thread context switch and neither
1631 ; needs saving or restoration.
1633 ; In all other cases, the context must be saved unless we are just re-enabling
1637 cmplw r13,r15 ; Are the levels the same?
1638 cmplwi cr2,r14,0 ; Is there any saved context?
1639 bne- vsmstsave ; Levels are different, we need to save...
1641 beq- cr2,vrenable ; No saved context at all, enable and go...
1643 lwz r20,SAVlvlvec(r14) ; Get the level of the top savearea
1646 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1647 li r2,0x5F03 ; (TEST/DEBUG)
1648 mr r3,r15 ; (TEST/DEBUG)
1649 mr r5,r20 ; (TEST/DEBUG)
1650 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1653 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1654 mr r8,r4 ; Save this
1655 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1656 mr r4,r2 ; Set value
1657 mtlr r3 ; Set link register
1658 li r3,1 ; Display address
1660 mr r4,r8 ; Restore it
1663 cmplw r15,r20 ; Is the top level the same as the current?
1664 li r0,1 ; Get the invalid flag
1665 bne- vrenable ; Not the same, just enable and go...
1667 stw r0,SAVlvlvec(r14) ; Invalidate that top savearea
1669 b vrenable ; Then enable and go...
1672 ; We need to save the "old" context here. The LIFO queueing scheme works
1673 ; out for all cases because if both the "new" and "old" activations are the
1674 ; same, there can not be any saved state to load. the "new" level is
1677 ; When we save the context, we either use a new savearea, or the free
1678 ; one that is cached at the head of the list.
1680 vsmstsave: beq- cr2,vsgetsave ; There is no possible cached save area
1682 lwz r5,SAVlvlvec(r14) ; Get the level of first facility savearea
1684 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1685 li r2,0x5F04 ; (TEST/DEBUG)
1686 mr r3,r15 ; (TEST/DEBUG)
1687 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1690 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1691 mr r8,r4 ; Save this
1692 mr r7,r5 ; Save this
1693 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1694 mr r4,r2 ; Set value
1695 mtlr r3 ; Set link register
1696 li r3,1 ; Display address
1698 mr r4,r8 ; Restore it
1699 mr r5,r7 ; Restore it
1702 mr r3,r14 ; Assume we are invalid
1703 cmplwi r5,1 ; Is it invalid?
1704 cmplw cr1,r5,r13 ; Is the SA level the active one?
1705 beq+ vsusecache ; Invalid, just use it...
1706 beq- cr1,vsnosave ; The SA level is active, it is already saved...
1708 vsgetsave: mr r3,r4 ; Use the interrupt save as the context savearea if none cached
1710 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1711 li r2,0x5F05 ; (TEST/DEBUG)
1712 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1715 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1716 mr r8,r4 ; Save this
1717 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1718 mr r4,r2 ; Set value
1719 mtlr r3 ; Set link register
1720 li r3,1 ; Display address
1722 mr r4,r8 ; Restore it
1727 bl vsrchsave ; Find a free savearea
1729 stw r3,ACT_MACT_VMX(r12) ; Set this as the latest context savearea for the thread
1730 mfsprg r6,0 ; Get back per_processor block
1731 stw r14,SAVprevec(r3) ; And then chain this in front
1732 oris r7,r7,hi16(SAVvmxvalid) ; Set the allocated bit
1733 stw r12,SAVact(r3) ; Make sure we point to the right guy
1734 stw r7,SAVflags(r3) ; Set the allocation flags
1736 vsusecache: la r11,savevr0(r3) ; Point to the 1st line in area
1737 stw r13,SAVlvlvec(r3) ; Set this context level
1739 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
1740 li r2,0x5F06 ; (TEST/DEBUG)
1741 mr r5,r13 ; (TEST/DEBUG)
1742 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
1746 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
1747 mr r8,r4 ; Save this
1748 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
1749 mr r4,r2 ; Set value
1750 mtlr r3 ; Set link register
1751 li r3,1 ; Display address
1753 mr r4,r8 ; Restore it
1755 mfsprg r6,0 ; Get back per_processor block
1760 lwz r10,liveVRS(r6) ; Get the right VRSave register
1761 lis r9,0x5555 ; Mask with odd bits set
1762 rlwinm r11,r10,1,0,31 ; Shift over 1
1763 ori r9,r9,0x5555 ; Finish mask
1764 or r12,r10,r11 ; After this, even bits show which lines to zap
1766 stw r13,SAVlvlvec(r3) ; Set the savearea level
1767 andc r13,r12,r9 ; Clear out odd bits
1769 la r20,savevr0(r3) ; Point to line 0
1770 rlwinm r24,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
1771 la r23,savevrvalid(r3) ; Point to the saved register mask field
1772 or r24,r13,r24 ; Set the odd bits
1773 ; (bit 0 is line 0, bit 1 is line 8,
1774 ; bit 2 is line 1, bit 3 is line 9, etc.
1775 dcba br0,r23 ; Allocate the cache for it
1776 rlwimi r24,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
1777 la r21,savevr2(r3) ; Point to line 1
1778 mtcrf 255,r24 ; Load up the CRs
1779 stw r10,savevrvalid(r3) ; Save the validity information
1780 mr r22,r20 ; Start registers off
1782 ; Save the current vector state
1785 bf 0,nol0 ; No line 0 to do...
1786 dcba br0,r20 ; Allocate cache line 0
1789 la r20,savevr4(r3) ; Point to line 2
1790 bf 2,nol1 ; No line 1 to do...
1791 dcba br0,r21 ; Allocate cache line 1
1794 la r21,savevr6(r3) ; Point to line 3
1795 bf 4,nol2 ; No line 2 to do...
1796 dcba br0,r20 ; Allocate cache line 2
1799 li r30,16 ; Get offset for odd registers
1800 bf 16,novr0 ; Do not save VR0...
1801 stvxl v0,br0,r22 ; Save VR0
1804 la r23,savevr2(r3) ; Point to V2/V3 pair
1805 bf 17,novr1 ; Do not save VR1...
1806 stvxl v1,r30,r22 ; Save VR1
1809 la r20,savevr8(r3) ; Point to line 4
1810 bf 6,nol3 ; No line 3 to do...
1811 dcba br0,r21 ; Allocate cache line 3
1814 la r22,savevr4(r3) ; Point to V4/V5 pair
1815 bf 18,novr2 ; Do not save VR2...
1816 stvxl v2,br0,r23 ; Save VR2
1819 bf 19,novr3 ; Do not save VR3...
1820 stvxl v3,r30,r23 ; Save VR3
1824 ; Note: CR4 is now free
1826 la r21,savevr10(r3) ; Point to line 5
1827 bf 8,nol4 ; No line 4 to do...
1828 dcba br0,r20 ; Allocate cache line 4
1831 la r23,savevr6(r3) ; Point to R6/R7 pair
1832 bf 20,novr4 ; Do not save VR4...
1833 stvxl v4,br0,r22 ; Save VR4
1836 bf 21,novr5 ; Do not save VR5...
1837 stvxl v5,r30,r22 ; Save VR5
1840 mtcrf 0x08,r10 ; Set CRs for registers 16-19
1841 la r20,savevr12(r3) ; Point to line 6
1842 bf 10,nol5 ; No line 5 to do...
1843 dcba br0,r21 ; Allocate cache line 5
1846 la r22,savevr8(r3) ; Point to V8/V9 pair
1847 bf 22,novr6 ; Do not save VR6...
1848 stvxl v6,br0,r23 ; Save VR6
1851 bf 23,novr7 ; Do not save VR7...
1852 stvxl v7,r30,r23 ; Save VR7
1856 ; Note: CR5 is now free
1858 la r21,savevr14(r3) ; Point to line 7
1859 bf 12,nol6 ; No line 6 to do...
1860 dcba br0,r20 ; Allocate cache line 6
1863 la r23,savevr10(r3) ; Point to V10/V11 pair
1864 bf 24,novr8 ; Do not save VR8...
1865 stvxl v8,br0,r22 ; Save VR8
1868 bf 25,novr9 ; Do not save VR9...
1869 stvxl v9,r30,r22 ; Save VR9
1872 mtcrf 0x04,r10 ; Set CRs for registers 20-23
1873 la r20,savevr16(r3) ; Point to line 8
1874 bf 14,nol7 ; No line 7 to do...
1875 dcba br0,r21 ; Allocate cache line 7
1878 la r22,savevr12(r3) ; Point to V12/V13 pair
1879 bf 26,novr10 ; Do not save VR10...
1880 stvxl v10,br0,r23 ; Save VR10
1883 bf 27,novr11 ; Do not save VR11...
1884 stvxl v11,r30,r23 ; Save VR11
1889 ; Note: CR6 is now free
1891 la r21,savevr18(r3) ; Point to line 9
1892 bf 1,nol8 ; No line 8 to do...
1893 dcba br0,r20 ; Allocate cache line 8
1896 la r23,savevr14(r3) ; Point to V14/V15 pair
1897 bf 28,novr12 ; Do not save VR12...
1898 stvxl v12,br0,r22 ; Save VR12
1901 bf 29,novr13 ; Do not save VR13...
1902 stvxl v13,r30,r22 ; Save VR13
1905 mtcrf 0x02,r10 ; Set CRs for registers 24-27
1906 la r20,savevr20(r3) ; Point to line 10
1907 bf 3,nol9 ; No line 9 to do...
1908 dcba br0,r21 ; Allocate cache line 9
1911 la r22,savevr16(r3) ; Point to V16/V17 pair
1912 bf 30,novr14 ; Do not save VR14...
1913 stvxl v14,br0,r23 ; Save VR14
1916 bf 31,novr15 ; Do not save VR15...
1917 stvxl v15,r30,r23 ; Save VR15
1921 ; Note: CR7 is now free
1923 la r21,savevr22(r3) ; Point to line 11
1924 bf 5,nol10 ; No line 10 to do...
1925 dcba br0,r20 ; Allocate cache line 10
1928 la r23,savevr18(r3) ; Point to V18/V19 pair
1929 bf 16,novr16 ; Do not save VR16...
1930 stvxl v16,br0,r22 ; Save VR16
1933 bf 17,novr17 ; Do not save VR17...
1934 stvxl v17,r30,r22 ; Save VR17
1937 mtcrf 0x01,r10 ; Set CRs for registers 28-31
1939 ; Note: All registers have been or are accounted for in CRs
1941 la r20,savevr24(r3) ; Point to line 12
1942 bf 7,nol11 ; No line 11 to do...
1943 dcba br0,r21 ; Allocate cache line 11
1946 la r22,savevr20(r3) ; Point to V20/V21 pair
1947 bf 18,novr18 ; Do not save VR18...
1948 stvxl v18,br0,r23 ; Save VR18
1951 bf 19,novr19 ; Do not save VR19...
1952 stvxl v19,r30,r23 ; Save VR19
1955 la r21,savevr26(r3) ; Point to line 13
1956 bf 9,nol12 ; No line 12 to do...
1957 dcba br0,r20 ; Allocate cache line 12
1960 la r23,savevr22(r3) ; Point to V22/V23 pair
1961 bf 20,novr20 ; Do not save VR20...
1962 stvxl v20,br0,r22 ; Save VR20
1965 bf 21,novr21 ; Do not save VR21...
1966 stvxl v21,r30,r22 ; Save VR21
1969 la r20,savevr28(r3) ; Point to line 14
1970 bf 11,nol13 ; No line 13 to do...
1971 dcba br0,r21 ; Allocate cache line 13
1974 la r22,savevr24(r3) ; Point to V24/V25 pair
1975 bf 22,novr22 ; Do not save VR22...
1976 stvxl v22,br0,r23 ; Save VR22
1979 bf 23,novr23 ; Do not save VR23...
1980 stvxl v23,r30,r23 ; Save VR23
1983 la r21,savevr30(r3) ; Point to line 15
1984 bf 13,nol14 ; No line 14 to do...
1985 dcba br0,r20 ; Allocate cache line 14
1988 la r23,savevr26(r3) ; Point to V26/V27 pair
1989 bf 24,novr24 ; Do not save VR24...
1990 stvxl v24,br0,r22 ; Save VR24
1993 bf 25,novr25 ; Do not save VR25...
1994 stvxl v25,r30,r22 ; Save VR25
1997 bf 15,nol15 ; No line 15 to do...
1998 dcba br0,r21 ; Allocate cache line 15
2002 ; Note: All cache lines allocated now
2004 la r22,savevr28(r3) ; Point to V28/V29 pair
2005 bf 26,novr26 ; Do not save VR26...
2006 stvxl v26,br0,r23 ; Save VR26
2009 bf 27,novr27 ; Do not save VR27...
2010 stvxl v27,r30,r23 ; Save VR27
2013 la r23,savevr30(r3) ; Point to V30/V31 pair
2014 bf 28,novr28 ; Do not save VR28...
2015 stvxl v28,br0,r22 ; Save VR28
2018 mfvscr v27 ; Get the VSCR
2019 bf 29,novr29 ; Do not save VR29...
2020 stvxl v29,r30,r22 ; Save VR29
2023 la r22,savevscr(r3) ; Point to the VSCR save area
2024 bf 30,novr30 ; Do not save VR30...
2025 stvxl v30,br0,r23 ; Save VR30
2028 dcba br0,r22 ; Allocate VSCR savearea
2029 bf 31,novr31 ; Do not save VR31...
2030 stvxl v31,r30,r23 ; Save VR31
2033 stvxl v27,br0,r22 ; Save the VSCR
2038 * Now check out the current thread and see if we need to load up his context.
2039 * If we do (and this should be the normal case), do it and then release the
2042 * If we don't (remember, we already took care of the case where we just enable
2043 * the vector), we need to fill the registers with garbage, because this thread has
2044 * never used them before and some thieving bastard could hack the old values
2045 * of some thread! Just imagine what would happen if they could! Why, nothing
2046 * would be safe! My Gosh! It's terrifying!
2049 vsnosave: lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one
2050 lwz r14,ACT_MACT_VMX(r17) ; Point to the top of the "new" context stack
2051 lwz r13,ACT_MACT_VMXlvl(r17) ; Get the "new" active level
2054 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
2055 li r2,0x5F07 ; (TEST/DEBUG)
2056 mr r1,r15 ; (TEST/DEBUG)
2057 mr r3,r14 ; (TEST/DEBUG)
2058 mr r5,r13 ; (TEST/DEBUG)
2059 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
2063 cmplwi cr1,r14,0 ; Do we possibly have some context to load?
2064 stw r15,ACT_MACT_VMXlvl(r17) ; Set the "new" active level
2065 la r23,savevscr(r14) ; Point to the VSCR
2066 stw r18,ACT_MACT_VMXcpu(r17) ; Set the active CPU
2067 la r20,savevr0(r14) ; Point to first line to bring in
2068 stw r17,PP_VMX_THREAD(r6) ; Store current thread address in vmx_thread to claim vector for thread
2069 beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use...
2070 lwz r0,SAVlvlvec(r14) ; Get the level of first facility savearea
2071 cmplw r0,r15 ; Top level correct to load?
2072 bne- ProtectTheAmericanWay ; No, go initialize...
2075 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
2076 li r2,0x5F08 ; (TEST/DEBUG)
2077 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
2081 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
2082 mr r22,r4 ; Save this
2083 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
2084 mr r4,r2 ; Set value
2085 mtlr r3 ; Set link register
2086 li r3,1 ; Display address
2088 mr r4,r22 ; Restore it
2093 li r0,1 ; Get the level invalid indication
2094 lwz r22,savevrsave(r4) ; Get the most current VRSAVE
2095 lwz r10,savevrvalid(r14) ; Get the valid VRs in the savearea
2096 lis r9,0x5555 ; Mask with odd bits set
2097 and r10,r10,r22 ; Figure out just what registers need to be loaded
2098 ori r9,r9,0x5555 ; Finish mask
2099 rlwinm r11,r10,1,0,31 ; Shift over 1
2100 stw r0,SAVlvlvec(r14) ; Mark the savearea invalid because we are activating again
2101 or r12,r10,r11 ; After this, even bits show which lines to touch
2102 dcbt br0,r23 ; Touch in the VSCR
2103 andc r13,r12,r9 ; Clear out odd bits
2105 la r20,savevr0(r14) ; Point to line 0
2106 rlwinm r3,r13,15,0,15 ; Move line 8-15 flags to high order odd bits
2107 la r21,savevr2(r3) ; Point to line 1
2108 or r3,r13,r3 ; Set the odd bits
2109 ; (bit 0 is line 0, bit 1 is line 8,
2110 ; bit 2 is line 1, bit 3 is line 9, etc.
2111 lvxl v31,br0,r23 ; Get the VSCR
2112 rlwimi r3,r10,16,16,31 ; Put vrsave 0 - 15 into positions 16 - 31
2113 mtvscr v31 ; Slam the VSCR value
2114 mtcrf 255,r3 ; Load up the CRs
2115 mr r22,r20 ; Start registers off
2117 ; Load the new vector state
2120 bf 0,lnol0 ; No line 0 to do...
2121 dcbt br0,r20 ; Touch cache line 0
2124 la r20,savevr4(r14) ; Point to line 2
2125 bf 2,lnol1 ; No line 1 to do...
2126 dcbt br0,r21 ; Touch cache line 1
2129 la r21,savevr6(r14) ; Point to line 3
2130 bf 4,lnol2 ; No line 2 to do...
2131 dcbt br0,r20 ; Touch cache line 2
2134 li r30,16 ; Get offset for odd registers
2135 bf 16,lnovr0 ; Do not restore VR0...
2136 lvxl v0,br0,r22 ; Restore VR0
2139 la r23,savevr2(r14) ; Point to V2/V3 pair
2140 bf 17,lnovr1 ; Do not restore VR1...
2141 lvxl v1,r30,r22 ; Restore VR1
2144 la r20,savevr8(r14) ; Point to line 4
2145 bf 6,lnol3 ; No line 3 to do...
2146 dcbt br0,r21 ; Touch cache line 3
2149 la r22,savevr4(r14) ; Point to V4/V5 pair
2150 bf 18,lnovr2 ; Do not restore VR2...
2151 lvxl v2,br0,r23 ; Restore VR2
2154 bf 19,lnovr3 ; Do not restore VR3...
2155 lvxl v3,r30,r23 ; Restore VR3
2159 ; Note: CR4 is now free
2161 la r21,savevr10(r14) ; Point to line 5
2162 bf 8,lnol4 ; No line 4 to do...
2163 dcbt br0,r20 ; Touch cache line 4
2166 la r23,savevr6(r14) ; Point to R6/R7 pair
2167 bf 20,lnovr4 ; Do not restore VR4...
2168 lvxl v4,br0,r22 ; Restore VR4
2171 bf 21,lnovr5 ; Do not restore VR5...
2172 lvxl v5,r30,r22 ; Restore VR5
2175 mtcrf 0x08,r10 ; Set CRs for registers 16-19
2176 la r20,savevr12(r14) ; Point to line 6
2177 bf 10,lnol5 ; No line 5 to do...
2178 dcbt br0,r21 ; Touch cache line 5
2181 la r22,savevr8(r14) ; Point to V8/V9 pair
2182 bf 22,lnovr6 ; Do not restore VR6...
2183 lvxl v6,br0,r23 ; Restore VR6
2186 bf 23,lnovr7 ; Do not restore VR7...
2187 lvxl v7,r30,r23 ; Restore VR7
2191 ; Note: CR5 is now free
2193 la r21,savevr14(r14) ; Point to line 7
2194 bf 12,lnol6 ; No line 6 to do...
2195 dcbt br0,r20 ; Touch cache line 6
2198 la r23,savevr10(r14) ; Point to V10/V11 pair
2199 bf 24,lnovr8 ; Do not restore VR8...
2200 lvxl v8,br0,r22 ; Restore VR8
2203 bf 25,lnovr9 ; Do not save VR9...
2204 lvxl v9,r30,r22 ; Restore VR9
2207 mtcrf 0x04,r10 ; Set CRs for registers 20-23
2208 la r20,savevr16(r14) ; Point to line 8
2209 bf 14,lnol7 ; No line 7 to do...
2210 dcbt br0,r21 ; Touch cache line 7
2213 la r22,savevr12(r14) ; Point to V12/V13 pair
2214 bf 26,lnovr10 ; Do not restore VR10...
2215 lvxl v10,br0,r23 ; Restore VR10
2218 bf 27,lnovr11 ; Do not restore VR11...
2219 lvxl v11,r30,r23 ; Restore VR11
2224 ; Note: CR6 is now free
2226 la r21,savevr18(r14) ; Point to line 9
2227 bf 1,lnol8 ; No line 8 to do...
2228 dcbt br0,r20 ; Touch cache line 8
2231 la r23,savevr14(r14) ; Point to V14/V15 pair
2232 bf 28,lnovr12 ; Do not restore VR12...
2233 lvxl v12,br0,r22 ; Restore VR12
2236 bf 29,lnovr13 ; Do not restore VR13...
2237 lvxl v13,r30,r22 ; Restore VR13
2240 mtcrf 0x02,r10 ; Set CRs for registers 24-27
2241 la r20,savevr20(r14) ; Point to line 10
2242 bf 3,lnol9 ; No line 9 to do...
2243 dcbt br0,r21 ; Touch cache line 9
2246 la r22,savevr16(r14) ; Point to V16/V17 pair
2247 bf 30,lnovr14 ; Do not restore VR14...
2248 lvxl v14,br0,r23 ; Restore VR14
2251 bf 31,lnovr15 ; Do not restore VR15...
2252 lvxl v15,r30,r23 ; Restore VR15
2256 ; Note: CR7 is now free
2258 la r21,savevr22(r14) ; Point to line 11
2259 bf 5,lnol10 ; No line 10 to do...
2260 dcbt br0,r20 ; Touch cache line 10
2263 la r23,savevr18(r14) ; Point to V18/V19 pair
2264 bf 16,lnovr16 ; Do not restore VR16...
2265 lvxl v16,br0,r22 ; Restore VR16
2268 bf 17,lnovr17 ; Do not restore VR17...
2269 lvxl v17,r30,r22 ; Restore VR17
2272 mtcrf 0x01,r10 ; Set CRs for registers 28-31
2274 ; Note: All registers have been or are accounted for in CRs
2276 la r20,savevr24(r14) ; Point to line 12
2277 bf 7,lnol11 ; No line 11 to do...
2278 dcbt br0,r21 ; Touch cache line 11
2281 la r22,savevr20(r14) ; Point to V20/V21 pair
2282 bf 18,lnovr18 ; Do not restore VR18...
2283 lvxl v18,br0,r23 ; Restore VR18
2286 bf 19,lnovr19 ; Do not restore VR19...
2287 lvxl v19,r30,r23 ; Restore VR19
2290 la r21,savevr26(r14) ; Point to line 13
2291 bf 9,lnol12 ; No line 12 to do...
2292 dcbt br0,r20 ; Touch cache line 12
2295 la r23,savevr22(r14) ; Point to V22/V23 pair
2296 bf 20,lnovr20 ; Do not restore VR20...
2297 lvxl v20,br0,r22 ; Restore VR20
2300 bf 21,lnovr21 ; Do not restore VR21...
2301 lvxl v21,r30,r22 ; Restore VR21
2304 la r20,savevr28(r14) ; Point to line 14
2305 bf 11,lnol13 ; No line 13 to do...
2306 dcbt br0,r21 ; Touch cache line 13
2309 la r22,savevr24(r14) ; Point to V24/V25 pair
2310 bf 22,lnovr22 ; Do not restore VR22...
2311 lvxl v22,br0,r23 ; Restore VR22
2314 bf 23,lnovr23 ; Do not restore VR23...
2315 lvxl v23,r30,r23 ; Restore VR23
2318 la r21,savevr30(r14) ; Point to line 15
2319 bf 13,lnol14 ; No line 14 to do...
2320 dcbt br0,r20 ; Touch cache line 14
2323 la r23,savevr26(r14) ; Point to V26/V27 pair
2324 bf 24,lnovr24 ; Do not restore VR24...
2325 lvxl v24,br0,r22 ; Restore VR24
2328 bf 25,lnovr25 ; Do not restore VR25...
2329 lvxl v25,r30,r22 ; Restore VR25
2332 bf 15,lnol15 ; No line 15 to do...
2333 dcbt br0,r21 ; Touch cache line 15
2337 ; Note: All needed cache lines have been touched now
2339 la r22,savevr28(r14) ; Point to V28/V29 pair
2340 bf 26,lnovr26 ; Do not restore VR26...
2341 lvxl v26,br0,r23 ; Restore VR26
2344 bf 27,lnovr27 ; Do not restore VR27...
2345 lvxl v27,r30,r23 ; Restore VR27
2348 la r23,savevr30(r14) ; Point to V30/V31 pair
2349 bf 28,lnovr28 ; Do not restore VR28...
2350 lvxl v28,br0,r22 ; Restore VR28
2353 bf 29,lnovr29 ; Do not restore VR29...
2354 lvxl v29,r30,r22 ; Restore VR29
2357 bf 30,lnovr30 ; Do not restore VR30...
2358 lvxl v30,br0,r23 ; Restore VR30
2362 ; Everything is restored now except for VR31. We need it to get
2363 ; the QNaNBarbarian value to put into idle vector registers
2366 lis r5,hi16(EXT(QNaNbarbarian)) ; Get address of empty value
2367 cmpwi r10,-1 ; Handle the quick case of all registers in use
2368 ori r5,r5,lo16(EXT(QNaNbarbarian)) ; Get low address of empty value
2369 beq- mstlvr31 ; Not likely, but all are in use...
2370 mtcrf 255,r10 ; Get mask of valid registers
2371 lvxl v31,br0,r5 ; Initialize VR31 to the empty value
2373 bt 0,ni0 ; Register is ok already...
2374 vor v0,v31,v31 ; Copy into the next register
2376 bt 1,ni1 ; Register is ok already...
2377 vor v1,v31,v31 ; Copy into the next register
2379 bt 2,ni2 ; Register is ok already...
2380 vor v2,v31,v31 ; Copy into the next register
2382 bt 3,ni3 ; Register is ok already...
2383 vor v3,v31,v31 ; Copy into the next register
2385 bt 4,ni4 ; Register is ok already...
2386 vor v4,v31,v31 ; Copy into the next register
2388 bt 5,ni5 ; Register is ok already...
2389 vor v5,v31,v31 ; Copy into the next register
2391 bt 6,ni6 ; Register is ok already...
2392 vor v6,v31,v31 ; Copy into the next register
2394 bt 7,ni7 ; Register is ok already...
2395 vor v7,v31,v31 ; Copy into the next register
2397 bt 8,ni8 ; Register is ok already...
2398 vor v8,v31,v31 ; Copy into the next register
2400 bt 9,ni9 ; Register is ok already...
2401 vor v9,v31,v31 ; Copy into the next register
2403 bt 10,ni10 ; Register is ok already...
2404 vor v10,v31,v31 ; Copy into the next register
2406 bt 11,ni11 ; Register is ok already...
2407 vor v11,v31,v31 ; Copy into the next register
2409 bt 12,ni12 ; Register is ok already...
2410 vor v12,v31,v31 ; Copy into the next register
2412 bt 13,ni13 ; Register is ok already...
2413 vor v13,v31,v31 ; Copy into the next register
2415 bt 14,ni14 ; Register is ok already...
2416 vor v14,v31,v31 ; Copy into the next register
2418 bt 15,ni15 ; Register is ok already...
2419 vor v15,v31,v31 ; Copy into the next register
2421 bt 16,ni16 ; Register is ok already...
2422 vor v16,v31,v31 ; Copy into the next register
2424 bt 17,ni17 ; Register is ok already...
2425 vor v17,v31,v31 ; Copy into the next register
2427 bt 18,ni18 ; Register is ok already...
2428 vor v18,v31,v31 ; Copy into the next register
2430 bt 19,ni19 ; Register is ok already...
2431 vor v19,v31,v31 ; Copy into the next register
2433 bt 20,ni20 ; Register is ok already...
2434 vor v20,v31,v31 ; Copy into the next register
2436 bt 21,ni21 ; Register is ok already...
2437 vor v21,v31,v31 ; Copy into the next register
2439 bt 22,ni22 ; Register is ok already...
2440 vor v22,v31,v31 ; Copy into the next register
2442 bt 23,ni23 ; Register is ok already...
2443 vor v23,v31,v31 ; Copy into the next register
2445 bt 24,ni24 ; Register is ok already...
2446 vor v24,v31,v31 ; Copy into the next register
2448 bt 25,ni25 ; Register is ok already...
2449 vor v25,v31,v31 ; Copy into the next register
2451 bt 26,ni26 ; Register is ok already...
2452 vor v26,v31,v31 ; Copy into the next register
2454 bt 27,ni27 ; Register is ok already...
2455 vor v27,v31,v31 ; Copy into the next register
2457 bt 28,ni28 ; Register is ok already...
2458 vor v28,v31,v31 ; Copy into the next register
2460 bt 29,ni29 ; Register is ok already...
2461 vor v29,v31,v31 ; Copy into the next register
2463 bt 30,ni30 ; Register is ok already...
2464 vor v30,v31,v31 ; Copy into the next register
2466 bf 31,lnovr31 ; R31 is empty, no need to restore...
2468 mstlvr31: lvxl v31,r30,r23 ; Restore VR31
2473 lwz r9,SAVflags(r4) /* Get the flags of the current savearea */
2474 lwz r8,savesrr1(r4) ; Get the msr of the interrupted guy
2475 rlwinm r5,r4,0,0,19 /* Get the page address of the savearea */
2476 oris r8,r8,hi16(MASK(MSR_VEC)) ; Enable the vector facility
2477 lwz r10,ACT_MACT_SPF(r17) ; Get the special flags
2478 lis r7,hi16(SAVattach) /* Get the attached flag */
2479 lwz r5,SACvrswap(r5) /* Get Virtual to Real translation */
2480 oris r10,r10,hi16(vectorUsed|vectorCng) ; Set that we used vectors
2481 mr. r15,r15 ; See if we are doing this for user state
2482 stw r8,savesrr1(r4) ; Set the msr of the interrupted guy
2483 andc r9,r9,r7 /* Clear the attached bit */
2484 xor r3,r4,r5 /* Get the real address of the savearea */
2485 stw r9,SAVflags(r4) /* Set the flags of the current savearea */
2486 bne- vrnuser ; We are not user state...
2487 stw r10,ACT_MACT_SPF(r17) ; Set the activation copy
2488 stw r10,spcFlags(r6) ; Set per_proc copy
2492 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
2493 li r2,0x5F0A ; (TEST/DEBUG)
2494 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
2497 mr r8,r3 ; Save this
2498 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
2499 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
2500 mr r4,r2 ; Set value
2501 mtlr r3 ; Set link register
2502 li r3,1 ; Display address
2504 mr r3,r8 ; Restore it
2507 b EXT(exception_exit) /* Exit from the fray... */
2510 * Initialize the registers to some bogus value
2511 * We make sure that non-Java mode is the default here
2514 ProtectTheAmericanWay:
2517 lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG)
2518 li r2,0x5F09 ; (TEST/DEBUG)
2519 oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG)
2522 lis r3,hi16(EXT(GratefulDeb)) ; Point to top of display
2523 mr r8,r4 ; Save this
2524 ori r3,r3,lo16(EXT(GratefulDeb)) ; Put in bottom part
2525 mr r4,r2 ; Set value
2526 mtlr r3 ; Set link register
2527 li r3,1 ; Display address
2529 mr r4,r8 ; Restore it
2532 lis r5,hi16(EXT(QNaNbarbarian)) ; Get address of empty value
2533 vspltish v1,1 ; Turn on the non-Java bit and saturate
2534 ori r5,r5,lo16(EXT(QNaNbarbarian)) ; Get low address of empty value
2535 vspltisw v2,1 ; Turn on the saturate bit
2536 lvxl v0,br0,r5 ; Initialize VR0
2537 vxor v1,v1,v2 ; Turn off saturate
2539 vor v2,v0,v0 ; Copy into the next register
2540 mtvscr v1 ; Clear the vector status register
2541 vor v3,v0,v0 ; Copy into the next register
2542 vor v1,v0,v0 ; Copy into the next register
2543 vor v4,v0,v0 ; Copy into the next register
2544 vor v5,v0,v0 ; Copy into the next register
2545 vor v6,v0,v0 ; Copy into the next register
2546 vor v7,v0,v0 ; Copy into the next register
2547 vor v8,v0,v0 ; Copy into the next register
2548 vor v9,v0,v0 ; Copy into the next register
2549 vor v10,v0,v0 ; Copy into the next register
2550 vor v11,v0,v0 ; Copy into the next register
2551 vor v12,v0,v0 ; Copy into the next register
2552 vor v13,v0,v0 ; Copy into the next register
2553 vor v14,v0,v0 ; Copy into the next register
2554 vor v15,v0,v0 ; Copy into the next register
2555 vor v16,v0,v0 ; Copy into the next register
2556 vor v17,v0,v0 ; Copy into the next register
2557 vor v18,v0,v0 ; Copy into the next register
2558 vor v19,v0,v0 ; Copy into the next register
2559 vor v20,v0,v0 ; Copy into the next register
2560 vor v21,v0,v0 ; Copy into the next register
2561 vor v22,v0,v0 ; Copy into the next register
2562 vor v23,v0,v0 ; Copy into the next register
2563 vor v24,v0,v0 ; Copy into the next register
2564 vor v25,v0,v0 ; Copy into the next register
2565 vor v26,v0,v0 ; Copy into the next register
2566 vor v27,v0,v0 ; Copy into the next register
2567 vor v28,v0,v0 ; Copy into the next register
2568 vor v29,v0,v0 ; Copy into the next register
2569 vor v30,v0,v0 ; Copy into the next register
2570 vor v31,v0,v0 ; Copy into the next register
2571 b vrenable ; Finish setting it all up...
2574 ; Finds a unused vector area in the activation pointed
2575 ; to by R12s saved contexts. If none are found (unlikely but possible)
2576 ; and R3 is 0, a new area is allocated. If R3 is non-zero, it contains
2577 ; a pointer to a vector savearea that is free.
2580 vsrchsave: lwz r6,ACT_MACT_PCB(r12) ; Get the first "normal" savearea
2582 vsrnorm: mr. r5,r6 ; Is there another?
2583 beq- vsrvect ; No, search the floating point saveareas...
2584 lwz r7,SAVflags(r5) ; Get the flags for this guy
2585 lwz r6,SAVprev(r5) ; Get the previous savearea, just in case
2586 andis. r8,r7,hi16(SAVvmxvalid) ; Have we found an empty vector save in normal?
2587 beq+ vsrgot ; We found one...
2588 b vsrnorm ; Search again...
2590 vsrvect: lwz r6,ACT_MACT_FPU(r12) ; Get the first "floating point" savearea
2592 vsrvectx: mr. r5,r6 ; Is there another?
2593 beq- vsrget ; No, try to allocate one...
2594 lwz r7,SAVflags(r5) ; Get the flags for this guy
2595 lwz r6,SAVprefp(r5) ; Get the previous savearea, just in case
2596 andis. r8,r7,hi16(SAVvmxvalid) ; Have we found an empty vector save in float?
2597 bne- vsrvectx ; Search again...
2599 vsrgot: mr r3,r5 ; Get the savearea into the right register
2602 vsrget: mr. r5,r3 ; Do we allocate or use existing?
2603 beq+ vsrallo ; Allocate one...
2605 lwz r7,SAVflags(r3) ; Get the passed in area flags
2608 ; NOTE: save_get will return directly and set R7 to 0...
2610 vsrallo: b EXT(save_get) ; Get a fresh savearea
2614 * void lfs(fpsp,fpdp)
2616 * load the single precision float to the double
2618 * This routine is used by the alignment handler.
2621 ENTRY(lfs, TAG_NO_FRAME_USED)
2627 * fpsp stfs(fpdp,fpsp)
2629 * store the double precision float to the single
2631 * This routine is used by the alignment handler.
2634 ENTRY(stfs, TAG_NO_FRAME_USED)