|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.