Annotation of kernel/machdep/ppc/lowmem_vectors.s, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:  * Low-memory exception vector code for PowerPC MACH
        !            27:  *
        !            28:  * These are the only routines that are ever run with
        !            29:  * VM instruction translation switched off.
        !            30:  *
        !            31:  * The PowerPC is quite strange in that rather than having a set
        !            32:  * of exception vectors, the exception handlers are installed
        !            33:  * in well-known addresses in low memory. This code must be loaded
        !            34:  * at ZERO in physical memory. We do this by putting this code
        !            35:  * into a special segment (__VECTORS) and giving the segment
        !            36:  * a -segaddr of zero in the 'ld' command line.
        !            37:  *
        !            38:  * When this code is loaded into memory, it is loaded at physical
        !            39:  * address zero.
        !            40:  *
        !            41:  * This code handles all powerpc exceptions and is always entered
        !            42:  * in supervisor mode with translation off. It saves the minimum
        !            43:  * processor state before switching back on translation and
        !            44:  * jumping to the approprate routine.
        !            45:  *
        !            46:  * Vectors from 0x100 to 0x2fff occupy 0x100 bytes each (64 instructions)
        !            47:  *
        !            48:  * We use some of this space to decide which stack to use, and where to
        !            49:  * save the context etc, before        jumping to a generic handler.
        !            50:  */
        !            51: 
        !            52: #include <assym.h>
        !            53: #include <debug.h>
        !            54: #include <cpus.h>
        !            55:        
        !            56: #include <mach_debug.h>
        !            57: #include <machdep/ppc/asm.h>
        !            58: #include <machdep/ppc/proc_reg.h>
        !            59: #include <machdep/ppc/exception.h>
        !            60: #include <mach/ppc/vm_param.h>
        !            61: #include <machdep/ppc/nkdefs.h>
        !            62: #include <ppc/pcb_flags.h>
        !            63: 
        !            64: /*     Kernel origin point. Keep this in sync with the makefiles!
        !            65:        See MASTER.ppc and MAKEFILE.ppc!
        !            66: */
        !            67: #define        RELOC   0x10000
        !            68: 
        !            69: /*
        !            70:  * Define a couple of macros to make the Handler macro simpler
        !            71:  */
        !            72: #if    __STDC__
        !            73: #define        LHL(x)  LCL(_handler ## x)
        !            74: #define        LOC(y)  0x ## y
        !            75: #else /* __STDC__ */
        !            76: #define        LHL(x)  LCL(_handler/**/x)
        !            77: #define        LOC(y)  0x/**/y
        !            78: #endif /* __STDC__ */
        !            79: 
        !            80: /*
        !            81:  * Almost all handlers do exactly the same thing:
        !            82:  *     save r1-r3 into sprg1-3
        !            83:  *     load r3 with a value indicating which trap
        !            84:  *     load r2 with the per-processor save area pointer
        !            85:  *     branch to the generic entry code.
        !            86:  */
        !            87: #define        HANDLER2(a,v,l) LHL(a):                 @ \
        !            88:                        . = LOC(a)              @ \
        !            89:                        mtsprg  3,      r3      @ \
        !            90:                        mtsprg  2,      r2      @ \
        !            91:                        li      r3,     v       @ \
        !            92:                        mtsprg  1,      r1      @ \
        !            93:                        mfsprg  r2,     0       @ \
        !            94:                        b       LCL(l)
        !            95: 
        !            96: #define        HANDLER(a,v)    HANDLER2(a, v, _exception_entry)
        !            97:        
        !            98:        
        !            99: 
        !           100: 
        !           101: /*
        !           102:  * Here are the vectors
        !           103:  */
        !           104:        .section __VECTORS, __interrupts
        !           105:        .align  2
        !           106: 
        !           107:        .globl _ExceptionVectorsStart
        !           108: _ExceptionVectorsStart:        /* Used if relocating the exception vectors */
        !           109: 
        !           110: 
        !           111: /* 
        !           112:  * System reset - call debugger
        !           113:  */
        !           114: HANDLER(100, EXC_RESET)
        !           115: 
        !           116: 
        !           117: /*
        !           118:  * Machine check (physical bus error) - call debugger
        !           119:  */
        !           120: HANDLER(200, EXC_MACHINE_CHECK)
        !           121: 
        !           122: 
        !           123: /*
        !           124:  * Data access - page fault, invalid memory rights for operation
        !           125:  */
        !           126: HANDLER2(300, EXC_DATA_ACCESS, _MMU)
        !           127: 
        !           128: 
        !           129: /*
        !           130:  * Instruction access - as for data access
        !           131:  */
        !           132: HANDLER2(400,EXC_INSTRUCTION_ACCESS, _MMU)
        !           133: 
        !           134: 
        !           135: /*
        !           136:  * External interrupt
        !           137:  */
        !           138: HANDLER(500,EXC_INTERRUPT)
        !           139: 
        !           140: 
        !           141: /*
        !           142:  * Alignment - many reasons
        !           143:  */
        !           144: HANDLER(600,EXC_ALIGNMENT)
        !           145: 
        !           146: 
        !           147: /*
        !           148:  * Program - floating point exception, illegal inst, priv inst, user trap
        !           149:  */
        !           150: HANDLER2(700, EXC_PROGRAM, _BLUE_FAST_TRAP)
        !           151: 
        !           152: 
        !           153: /*
        !           154:  * Program - floating point disabled, illegal inst, priv inst, user trap
        !           155:  */
        !           156: HANDLER(800,EXC_FP_UNAVAILABLE)
        !           157: 
        !           158: 
        !           159: /*
        !           160:  * Decrementer - DEC register has passed zero.
        !           161:  */
        !           162: HANDLER(900,EXC_DECREMENTER)
        !           163: 
        !           164: 
        !           165: /*
        !           166:  * I/O controller interface error - MACH does not use this
        !           167:  * (601 only)
        !           168:  */
        !           169: HANDLER(a00,EXC_IO_ERROR)
        !           170: 
        !           171: 
        !           172: /*
        !           173:  * Reserved
        !           174:  */
        !           175: HANDLER(b00,EXC_RESERVED_0B)
        !           176: 
        !           177: 
        !           178: /*
        !           179:  * System call - generated by the sc instruction
        !           180:  */
        !           181: HANDLER(c00,EXC_SYSTEM_CALL)
        !           182: 
        !           183: 
        !           184: /*
        !           185:  * Trace - generated by single stepping
        !           186:  * (603, 603e and 604)
        !           187:  */
        !           188: HANDLER(d00,EXC_TRACE)
        !           189: 
        !           190: 
        !           191: /*
        !           192:  * Floating point assist
        !           193:  */
        !           194: HANDLER(e00,EXC_FP_ASSIST)
        !           195: 
        !           196: 
        !           197: /*
        !           198:  * Performance monitoring interrupt (Not implemented yet)
        !           199:  * (604)
        !           200:  */
        !           201: HANDLER(f00,EXC_PERFORMANCE_MON)
        !           202: 
        !           203: 
        !           204: /*
        !           205:  * Instruction translation miss - we inline this code.
        !           206:  * (603, 603e only)
        !           207:  *
        !           208:  * Upon entry (done for us by the machine):
        !           209:  *     srr0 :   addr of instruction that missed
        !           210:  *     srr1 :   bits 0-3   = saved CR0
        !           211:  *                    4     = lru way bit
        !           212:  *                    16-31 = saved msr
        !           213:  *     msr[tgpr] = 1  (so gpr0-3 become our temporary variables)
        !           214:  *     imiss:   ea that missed
        !           215:  *     icmp :   the compare value for the va that missed
        !           216:  *     hash1:   pointer to first hash pteg
        !           217:  *     hash2:   pointer to 2nd hash pteg
        !           218:  *
        !           219:  * Register usage:
        !           220:  *     tmp0:    saved counter
        !           221:  *     tmp1:    junk
        !           222:  *     tmp2:    pointer to pteg
        !           223:  *     tmp3:    current compare value
        !           224:  *
        !           225:  * This code is taken from the 603e User's Manual with
        !           226:  * some bugfixes and minor improvements to save bytes and cycles
        !           227:  */
        !           228: 
        !           229: L_handler1000:
        !           230:        . = 0x1000
        !           231: 
        !           232:        mfspr   tmp2,   hash1
        !           233:        mfctr   tmp0                            /* use tmp0 to save ctr */
        !           234:        mfspr   tmp3,   icmp
        !           235: 
        !           236: .L_imiss_find_pte_in_pteg:
        !           237:        li      tmp1,   8                       /* count */
        !           238:        subi    tmp2,   tmp2,   8               /* offset for lwzu */
        !           239:        mtctr   tmp1                            /* count... */
        !           240:        
        !           241: .L_imiss_pteg_loop:
        !           242:        lwz     tmp1,   8(tmp2)                 /* check pte0 for match... */
        !           243:        addi    tmp2,   tmp2,   8
        !           244:        cmpw    CR0,    tmp1,   tmp3
        !           245: #if 0
        !           246:        bdnzf+  CR0+lt, .L_imiss_pteg_loop
        !           247: #else
        !           248:        bc      0, 2,   .L_imiss_pteg_loop
        !           249: #endif
        !           250:        beq+    CR0,    .L_imiss_found_pte
        !           251: 
        !           252:        /* Not found in PTEG, we must scan 2nd then give up */
        !           253: 
        !           254:        andi.   tmp1,   tmp3,   MASK(PTE0_HASH_ID)
        !           255:        bne-    .L_imiss_do_no_hash_exception           /* give up */
        !           256: 
        !           257:        mfspr   tmp2,   hash2
        !           258:        ori     tmp3,   tmp3,   MASK(PTE0_HASH_ID)
        !           259:        b       .L_imiss_find_pte_in_pteg
        !           260: 
        !           261: .L_imiss_found_pte:
        !           262: 
        !           263:        lwz     tmp1,   4(tmp2)                         /* get pte1_t */
        !           264:        andi.   tmp3,   tmp1,   MASK(PTE1_WIMG_GUARD)   /* Fault? */
        !           265:        bne-    .L_imiss_do_prot_exception              /* Guarded - illegal */
        !           266: 
        !           267:        /* Ok, we've found what we need to, restore and rfi! */
        !           268: 
        !           269:        mtctr   tmp0                                    /* restore ctr */
        !           270:        mfsrr1  tmp3
        !           271:        mfspr   tmp0,   imiss
        !           272:        mtcrf   0x80,   tmp3                            /* Restore CR0 */
        !           273:        mtspr   rpa,    tmp1                            /* set the pte */
        !           274:        ori     tmp1,   tmp1,   MASK(PTE1_REFERENCED)   /* set referenced */
        !           275:        tlbli   tmp0
        !           276:        sth     tmp1,   6(tmp2)
        !           277:        rfi
        !           278:        
        !           279: .L_imiss_do_prot_exception:
        !           280:        /* set up srr1 to indicate protection exception... */
        !           281:        mfsrr1  tmp3
        !           282:        andi.   tmp2,   tmp3,   0xffff
        !           283:        addis   tmp2,   tmp2,   MASK(SRR1_TRANS_PROT) >> 16
        !           284:        b       .L_imiss_do_exception
        !           285:        
        !           286: .L_imiss_do_no_hash_exception:
        !           287:        /* clean up registers for protection exception... */
        !           288:        mfsrr1  tmp3
        !           289:        andi.   tmp2,   tmp3,   0xffff
        !           290:        addis   tmp2,   tmp2,   MASK(SRR1_TRANS_HASH) >> 16
        !           291:        
        !           292:        /* And the entry into the usual instruction fault handler ... */
        !           293: .L_imiss_do_exception:
        !           294: 
        !           295:        mtctr   tmp0                                    /* Restore ctr */
        !           296:        mtsrr1  tmp2                                    /* Set up srr1 */
        !           297:        mfmsr   tmp0                                    
        !           298:        xoris   tmp0,   tmp0,   MASK(MSR_TGPR)>>16      /* no TGPR */
        !           299:        mtcrf   0x80,   tmp3                            /* Restore CR0 */
        !           300:        mtmsr   tmp0                                    /* reset MSR[TGPR] */
        !           301:        ba      0x400                                   /* Instr Access */
        !           302:        
        !           303: /*
        !           304:  * Data load translation miss
        !           305:  * (603, 603e only)
        !           306:  *
        !           307:  * Upon entry (done for us by the machine):
        !           308:  *     srr0 :   addr of instruction that missed
        !           309:  *     srr1 :   bits 0-3   = saved CR0
        !           310:  *                    4     = lru way bit
        !           311:  *                    5     = 1 if store
        !           312:  *                    16-31 = saved msr
        !           313:  *     msr[tgpr] = 1  (so gpr0-3 become our temporary variables)
        !           314:  *     dmiss:   ea that missed
        !           315:  *     dcmp :   the compare value for the va that missed
        !           316:  *     hash1:   pointer to first hash pteg
        !           317:  *     hash2:   pointer to 2nd hash pteg
        !           318:  *
        !           319:  * Register usage:
        !           320:  *     tmp0:    saved counter
        !           321:  *     tmp1:    junk
        !           322:  *     tmp2:    pointer to pteg
        !           323:  *     tmp3:    current compare value
        !           324:  *
        !           325:  * This code is taken from the 603e User's Manual with
        !           326:  * some bugfixes and minor improvements to save bytes and cycles
        !           327:  */
        !           328: 
        !           329: L_handler1100:
        !           330:        . = 0x1100
        !           331: 
        !           332:        mfspr   tmp2,   hash1
        !           333:        mfctr   tmp0                            /* use tmp0 to save ctr */
        !           334:        mfspr   tmp3,   dcmp
        !           335: 
        !           336: .L_dlmiss_find_pte_in_pteg:
        !           337:        li      tmp1,   8                       /* count */
        !           338:        subi    tmp2,   tmp2,   8               /* offset for lwzu */
        !           339:        mtctr   tmp1                            /* count... */
        !           340:        
        !           341: .L_dlmiss_pteg_loop:
        !           342:        lwz     tmp1,   8(tmp2)                 /* check pte0 for match... */
        !           343:        addi    tmp2,   tmp2,   8
        !           344:        cmpw    CR0,    tmp1,   tmp3
        !           345: #if 0
        !           346:        bdnzf+  CR0+lt, .L_dlmiss_pteg_loop
        !           347: #else
        !           348:        bc      0,2,    .L_dlmiss_pteg_loop
        !           349: #endif
        !           350:        beq+    CR0,    .L_dmiss_found_pte
        !           351: 
        !           352:        /* Not found in PTEG, we must scan 2nd then give up */
        !           353: 
        !           354:        andi.   tmp1,   tmp3,   MASK(PTE0_HASH_ID)      /* already at 2nd? */
        !           355:        bne-    .L_dmiss_do_no_hash_exception           /* give up */
        !           356: 
        !           357:        mfspr   tmp2,   hash2
        !           358:        ori     tmp3,   tmp3,   MASK(PTE0_HASH_ID)
        !           359:        b       .L_dlmiss_find_pte_in_pteg
        !           360: 
        !           361: .L_dmiss_found_pte:
        !           362: 
        !           363:        lwz     tmp1,   4(tmp2)                         /* get pte1_t */
        !           364: 
        !           365:        /* Ok, we've found what we need to, restore and rfi! */
        !           366: 
        !           367:        mtctr   tmp0                                    /* restore ctr */
        !           368:        mfsrr1  tmp3
        !           369:        mfspr   tmp0,   dmiss
        !           370:        mtcrf   0x80,   tmp3                            /* Restore CR0 */
        !           371:        mtspr   rpa,    tmp1                            /* set the pte */
        !           372:        ori     tmp1,   tmp1,   MASK(PTE1_REFERENCED)   /* set referenced */
        !           373:        tlbld   tmp0                                    /* load up tlb */
        !           374:        sth     tmp1,   6(tmp2)                         /* sth is faster? */
        !           375:        rfi
        !           376:        
        !           377:        /* This code is shared with data store translation miss */
        !           378:        
        !           379: .L_dmiss_do_no_hash_exception:
        !           380:        /* clean up registers for protection exception... */
        !           381:        mfsrr1  tmp3
        !           382:        /* prepare to set DSISR_WRITE_BIT correctly from srr1 info */
        !           383:        rlwinm  tmp1,   tmp3,   9,      6,      6
        !           384:        addis   tmp1,   tmp1,   MASK(SRR1_TRANS_NO_PTE) >> 16
        !           385: 
        !           386:        /* And the entry into the usual data fault handler ... */
        !           387: 
        !           388:        mtctr   tmp0                                    /* Restore ctr */
        !           389:        andi.   tmp2,   tmp3,   0xffff                  /* Clean up srr1 */
        !           390:        mtsrr1  tmp2                                    /* Set srr1 */
        !           391:        mtdsisr tmp1
        !           392:        mfspr   tmp2,   dmiss
        !           393:        mtdar   tmp2
        !           394:        mfmsr   tmp0
        !           395:        xoris   tmp0,   tmp0,   MASK(MSR_TGPR)>>16      /* no TGPR */
        !           396:        mtcrf   0x80,   tmp3                            /* Restore CR0 */
        !           397:        sync
        !           398:        mtmsr   tmp0                                    /* reset MSR[TGPR] */
        !           399:        ba      0x300                                   /* Data Access */
        !           400:        
        !           401: /*
        !           402:  * Data store translation miss (similar to data load)
        !           403:  * (603, 603e only)
        !           404:  *
        !           405:  * Upon entry (done for us by the machine):
        !           406:  *     srr0 :   addr of instruction that missed
        !           407:  *     srr1 :   bits 0-3   = saved CR0
        !           408:  *                    4     = lru way bit
        !           409:  *                    5     = 1 if store
        !           410:  *                    16-31 = saved msr
        !           411:  *     msr[tgpr] = 1  (so gpr0-3 become our temporary variables)
        !           412:  *     dmiss:   ea that missed
        !           413:  *     dcmp :   the compare value for the va that missed
        !           414:  *     hash1:   pointer to first hash pteg
        !           415:  *     hash2:   pointer to 2nd hash pteg
        !           416:  *
        !           417:  * Register usage:
        !           418:  *     tmp0:    saved counter
        !           419:  *     tmp1:    junk
        !           420:  *     tmp2:    pointer to pteg
        !           421:  *     tmp3:    current compare value
        !           422:  *
        !           423:  * This code is taken from the 603e User's Manual with
        !           424:  * some bugfixes and minor improvements to save bytes and cycles
        !           425:  */
        !           426: 
        !           427: L_handler1200:
        !           428:        . = 0x1200
        !           429: 
        !           430:        mfspr   tmp2,   hash1
        !           431:        mfctr   tmp0                            /* use tmp0 to save ctr */
        !           432:        mfspr   tmp3,   dcmp
        !           433: 
        !           434: .L_dsmiss_find_pte_in_pteg:
        !           435:        li      tmp1,   8                       /* count */
        !           436:        subi    tmp2,   tmp2,   8               /* offset for lwzu */
        !           437:        mtctr   tmp1                            /* count... */
        !           438:        
        !           439: .L_dsmiss_pteg_loop:
        !           440:        lwz     tmp1,   8(tmp2)                 /* check pte0 for match... */
        !           441:        addi    tmp2,   tmp2,   8
        !           442:        cmpw    CR0,    tmp1,   tmp3
        !           443: #if 0
        !           444:        bdnzf+  CR0+lt, .L_dsmiss_pteg_loop
        !           445: #else
        !           446:        bc      0,2,    .L_dsmiss_pteg_loop
        !           447: #endif
        !           448:        beq+    CR0,    .L_dsmiss_found_pte
        !           449: 
        !           450:        /* Not found in PTEG, we must scan 2nd then give up */
        !           451: 
        !           452:        andi.   tmp1,   tmp3,   MASK(PTE0_HASH_ID)      /* already at 2nd? */
        !           453:        bne-    .L_dmiss_do_no_hash_exception           /* give up */
        !           454: 
        !           455:        mfspr   tmp2,   hash2
        !           456:        ori     tmp3,   tmp3,   MASK(PTE0_HASH_ID)
        !           457:        b       .L_dsmiss_find_pte_in_pteg
        !           458: 
        !           459: .L_dsmiss_found_pte:
        !           460: 
        !           461:        lwz     tmp1,   4(tmp2)                         /* get pte1_t */
        !           462:        andi.   tmp3,   tmp1,   MASK(PTE1_CHANGED)      /* unchanged, check? */
        !           463:        beq-    .L_dsmiss_check_prot                    /* yes, check prot */
        !           464: 
        !           465: .L_dsmiss_resolved:
        !           466:        /* Ok, we've found what we need to, restore and rfi! */
        !           467: 
        !           468:        mtctr   tmp0                                    /* restore ctr */
        !           469:        mfsrr1  tmp3
        !           470:        mfspr   tmp0,   dmiss
        !           471:        mtcrf   0x80,   tmp3                            /* Restore CR0 */
        !           472:        mtspr   rpa,    tmp1                            /* set the pte */
        !           473:        tlbld   tmp0                                    /* load up tlb */
        !           474:        rfi
        !           475:        
        !           476: .L_dsmiss_check_prot:
        !           477:        /* PTE is unchanged, we must check that we can write */
        !           478:        rlwinm. tmp3,   tmp1,   30,     0,      1       /* check PP[1] */
        !           479:        bge-    .L_dsmiss_check_prot_user_kern
        !           480:        andi.   tmp3,   tmp1,   1                       /* check PP[0] */
        !           481:        beq+    .L_dsmiss_check_prot_ok
        !           482:        
        !           483: .L_dmiss_do_prot_exception:
        !           484:        /* clean up registers for protection exception... */
        !           485:        mfsrr1  tmp3
        !           486:        /* prepare to set DSISR_WRITE_BIT correctly from srr1 info */
        !           487:        rlwinm  tmp1,   tmp3,   9,      6,      6
        !           488:        addis   tmp1,   tmp1,   MASK(SRR1_TRANS_NO_PTE) >> 16
        !           489: 
        !           490:        /* And the entry into the usual data fault handler ... */
        !           491:        mtctr   tmp0                                    /* Restore ctr */
        !           492:        andi.   tmp2,   tmp3,   0xffff                  /* Clean up srr1 */
        !           493:        mtsrr1  tmp2                                    /* Set srr1 */
        !           494:        mtdsisr tmp1
        !           495:        mfspr   tmp2,   dmiss
        !           496:        mtdar   tmp2
        !           497:        mfmsr   tmp0
        !           498:        xoris   tmp0,   tmp0,   MASK(MSR_TGPR)>>16      /* no TGPR */
        !           499:        mtcrf   0x80,   tmp3                            /* Restore CR0 */
        !           500:        sync
        !           501:        mtmsr   tmp0                                    /* reset MSR[TGPR] */
        !           502:        ba      0x300                                   /* Data Access */
        !           503:        
        !           504: /* NB - if we knew we were on a 603e we could test just the MSR_KEY bit */
        !           505: .L_dsmiss_check_prot_user_kern:
        !           506:        mfsrr1  tmp3
        !           507:        andi.   tmp3,   tmp3,   MASK(MSR_PR)
        !           508:        beq+    .L_dsmiss_check_prot_kern
        !           509:        mfspr   tmp3,   dmiss                           /* check user privs */
        !           510:        mfsrin  tmp3,   tmp3                            /* get excepting SR */
        !           511:        andis.  tmp3,   tmp3,   0x2000                  /* Test SR ku bit */
        !           512:        beq+    .L_dsmiss_check_prot_ok
        !           513:        b       .L_dmiss_do_prot_exception
        !           514: 
        !           515: .L_dsmiss_check_prot_kern:
        !           516:        mfspr   tmp3,   dmiss                           /* check kern privs */
        !           517:        mfsrin  tmp3,   tmp3
        !           518:        andis.  tmp3,   tmp3,   0x4000                  /* Test SR Ks bit */
        !           519:        bne-    .L_dmiss_do_prot_exception
        !           520: 
        !           521: .L_dsmiss_check_prot_ok:
        !           522:        /* Ok, mark as referenced and changed before resolving the fault */
        !           523:        ori     tmp1,   tmp1,   (MASK(PTE1_REFERENCED)|MASK(PTE1_CHANGED))
        !           524:        sth     tmp1,   6(tmp2)
        !           525:        b       .L_dsmiss_resolved
        !           526:        
        !           527: /*
        !           528:  * Instruction address breakpoint
        !           529:  * (603, 603e and 604)
        !           530:  *
        !           531:  */
        !           532: HANDLER(1300,EXC_INSTRUCTION_BKPT)
        !           533: 
        !           534: 
        !           535: /*
        !           536:  * System management interrupt
        !           537:  * (603, 603e and 604)
        !           538:  */
        !           539: HANDLER(1400,EXC_SYSTEM_MANAGEMENT)
        !           540: 
        !           541: 
        !           542: /*
        !           543:  * There is now a large gap of reserved traps
        !           544:  */
        !           545: HANDLER(1500,EXC_RESERVED_15)
        !           546: HANDLER(1600,EXC_RESERVED_16)
        !           547: HANDLER(1700,EXC_RESERVED_17)
        !           548: HANDLER(1800,EXC_RESERVED_18)
        !           549: HANDLER(1900,EXC_RESERVED_19)
        !           550: HANDLER(1a00,EXC_RESERVED_1A)
        !           551: HANDLER(1b00,EXC_RESERVED_1B)
        !           552: HANDLER(1c00,EXC_RESERVED_1C)
        !           553: HANDLER(1d00,EXC_RESERVED_1D)
        !           554: HANDLER(1e00,EXC_RESERVED_1E)
        !           555: HANDLER(1f00,EXC_RESERVED_1F)
        !           556: 
        !           557: 
        !           558: /*
        !           559:  * Run mode/ trace exception - single stepping on 601 processors
        !           560:  * (601 only)
        !           561:  */
        !           562: HANDLER(2000,EXC_RUNMODE_TRACE)
        !           563: 
        !           564: 
        !           565: /*
        !           566:  * There is another large gap of reserved traps
        !           567:  */
        !           568: HANDLER(2100,EXC_RESERVED_21)
        !           569: HANDLER(2200,EXC_RESERVED_22)
        !           570: HANDLER(2300,EXC_RESERVED_23)
        !           571: HANDLER(2400,EXC_RESERVED_24)
        !           572: HANDLER(2500,EXC_RESERVED_25)
        !           573: HANDLER(2600,EXC_RESERVED_26)
        !           574: HANDLER(2700,EXC_RESERVED_27)
        !           575: HANDLER(2800,EXC_RESERVED_28)
        !           576: HANDLER(2900,EXC_RESERVED_29)
        !           577: HANDLER(2a00,EXC_RESERVED_2A)
        !           578: HANDLER(2b00,EXC_RESERVED_2B)
        !           579: HANDLER(2c00,EXC_RESERVED_2C)
        !           580: HANDLER(2d00,EXC_RESERVED_2D)
        !           581: HANDLER(2e00,EXC_RESERVED_2E)
        !           582: HANDLER(2f00,EXC_RESERVED_2F)
        !           583: 
        !           584: /* Remember that at 0x3000 is just past the end of the trap table */
        !           585:        . = 0x3000
        !           586: 
        !           587: 
        !           588: 
        !           589: 
        !           590: 
        !           591: /*
        !           592:  * L_exception_entry(type)
        !           593:  *
        !           594:  * This is the common exception handling routine called by any
        !           595:  * type of system exception. (except 603 translation miss exceptions)
        !           596:  *
        !           597:  * Entry:      via a system exception handler, thus interrupts off, VM off.
        !           598:  *              Entry r1-r3 have been saved in sprg1-3. 
        !           599:  *              r2 - byte offset into per_proc_info of this CPU
        !           600:  *             r3 - contains the exception number.
        !           601:  *
        !           602:  * Exit:       srr0 and srr1 saved in per_proc_info structure
        !           603:  *              r3 (supplied) saved in per_proc_info structure
        !           604:  *              cr            saved in per_proc_info structure
        !           605:  *              original r1-3 saved in sprg1-3.
        !           606:  *                 r1 - is scratch
        !           607:  *                 r2 - byte offset into per_proc_info of this CPU
        !           608:  *                 r3  -contains exception info as for entry
        !           609:  *
        !           610:  *              The exception handler is entered with
        !           611:  *              VM on, interrupts still switched off
        !           612:  */
        !           613: 
        !           614:                
        !           615: L_exception_entry:
        !           616: 
        !           617:        /* Save SRR0 and SRR1 plus cr and r3 into PER_PROC structure */
        !           618:        
        !           619:        stw     r3,     PP_SAVE_EXCEPTION_TYPE(r2)
        !           620:        mfsrr0  r1
        !           621:        mfsrr1  r3
        !           622:        stw     r1,     PP_SAVE_SRR0(r2)
        !           623:        stw     r3,     PP_SAVE_SRR1(r2)
        !           624:        mfdar   r1
        !           625:        mfdsisr r3
        !           626:        stw     r1,     PP_SAVE_DAR(r2)
        !           627:        stw     r3,     PP_SAVE_DSISR(r2)
        !           628:        mfcr    r1
        !           629:        stw     r1,     PP_SAVE_CR(r2)
        !           630:        
        !           631: .L_Common:
        !           632:        /* Remap the kernel using seg reg 0, and I/O via seg reg 5 */
        !           633: 
        !           634:        lis     r3,     (KERNEL_SEG_REG0_VALUE >> 16)
        !           635: #if PPC_SID_KERNEL != 0
        !           636:                /* if PPC_SID_KERNEL == 0, then bottom 16 bits are 0,
        !           637:                 * so save an instruction - big deal
        !           638:                 */
        !           639:        ori     r3,     r3,     (KERNEL_SEG_REG0_VALUE & 0xFFFF)
        !           640: #endif
        !           641:        mtsr    sr0,    r3              /* Kernel SR0 */
        !           642:        ori     r1,     r3,     1       /* Kernel SR1 */
        !           643:        mtsr    sr1,    r1
        !           644:        ori     r1,     r3,     2
        !           645:        mtsr    sr2,    r1
        !           646:        ori     r1,     r3,     3
        !           647:        mtsr    sr3,    r1
        !           648:                
        !           649:        /* jump into main handler code switching on VM at the same time */
        !           650: 
        !           651:        /* We assume kernel data is mapped contiguously in physical
        !           652:         * memory, otherwise we need to switch on (at least) virtual data.
        !           653:         */
        !           654:        lwz     r3,     PP_SAVE_EXCEPTION_TYPE(r2)
        !           655:        lwz     r1,     PP_PHYS_EXCEPTION_HANDLERS(r2)
        !           656:        lwzx    r1,     r1,     r3
        !           657:        lwz     r2,     PP_VIRT_PER_PROC(r2)
        !           658:        mtsrr0  r1
        !           659:                
        !           660:        li      r1,     MSR_SUPERVISOR_INT_OFF
        !           661:        mtsrr1  r1
        !           662:        rfi             /* into the exception handler with VM on */
        !           663: 
        !           664: 
        !           665: 
        !           666: 
        !           667: 
        !           668: 
        !           669: /*
        !           670:  * exception_exit(sr0,srr0,srr1)
        !           671:  *
        !           672:  * This is the trampoline code used when exiting into a foreign
        !           673:  * address space.
        !           674:  *
        !           675:  * NMGS TODO - can't we skip exception_exit by relying on translations
        !           676:  * NMGS TODO   even after we've loaded sr0? Docs aren't clear. Using
        !           677:  * NMGS TODO   1-1 kernel text mapping would definately avoid this need.
        !           678:  *
        !           679:  * Entry :      entry via rfi, MSR = MSR_VM_OFF
        !           680:  *               r1-3 saved in sprg1-3
        !           681:  *              r1 = user's sr0 - used to construct sr1 too
        !           682:  *               r2 = user's srr0 (instruction pointer)
        !           683:  *               r3 = user's srr1 (msr)
        !           684:  *
        !           685:  * Exit :       this routine restores the users' space and rfis.
        !           686:  */
        !           687:        
        !           688:        .data
        !           689:        .align  ALIGNMENT
        !           690:        .globl  EXT(exception_exit)
        !           691: EXT(exception_exit):
        !           692:        .long   exception_exit_fn       /* phys addr of fn */
        !           693: 
        !           694: 
        !           695:        .section __VECTORS, __interrupts
        !           696:        .align  2
        !           697:        
        !           698: exception_exit_fn:
        !           699: 
        !           700:        mtsrr0  r2
        !           701:        mtsrr1  r3
        !           702: 
        !           703:        mtsr    sr0,    r1              /* Restore user space SR0 */
        !           704:        ori     r2,     r1,     1
        !           705:        mtsr    sr1,    r2              /* Restore user space SR1 */
        !           706:        ori     r2,     r1,     2
        !           707:        mtsr    sr2,    r2
        !           708:        ori     r2,     r1,     3
        !           709:        mtsr    sr3,    r2
        !           710:                
        !           711:        mfsprg  r1,     1
        !           712:        mfsprg  r2,     2
        !           713:        mfsprg  r3,     3
        !           714:        rfi
        !           715: 
        !           716: 
        !           717: /*
        !           718: ** Blue Box Fast Trap entry
        !           719: **
        !           720: ** Entry:      VM switched OFF
        !           721: **             Interrupts OFF
        !           722: **             Data/Inst Relocation OFF
        !           723: **              r1-r3 have been saved in sprg1-3. 
        !           724: **              r2 - ptr to per_proc_info of this CPU
        !           725: **             r3 - contains the exception number.
        !           726: **
        !           727: **
        !           728: */
        !           729:        .align 5
        !           730: L_BLUE_FAST_TRAP:
        !           731:        mfcr    r1                      
        !           732:        stw     r1,     PP_SAVE_CR(r2)
        !           733:        /* Check for Trap program exception */
        !           734:        mfsrr1  r1                      
        !           735:        mtcrf   0x70,   r1              
        !           736: //     bt+     12,     EmulateUnimplementedInstructions
        !           737: //     bt      13,     EmulatePrivilegedInstructions
        !           738:        bf      14,     1f
        !           739: 
        !           740:        /* check for bluebox enabled */
        !           741:        lwz     r1,     PP_CPU_DATA(r2)
        !           742:        lwz     r1,     CPU_FLAGS(r1)
        !           743:        rlwinm. r1,r1,0,PCB_BB_BIT,PCB_BB_BIT
        !           744:        beq     1f      /* exit if bb not enabled */
        !           745: 
        !           746: 
        !           747:        /* Now save some state for working room */
        !           748:        stw     r4,     PP_SAVE_R4(r2)
        !           749:        stw     r5,     PP_SAVE_R5(r2)
        !           750:        stw     r6,     PP_SAVE_R6(r2)
        !           751:        stw     r7,     PP_SAVE_R7(r2)
        !           752: 
        !           753:        /* Turn on Data Reloction to get instruction */
        !           754:        mfmsr   r1
        !           755:        ori     r5,     r1,     MASK(MSR_DR)
        !           756:        mtmsr   r5
        !           757:        isync
        !           758: 
        !           759:        /* read in offending instruction */     
        !           760:        mfsrr0  r6
        !           761:        lwz     r7,     0(r6)
        !           762: 
        !           763:        /* turn Data Relocation back off*/
        !           764:        mtmsr   r1
        !           765:        isync   
        !           766: 
        !           767:        /* check the trap instruction */
        !           768:        xoris   r6,     r7,     0xFFF
        !           769:        cmplwi  cr7,    r6,     17
        !           770:        bge     cr7,    2f
        !           771: 
        !           772:        /*
        !           773:        ** Once here
        !           774:        **      r1-r3 -> sprg1-3
        !           775:        **      r4-r7 -> PP_SAVE_R4-7
        !           776:        **      cr    -> PP_SAVE_CR
        !           777:        **      r2    -> Per Processor Info Block
        !           778:        **      r3    -> exception type
        !           779:        */ 
        !           780:        stw     r0,     PP_SAVE_R0(r2)
        !           781: 
        !           782:        mfspr   r0,     srr0
        !           783:        stw     r0,     PP_SAVE_SRR0(r2)
        !           784: 
        !           785:        mfspr   r0,     srr1
        !           786:        stw     r0,     PP_SAVE_SRR1(r2)
        !           787: 
        !           788:        mfsprg  r0,     1
        !           789:        stw     r0,     PP_SAVE_R1(r2)
        !           790: 
        !           791:        mfsprg  r0,     2
        !           792:        stw     r0,     PP_SAVE_R2(r2)
        !           793: 
        !           794:        mfsprg  r0,     3
        !           795:        stw     r0,     PP_SAVE_R3(r2)
        !           796: 
        !           797:        stw     r8,     PP_SAVE_R8(r2)
        !           798:        stw     r9,     PP_SAVE_R9(r2)
        !           799:        stw     r10,    PP_SAVE_R10(r2)
        !           800:        stw     r11,    PP_SAVE_R11(r2)
        !           801:        stw     r12,    PP_SAVE_R12(r2)
        !           802: 
        !           803:        /*
        !           804:        ** functions 0-15 -> Call
        !           805:        **             16 -> Exit
        !           806:        */
        !           807:        cmplwi  cr7,    r6,     16
        !           808:        beq     cr7,    .L_ExitPseudoKernel
        !           809: 
        !           810: /*QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
        !           811:  * void                 CallPseudoKernel        ( void )
        !           812:  *
        !           813:  * This op provides a means of invoking the BlueBox PseudoKernel from a
        !           814:  * system (68k) or native (PPC) context while changing BlueBox interruption
        !           815:  * state atomically. As an added bonus, this op clobbers only r0 while leaving
        !           816:  * the rest of PPC user state registers intact.
        !           817:  *
        !           818:  * This op is invoked as follows:
        !           819:  *      li r0, kCallPseudoKernelNumber  // load this op's firmware call number
        !           820:  *      sc                              // invoke CallPseudoKernel
        !           821:  *      dc.l    CallPseudoKernelDescriptorPtr   // static pointer to CallPseudoK
        !           822: ernelDescriptor
        !           823:  *
        !           824:  * NOTE: The CallPseudoKernelDescriptor and the word pointed to by
        !           825:  * intControlAddr must be locked, else this op will crash the kernel.
        !           826:  *
        !           827: QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ*/
        !           828: 
        !           829:         // word following the twi is the descriptor's address
        !           830:         lwz     r3,    PP_SAVE_SRR0(r2)
        !           831: 
        !           832:         lwz     r10,   PP_SAVE_CR(r2)       // setup r10 with CR
        !           833: 
        !           834:        /* Turn on Data Relocation */
        !           835:        mtmsr   r5
        !           836:        isync
        !           837: 
        !           838:         lwz     r3,     4(r3)           // get descriptor's address
        !           839: 
        !           840:         lwz     r11,    CPKD_INTCONTROLADDR(r3)
        !           841:         lwz     r4,     CPKD_PC(r3)
        !           842:         lwz     r6,     CPKD_NEWSTATE(r3)
        !           843:         lwz     r7,     CPKD_INTSTATEMASK(r3)
        !           844:         lwz     r8,     0(r11)          // get current interruption control word
        !           845: //     lwz     r5,     CPKD_GPR0(r3)
        !           846:         lwz     r12,    CPKD_SYSCONTEXTSTATE(r3)
        !           847:         andc    r9,    r8,     r7      // remove current state
        !           848:         and     r8,    r8,     r7      // extract current state
        !           849:         cmplw   r8,    r12             // test for entry from system context
        !           850:         or      r9,    r9,     r6      // insert new state
        !           851:         bne     .L_CallFromAlternateContext
        !           852: 
        !           853: .L_CallFromSystemContext:
        !           854:         lwz     r6,     CPKD_INTCR2SHIFT(r3)
        !           855:         lwz     r7,     CPKD_INTCR2MASK(r3)
        !           856:         srw     r10,   r10,    r6      // position live CR2 from cr register as required
        !           857:         andc    r9,    r9,     r7      // remove old backup CR2
        !           858:         and     r10,   r10,    r7      // mask live CR2
        !           859:         or      r9,    r9,     r10     // insert CR2 into backup CR2
        !           860:         b       .L_CallContinue
        !           861: 
        !           862: .L_CallFromAlternateContext:
        !           863: .L_CallContinue:
        !           864:         stw     r9,     0(r11)          // update interruption control word
        !           865: 
        !           866:        /* turn Data Relocation back off*/
        !           867:        mtmsr   r1
        !           868:        isync   
        !           869: 
        !           870:         /* introduce new pc and gr0 contents */
        !           871:         lwz     r6,    PP_SAVE_SRR1(r2)
        !           872:         stw     r4,    PP_SAVE_SRR0(r2)
        !           873: //     stw     r5,     PP_SAVE_R0(r2)
        !           874: 
        !           875:        // insert updated fe0, fe1, se, and be bits into user msr
        !           876:         rlwimi  r6,    r6,     0,      MSR_FE1_BIT,    MSR_FE0_BIT
        !           877:        /* Disable FPU */
        !           878:        rlwinm  r6,     r6,     0,      MSR_FP_BIT+1,   MSR_FP_BIT-1
        !           879: 
        !           880:         /* zero single step and branch step control in user msr */
        !           881:         stw     r6,    PP_SAVE_SRR1(r2) // update user msr
        !           882: 
        !           883: .L_BlueBoxCommonExit:
        !           884:        /*
        !           885:        ** Restore State for Exit
        !           886:        */
        !           887:        lwz     r4,     PP_SAVE_CR(r2)
        !           888:        stwcx.  r4,     0,      r2              /* clear existing reservation */
        !           889:        mtcr    r4                              /* update cr, it is live */
        !           890: 
        !           891:        /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
        !           892:         * as arguments */
        !           893:        lwz     r0,     PP_SAVE_R1(r2)
        !           894:        mtsprg  1,      r0
        !           895: 
        !           896:        lwz     r0,     PP_SAVE_R2(r2)
        !           897:        mtsprg  2,      r0
        !           898: 
        !           899:        lwz     r0,     PP_SAVE_R3(r2)
        !           900:        mtsprg  3,      r0
        !           901: 
        !           902:        lwz     r0,     PP_SAVE_R0(r2)
        !           903: 
        !           904:        lwz     r4,     PP_SAVE_R4(r2)
        !           905:        lwz     r5,     PP_SAVE_R5(r2)
        !           906:        lwz     r6,     PP_SAVE_R6(r2)
        !           907:        lwz     r7,     PP_SAVE_R7(r2)
        !           908:        lwz     r8,     PP_SAVE_R8(r2)
        !           909:        lwz     r9,     PP_SAVE_R9(r2)
        !           910:        lwz     r10,    PP_SAVE_R10(r2)
        !           911:        lwz     r11,    PP_SAVE_R11(r2)
        !           912:        lwz     r12,    PP_SAVE_R12(r2)
        !           913: 
        !           914: 
        !           915:        /*
        !           916:        ** Setup parameters for exit code
        !           917:        */
        !           918:        mfsr    r1,     sr0
        !           919:        lwz     r3,     PP_SAVE_SRR1(r2)        /* load the last register... */
        !           920:        lwz     r2,     PP_SAVE_SRR0(r2)        /* For trampoline */
        !           921: 
        !           922:        b       exception_exit_fn
        !           923: 
        !           924: 
        !           925: 2:
        !           926:        lwz     r7,     PP_SAVE_R7(r2)
        !           927:        lwz     r6,     PP_SAVE_R6(r2)
        !           928:        lwz     r5,     PP_SAVE_R5(r2)
        !           929:        lwz     r4,     PP_SAVE_R4(r2)
        !           930: 1:
        !           931:        lwz     r1,     PP_SAVE_CR(r2)
        !           932:        mtcr    r1
        !           933:        b       L_exception_entry
        !           934: 
        !           935: 
        !           936: 
        !           937: /*QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
        !           938:  * void ExitPseudoKernel ( ExitPseudoKernelDescriptorPtr exitDescriptor )
        !           939:  *
        !           940:  * This op provides a means of exiting from the BlueBox PseudoKernel to a
        !           941:  * user context while changing the BlueBox interruption state atomically.
        !           942:  * It also allows all of the user state PPC registers to be loaded.
        !           943:  *
        !           944:  * This op is invoked as follows:
        !           945:  *      lwz r3, ExitPseudoKernelDescriptorPtr
        !           946:  *      li r0, kCallPseudoKernelNumber  // load this op's firmware call number
        !           947:  *      sc                              // invoke CallPseudoKernel
        !           948:  *
        !           949: QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ*/
        !           950: .L_ExitPseudoKernel:
        !           951:        /* Turn on Data Relocation */
        !           952:        mtmsr   r5
        !           953:        isync
        !           954: 
        !           955:        /* start of actual routine */
        !           956: 
        !           957:        //mfspr r9,     srr1
        !           958:         lwz     r9,    PP_SAVE_SRR1(r2)
        !           959: 
        !           960:        //mfsprg        r3,     3               // restore r3, it is exitdescptr
        !           961:        lwz     r3,     PP_SAVE_R3(r2)
        !           962: 
        !           963:        lwz     r8,     EPKD_CR(r3)
        !           964: 
        !           965:        lwz     r11,    EPKD_INTCONTROLADDR(r3)
        !           966:        lwz     r4,     EPKD_PC(r3)
        !           967:        lwz     r7,     EPKD_NEWSTATE(r3)
        !           968:        lwz     r10,    EPKD_INTSTATEMASK(r3)
        !           969:        lwz     r5,     0(r11)  // get current interruption control word
        !           970:        lwz     r0,     EPKD_SYSCONTEXTSTATE(r3)
        !           971:        andc    r12,    r5,     r10     // remove current state
        !           972:        cmplw   r7,     r0              // test for exit to system context
        !           973:        or      r12,    r12,    r7      // insert new state
        !           974:        lwz     r0,     EPKD_MSRUPDATE(r3)
        !           975:        beq     .L_ExitToSystemContext
        !           976: 
        !           977: .L_ExitToAlternateContext:
        !           978:        lwz     r5,     EPKD_INTPENDINGMASK(r3)
        !           979:        lwz     r6,     EPKD_INTPENDINGPC(r3)
        !           980:        and.    r7,     r12,    r5      // test for pending 'rupt in backup cr2
        !           981:        beq     .L_ExitUpdateRuptControlWord    //   and enter alternate context if none pending
        !           982:        mr      r4,     r6              // otherwise, introduce entry abort pc
        !           983:        b       .L_ExitNoUpdateRuptControlWord  //   and prepare to reenter pseudokernel
        !           984: 
        !           985: .L_ExitToSystemContext:
        !           986:        lwz     r5,     EPKD_INTCR2SHIFT(r3)
        !           987:        lwz     r6,     EPKD_INTCR2MASK(r3)             
        !           988:        slw     r7,     r12,    r5      // position backup cr2
        !           989:        and     r7,     r7,     r6      //   and mask it
        !           990:        or      r8,     r8,     r7      //   then or it into the live cr2
        !           991:                                                                                        // ...fall through into system context
        !           992: 
        !           993: .L_ExitUpdateRuptControlWord:
        !           994:        rlwimi  r9,     r0,     0,      MSR_FE0_BIT,    MSR_FE1_BIT
        !           995:        /* Disable FPU */
        !           996:        rlwinm  r9,     r9,     0,      MSR_FP_BIT+1,   MSR_FP_BIT-1
        !           997:                // insert updated fe0, fe1, se, and be bits into user msr
        !           998:        stw     r12,    0(r11)          // update interruption control word 
        !           999: .L_ExitNoUpdateRuptControlWord:
        !          1000:        lwz     r5,     EPKD_GPR0(r3)
        !          1001:        lwz     r6,     EPKD_SP(r3)
        !          1002:        lwz     r7,     EPKD_GPR3(r3)
        !          1003: 
        !          1004:        /* turn Data Relocation back off */
        !          1005:        mtmsr   r1
        !          1006:        isync
        !          1007:                                                                                        // load caller's new register content
        !          1008: 
        !          1009:        stw     r4,     PP_SAVE_SRR0(r2)
        !          1010:        stw     r5,     PP_SAVE_R0(r2)
        !          1011:        stw     r6,     PP_SAVE_R1(r2)
        !          1012:        stw     r7,     PP_SAVE_R3(r2)
        !          1013:        stw     r8,     PP_SAVE_CR(r2)
        !          1014:        stw     r9,     PP_SAVE_SRR1(r2)
        !          1015: 
        !          1016:        b       .L_BlueBoxCommonExit
        !          1017: 
        !          1018: #if 1
        !          1019: /*
        !          1020: ** EmulateUnimplementedInstructions
        !          1021: **
        !          1022: ** Entry       r1-r3 have been saved in sprg1-3. 
        !          1023: **             r2 - byte offset into per_proc_info of this CPU
        !          1024: **             r3 - contains the exception number.
        !          1025: **              cr   saved in per_proc_info structure
        !          1026: **
        !          1027: */
        !          1028: EmulatePrivilegedInstructions:
        !          1029: EmulateUnimplementedInstructions:
        !          1030:        stw     r0,PP_SAVE_R0+( 0*4)(r2)
        !          1031:        stmw    r4,PP_SAVE_R0+( 4*4)(r2)
        !          1032: 
        !          1033:        //la    UnimpMQptr,RegMQ(ContextPtr)
        !          1034:        //lwz   ContextPtr,XCP_GPR_0_31+(ContextPtr*4)(KernelDataPtr)
        !          1035: 
        !          1036: 
        !          1037: #if CountExceptions
        !          1038: //     Assume that the instruction will be emulated, so increment the count.
        !          1039:        //lwz   DataTemp,NI+EmulatedUnimpInstCount(KernelDataPtr)
        !          1040:        //lwz   MemProcPtr,MemProcBasePtr(KernelDataPtr)
        !          1041:        //addi  DataTemp,DataTemp,1
        !          1042:        //stw   DataTemp,NI+EmulatedUnimpInstCount(KernelDataPtr)
        !          1043: #else
        !          1044:        //lwz   MemProcPtr,MemProcBasePtr(KernelDataPtr)
        !          1045: #endif
        !          1046: 
        !          1047:        mfmsr   MSR_Disabled
        !          1048:        //ori   MSR_Enabled,MSR_Disabled,msr_dr
        !          1049:        ori     MSR_Enabled,MSR_Disabled,MASK(MSR_DR)
        !          1050: 
        !          1051:        mtmsr   MSR_Enabled             // enable Data Relocation
        !          1052:        isync
        !          1053:        lwz     MemInstr,0(SavedSRR0)   // read the faulty instruction
        !          1054:        mtmsr   MSR_Disabled            // disable data relocation
        !          1055:        isync
        !          1056: 
        !          1057:        //rlwinm DataTemp,MemInstr,6,0x000003F          // get Opcode field
        !          1058:        rlwinm  DataTemp,MemInstr,6,26,31       // get Opcode field
        !          1059:        cmpwi   cr6,DataTemp,9
        !          1060:        cmpwi   cr0,DataTemp,22
        !          1061:        cmpwi   cr1,DataTemp,31
        !          1062: 
        !          1063:        //lwz   MemDataH,UnimpDefaults(KernelDataPtr)
        !          1064:        lis     MemDataH,0xFFFF
        !          1065:        ori     MemDataH,MemDataH,0xFFFF
        !          1066: 
        !          1067:        //rlwinm        MemDataL,MemCtxFlags,b_CtxFlagEmulatePowerCompatible-b_EmulatePOWERmaskLSB,1<<(31-b_EmulatePOWERmaskLSB)
        !          1068:        rlwinm  MemDataL,MemCtxFlags,b_CtxFlagEmulatePowerCompatible-b_EmulatePOWERmaskLSB,14,14)
        !          1069:        neg             MemDataL,MemDataL
        !          1070:        //rlwimi        MemDataL,MemCtxFlags,b_CtxFlagEmulateOptionalInstr-b_EmulateOptional,1<<(31-b_EmulateOptional)
        !          1071:        rlwimi  MemDataL,MemCtxFlags,b_CtxFlagEmulateOptionalInstr-b_EmulateOptional,16,16)
        !          1072:        or              MemDataL,MemDataL,MemDataH
        !          1073:        //rlwimi        MemDataL,MemInstr,0,0x000007FF
        !          1074:        rlwimi  MemDataL,MemInstr,0,21,31
        !          1075: 
        !          1076:        //rlwimi        MemCtxFlags,MemCtxFlags,(b_CtxFlagStepTraceEnabled-b_CtxFlagTracePending)&0x1F,1<<(31-b_CtxFlagTracePending)
        !          1077:        rlwimi  MemCtxFlags,MemCtxFlags,(b_CtxFlagStepTraceEnabled-b_CtxFlagTracePending)&0x1F,b_CtxFlagTracePending,b_CtxFlagTracePending)
        !          1078: 
        !          1079:        //rlwinm        UnimpRSRT,MemInstr,13+0,0x0000007C
        !          1080:        rlwinm  UnimpRSRT,MemInstr,13+0,25,29
        !          1081:        //rlwinm        UnimpRA,MemInstr,13+5,0x0000007C
        !          1082:        rlwinm  UnimpRA,MemInstr,13+5,25,29
        !          1083: //     001001 rt-rt ra-ra si-si si-si si-si s          dozi            rt,ra,si
        !          1084:        beq     cr6,EmulateDOZI
        !          1085: 
        !          1086:        mtcrf   0x3F,MemDataL
        !          1087:        //rlwinm        UnimpRB,MemInstr,13+10,0x0000007C
        !          1088:        rlwinm  UnimpRB,MemInstr,13+10,25,29
        !          1089: //     010110 rs-rs ra-ra rb-rb mb-mb me-me .          rlmi[.]         ra,rs,rb,mb,me
        !          1090:        beq     cr0,EmulateRLMI
        !          1091: 
        !          1092:        bne     cr1,EmulateOp31done
        !          1093:        //rlwinm        MemDataL,MemInstr,2,0x000000F8          // low 5 bits of XO field * 8
        !          1094:        rlwinm  MemDataL,MemInstr,2,24,28               // low 5 bits of XO field * 8
        !          1095:        add     MemDataL,MemDataL,MemProcPtr
        !          1096: //     lwz     MemDataH,EmulateOp31Lookup+0-MemProcBase(MemDataL)
        !          1097:        //rlwinm        DataTemp,MemInstr,26,0x0000001F         // high 5 bits of XO field
        !          1098:        rlwinm  DataTemp,MemInstr,26,27,31      // high 5 bits of XO field
        !          1099: //     lwz     MemDataL,EmulateOp31Lookup+4-MemProcBase(MemDataL)
        !          1100:        rotlw.  MemDataH,MemDataH,DataTemp              // see if supported XO field
        !          1101:        add     MemDataL,MemDataL,MemProcPtr            // compute routine address
        !          1102:        mtlr    MemDataL
        !          1103: 
        !          1104:        bltlr                           // dispatch to supported proc
        !          1105: EmulateOp31done:
        !          1106: 
        !          1107: //     100001 rt-rt ra-ra d---d d---d d---d d  lwzu            rt,d(ra)
        !          1108: //     100011 rt-rt ra-ra d---d d---d d---d d  lbzu            rt,d(ra)
        !          1109: //     100101 rs-rs ra-ra d---d d---d d---d d  stwu            rs,d(ra)
        !          1110: //     100111 rs-rs ra-ra d---d d---d d---d d  stbu            rs,d(ra)
        !          1111: //     101001 rt-rt ra-ra d---d d---d d---d d  lhzu            rt,d(ra)
        !          1112: //     101011 rt-rt ra-ra d---d d---d d---d d  lhau            rt,d(ra)
        !          1113: //     101101 rs-rs ra-ra d---d d---d d---d d  sthu            rs,d(ra)
        !          1114: //     101110 rt-rt ra-ra d---d d---d d---d d  lmw                     rt,d(ra)
        !          1115: //     110001 ft-ft ra-ra d---d d---d d---d d  lfsu            ft,d(ra)
        !          1116: //     110011 ft-ft ra-ra d---d d---d d---d d  lfdu            ft,d(ra)
        !          1117: //     110101 fs-fs ra-ra d---d d---d d---d d  stfsu           fs,d(ra)
        !          1118: //     110111 fs-fs ra-ra d---d d---d d---d d  stfdu           fs,d(ra)
        !          1119:        ble     cr1,EmulateILLEGAL      // primary opcode <= 31 are illegal
        !          1120:        lis     MemDataH,0x55565500>>16 // mask for valid primary opcodes
        !          1121:        ori     MemDataH,MemDataH,0x55565500&0xFFFF
        !          1122:        rotlw.  MemDataH,MemDataH,DataTemp                      // see if this opcode is legal
        !          1123:        blt     EmulatePowerMemoryInvalidForm           // if legal opcode, must be invalid form
        !          1124: 
        !          1125: EmulateILLEGAL:
        !          1126: EmulateDisabledPowerMQ:
        !          1127: EmulateDisabledPowerRTC:
        !          1128: EmulateDisabledPowerDEC:
        !          1129: EmulateDisabledPowerComplex:
        !          1130: EmulateDisabledInvalidSPR:
        !          1131: EmulateDisabledPowerCLCS:
        !          1132: EmulateDisabledPowerMemory:
        !          1133: EmulateDisabledOptional:
        !          1134:        mtcrf   0x70,SavedSRR1          // test SRR1 flags for original cause
        !          1135:        li      Tmp1,ecInvalidInstr     // invalid instruction
        !          1136:        bf      13,GenerateInvalidInstructionException  // If not privileged, use ecInvalidInstr
        !          1137: EmulatePRIVILEGED:
        !          1138:        mtcrf   0x0F,SavedSRR1          // test SRR1 flags for PR bit
        !          1139:        li      Tmp1,ecInvalidInstr     // invalid instruction
        !          1140: //     bf      b_msr_pr,GenerateInvalidInstructionException    // If privileged, use ecInvalidInstr
        !          1141:        li      Tmp1,ecPrivilegedInstr  // privileged instruction
        !          1142: GenerateInvalidInstructionException:
        !          1143: #if CountExceptions
        !          1144: //     The instruction was really invalid, so decrement the emulated instruction count.
        !          1145:        //lwz           Tmp2,NI+EmulatedUnimpInstCount(KernelDataPtr)
        !          1146:        //lmw           r14,XCP_GPR_0_31+(14*4)(KernelDataPtr)
        !          1147:        subi    Tmp2,Tmp2,1
        !          1148:        //stw           Tmp2,NI+EmulatedUnimpInstCount(KernelDataPtr)
        !          1149: #else
        !          1150:        //lmw           r14,XCP_GPR_0_31+(14*4)(KernelDataPtr)
        !          1151: #endif
        !          1152: //     lwz             ContextPtr,ActiveContextPtr(KernelDataPtr)
        !          1153: //     lwz             ContextStateFlags,ActiveCtxFlags(KernelDataPtr)
        !          1154:        b               GenerateException                                       // call the exception handler
        !          1155: 
        !          1156: 
        !          1157: EmulateOp31Lookup:
        !          1158:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 00
        !          1159:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 01
        !          1160:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 02
        !          1161:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 03
        !          1162:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 04
        !          1163:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 05
        !          1164:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 06
        !          1165:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 07
        !          1166: //     011111 rt-rt ra-ra rb-rb 01000 01000 .  doz[.]          rt,ra,rb
        !          1167: //     011111 rt-rt ra-ra xxxxx 01011 01000 .  abs[.]          rt,ra
        !          1168: //     011111 rt-rt ra-ra xxxxx 01111 01000 .  nabs[.]         rt,ra
        !          1169: //     011111 rt-rt ra-ra rb-rb 11000 01000 .  dozo[.]         rt,ra,rb
        !          1170: //     011111 rt-rt ra-ra xxxxx 11011 01000 .  abso[.]         rt,ra
        !          1171: //     011111 rt-rt ra-ra xxxxx 11111 01000 .  nabso[.]        rt,ra
        !          1172:        .long   0x00910091,EmulateDOZ_ABS_NABS-MemProcBase              // 08
        !          1173:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 09
        !          1174:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 0A
        !          1175: //     011111 rt-rt ra-ra rb-rb 00011 01011 .  mul[.]          rt,ra,rb
        !          1176: //     011111 rt-rt ra-ra rb-rb 01010 01011 .  div[.]          rt,ra,rb
        !          1177: //     011111 rt-rt ra-ra rb-rb 01011 01011 .  divs[.]         rt,ra,rb
        !          1178: //     011111 rt-rt ra-ra rb-rb 10011 01011 .  mulo[.]         rt,ra,rb
        !          1179: //     011111 rt-rt ra-ra rb-rb 11010 01011 .  divo[.]         rt,ra,rb
        !          1180: //     011111 rt-rt ra-ra rb-rb 11011 01011 .  divso[.]        rt,ra,rb
        !          1181:        .long   0x10301030,EmulateMUL_DIV_DIVS-MemProcBase              // 0B
        !          1182:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 0C
        !          1183:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 0D
        !          1184:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 0E
        !          1185:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 0F
        !          1186:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 10
        !          1187:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 11
        !          1188:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 12
        !          1189: //     011111 rt-rt 00000 xxxxx 01010 10011 x  mfmq            rt
        !          1190: //     011111 rt-rt 00001 xxxxx 01010 10011 x  mfxer           rt
        !          1191: //     011111 rt-rt 00010 xxxxx 01010 10011 x  mfspr           rt,0x2
        !          1192: //     011111 rt-rt 00011 xxxxx 01010 10011 x  mfspr           rt,0x3
        !          1193: //     011111 rt-rt 00100 xxxxx 01010 10011 x  mfrtcu          rt
        !          1194: //     011111 rt-rt 00101 xxxxx 01010 10011 x  mfrtcl          rt
        !          1195: //     011111 rt-rt 00110 xxxxx 01010 10011 x  mfdec           rt
        !          1196: //     011111 rt-rt 00111 xxxxx 01010 10011 x  mfspr           rt,0x7
        !          1197: //     011111 rt-rt 01000 xxxxx 01010 10011 x  mflr            rt
        !          1198: //     011111 rt-rt 01001 xxxxx 01010 10011 x  mfctr           rt
        !          1199: //     011111 rt-rt 01010 xxxxx 01010 10011 x  mfspr           rt,0xA
        !          1200: //     011111 rt-rt 01011 xxxxx 01010 10011 x  mfspr           rt,0xB
        !          1201: //     011111 rt-rt 01100 xxxxx 01010 10011 x  mfspr           rt,0xC
        !          1202: //     011111 rt-rt 01101 xxxxx 01010 10011 x  mfspr           rt,0xD
        !          1203: //     011111 rt-rt 01110 xxxxx 01010 10011 x  mfspr           rt,0xE
        !          1204: //     011111 rt-rt 01111 xxxxx 01010 10011 x  mfspr           rt,0xF
        !          1205: //     011111 rt-rt 11111 01000 01010 10011 x  mfspr           rt,287
        !          1206: //     011111 rt-rt 11000 11101 01010 10011 x  mfspr           rt,952
        !          1207: //     011111 rt-rt 11001 11101 01010 10011 x  mfspr           rt,953
        !          1208: //     011111 rt-rt 11010 11101 01010 10011 x  mfspr           rt,954
        !          1209: //     011111 rt-rt 11011 11101 01010 10011 x  mfspr           rt,955
        !          1210: //     011111 rt-rt 11100 11101 01010 10011 x  mfspr           rt,956
        !          1211: //     011111 rt-rt 11101 11101 01010 10011 x  mfspr           rt,957
        !          1212: //     011111 rt-rt 11110 11101 01010 10011 x  mfspr           rt,958
        !          1213: //     011111 rt-rt 11111 11101 01010 10011 x  mfspr           rt,959
        !          1214: //     011111 rt-rt 01100 01000 01011 10011 x  mftb            rt
        !          1215: //     011111 rt-rt 01101 01000 01011 10011 x  mftbu           rt
        !          1216: //     011111 rs-rs 00000 xxxxx 01110 10011 x  mtmq            rs
        !          1217: //     011111 rs-rs 00001 xxxxx 01110 10011 x  mtxer           rs
        !          1218: //     011111 rs-rs 00010 xxxxx 01110 10011 x  mtspr           0x2,rs
        !          1219: //     011111 rs-rs 00011 xxxxx 01110 10011 x  mtspr           0x3,rs
        !          1220: //     011111 rs-rs 00100 xxxxx 01110 10011 x  mtspr           0x4,rs
        !          1221: //     011111 rs-rs 00101 xxxxx 01110 10011 x  mtspr           0x5,rs
        !          1222: //     011111 rs-rs 00110 xxxxx 01110 10011 x  mtspr           0x6,rs
        !          1223: //     011111 rs-rs 00111 xxxxx 01110 10011 x  mtspr           0x7,rs
        !          1224: //     011111 rs-rs 01000 xxxxx 01110 10011 x  mtlr            rs
        !          1225: //     011111 rs-rs 01001 xxxxx 01110 10011 x  mtctr           rs
        !          1226: //     011111 rs-rs 01010 xxxxx 01110 10011 x  mtspr           0xA,rs
        !          1227: //     011111 rs-rs 01011 xxxxx 01110 10011 x  mtspr           0xB,rs
        !          1228: //     011111 rs-rs 01100 xxxxx 01110 10011 x  mtspr           0xC,rs
        !          1229: //     011111 rs-rs 01101 xxxxx 01110 10011 x  mtspr           0xD,rs
        !          1230: //     011111 rs-rs 01110 xxxxx 01110 10011 x  mtspr           0xE,rs
        !          1231: //     011111 rs-rs 01111 xxxxx 01110 10011 x  mtspr           0xF,rs
        !          1232: //     011111 rs-rs 11000 11101 01110 10011 x  mtspr           952,rs
        !          1233: //     011111 rs-rs 11001 11101 01110 10011 x  mtspr           953,rs
        !          1234: //     011111 rs-rs 11010 11101 01110 10011 x  mtspr           954,rs
        !          1235: //     011111 rs-rs 11011 11101 01110 10011 x  mtspr           955,rs
        !          1236: //     011111 rs-rs 11100 11101 01110 10011 x  mtspr           956,rs
        !          1237: //     011111 rs-rs 11101 11101 01110 10011 x  mtspr           957,rs
        !          1238: //     011111 rs-rs 11110 11101 01110 10011 x  mtspr           958,rs
        !          1239: //     011111 rs-rs 11111 11101 01110 10011 x  mtspr           959,rs
        !          1240: //     011111 rt-rt ra-ra xxxxx 10000 10011 x  clcs            rt,ra
        !          1241:        .long   0x00328000,EmulateMFSPR_MFTB_MTSPR_CLCS-MemProcBase     // 13
        !          1242:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 14
        !          1243: //     011111 rt-rt ra-ra rb-rb 01000 10101 .  lscbx[.]        rt,ra,rb
        !          1244: //     011111 rt-rt ra-ra rb-rb 10000 10101 x  lswx            rt,ra,rb
        !          1245: //     011111 rt-rt ra-ra nb-nb 10010 10101 x  lswi            rt,ra,nb
        !          1246:        .long   0x0080A000,EmulatePowerMemoryInvalidForm-MemProcBase    // 15
        !          1247:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 16
        !          1248: //     011111 rt-rt ra-ra rb-rb 00001 10111 x  lwzux           rt,ra,rb
        !          1249: //     011111 rt-rt ra-ra rb-rb 00011 10111 x  lbzux           rt,ra,rb
        !          1250: //     011111 rs-rs ra-ra rb-rb 00101 10111 x  stwux           rs,ra,rb
        !          1251: //     011111 rs-rs ra-ra rb-rb 00111 10111 x  stbux           rs,ra,rb
        !          1252: //     011111 rt-rt ra-ra rb-rb 01001 10111 x  lhzux           rt,ra,rb
        !          1253: //     011111 rt-rt ra-ra rb-rb 01011 10111 x  lhaux           rt,ra,rb
        !          1254: //     011111 rs-rs ra-ra rb-rb 01101 10111 x  sthux           rs,ra,rb
        !          1255: //     011111 ft-ft ra-ra rb-rb 10001 10111 x  lfsux           ft,ra,rb
        !          1256: //     011111 ft-ft ra-ra rb-rb 10011 10111 x  lfdux           ft,ra,rb
        !          1257: //     011111 fs-fs ra-ra rb-rb 10101 10111 x  stfsux          fs,ra,rb
        !          1258: //     011111 fs-fs ra-ra rb-rb 10111 10111 x  stfdux          fs,ra,rb
        !          1259: //     011111 fs-fs ra-ra rb-rb 11110 10111 x  stfiwx          fs,ra,rb
        !          1260:        .long   0x55545502,EmulateUpdateMemOps_STFIWX-MemProcBase       // 17
        !          1261: //     011111 rs-rs ra-ra rb-rb 00100 11000 .  slq[.]          ra,rs,rb
        !          1262: //     011111 rs-rs ra-ra sh-sh 00101 11000 .  sliq[.]         ra,rs,sh
        !          1263: //     011111 rs-rs ra-ra rb-rb 00110 11000 .  sllq[.]         ra,rs,rb
        !          1264: //     011111 rs-rs ra-ra sh-sh 00111 11000 .  slliq[.]        ra,rs,sh
        !          1265: //     011111 rs-rs ra-ra rb-rb 10100 11000 .  srq[.]          ra,rs,rb
        !          1266: //     011111 rs-rs ra-ra sh-sh 10101 11000 .  sriq[.]         ra,rs,sh
        !          1267: //     011111 rs-rs ra-ra rb-rb 10110 11000 .  srlq[.]         ra,rs,rb
        !          1268: //     011111 rs-rs ra-ra sh-sh 10111 11000 .  srliq[.]        ra,rs,sh
        !          1269: //     011111 rs-rs ra-ra rb-rb 11100 11000 .  sraq[.]         ra,rs,rb
        !          1270: //     011111 rs-rs ra-ra sh-sh 11101 11000 .  sraiq[.]        ra,rs,sh
        !          1271:        .long   0x0F000F0C,EmulateSHIFTQ-MemProcBase                    // 18
        !          1272: //     011111 rs-rs ra-ra rb-rb 00100 11001 .  sle[.]          ra,rs,rb
        !          1273: //     011111 rs-rs ra-ra rb-rb 00110 11001 .  sleq[.]         ra,rs,rb
        !          1274: //     011111 rs-rs ra-ra rb-rb 10000 11001 .  rrib[.]         ra,rs,rb
        !          1275: //     011111 rs-rs ra-ra rb-rb 10100 11001 .  sre[.]          ra,rs,rb
        !          1276: //     011111 rs-rs ra-ra rb-rb 10110 11001 .  sreq[.]         ra,rs,rb
        !          1277: //     011111 rs-rs ra-ra rb-rb 11100 11001 .  srea[.]         ra,rs,rb
        !          1278:        .long   0x0A008A08,EmulateRRIB_SHIFTE-MemProcBase               // 19
        !          1279:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 1A
        !          1280:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 1B
        !          1281:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 1C
        !          1282: //     011111 rs-rs ra-ra rb-rb 00000 11101 .  maskg[.]        ra,rs,rb
        !          1283: //     011111 rs-rs ra-ra rb-rb 10000 11101 .  maskir[.]       ra,rs,rb
        !          1284:        .long   0x80008000,EmulateMASKG_MASKIR-MemProcBase              // 1D
        !          1285:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 1E
        !          1286:        .long   0x00000000,EmulateILLEGAL-MemProcBase                   // 1F
        !          1287: 
        !          1288: 
        !          1289: EmulateUpdateRT_cr0_xer_mq:
        !          1290:        stw     MemDataH,0(UnimpMQptr)  // update MQ in context block
        !          1291: EmulateUpdateRT_cr0_xer:                                                               // update XER (live XER already updated)
        !          1292: EmulateUpdateRT_cr0:
        !          1293:        bf      31,EmulateUpdateRT      // test the Rc bit
        !          1294:        mfcr    DataTemp                // get current CR0
        !          1295:        //rlwimi        SavedCR,DataTemp,0,0xF0000000   // update saved CR0
        !          1296:        rlwimi  SavedCR,DataTemp,0,0,3  // update saved CR0
        !          1297: EmulateUpdateRT:
        !          1298:        stwx    MemDataL,KernelDataPtr,UnimpRT  // update RT
        !          1299:        b       CompleteMemOpDone       // instruction emulation complete
        !          1300: 
        !          1301: 
        !          1302: EmulateDOZ_ABS_NABS:
        !          1303: //                1 11111 11112 22222 22223 3
        !          1304: //     012345 67890 12345 67890 12345 67890 1
        !          1305: //     ------ ----- ----- ----- ----- ----- -
        !          1306: //     011111 rt-rt ra-ra rb-rb 01000 01000 .          doz[.]          rt,ra,rb
        !          1307: //     011111 rt-rt ra-ra xxxxx 01011 01000 .          abs[.]          rt,ra
        !          1308: //     011111 rt-rt ra-ra xxxxx 01111 01000 .          nabs[.]         rt,ra
        !          1309: //     011111 rt-rt ra-ra rb-rb 11000 01000 .          dozo[.]         rt,ra,rb
        !          1310: //     011111 rt-rt ra-ra xxxxx 11011 01000 .          abso[.]         rt,ra
        !          1311: //     011111 rt-rt ra-ra xxxxx 11111 01000 .          nabso[.]        rt,ra
        !          1312:        bf      b_EmulatePowerComplex,EmulateDisabledPowerComplex
        !          1313:        lwzx    UnimpRA,KernelDataPtr,UnimpRA           // get RA
        !          1314:        bf      24,EmulateDOZ
        !          1315: EmulateABS_NABS:
        !          1316: //     011111 rt-rt ra-ra xxxxx 01011 01000 .          abs[.]          rt,ra
        !          1317: //     011111 rt-rt ra-ra xxxxx 01111 01000 .          nabs[.]         rt,ra
        !          1318: //     011111 rt-rt ra-ra xxxxx 11011 01000 .          abso[.]         rt,ra
        !          1319: //     011111 rt-rt ra-ra xxxxx 11111 01000 .          nabso[.]        rt,ra
        !          1320:        bt      21,EmulateABSO_NABSO
        !          1321: //     011111 rt-rt ra-ra xxxxx 01011 01000 .          abs[.]          rt,ra
        !          1322: //     011111 rt-rt ra-ra xxxxx 01111 01000 .          nabs[.]         rt,ra
        !          1323:        mr.     MemDataL,UnimpRA        // get operand, update cr0
        !          1324: //     crxor   23,23,lt                // exchange abs with nabs if negative
        !          1325:        crxor   23,23,lt_b              // exchange abs with nabs if negative
        !          1326:        bf      23,EmulateUpdateRT_cr0  // return unchanged result
        !          1327:        neg.    MemDataL,UnimpRA        // negate operand, update cr0
        !          1328:        b       EmulateUpdateRT_cr0     // return negated result
        !          1329: 
        !          1330: 
        !          1331: EmulateABSO_NABSO:
        !          1332: //     011111 rt-rt ra-ra xxxxx 11011 01000 .          abso[.]         rt,ra
        !          1333: //     011111 rt-rt ra-ra xxxxx 11111 01000 .          nabso[.]        rt,ra
        !          1334:        li      MemDataL,0
        !          1335:        addo.   MemDataL,UnimpRA,MemDataL       // get operand, clear OV, cr0
        !          1336: //     crxor   23,23,lt                // exchange abs with nabs if negative
        !          1337:        crxor   23,23,lt_b              // exchange abs with nabs if negative
        !          1338:        bf      23,EmulateUpdateRT_cr0_xer      // return unchanged result
        !          1339:        nego.   MemDataL,UnimpRA        // negate operand, update OV, cr0
        !          1340:        b       EmulateUpdateRT_cr0_xer // return negated result
        !          1341: 
        !          1342: 
        !          1343: EmulateDOZI:
        !          1344: //     001001 rt-rt ra-ra si-si si-si si-si s          dozi            rt,ra,si
        !          1345:        mtcrf   0x3F,MemDataL
        !          1346:        bf              b_EmulatePowerComplex,EmulateDisabledPowerComplex
        !          1347:        lwzx    UnimpRA,KernelDataPtr,UnimpRA           // get RA
        !          1348:        extsh   UnimpRB,MemInstr                                        // get SI
        !          1349:        cmpw    cr1,UnimpRB,UnimpRA                                     // see if SI < RA
        !          1350:        sub     MemDataL,MemDataL,MemDataL                      // assume zero
        !          1351:        blt     cr1,EmulateUpdateRT                                     // return zero when difference < zero
        !          1352:        sub     MemDataL,UnimpRB,UnimpRA                        // compute difference
        !          1353:        b               EmulateUpdateRT                                         // return difference when >= zero
        !          1354: 
        !          1355: 
        !          1356: EmulateDOZ:
        !          1357: //     011111 rt-rt ra-ra rb-rb 01000 01000 .          doz[.]          rt,ra,rb
        !          1358: //     011111 rt-rt ra-ra rb-rb 11000 01000 .          dozo[.]         rt,ra,rb
        !          1359:        lwzx    UnimpRB,KernelDataPtr,UnimpRB           // get RB
        !          1360:        bt              21,EmulateDOZO
        !          1361: //     011111 rt-rt ra-ra rb-rb 01000 01000 .          doz[.]          rt,ra,rb
        !          1362:        cmpw    cr1,UnimpRB,UnimpRA                                     // see if RB < RA
        !          1363:        sub.    MemDataL,MemDataL,MemDataL                      // assume zero
        !          1364:        blt             cr1,EmulateUpdateRT_cr0                         // return zero when difference < zero
        !          1365:        sub.    MemDataL,UnimpRB,UnimpRA                        // compute difference
        !          1366:        b               EmulateUpdateRT_cr0                                     // return difference when >= zero
        !          1367: 
        !          1368: 
        !          1369: EmulateDOZO:
        !          1370: //     011111 rt-rt ra-ra rb-rb 11000 01000 .          dozo[.]         rt,ra,rb
        !          1371:        cmpw    cr1,UnimpRB,UnimpRA                                     // see if RB < RA
        !          1372:        subo.   MemDataL,MemDataL,MemDataL                      // assume zero
        !          1373:        blt             cr1,EmulateUpdateRT_cr0_xer                     // return zero when difference < zero
        !          1374:        subo.   MemDataL,UnimpRB,UnimpRA                        // compute difference
        !          1375:        b               EmulateUpdateRT_cr0_xer                         // return difference when >= zero
        !          1376: 
        !          1377: 
        !          1378: EmulateMUL_DIV_DIVS:
        !          1379: //                1 11111 11112 22222 22223 3
        !          1380: //     012345 67890 12345 67890 12345 67890 1
        !          1381: //     ------ ----- ----- ----- ----- ----- -
        !          1382: //     011111 rt-rt ra-ra rb-rb 00011 01011 .          mul[.]          rt,ra,rb
        !          1383: //     011111 rt-rt ra-ra rb-rb 01010 01011 .          div[.]          rt,ra,rb
        !          1384: //     011111 rt-rt ra-ra rb-rb 01011 01011 .          divs[.]         rt,ra,rb
        !          1385: //     011111 rt-rt ra-ra rb-rb 10011 01011 .          mulo[.]         rt,ra,rb
        !          1386: //     011111 rt-rt ra-ra rb-rb 11010 01011 .          divo[.]         rt,ra,rb
        !          1387: //     011111 rt-rt ra-ra rb-rb 11011 01011 .          divso[.]        rt,ra,rb
        !          1388:        bf              b_EmulatePowerMQ,EmulateDisabledPowerMQ
        !          1389:        lwzx    UnimpRB,KernelDataPtr,UnimpRB           // get RB
        !          1390:        lwzx    UnimpRA,KernelDataPtr,UnimpRA           // get RA
        !          1391:        bf              22,EmulateMUL
        !          1392: //     011111 rt-rt ra-ra rb-rb 01010 01011 .          div[.]          rt,ra,rb
        !          1393: //     011111 rt-rt ra-ra rb-rb 01011 01011 .          divs[.]         rt,ra,rb
        !          1394: //     011111 rt-rt ra-ra rb-rb 11010 01011 .          divo[.]         rt,ra,rb
        !          1395: //     011111 rt-rt ra-ra rb-rb 11011 01011 .          divso[.]        rt,ra,rb
        !          1396:        cmpwi   cr1,UnimpRB,0                                           // anything / 00000000 is undefined
        !          1397:        bt              25,EmulateDIVS
        !          1398: //     011111 rt-rt ra-ra rb-rb 01010 01011 .          div[.]          rt,ra,rb
        !          1399: //     011111 rt-rt ra-ra rb-rb 11010 01011 .          divo[.]         rt,ra,rb
        !          1400: 
        !          1401:        lwz             UnimpMQtmp,0(UnimpMQptr)                        // get MQ from context block
        !          1402:        srwi    MemDataL,UnimpMQtmp,31                          // get Sign(MQ)
        !          1403:        add.    MemDataL,MemDataL,UnimpRA                       // see if RA=Sign(MQ)
        !          1404:        bne             EmulateDIV                                                      // perform complex 64 bit divide when RA<>Sign(MQ)
        !          1405:        mr              UnimpRA,UnimpMQtmp                                      // perform 32 bit DIVS (MQ/RB) when RA=Sign(MQ)
        !          1406: 
        !          1407: EmulateDIVS:
        !          1408: //     011111 rt-rt ra-ra rb-rb 01011 01011 .          divs[.]         rt,ra,rb
        !          1409: //     011111 rt-rt ra-ra rb-rb 11011 01011 .          divso[.]        rt,ra,rb
        !          1410:        cmpwi   cr0,UnimpRB,-1                                          // 80000000 / FFFFFFFF is undefined
        !          1411:        bt              21,EmulateDIVSO
        !          1412: //     011111 rt-rt ra-ra rb-rb 01011 01011 .          divs[.]         rt,ra,rb
        !          1413:        beq             cr0,EmulateDIVS_neg_one                         // handle RA / FFFFFFFF (just negate)
        !          1414:        beq             cr1,EmulateDIVS_zero                            // handle RA / 00000000
        !          1415:        divw    MemDataL,UnimpRA,UnimpRB                        // quotient <- RA / RB
        !          1416: EmulateDIVS_rem_calc:
        !          1417:        mullw   MemDataH,MemDataL,UnimpRB                       // quotient * RB
        !          1418:        sub.    MemDataH,UnimpRA,MemDataH                       // remainder <- RA - (quotient * RB)
        !          1419:        b               EmulateUpdateRT_cr0_xer_mq
        !          1420: EmulateDIVS_neg_one:
        !          1421:        neg             MemDataL,UnimpRA                                        // quotient <- -RA
        !          1422:        sub.    MemDataH,UnimpRA,UnimpRA                        // remainder <- 00000000
        !          1423:        b               EmulateUpdateRT_cr0_xer_mq
        !          1424: 
        !          1425: EmulateDIVSO:
        !          1426: //     011111 rt-rt ra-ra rb-rb 11011 01011 .          divso[.]        rt,ra,rb
        !          1427:        divwo   MemDataL,UnimpRA,UnimpRB                        // quotient <- RA / RB, compute OV bit
        !          1428:        beq             cr0,EmulateDIVS_neg_one                         // handle RA / FFFFFFFF (just negate)
        !          1429:        bne             cr1,EmulateDIVS_rem_calc                        // compute remainder, unless RA / 00000000
        !          1430: EmulateDIVS_zero:
        !          1431:        //rlwinm        DataTemp,UnimpRA,2,0x00000002           // quotient <- 00000001 when RA < 0
        !          1432:        rlwinm  DataTemp,UnimpRA,2,30,30// quotient <- 00000001 when RA < 0
        !          1433:        subi    MemDataL,DataTemp,1                                     // quotient <- FFFFFFFF when RA >= 0
        !          1434:        mr.             MemDataH,UnimpRA                                        // remainder <- RA
        !          1435:        b               EmulateUpdateRT_cr0_xer_mq
        !          1436: 
        !          1437: 
        !          1438: EmulateDIV:
        !          1439:        mfxer   UnimpXERtmp                     // save XER CA bit
        !          1440:        beq     cr1,EmulateDIV_zero             // handle RA / 00000000
        !          1441: 
        !          1442:        cmpwi   cr0,UnimpRB,0                   // test sign of RB
        !          1443:        cmpwi   cr1,UnimpRA,0                   // test sign of RA
        !          1444: //     crxor   (cr1*4)+so,(cr0*4)+lt,(cr1*4)+lt// compute sign of quotient
        !          1445:        crxor   (rcr1*4)+so_b,(rcr0*4)+lt_b,(rcr1*4)+lt_b// compute sign of quotient
        !          1446:        bge     cr0,EmulateDIV_denom_ok         // compute abs (RB)
        !          1447:        neg     UnimpRB,UnimpRB                 // UnimpRB <- abs (32 bit denom)
        !          1448: EmulateDIV_denom_ok:
        !          1449:        bge     cr1,EmulateDIV_numer_ok         // compute abs (RA||MQ)
        !          1450:        subfic  UnimpMQtmp,UnimpMQtmp,0         // UnimpRA/UnimpMQtmp <- abs (64 bit numerator)
        !          1451:        subfze  UnimpRA,UnimpRA
        !          1452: EmulateDIV_numer_ok:   
        !          1453:        cmplw   UnimpRA,UnimpRB                 // see if abs(quotient) fits in 32 bits
        !          1454:        bge     EmulateDIV_initial_ovfl         // handle overflow
        !          1455: 
        !          1456: #if    0
        !          1457: //     Slower, but smaller divide algorithm
        !          1458:        mfctr   DataTemp                        // save the CTR register
        !          1459:        li      MemDataL,32                     // loop for 32 bits
        !          1460:        mtctr   MemDataL                        // setup the counter
        !          1461: EmulateDIV_shift:
        !          1462:        slwi    UnimpRA,UnimpRA,1               // shift 64 bit remainder
        !          1463:        //rlwimi        UnimpRA,UnimpMQtmp,1,0x00000001         // shift in MSB of low 32 bits
        !          1464:        rlwimi  UnimpRA,UnimpMQtmp,1,31,31      // shift in MSB of low 32 bits
        !          1465:        cmplw   UnimpRA,UnimpRB                 // Q = remainder >= denominator
        !          1466:        slwi    UnimpMQtmp,UnimpMQtmp,1         // shift in the quotient bit (assume Q=0)
        !          1467:        blt     EmulateDIV_q0                   // branch when Q=0
        !          1468: EmulateDIV_q1:
        !          1469:        sub     UnimpRA,UnimpRA,UnimpRB         // subtract denom from remainder
        !          1470:        ori     UnimpMQtmp,UnimpMQtmp,1         // set the quotient bit (Q=1)
        !          1471: EmulateDIV_q0:
        !          1472:        bdnz    EmulateDIV_shift                // loop for 32 bits
        !          1473:        mtctr   DataTemp                        // restore the CTR register
        !          1474:        mr      MemDataH,UnimpRA                // MemDataH <- remainder
        !          1475: #else
        !          1476: //     about 1.5x faster, but bigger divide algorithm
        !          1477:        cntlzw  MemDataL,UnimpRB                // MemDataL <- denominator shift amount
        !          1478:        xor     UnimpRA,UnimpRA,UnimpMQtmp      // merge numerator halves for left shift
        !          1479:        slw     UnimpRB,UnimpRB,MemDataL        // UnimpRB <- normalized denom
        !          1480:        rotlw   UnimpRA,UnimpRA,MemDataL        // rotate numer.high xor numer.low
        !          1481:        slw     UnimpMQtmp,UnimpMQtmp,MemDataL  // shift numer.low
        !          1482:        xor             UnimpRA,UnimpRA,UnimpMQtmp// UnimpRA/UnimpMQtmp <- left shifted numer.high/low
        !          1483: 
        !          1484:        srwi    DataTemp,UnimpRB,16     // get upper 16 bits of normalized denom
        !          1485:        divwu   MemDataH,UnimpRA,DataTemp       // compute first 16 bits of quotient estimate
        !          1486:        mullw   DataTemp,MemDataH,DataTemp      // quotient * upper(denom)
        !          1487:        sub             UnimpRA,UnimpRA,DataTemp// compute remainder using upper 16 bits of denom
        !          1488:        slwi    UnimpRA,UnimpRA,16              // shift remainder left by 16 bit
        !          1489:        //rlwimi        UnimpRA,UnimpMQtmp,16,0x0000FFFF
        !          1490:        rlwimi  UnimpRA,UnimpMQtmp,16,16,31
        !          1491:        slwi    UnimpMQtmp,UnimpMQtmp,16
        !          1492:        //rlwinm        DataTemp,UnimpRB,0,0x0000FFFF           // get lower 16 bits of normalized denom
        !          1493:        rlwinm  DataTemp,UnimpRB,0,16,31// get lower 16 bits of normalized denom
        !          1494:        mullw   DataTemp,MemDataH,DataTemp                      // quotient * lower(denom)
        !          1495:        subfc   UnimpRA,DataTemp,UnimpRA                        // compute remainder using lower 16 bits of denom
        !          1496:        subfe.  DataTemp,DataTemp,DataTemp                      // compute borrow
        !          1497:        add             UnimpMQtmp,UnimpMQtmp,MemDataH          // shift in quotient
        !          1498:        bge             EmulateDIV_compute_low
        !          1499: EmulateDIV_correct_high:
        !          1500:        addc    UnimpRA,UnimpRA,UnimpRB
        !          1501:        addze.  DataTemp,DataTemp
        !          1502:        subi    UnimpMQtmp,UnimpMQtmp,1
        !          1503:        blt             EmulateDIV_correct_high
        !          1504: 
        !          1505: EmulateDIV_compute_low:
        !          1506:        srwi    DataTemp,UnimpRB,16                                     // get upper 16 bits of normalized denom
        !          1507:        divwu   MemDataH,UnimpRA,DataTemp                       // compute next 16 bits of quotient estimate
        !          1508:        mullw   DataTemp,MemDataH,DataTemp                      // quotient * upper(denom)
        !          1509:        sub             UnimpRA,UnimpRA,DataTemp                        // compute remainder using upper 16 bits of denom
        !          1510:        slwi    UnimpRA,UnimpRA,16                                      // shift remainder left by 16 bit
        !          1511:        //rlwimi        UnimpRA,UnimpMQtmp,16,0x0000FFFF
        !          1512:        rlwimi  UnimpRA,UnimpMQtmp,16,16,31
        !          1513:        slwi    UnimpMQtmp,UnimpMQtmp,16
        !          1514:        //rlwinm        DataTemp,UnimpRB,0,0x0000FFFF           // get lower 16 bits of normalized denom
        !          1515:        rlwinm  DataTemp,UnimpRB,0,16,31                // get lower 16 bits of normalized denom
        !          1516:        mullw   DataTemp,MemDataH,DataTemp                      // quotient * lower(denom)
        !          1517:        subfc   UnimpRA,DataTemp,UnimpRA                        // compute remainder using lower 16 bits of denom
        !          1518:        subfe.  DataTemp,DataTemp,DataTemp                      // compute borrow
        !          1519:        add             UnimpMQtmp,UnimpMQtmp,MemDataH          // shift in quotient
        !          1520:        bge             EmulateDIV_low_done
        !          1521: EmulateDIV_correct_low:
        !          1522:        addc    UnimpRA,UnimpRA,UnimpRB
        !          1523:        addze.  DataTemp,DataTemp
        !          1524:        subi    UnimpMQtmp,UnimpMQtmp,1
        !          1525:        blt             EmulateDIV_correct_low
        !          1526: EmulateDIV_low_done:
        !          1527:        srw             MemDataH,UnimpRA,MemDataL                       // MemDataH <- remainder
        !          1528: #endif
        !          1529: 
        !          1530: EmulateDIV_correct_signs:
        !          1531:        mr.             MemDataL,UnimpMQtmp                                     // MemDataL <- quotient
        !          1532:        bge             cr1,EmulateDIV_r_done
        !          1533:        neg             MemDataH,MemDataH
        !          1534: EmulateDIV_r_done:
        !          1535:        bns             cr1,EmulateDIV_q_done
        !          1536:        neg.    MemDataL,MemDataL
        !          1537: EmulateDIV_q_done:
        !          1538:        bf              21,EmulateDIV_xer_done
        !          1539: //     crxor   (cr0*4)+lt,(cr0*4)+lt,(cr1*4)+so
        !          1540:        crxor   (rcr0*4)+lt_b,(rcr0*4)+lt_b,(rcr1*4)+so_b
        !          1541:        //rlwinm        UnimpXERtmp,UnimpXERtmp,0,0xBFFFFFFF// clear OV bit
        !          1542:        rlwinm  UnimpXERtmp,UnimpXERtmp,0,2,0   // clear OV bit
        !          1543:        bge             EmulateDIV_xer_done
        !          1544:        oris    UnimpXERtmp,UnimpXERtmp,0xC000          // set SO and OV bits
        !          1545: EmulateDIV_xer_done:
        !          1546:        mtxer   UnimpXERtmp                                                     // restore XER
        !          1547:        mr.             MemDataH,MemDataH
        !          1548:        b               EmulateUpdateRT_cr0_xer_mq
        !          1549: 
        !          1550: EmulateDIV_initial_ovfl:
        !          1551: //     I can't figure out the 601 algorithm for undefined overflow quo/rem.
        !          1552: //     Instead, return the values that would be computed for divide by zero.
        !          1553: EmulateDIV_zero:
        !          1554:        bf      21,EmulateDIV_zero_xer_done
        !          1555:        oris    UnimpXERtmp,UnimpXERtmp,0xC000          // set SO and OV bits
        !          1556: EmulateDIV_zero_xer_done:
        !          1557:        mtxer   UnimpXERtmp                             // restore XER
        !          1558:        not     MemDataL,UnimpRA
        !          1559:        srwi    DataTemp,UnimpRA,31
        !          1560:        mr.     MemDataH,UnimpMQtmp
        !          1561:        add     MemDataL,DataTemp,MemDataL
        !          1562:        b       EmulateUpdateRT_cr0_xer_mq
        !          1563: 
        !          1564: 
        !          1565: EmulateMUL:
        !          1566: //     011111 rt-rt ra-ra rb-rb 00011 01011 .          mul[.]          rt,ra,rb
        !          1567: //     011111 rt-rt ra-ra rb-rb 10011 01011 .          mulo[.]         rt,ra,rb
        !          1568:        mulhw   MemDataL,UnimpRA,UnimpRB                        // RT <- low 32 bits of product
        !          1569:        bt              21,EmulateMULO
        !          1570: //     011111 rt-rt ra-ra rb-rb 00011 01011 .          mul[.]          rt,ra,rb
        !          1571:        mullw.  MemDataH,UnimpRA,UnimpRB                        // MQ <- high 32 bits of product
        !          1572:        b               EmulateUpdateRT_cr0_xer_mq
        !          1573: 
        !          1574: EmulateMULO:
        !          1575: //     011111 rt-rt ra-ra rb-rb 10011 01011 .          mulo[.]         rt,ra,rb
        !          1576:        mullwo. MemDataH,UnimpRA,UnimpRB        // MQ <- high 32 bits of product (update OV)
        !          1577:        b               EmulateUpdateRT_cr0_xer_mq
        !          1578: 
        !          1579: 
        !          1580: EmulateMFSPR_MFTB_MTSPR_CLCS:
        !          1581: //                1 11111 11112 22222 22223 3
        !          1582: //     012345 67890 12345 67890 12345 67890 1
        !          1583: //     ------ ----- ----- ----- ----- ----- -
        !          1584: //     011111 rt-rt 00000 xxxxx 01010 10011 x          mfmq            rt
        !          1585: //     011111 rt-rt 00001 xxxxx 01010 10011 x          mfxer           rt
        !          1586: //     011111 rt-rt 00010 xxxxx 01010 10011 x          mfspr           rt,0x2
        !          1587: //     011111 rt-rt 00011 xxxxx 01010 10011 x          mfspr           rt,0x3
        !          1588: //     011111 rt-rt 00100 xxxxx 01010 10011 x          mfrtcu          rt
        !          1589: //     011111 rt-rt 00101 xxxxx 01010 10011 x          mfrtcl          rt
        !          1590: //     011111 rt-rt 00110 xxxxx 01010 10011 x          mfdec           rt
        !          1591: //     011111 rt-rt 00111 xxxxx 01010 10011 x          mfspr           rt,0x7
        !          1592: //     011111 rt-rt 01000 xxxxx 01010 10011 x          mflr            rt
        !          1593: //     011111 rt-rt 01001 xxxxx 01010 10011 x          mfctr           rt
        !          1594: //     011111 rt-rt 01010 xxxxx 01010 10011 x          mfspr           rt,0xA
        !          1595: //     011111 rt-rt 01011 xxxxx 01010 10011 x          mfspr           rt,0xB
        !          1596: //     011111 rt-rt 01100 xxxxx 01010 10011 x          mfspr           rt,0xC
        !          1597: //     011111 rt-rt 01101 xxxxx 01010 10011 x          mfspr           rt,0xD
        !          1598: //     011111 rt-rt 01110 xxxxx 01010 10011 x          mfspr           rt,0xE
        !          1599: //     011111 rt-rt 01111 xxxxx 01010 10011 x          mfspr           rt,0xF
        !          1600: //     011111 rt-rt 11111 01000 01010 10011 x          mfspr           rt,287
        !          1601: //     011111 rt-rt 11000 11101 01010 10011 x          mfspr           rt,952
        !          1602: //     011111 rt-rt 11001 11101 01010 10011 x          mfspr           rt,953
        !          1603: //     011111 rt-rt 11010 11101 01010 10011 x          mfspr           rt,954
        !          1604: //     011111 rt-rt 11011 11101 01010 10011 x          mfspr           rt,955
        !          1605: //     011111 rt-rt 11100 11101 01010 10011 x          mfspr           rt,956
        !          1606: //     011111 rt-rt 11101 11101 01010 10011 x          mfspr           rt,957
        !          1607: //     011111 rt-rt 11110 11101 01010 10011 x          mfspr           rt,958
        !          1608: //     011111 rt-rt 11111 11101 01010 10011 x          mfspr           rt,959
        !          1609: //     011111 rt-rt 01100 01000 01011 10011 x          mftb            rt
        !          1610: //     011111 rt-rt 01101 01000 01011 10011 x          mftbu           rt
        !          1611: //     011111 rs-rs 00000 xxxxx 01110 10011 x          mtmq            rs
        !          1612: //     011111 rs-rs 00001 xxxxx 01110 10011 x          mtxer           rs
        !          1613: //     011111 rs-rs 00010 xxxxx 01110 10011 x          mtspr           0x2,rs
        !          1614: //     011111 rs-rs 00011 xxxxx 01110 10011 x          mtspr           0x3,rs
        !          1615: //     011111 rs-rs 00100 xxxxx 01110 10011 x          mtspr           0x4,rs
        !          1616: //     011111 rs-rs 00101 xxxxx 01110 10011 x          mtspr           0x5,rs
        !          1617: //     011111 rs-rs 00110 xxxxx 01110 10011 x          mtspr           0x6,rs
        !          1618: //     011111 rs-rs 00111 xxxxx 01110 10011 x          mtspr           0x7,rs
        !          1619: //     011111 rs-rs 01000 xxxxx 01110 10011 x          mtlr            rs
        !          1620: //     011111 rs-rs 01001 xxxxx 01110 10011 x          mtctr           rs
        !          1621: //     011111 rs-rs 01010 xxxxx 01110 10011 x          mtspr           0xA,rs
        !          1622: //     011111 rs-rs 01011 xxxxx 01110 10011 x          mtspr           0xB,rs
        !          1623: //     011111 rs-rs 01100 xxxxx 01110 10011 x          mtspr           0xC,rs
        !          1624: //     011111 rs-rs 01101 xxxxx 01110 10011 x          mtspr           0xD,rs
        !          1625: //     011111 rs-rs 01110 xxxxx 01110 10011 x          mtspr           0xE,rs
        !          1626: //     011111 rs-rs 01111 xxxxx 01110 10011 x          mtspr           0xF,rs
        !          1627: //     011111 rs-rs 11000 11101 01110 10011 x          mtspr           952,rs
        !          1628: //     011111 rs-rs 11001 11101 01110 10011 x          mtspr           953,rs
        !          1629: //     011111 rs-rs 11010 11101 01110 10011 x          mtspr           954,rs
        !          1630: //     011111 rs-rs 11011 11101 01110 10011 x          mtspr           955,rs
        !          1631: //     011111 rs-rs 11100 11101 01110 10011 x          mtspr           956,rs
        !          1632: //     011111 rs-rs 11101 11101 01110 10011 x          mtspr           957,rs
        !          1633: //     011111 rs-rs 11110 11101 01110 10011 x          mtspr           958,rs
        !          1634: //     011111 rs-rs 11111 11101 01110 10011 x          mtspr           959,rs
        !          1635: //     011111 rt-rt ra-ra xxxxx 10000 10011 x          clcs            rt,ra
        !          1636:        bt              25,EmulateMFTB
        !          1637:        bt              21,EmulateCLCS
        !          1638:        cmpwi   cr0,UnimpRA,0x10*4                                      // test for 1xxxx, privileged
        !          1639:        cmpwi   cr1,UnimpRA,0*4
        !          1640:        cmpwi   cr6,UnimpRA,1*4
        !          1641:        bt              23,EmulateMTSPR
        !          1642: EmulateMFSPR:
        !          1643:        bge             EmulatePrivilegedMFSPR                          // privileged SPR
        !          1644: //     011111 rt-rt 00000 xxxxx 01010 10011 x          mfmq            rt
        !          1645: //     011111 rt-rt 00001 xxxxx 01010 10011 x          mfxer           rt
        !          1646: //     011111 rt-rt 00010 xxxxx 01010 10011 x          mfspr           rt,0x2
        !          1647: //     011111 rt-rt 00011 xxxxx 01010 10011 x          mfspr           rt,0x3
        !          1648: //     011111 rt-rt 00100 xxxxx 01010 10011 x          mfrtcu          rt
        !          1649: //     011111 rt-rt 00101 xxxxx 01010 10011 x          mfrtcl          rt
        !          1650: //     011111 rt-rt 00110 xxxxx 01010 10011 x          mfdec           rt
        !          1651: //     011111 rt-rt 00111 xxxxx 01010 10011 x          mfspr           rt,0x7
        !          1652: //     011111 rt-rt 01000 xxxxx 01010 10011 x          mflr            rt
        !          1653: //     011111 rt-rt 01001 xxxxx 01010 10011 x          mfctr           rt
        !          1654: //     011111 rt-rt 01010 xxxxx 01010 10011 x          mfspr           rt,0xA
        !          1655: //     011111 rt-rt 01011 xxxxx 01010 10011 x          mfspr           rt,0xB
        !          1656: //     011111 rt-rt 01100 xxxxx 01010 10011 x          mfspr           rt,0xC
        !          1657: //     011111 rt-rt 01101 xxxxx 01010 10011 x          mfspr           rt,0xD
        !          1658: //     011111 rt-rt 01110 xxxxx 01010 10011 x          mfspr           rt,0xE
        !          1659: //     011111 rt-rt 01111 xxxxx 01010 10011 x          mfspr           rt,0xF
        !          1660: //     CR0 is set as follows:
        !          1661: //             0,1,5,6,8,9 - lt,gt,eq cleared, so set based upon xer 
        !          1662: //             2,3,4,7,A,B,C,D,E,F - based upon add. ra,rb
        !          1663:        crclr   lt_b
        !          1664:        beq     cr1,EmulateMFMQ         // SPR=0, MFMQ
        !          1665:        beq     cr6,EmulateMFXER        // SPR=1, MFXER
        !          1666:        cmpwi   cr1,UnimpRA,5*4
        !          1667:        cmpwi   cr6,UnimpRA,6*4
        !          1668:        beq     cr1,EmulateMFRTC        // SPR=5, MFRTCL
        !          1669:        beq     cr6,EmulateMFDEC        // SPR=6, MFDEC
        !          1670:        cmpwi   cr1,UnimpRA,8*4
        !          1671:        cmpwi   cr6,UnimpRA,9*4
        !          1672:        beq     cr1,EmulateMFLR         // SPR=8, MFLR
        !          1673:        beq     cr6,EmulateMFCTR        // SPR=9, MFCTR
        !          1674: 
        !          1675: //     compute CR0 for RTCU and invalid SPR encodings
        !          1676:        cmpwi   cr6,UnimpRA,4*4
        !          1677:        lwzx    UnimpRA,KernelDataPtr,UnimpRA           // get RA
        !          1678:        lwzx    UnimpRB,KernelDataPtr,UnimpRB           // get RB
        !          1679:        add.    MemDataL,UnimpRA,UnimpRB                        // cr0 based upon RA+RB
        !          1680:        beq             cr6,EmulateMFRTC                                        // SPR=4, MFRTCU
        !          1681:        bf              b_EmulateInvalidSPR,EmulateDisabledInvalidSPR
        !          1682:        b               EmulateUpdateCR0
        !          1683: 
        !          1684: EmulateMFMQ:
        !          1685: //     011111 rt-rt 00000 xxxxx 01010 10011 x          mfmq            rt
        !          1686:        bf              b_EmulatePowerMQ,EmulateDisabledPowerMQ
        !          1687:        lwz             MemDataL,0(UnimpMQptr)                          // get MQ from context block
        !          1688:        b               EmulateUpdateRT_cr0
        !          1689: 
        !          1690: EmulateMFXER:
        !          1691: //     011111 rt-rt 00001 xxxxx 01010 10011 x          mfxer           rt
        !          1692:        bf              b_EmulateInvalidSPR,EmulateDisabledInvalidSPR
        !          1693:        mtcrf   0x80,SavedCR                                            // restore CR0
        !          1694:        //.long (31<<26)+(MemDataL<<21)+(sprXER<<16)+(339<<1)+(1<<0)    // mfxer.       MemDataL
        !          1695:        .long   (31<<26)+(dMemDataL<<21)+(sprXER<<16)+(339<<1)+(1<<0)   // mfxer.       MemDataL
        !          1696:        b               EmulateUpdateRT_cr0
        !          1697: 
        !          1698: EmulateMFRTC:
        !          1699: //     011111 rt-rt 00100 xxxxx 01010 10011 x          mfrtcu          rt
        !          1700: //     011111 rt-rt 00101 xxxxx 01010 10011 x          mfrtcl          rt
        !          1701:        bf              b_EmulatePowerRTC,EmulateDisabledPowerRTC
        !          1702: RetryMFRTC:
        !          1703:        mftbu   MemDataH                                                        // read the 64 bit Time Base register
        !          1704:        mftb    MemDataL
        !          1705:        mftbu   DataTemp
        !          1706:        cmplw   cr1,DataTemp,MemDataH
        !          1707:        bne-    cr1,RetryMFRTC                                          // retry if high half changed
        !          1708: 
        !          1709:        //lwz           DataTemp,TBtoRTCmult(KernelDataPtr)     // TBtoRTCmult
        !          1710:        //lbz           UnimpRA,TBtoRTCshL(KernelDataPtr)       // TBtoRTCshL
        !          1711:        //lbz           UnimpRB,TBtoRTCshR(KernelDataPtr)       // TBtoRTCshR
        !          1712:        mullw   UnimpMQptr,MemDataH,DataTemp            // TBU*TBtoRTCmult (L)
        !          1713:        mulhwu  UnimpMQtmp,MemDataL,DataTemp            // TBL*TBtoRTCmult (H)
        !          1714:        add             UnimpMQptr,UnimpMQptr,UnimpMQtmp        // TBU*TBtoRTCmult (L) + TBL*TBtoRTCmult (H)
        !          1715: 
        !          1716:        bne             cr6,EmulateMFRTCL
        !          1717: 
        !          1718: EmulateMFRTCU:
        !          1719: //     011111 rt-rt 00100 xxxxx 01010 10011 x          mfrtcu          rt
        !          1720:        cmplw   cr1,UnimpMQptr,UnimpMQtmp                       // test for carry out
        !          1721:        srw             UnimpMQptr,UnimpMQptr,UnimpRB
        !          1722:        mulhwu  MemDataL,MemDataH,DataTemp                      // TBU*TBtoRTCmult (upper 32 bits)
        !          1723:        bge+    cr1,$+8
        !          1724:        addi    MemDataL,MemDataL,1                                     // add in carry out
        !          1725:        slw             MemDataL,MemDataL,UnimpRA                       // TBU*TBtoRTCmult (H) left  shifted by TBtoRTCshL
        !          1726:        add             MemDataL,MemDataL,UnimpMQptr            // 32 bit integer seconds
        !          1727:        b               EmulateUpdateRT_cr0
        !          1728: 
        !          1729: EmulateMFRTCL:
        !          1730: //     011111 rt-rt 00101 xxxxx 01010 10011 x          mfrtcl          rt
        !          1731:        mullw   MemDataL,MemDataL,DataTemp                      // TBL*TBtoRTCmult (L)
        !          1732:        srw             MemDataL,MemDataL,UnimpRB                       // TBL*TBtoRTCmult (L) right shifted by TBtoRTCshR
        !          1733:        slw             UnimpMQptr,UnimpMQptr,UnimpRA
        !          1734:        add             MemDataL,MemDataL,UnimpMQptr            // 32 bit fractional seconds
        !          1735:        lis             DataTemp,1000000000>>16
        !          1736:        ori             DataTemp,DataTemp,1000000000&0xFFFF
        !          1737:        mulhwu  MemDataL,MemDataL,DataTemp                      // convert fraction to nanoseconds
        !          1738:        b               EmulateUpdateRT_cr0
        !          1739: 
        !          1740: EmulateMFDEC:
        !          1741: //     011111 rt-rt 00110 xxxxx 01010 10011 x          mfdec           rt
        !          1742:        bf              b_EmulatePowerDEC,EmulateDisabledPowerDEC
        !          1743:        mfspr   MemDataL,fromDEC                                        // get DEC
        !          1744:        b               EmulateUpdateRT_cr0
        !          1745: 
        !          1746: EmulateMFLR:
        !          1747: //     011111 rt-rt 01000 xxxxx 01010 10011 x          mflr            rt
        !          1748:        bf              b_EmulateInvalidSPR,EmulateDisabledInvalidSPR
        !          1749:        mtcrf   0x80,SavedCR                                            // restore CR0
        !          1750:        mtlr    SavedLR                                                         // get LR
        !          1751:        //.long (31<<26)+(MemDataL<<21)+(sprLR<<16)+(339<<1)+(1<<0)     // mflr.        MemDataL
        !          1752:        .long   (31<<26)+(dMemDataL<<21)+(sprLR<<16)+(339<<1)+(1<<0)    // mflr.        MemDataL
        !          1753:        b               EmulateUpdateRT_cr0
        !          1754: 
        !          1755: EmulateMFCTR:
        !          1756: //     011111 rt-rt 01001 xxxxx 01010 10011 x          mfctr           rt
        !          1757:        bf              b_EmulateInvalidSPR,EmulateDisabledInvalidSPR
        !          1758:        mtcrf   0x80,SavedCR                                            // restore CR0
        !          1759:        //.long (31<<26)+(MemDataL<<21)+(sprCTR<<16)+(339<<1)+(1<<0)// mfctr.   MemDataL
        !          1760:        .long   (31<<26)+(dMemDataL<<21)+(sprCTR<<16)+(339<<1)+(1<<0)// mfctr.  MemDataL
        !          1761:        b               EmulateUpdateRT_cr0
        !          1762: 
        !          1763: 
        !          1764:        // the following registers are specific to the 604 and allow
        !          1765:        // performance monitoring for the entire system.
        !          1766:        // For now the access to these privileged registers is allowed to
        !          1767:        // let people do their thing. tjm
        !          1768:        //
        !          1769:        // The registers are:
        !          1770:        //              MMCR0:  SPR - 952
        !          1771:        //              PMC1:   SPR - 953
        !          1772:        //              PMC2:   SPR - 954
        !          1773:        //              SIA:    SPR - 955
        !          1774:        //              MMCR1:  SPR - 956
        !          1775:        //              PMC3:   SPR - 957
        !          1776:        //              PMC4:   SPR - 958
        !          1777:        //              SDA:    SPR - 959
        !          1778:        //
        !          1779:        //              PVR:    SPR - 287
        !          1780: 
        !          1781: EmulatePrivilegedMFSPR:
        !          1782: //     011111 rt-rt 11111 01000 01010 10011 x          mfspr           rt,287
        !          1783: //     011111 rt-rt 11000 11101 01010 10011 x          mfspr           rt,952
        !          1784: //     011111 rt-rt 11001 11101 01010 10011 x          mfspr           rt,953
        !          1785: //     011111 rt-rt 11010 11101 01010 10011 x          mfspr           rt,954
        !          1786: //     011111 rt-rt 11011 11101 01010 10011 x          mfspr           rt,955
        !          1787: //     011111 rt-rt 11100 11101 01010 10011 x          mfspr           rt,956
        !          1788: //     011111 rt-rt 11101 11101 01010 10011 x          mfspr           rt,957
        !          1789: //     011111 rt-rt 11110 11101 01010 10011 x          mfspr           rt,958
        !          1790: //     011111 rt-rt 11111 11101 01010 10011 x          mfspr           rt,959
        !          1791:        mtcrf   0x80,SavedCR                                            // restore CR0
        !          1792:        //rlwinm        UnimpRB,MemInstr,11+10,0x000003FF       // get SPR field
        !          1793:        rlwinm  UnimpRB,MemInstr,11+10,22,31    // get SPR field
        !          1794:        cmplwi  cr1,UnimpRB,((287&0x1F)<<5)|(287>>5)// test for PVR Register
        !          1795:        beq             cr1,EmulateMFPVR                                        // SPR=287, MFPVR
        !          1796: 
        !          1797:        bf              b_EmulatePrivSPRperf0,EmulatePRIVILEGED
        !          1798:                                                                // 604 and Sirocco
        !          1799:        cmplwi  cr1,UnimpRB,((sprMMCR0&0x1F)<<5)|(sprMMCR0>>5)  // test for MMCR0 Register
        !          1800:        beq             cr1,EmulateMFMMCR0                                      // SPR=952, MFMMCR0
        !          1801:        cmplwi  cr1,UnimpRB,((sprPMC1&0x1F)<<5)|(sprPMC1>>5)    // test for PMC1 Register
        !          1802:        beq             cr1,EmulateMFPMC1                                       // SPR=953, MFPMC1
        !          1803:        cmplwi  cr1,UnimpRB,((sprPMC2&0x1F)<<5)|(sprPMC2>>5)    // test for PMC2 Register
        !          1804:        beq             cr1,EmulateMFPMC2                                       // SPR=954, MFPMC2
        !          1805:        cmplwi  cr1,UnimpRB,((sprSIA&0x1F)<<5)|(sprSIA>>5)              // test for SIA Register
        !          1806:        beq             cr1,EmulateMFSIA                                        // SPR=955, MFSIA
        !          1807: 
        !          1808:        bf              b_EmulatePrivSPRperf,EmulatePrivilegedMFSPRNoSDA
        !          1809:                                                                                                                // 604 and Sirocco
        !          1810:        cmplwi  cr1,UnimpRB,((sprSDA&0x1F)<<5)|(sprSDA>>5)              // test for SDA Register
        !          1811:        beq             cr1,EmulateMFSDA                                        // SPR=959, MFSDA
        !          1812: 
        !          1813: EmulatePrivilegedMFSPRNoSDA:
        !          1814:        bf              b_EmulatePrivSPRperf2,EmulatePRIVILEGED
        !          1815:                                                                                                                // Sirocco only
        !          1816:        cmplwi  cr1,UnimpRB,((sprMMCR1&0x1F)<<5)|(sprMMCR1>>5)  // test for MMCR1 Register
        !          1817:        beq             cr1,EmulateMFMMCR1                                      // SPR=956, MFMMCR1
        !          1818:        cmplwi  cr1,UnimpRB,((sprPMC3&0x1F)<<5)|(sprPMC3>>5)    // test for PMC3 Register
        !          1819:        beq             cr1,EmulateMFPMC3                                       // SPR=957, MFPMC3
        !          1820:        cmplwi  cr1,UnimpRB,((sprPMC4&0x1F)<<5)|(sprPMC4>>5)    // test for PMC4 Register
        !          1821:        beq             cr1,EmulateMFPMC4                                       // SPR=958, MFPMC4
        !          1822: 
        !          1823:        b               EmulatePRIVILEGED
        !          1824: 
        !          1825: EmulateMFPVR:
        !          1826: //     011111 rt-rt 11111 01000 01010 10011 x          mfspr           rt,287
        !          1827:        bf              b_EmulatePrivMFPVR,EmulatePRIVILEGED
        !          1828:        //.long (31<<26)+(MemDataL<<21)+((sprPVR&0x1F)<<16)+((sprPVR>>5)<<11)+(339<<1)+(1<<0)
        !          1829:        .long   (31<<26)+(dMemDataL<<21)+((sprPVR&0x1F)<<16)+((sprPVR>>5)<<11)+(339<<1)+(1<<0)
        !          1830:        b               EmulateUpdateRT_cr0
        !          1831: 
        !          1832: EmulateMFMMCR0:
        !          1833: //     011111 rt-rt 11000 11101 01010 10011 x          mfspr           rt,952
        !          1834:        //.long (31<<26)+(MemDataL<<21)+((sprMMCR0&0x1F)<<16)+((sprMMCR0>>5)<<11)+(339<<1)+(1<<0)
        !          1835:        .long   (31<<26)+(dMemDataL<<21)+((sprMMCR0&0x1F)<<16)+((sprMMCR0>>5)<<11)+(339<<1)+(1<<0)
        !          1836:        b               EmulateUpdateRT_cr0
        !          1837: 
        !          1838: EmulateMFPMC1:
        !          1839: //     011111 rt-rt 11001 11101 01010 10011 x          mfspr           rt,953
        !          1840:        //.long (31<<26)+(MemDataL<<21)+((sprPMC1&0x1F)<<16)+((sprPMC1>>5)<<11)+(339<<1)+(1<<0)
        !          1841:        .long   (31<<26)+(dMemDataL<<21)+((sprPMC1&0x1F)<<16)+((sprPMC1>>5)<<11)+(339<<1)+(1<<0)
        !          1842:        b               EmulateUpdateRT_cr0
        !          1843: 
        !          1844: EmulateMFPMC2:
        !          1845: //     011111 rt-rt 11010 11101 01010 10011 x          mfspr           rt,954
        !          1846:        //.long (31<<26)+(MemDataL<<21)+((sprPMC2&0x1F)<<16)+((sprPMC2>>5)<<11)+(339<<1)+(1<<0)
        !          1847:        .long   (31<<26)+(dMemDataL<<21)+((sprPMC2&0x1F)<<16)+((sprPMC2>>5)<<11)+(339<<1)+(1<<0)
        !          1848:        b               EmulateUpdateRT_cr0
        !          1849: 
        !          1850: EmulateMFSIA:
        !          1851: //     011111 rt-rt 11011 11101 01010 10011 x          mfspr           rt,955
        !          1852:        //.long (31<<26)+(MemDataL<<21)+((sprSIA&0x1F)<<16)+((sprSIA>>5)<<11)+(339<<1)+(1<<0)
        !          1853:        .long   (31<<26)+(dMemDataL<<21)+((sprSIA&0x1F)<<16)+((sprSIA>>5)<<11)+(339<<1)+(1<<0)
        !          1854:        b               EmulateUpdateRT_cr0
        !          1855: 
        !          1856: EmulateMFMMCR1:
        !          1857: //     011111 rt-rt 11000 11101 01010 10011 x          mfspr           rt,956
        !          1858:        //.long (31<<26)+(MemDataL<<21)+((sprMMCR1&0x1F)<<16)+((sprMMCR1>>5)<<11)+(339<<1)+(1<<0)
        !          1859:        .long   (31<<26)+(dMemDataL<<21)+((sprMMCR1&0x1F)<<16)+((sprMMCR1>>5)<<11)+(339<<1)+(1<<0)
        !          1860:        b               EmulateUpdateRT_cr0
        !          1861: 
        !          1862: EmulateMFPMC3:
        !          1863: //     011111 rt-rt 11001 11101 01010 10011 x          mfspr           rt,957
        !          1864:        //.long (31<<26)+(MemDataL<<21)+((sprPMC3&0x1F)<<16)+((sprPMC3>>5)<<11)+(339<<1)+(1<<0)
        !          1865:        .long   (31<<26)+(dMemDataL<<21)+((sprPMC3&0x1F)<<16)+((sprPMC3>>5)<<11)+(339<<1)+(1<<0)
        !          1866:        b               EmulateUpdateRT_cr0
        !          1867: 
        !          1868: EmulateMFPMC4:
        !          1869: //     011111 rt-rt 11010 11101 01010 10011 x          mfspr           rt,958
        !          1870:        //.long (31<<26)+(MemDataL<<21)+((sprPMC4&0x1F)<<16)+((sprPMC4>>5)<<11)+(339<<1)+(1<<0)
        !          1871:        .long   (31<<26)+(dMemDataL<<21)+((sprPMC4&0x1F)<<16)+((sprPMC4>>5)<<11)+(339<<1)+(1<<0)
        !          1872:        b               EmulateUpdateRT_cr0
        !          1873: 
        !          1874: EmulateMFSDA:
        !          1875: //     011111 rt-rt 11111 11101 01010 10011 x          mfspr           rt,959
        !          1876:        //.long (31<<26)+(MemDataL<<21)+((sprSDA&0x1F)<<16)+((sprSDA>>5)<<11)+(339<<1)+(1<<0)
        !          1877:        .long   (31<<26)+(dMemDataL<<21)+((sprSDA&0x1F)<<16)+((sprSDA>>5)<<11)+(339<<1)+(1<<0)
        !          1878:        b               EmulateUpdateRT_cr0
        !          1879: 
        !          1880: 
        !          1881: EmulateMFTB:
        !          1882: //     011111 rt-rt 01100 01000 01011 10011 x          mftb            rt
        !          1883: //     011111 rt-rt 01101 01000 01011 10011 x          mftbu           rt
        !          1884:        //rlwinm        DataTemp,MemInstr,6+5+10,0x000003FF     // get the TBR field
        !          1885:        rlwinm  DataTemp,MemInstr,6+5+10,22,31  // get the TBR field
        !          1886:        cmplwi  cr1,DataTemp,((268&0x1F)<<5)|(268>>5)   // test for MFTBl
        !          1887:        cmplwi  cr6,DataTemp,((269&0x1F)<<5)|(269>>5)   // test for MFTBu
        !          1888: //     cror    cr0*4+eq,cr1*4+eq,cr6*4+eq                      // see if valid TBR field
        !          1889:        cror    rcr0*4+eq_b,rcr1*4+eq_b,rcr6*4+eq_b                     // see if valid TBR field
        !          1890:        bne             cr0,EmulateILLEGAL                                      // invalid TBR field
        !          1891: 
        !          1892: RetryMFTB:
        !          1893:        mfspr   MemDataH,fromRTCU                                       // assuming 601, read Power RTC timer
        !          1894:        mfspr   MemDataL,fromRTCL
        !          1895:        mfspr   DataTemp,fromRTCU
        !          1896:        xor.    DataTemp,DataTemp,MemDataH
        !          1897:        bne-    RetryMFTB                                                       // retry if high half changed
        !          1898:        lis             DataTemp,1000000000>>16
        !          1899:        ori             DataTemp,DataTemp,1000000000&0xFFFF
        !          1900:        mfspr   UnimpMQtmp,sprMQ                                        // preserve MQ from 601 multiply ops
        !          1901: 
        !          1902: //     011111 rt-rt 01100 01000 01011 10011 x          mftb            rt
        !          1903:        mullw   UnimpRB,MemDataH,DataTemp                       // convert Power timer to PowerPC timer
        !          1904:        mtspr   sprMQ,UnimpMQtmp                                        // restore MQ after 601 multiply ops
        !          1905:        add             MemDataL,MemDataL,UnimpRB                       // compute TBL
        !          1906:        beq             cr1,EmulateUpdateRT                                     // update RT register, when TBL
        !          1907: 
        !          1908: //     011111 rt-rt 01101 01000 01011 10011 x          mftbu           rt
        !          1909:        cmplw   MemDataL,UnimpRB                                        // test for carry out
        !          1910:        mulhwu  MemDataL,MemDataH,DataTemp                      // compute TBU
        !          1911:        mtspr   sprMQ,UnimpMQtmp                                        // restore MQ after 601 multiply ops
        !          1912:        bge             EmulateUpdateRT                                         // update RT register, when TBU, no carry out
        !          1913:        addi    MemDataL,MemDataL,1                                     // add in carry out
        !          1914:        b               EmulateUpdateRT                                         // update RT register, when TBU, carry out
        !          1915: 
        !          1916: 
        !          1917: EmulateMTSPR:
        !          1918:        lwzx    UnimpRS,KernelDataPtr,UnimpRS           // get RS
        !          1919:        bge             EmulatePrivilegedMTSPR                          // privileged SPR
        !          1920: //     011111 rs-rs 00000 xxxxx 01110 10011 x          mtmq            rs
        !          1921: //     011111 rs-rs 00001 xxxxx 01110 10011 x          mtxer           rs
        !          1922: //     011111 rs-rs 00010 xxxxx 01110 10011 x          mtspr           0x2,rs
        !          1923: //     011111 rs-rs 00011 xxxxx 01110 10011 x          mtspr           0x3,rs
        !          1924: //     011111 rs-rs 00100 xxxxx 01110 10011 x          mtspr           0x4,rs
        !          1925: //     011111 rs-rs 00101 xxxxx 01110 10011 x          mtspr           0x5,rs
        !          1926: //     011111 rs-rs 00110 xxxxx 01110 10011 x          mtspr           0x6,rs
        !          1927: //     011111 rs-rs 00111 xxxxx 01110 10011 x          mtspr           0x7,rs
        !          1928: //     011111 rs-rs 01000 xxxxx 01110 10011 x          mtlr            rs
        !          1929: //     011111 rs-rs 01001 xxxxx 01110 10011 x          mtctr           rs
        !          1930: //     011111 rs-rs 01010 xxxxx 01110 10011 x          mtspr           0xA,rs
        !          1931: //     011111 rs-rs 01011 xxxxx 01110 10011 x          mtspr           0xB,rs
        !          1932: //     011111 rs-rs 01100 xxxxx 01110 10011 x          mtspr           0xC,rs
        !          1933: //     011111 rs-rs 01101 xxxxx 01110 10011 x          mtspr           0xD,rs
        !          1934: //     011111 rs-rs 01110 xxxxx 01110 10011 x          mtspr           0xE,rs
        !          1935: //     011111 rs-rs 01111 xxxxx 01110 10011 x          mtspr           0xF,rs
        !          1936:        mr.             UnimpRS,UnimpRS                                         // cr0 based upon RS
        !          1937:        beq             cr1,EmulateMTMQ                                         // SPR=0, MTMQ
        !          1938:        bf              b_EmulateInvalidSPR,EmulateDisabledInvalidSPR
        !          1939:        beq             cr6,EmulateMTXER                                        // SPR=1, MTXER
        !          1940:        cmpwi   cr1,UnimpRA,8*4
        !          1941:        cmpwi   cr6,UnimpRA,9*4
        !          1942:        beq             cr1,EmulateMTLR                                         // SPR=8, MTLR
        !          1943:        beq             cr6,EmulateMTCTR                                        // SPR=9, MTCTR
        !          1944:        b               EmulateUpdateCR0
        !          1945: 
        !          1946: EmulateMTMQ:
        !          1947: //     011111 rs-rs 00000 xxxxx 01110 10011 x          mtmq            rs
        !          1948:        bf              b_EmulatePowerMQ,EmulateDisabledPowerMQ
        !          1949:        stw             UnimpRS,0(UnimpMQptr)                           // update MQ in context block
        !          1950:        b               EmulateUpdateCR0
        !          1951: 
        !          1952: EmulateMTXER:
        !          1953: //     011111 rs-rs 00001 xxxxx 01110 10011 x          mtxer           rs
        !          1954:        mtcrf   0x80,SavedCR                                            // restore CR0
        !          1955:        //.long (31<<26)+(UnimpRS<<21)+(0x01<<16)+(467<<1)+(1<<0)       //      mtxer.  UnimpRS
        !          1956:        .long   (31<<26)+(dUnimpRS<<21)+(0x01<<16)+(467<<1)+(1<<0)      //      mtxer.  UnimpRS
        !          1957:        b               EmulateUpdateCR0
        !          1958: 
        !          1959: EmulateMTLR:
        !          1960: //     011111 rs-rs 01000 xxxxx 01110 10011 x          mtlr            rs
        !          1961:        mtcrf   0x80,SavedCR                                            // restore CR0
        !          1962:        mr              SavedLR,UnimpRS                                         // update LR
        !          1963:        //.long (31<<26)+(UnimpRS<<21)+(0x08<<16)+(467<<1)+(1<<0)       //      mtlr.   UnimpRS
        !          1964:        .long   (31<<26)+(dUnimpRS<<21)+(0x08<<16)+(467<<1)+(1<<0)      //      mtlr.   UnimpRS
        !          1965:        b               EmulateUpdateCR0
        !          1966: 
        !          1967: EmulateMTCTR:
        !          1968: //     011111 rs-rs 01001 xxxxx 01110 10011 x          mtctr           rs
        !          1969:        mtcrf   0x80,SavedCR                                            // restore CR0
        !          1970:        //.long (31<<26)+(UnimpRS<<21)+(0x09<<16)+(467<<1)+(1<<0)       //      mtctr.  UnimpRS
        !          1971:        .long   (31<<26)+(dUnimpRS<<21)+(0x09<<16)+(467<<1)+(1<<0)      //      mtctr.  UnimpRS
        !          1972:        b               EmulateUpdateCR0
        !          1973: 
        !          1974: EmulatePrivilegedMTSPR:
        !          1975: //     011111 rs-rs 11000 11101 01110 10011 x          mtspr           952,rs
        !          1976: //     011111 rs-rs 11001 11101 01110 10011 x          mtspr           953,rs
        !          1977: //     011111 rs-rs 11010 11101 01110 10011 x          mtspr           954,rs
        !          1978: //     011111 rs-rs 11011 11101 01110 10011 x          mtspr           955,rs
        !          1979: //     011111 rs-rs 11100 11101 01110 10011 x          mtspr           956,rs
        !          1980: //     011111 rs-rs 11101 11101 01110 10011 x          mtspr           957,rs
        !          1981: //     011111 rs-rs 11110 11101 01110 10011 x          mtspr           958,rs
        !          1982: //     011111 rs-rs 11111 11101 01110 10011 x          mtspr           959,rs
        !          1983:        bf              b_EmulatePrivSPRperf0,EmulatePRIVILEGED
        !          1984:        mtcrf   0x80,SavedCR                                            // restore CR0
        !          1985:        //rlwinm        UnimpRB,MemInstr,11+10,0x000003FF       // get SPR field
        !          1986:        rlwinm  UnimpRB,MemInstr,11+10,22,31    // get SPR field
        !          1987:                                                                                                // 604 and Sirocco
        !          1988:        cmplwi  cr1,UnimpRB,((sprMMCR0&0x1F)<<5)|(sprMMCR0>>5)  // test for MMCR0 Register
        !          1989:        beq             cr1,EmulateMTMMCR0                                      // SPR=952, MTMMCR0
        !          1990:        cmplwi  cr1,UnimpRB,((sprPMC1&0x1F)<<5)|(sprPMC1>>5)    // test for PMC1 Register
        !          1991:        beq             cr1,EmulateMTPMC1                                       // SPR=953, MTPMC1
        !          1992:        cmplwi  cr1,UnimpRB,((sprPMC2&0x1F)<<5)|(sprPMC2>>5)    // test for PMC2 Register
        !          1993:        beq             cr1,EmulateMTPMC2                                       // SPR=954, MTPMC2
        !          1994:        cmplwi  cr1,UnimpRB,((sprSIA&0x1F)<<5)|(sprSIA>>5)              // test for SIA Register
        !          1995:        beq             cr1,EmulateMTSIA                                        // SPR=955, MTSIA
        !          1996: 
        !          1997:        bf              b_EmulatePrivSPRperf,EmulatePrivilegedMTSPRNoSDA
        !          1998:                                                                                                // Sirocco only
        !          1999:        cmplwi  cr1,UnimpRB,((sprSDA&0x1F)<<5)|(sprSDA>>5)              // test for SDA Register
        !          2000:        beq             cr1,EmulateMTSDA                                        // SPR=959, MTSDA
        !          2001: 
        !          2002: EmulatePrivilegedMTSPRNoSDA:
        !          2003:        bf              b_EmulatePrivSPRperf2,EmulatePRIVILEGED
        !          2004:                                                                                                                // Sirocco only
        !          2005:        cmplwi  cr1,UnimpRB,((sprMMCR1&0x1F)<<5)|(sprMMCR1>>5)  // test for MMCR1 Register
        !          2006:        beq             cr1,EmulateMTMMCR1                                      // SPR=956, MTMMCR1
        !          2007:        cmplwi  cr1,UnimpRB,((sprPMC3&0x1F)<<5)|(sprPMC3>>5)    // test for PMC3 Register
        !          2008:        beq             cr1,EmulateMTPMC3                                       // SPR=957, MTPMC3
        !          2009:        cmplwi  cr1,UnimpRB,((sprPMC4&0x1F)<<5)|(sprPMC4>>5)    // test for PMC4 Register
        !          2010:        beq             cr1,EmulateMTPMC4                                       // SPR=958, MTPMC4
        !          2011: 
        !          2012:        b               EmulatePRIVILEGED
        !          2013: 
        !          2014: EmulateMTMMCR0:
        !          2015: //     011111 rs-rs 11000 11101 01110 10011 x          mtspr           952,rs
        !          2016:        //.long (31<<26)+(UnimpRS<<21)+((sprMMCR0&0x1F)<<16)+((sprMMCR0>>5)<<11)+(467<<1)+(1<<0)
        !          2017:        .long   (31<<26)+(dUnimpRS<<21)+((sprMMCR0&0x1F)<<16)+((sprMMCR0>>5)<<11)+(467<<1)+(1<<0)
        !          2018:        b               EmulateUpdateCR0
        !          2019: 
        !          2020: EmulateMTPMC1:
        !          2021: //     011111 rs-rs 11001 11101 01110 10011 x          mtspr           953,rs
        !          2022:        //.long (31<<26)+(UnimpRS<<21)+((sprPMC1&0x1F)<<16)+((sprPMC1>>5)<<11)+(467<<1)+(1<<0)
        !          2023:        .long   (31<<26)+(dUnimpRS<<21)+((sprPMC1&0x1F)<<16)+((sprPMC1>>5)<<11)+(467<<1)+(1<<0)
        !          2024:        b               EmulateUpdateCR0
        !          2025: 
        !          2026: EmulateMTPMC2:
        !          2027: //     011111 rs-rs 11010 11101 01110 10011 x          mtspr           954,rs
        !          2028:        //.long (31<<26)+(UnimpRS<<21)+((sprPMC2&0x1F)<<16)+((sprPMC2>>5)<<11)+(467<<1)+(1<<0)
        !          2029:        .long   (31<<26)+(dUnimpRS<<21)+((sprPMC2&0x1F)<<16)+((sprPMC2>>5)<<11)+(467<<1)+(1<<0)
        !          2030:        b               EmulateUpdateCR0
        !          2031: 
        !          2032: EmulateMTSIA:
        !          2033: //     011111 rs-rs 11011 11101 01110 10011 x          mtspr           955,rs
        !          2034:        //.long (31<<26)+(UnimpRS<<21)+((sprSIA&0x1F)<<16)+((sprSIA>>5)<<11)+(467<<1)+(1<<0)
        !          2035:        .long   (31<<26)+(dUnimpRS<<21)+((sprSIA&0x1F)<<16)+((sprSIA>>5)<<11)+(467<<1)+(1<<0)
        !          2036:        b               EmulateUpdateCR0
        !          2037: 
        !          2038: EmulateMTMMCR1:
        !          2039: //     011111 rs-rs 11000 11101 01110 10011 x          mtspr           956,rs
        !          2040:        //.long (31<<26)+(UnimpRS<<21)+((sprMMCR1&0x1F)<<16)+((sprMMCR1>>5)<<11)+(467<<1)+(1<<0)
        !          2041:        .long   (31<<26)+(dUnimpRS<<21)+((sprMMCR1&0x1F)<<16)+((sprMMCR1>>5)<<11)+(467<<1)+(1<<0)
        !          2042:        b               EmulateUpdateCR0
        !          2043: 
        !          2044: EmulateMTPMC3:
        !          2045: //     011111 rs-rs 11001 11101 01110 10011 x          mtspr           957,rs
        !          2046:        //.long (31<<26)+(UnimpRS<<21)+((sprPMC3&0x1F)<<16)+((sprPMC3>>5)<<11)+(467<<1)+(1<<0)
        !          2047:        .long   (31<<26)+(dUnimpRS<<21)+((sprPMC3&0x1F)<<16)+((sprPMC3>>5)<<11)+(467<<1)+(1<<0)
        !          2048:        b               EmulateUpdateCR0
        !          2049: 
        !          2050: EmulateMTPMC4:
        !          2051: //     011111 rs-rs 11010 11101 01110 10011 x          mtspr           958,rs
        !          2052:        //.long (31<<26)+(UnimpRS<<21)+((sprPMC4&0x1F)<<16)+((sprPMC4>>5)<<11)+(467<<1)+(1<<0)
        !          2053:        .long   (31<<26)+(dUnimpRS<<21)+((sprPMC4&0x1F)<<16)+((sprPMC4>>5)<<11)+(467<<1)+(1<<0)
        !          2054:        b               EmulateUpdateCR0
        !          2055: 
        !          2056: EmulateMTSDA:
        !          2057: //     011111 rs-rs 11111 11101 01110 10011 x          mtspr           959,rs
        !          2058:        //.long (31<<26)+(UnimpRS<<21)+((sprSDA&0x1F)<<16)+((sprSDA>>5)<<11)+(467<<1)+(1<<0)
        !          2059:        .long   (31<<26)+(dUnimpRS<<21)+((sprSDA&0x1F)<<16)+((sprSDA>>5)<<11)+(467<<1)+(1<<0)
        !          2060:        b               EmulateUpdateCR0
        !          2061: 
        !          2062: 
        !          2063: EmulateCLCS:
        !          2064: //     011111 rt-rt ra-ra xxxxx 10000 10011 x          clcs            rt,ra
        !          2065:        bf              b_EmulatePowerCLCS,EmulateDisabledPowerCLCS
        !          2066:        //rlwinm.       UnimpRA,MemInstr,11+5,0x0000000F        // cr0 based upon low 4 bits of RA field
        !          2067:        rlwinm. UnimpRA,MemInstr,11+5,28,31     // cr0 based upon low 4 bits of RA field
        !          2068:        //rlwinm        MemDataL,MemInstr,11+5,0x0000000E       // setup to test for inst/data cache size
        !          2069:        rlwinm  MemDataL,MemInstr,11+5,28,30    // setup to test for inst/data cache size
        !          2070:        cmpwi   cr1,MemDataL,0xA                                        // inst/data cache sizes are special cases
        !          2071: //     la              UnimpRA,EmulateCLCS_info-MemProcBase(UnimpRA)
        !          2072:        lbzx    UnimpRA,MemProcPtr,UnimpRA                      // get the offset within ProcessorInfo
        !          2073:        //la            MemDataL,PI+ProcessorInfoStart(KernelDataPtr)
        !          2074:        beq             cr1,EmulateCLCS_word                            // inst/data cache size is 4 bytes
        !          2075:        lhzx    MemDataL,MemDataL,UnimpRA                       // all others are 2 bytes
        !          2076:        b               EmulateUpdateRT_cr0
        !          2077: EmulateCLCS_word:
        !          2078:        lwzx    MemDataL,MemDataL,UnimpRA                       // get the 4 byte inst/data cache size
        !          2079:        b               EmulateUpdateRT_cr0
        !          2080: 
        !          2081: EmulateCLCS_info:
        !          2082: #if    0
        !          2083:        .byte   DataCacheLineSize-ProcessorInfoStart            // x0000 :    64 - undefined
        !          2084:        .byte   DataCacheLineSize-ProcessorInfoStart            // x0001 :    64 - undefined
        !          2085:        .byte   DataCacheLineSize-ProcessorInfoStart            // x0010 :    64 - undefined
        !          2086:        .byte   DataCacheLineSize-ProcessorInfoStart            // x0011 :    64 - undefined
        !          2087: 
        !          2088:        .byte   DataCacheBlockSizeTouch-ProcessorInfoStart      // x0100 :    32 - touch cache sector size
        !          2089:        .byte   InstCacheBlockSize-ProcessorInfoStart           // x0101 :    32 - inst cache sector size
        !          2090:        .byte   DataCacheBlockSize-ProcessorInfoStart           // x0110 :    32 - data cache sector size
        !          2091:        .byte   CombinedCaches-ProcessorInfoStart                       // x0111 :     1 - combined cache
        !          2092: 
        !          2093:        .byte   InstCacheAssociativity-ProcessorInfoStart       // x1000 :     8 - inst cache set associativity
        !          2094:        .byte   DataCacheAssociativity-ProcessorInfoStart       // x1001 :     8 - data cache set associativity
        !          2095:        .byte   InstCacheTotalSize-ProcessorInfoStart           // x1010 : 32768 - inst cache size
        !          2096:        .byte   DataCacheTotalSize-ProcessorInfoStart           // x1011 : 32768 - data cache size
        !          2097: 
        !          2098:        .byte   InstCacheLineSize-ProcessorInfoStart            // x1100 :    64 - inst cache line size
        !          2099:        .byte   DataCacheLineSize-ProcessorInfoStart            // x1101 :    64 - data cache line size
        !          2100:        .byte   DataCacheLineSize-ProcessorInfoStart            // x1110 :    64 - min line size
        !          2101:        .byte   DataCacheLineSize-ProcessorInfoStart            // x1111 :    64 - max line size
        !          2102: #endif
        !          2103: 
        !          2104: 
        !          2105: 
        !          2106: EmulateRRIB_SHIFTE:
        !          2107: //                1 11111 11112 22222 22223 3
        !          2108: //     012345 67890 12345 67890 12345 67890 1
        !          2109: //     ------ ----- ----- ----- ----- ----- -
        !          2110: //     011111 rs-rs ra-ra rb-rb 00100 11001 .          sle[.]          ra,rs,rb
        !          2111: //     011111 rs-rs ra-ra rb-rb 00110 11001 .          sleq[.]         ra,rs,rb
        !          2112: //     011111 rs-rs ra-ra rb-rb 10000 11001 .          rrib[.]         ra,rs,rb
        !          2113: //     011111 rs-rs ra-ra rb-rb 10100 11001 .          sre[.]          ra,rs,rb
        !          2114: //     011111 rs-rs ra-ra rb-rb 10110 11001 .          sreq[.]         ra,rs,rb
        !          2115: //     011111 rs-rs ra-ra rb-rb 11100 11001 .          srea[.]         ra,rs,rb
        !          2116:        lwzx    UnimpRB,KernelDataPtr,UnimpRB           // get RB
        !          2117:        //rlwinm        UnimpRB,UnimpRB,0,0x1F                          // just use low 5 bits of RB
        !          2118:        rlwinm  UnimpRB,UnimpRB,0,27,31         // just use low 5 bits of RB
        !          2119:        bt              23,EmulateSHIFT
        !          2120: EmulateRRIB:
        !          2121: //     011111 rs-rs ra-ra rb-rb 10000 11001 .          rrib[.]         ra,rs,rb
        !          2122:        bf              b_EmulatePowerComplex,EmulateDisabledPowerComplex
        !          2123:        lwzx    UnimpRS,KernelDataPtr,UnimpRS           // get RS
        !          2124:        lis             DataTemp,0xFFFF8000                                     // mask for bit 0
        !          2125:        lwzx    MemDataL,KernelDataPtr,UnimpRA          // get RA
        !          2126:        srw             DataTemp,DataTemp,UnimpRB                       // mask for bit specified by RB
        !          2127:        srw             UnimpRS,UnimpRS,UnimpRB                         // position data to be inserted
        !          2128:        b               EmulateUpdateRA_cr0_insert                      // insert the bit
        !          2129: 
        !          2130: 
        !          2131: EmulateSHIFTQ:
        !          2132: //                1 11111 11112 22222 22223 3
        !          2133: //     012345 67890 12345 67890 12345 67890 1
        !          2134: //     ------ ----- ----- ----- ----- ----- -
        !          2135: //     011111 rs-rs ra-ra rb-rb 00100 11000 .          slq[.]          ra,rs,rb
        !          2136: //     011111 rs-rs ra-ra sh-sh 00101 11000 .          sliq[.]         ra,rs,sh
        !          2137: //     011111 rs-rs ra-ra rb-rb 00110 11000 .          sllq[.]         ra,rs,rb
        !          2138: //     011111 rs-rs ra-ra sh-sh 00111 11000 .          slliq[.]        ra,rs,sh
        !          2139: //     011111 rs-rs ra-ra rb-rb 10100 11000 .          srq[.]          ra,rs,rb
        !          2140: //     011111 rs-rs ra-ra sh-sh 10101 11000 .          sriq[.]         ra,rs,sh
        !          2141: //     011111 rs-rs ra-ra rb-rb 10110 11000 .          srlq[.]         ra,rs,rb
        !          2142: //     011111 rs-rs ra-ra sh-sh 10111 11000 .          srliq[.]        ra,rs,sh
        !          2143: //     011111 rs-rs ra-ra rb-rb 11100 11000 .          sraq[.]         ra,rs,rb
        !          2144: //     011111 rs-rs ra-ra sh-sh 11101 11000 .          sraiq[.]        ra,rs,sh
        !          2145:                        bt              25,EmulateSHIFT_imm
        !          2146: //     011111 rs-rs ra-ra rb-rb 00100 11000 .          slq[.]          ra,rs,rb
        !          2147: //     011111 rs-rs ra-ra rb-rb 00110 11000 .          sllq[.]         ra,rs,rb
        !          2148: //     011111 rs-rs ra-ra rb-rb 10100 11000 .          srq[.]          ra,rs,rb
        !          2149: //     011111 rs-rs ra-ra rb-rb 10110 11000 .          srlq[.]         ra,rs,rb
        !          2150: //     011111 rs-rs ra-ra rb-rb 11100 11000 .          sraq[.]         ra,rs,rb
        !          2151:        lwzx    UnimpRB,KernelDataPtr,UnimpRB           // get RB
        !          2152:        //rlwinm        UnimpRB,UnimpRB,0,0x3F                          // just use low 6 bits of RB
        !          2153:        rlwinm  UnimpRB,UnimpRB,0,26,31         // just use low 6 bits of RB
        !          2154:        bf              24,EmulateSHIFT
        !          2155: //     011111 rs-rs ra-ra rb-rb 00110 11000 .          sllq[.]         ra,rs,rb
        !          2156: //     011111 rs-rs ra-ra rb-rb 10110 11000 .          srlq[.]         ra,rs,rb
        !          2157:        cmpwi   cr0,UnimpRB,31
        !          2158:        crnot   23,23                                                           // clear bit 23, don't update MQ
        !          2159:        ble             EmulateSHIFT
        !          2160:        bf              b_EmulatePowerMQ,EmulateDisabledPowerMQ
        !          2161: //     011111 rs-rs ra-ra rb-rb 00110 11000 .          sllq[.]         ra,rs,rb        (rb>31)
        !          2162: //     011111 rs-rs ra-ra rb-rb 10110 11000 .          srlq[.]         ra,rs,rb        (rb>31)
        !          2163:        lwz             MemDataH,0(UnimpMQptr)                          // get MQ from context block
        !          2164:        li              DataTemp,-1
        !          2165:        //rlwinm        UnimpRB,UnimpRB,0,0x1F                          // just use low 5 bits of RB
        !          2166:        rlwinm  UnimpRB,UnimpRB,0,27,31         // just use low 5 bits of RB
        !          2167:        bt              21,EmulateSHIFT_srlq
        !          2168: EmulateSHIFT_sllq:
        !          2169: //     011111 rs-rs ra-ra rb-rb 00110 11000 .          sllq[.]         ra,rs,rb        (rb>31)
        !          2170:        slw             DataTemp,DataTemp,UnimpRB
        !          2171:        and.    MemDataL,MemDataH,DataTemp
        !          2172:        b               EmulateUpdateRA_cr0
        !          2173: 
        !          2174: EmulateSHIFT_srlq:
        !          2175: //     011111 rs-rs ra-ra rb-rb 10110 11000 .          srlq[.]         ra,rs,rb        (rb>31)
        !          2176:        srw     DataTemp,DataTemp,UnimpRB
        !          2177:        and.    MemDataL,MemDataH,DataTemp
        !          2178:        b       EmulateUpdateRA_cr0
        !          2179: 
        !          2180: EmulateSHIFT_imm:
        !          2181: //     011111 rs-rs ra-ra sh-sh 00101 11000 .          sliq[.]         ra,rs,sh
        !          2182: //     011111 rs-rs ra-ra sh-sh 00111 11000 .          slliq[.]        ra,rs,sh
        !          2183: //     011111 rs-rs ra-ra sh-sh 10101 11000 .          sriq[.]         ra,rs,sh
        !          2184: //     011111 rs-rs ra-ra sh-sh 10111 11000 .          srliq[.]        ra,rs,sh
        !          2185: //     011111 rs-rs ra-ra sh-sh 11101 11000 .          sraiq[.]        ra,rs,sh
        !          2186:        //rlwinm        UnimpRB,MemInstr,11+10,0x0000001F       // get SH
        !          2187:        rlwinm  UnimpRB,MemInstr,11+10,27,31    // get SH
        !          2188: EmulateSHIFT:
        !          2189: //     011111 rs-rs ra-ra rb-rb 00100 11000 .          slq[.]          ra,rs,rb
        !          2190: //     011111 rs-rs ra-ra sh-sh 00101 11000 .          sliq[.]         ra,rs,sh
        !          2191: //     011111 rs-rs ra-ra rb-rb 00110 11000 .          sllq[.]         ra,rs,rb        (rb<32)
        !          2192: //     011111 rs-rs ra-ra sh-sh 00111 11000 .          slliq[.]        ra,rs,sh
        !          2193: //     011111 rs-rs ra-ra rb-rb 10100 11000 .          srq[.]          ra,rs,rb
        !          2194: //     011111 rs-rs ra-ra sh-sh 10101 11000 .          sriq[.]         ra,rs,sh
        !          2195: //     011111 rs-rs ra-ra rb-rb 10110 11000 .          srlq[.]         ra,rs,rb        (rb<32)
        !          2196: //     011111 rs-rs ra-ra sh-sh 10111 11000 .          srliq[.]        ra,rs,sh
        !          2197: //     011111 rs-rs ra-ra rb-rb 11100 11000 .          sraq[.]         ra,rs,rb
        !          2198: //     011111 rs-rs ra-ra sh-sh 11101 11000 .          sraiq[.]        ra,rs,sh
        !          2199: //     011111 rs-rs ra-ra rb-rb 00100 11001 .          sle[.]          ra,rs,rb
        !          2200: //     011111 rs-rs ra-ra rb-rb 00110 11001 .          sleq[.]         ra,rs,rb
        !          2201: //     011111 rs-rs ra-ra rb-rb 10100 11001 .          sre[.]          ra,rs,rb
        !          2202: //     011111 rs-rs ra-ra rb-rb 10110 11001 .          sreq[.]         ra,rs,rb
        !          2203: //     011111 rs-rs ra-ra rb-rb 11100 11001 .          srea[.]         ra,rs,rb
        !          2204:        bf      b_EmulatePowerMQ,EmulateDisabledPowerMQ
        !          2205:        lwzx    UnimpRS,KernelDataPtr,UnimpRS           // get RS
        !          2206:        bt      21,EmulateSHIFT_right
        !          2207: 
        !          2208: EmulateSHIFT_left_logical:
        !          2209: //     011111 rs-rs ra-ra rb-rb 00100 11000 .          slq[.]          ra,rs,rb
        !          2210: //     011111 rs-rs ra-ra sh-sh 00101 11000 .          sliq[.]         ra,rs,sh
        !          2211: //     011111 rs-rs ra-ra rb-rb 00110 11000 .          sllq[.]         ra,rs,rb        (rb<32)
        !          2212: //     011111 rs-rs ra-ra sh-sh 00111 11000 .          slliq[.]        ra,rs,sh
        !          2213: //     011111 rs-rs ra-ra rb-rb 00100 11001 .          sle[.]          ra,rs,rb
        !          2214: //     011111 rs-rs ra-ra rb-rb 00110 11001 .          sleq[.]         ra,rs,rb
        !          2215:        slw.    MemDataL,UnimpRS,UnimpRB                        // RA <- RS shifted left by RB bits
        !          2216:        rotlw   MemDataH,UnimpRS,UnimpRB                        // MQ <- RS rotated left by RB bits
        !          2217:        bf              24,EmulateUpdateRA_cr0_mq
        !          2218: //     011111 rs-rs ra-ra rb-rb 00110 11000 .          sllq[.]         ra,rs,rb        (rb<32)
        !          2219: //     011111 rs-rs ra-ra sh-sh 00111 11000 .          slliq[.]        ra,rs,sh
        !          2220: //     011111 rs-rs ra-ra rb-rb 00110 11001 .          sleq[.]         ra,rs,rb
        !          2221:        li              DataTemp,-1
        !          2222:        slw             DataTemp,DataTemp,UnimpRB
        !          2223: EmulateUpdateRA_cr0_mq_merge:
        !          2224: //     011111 rs-rs ra-ra rb-rb 00110 11000 .          sllq[.]         ra,rs,rb        (rb<32)
        !          2225: //     011111 rs-rs ra-ra sh-sh 00111 11000 .          slliq[.]        ra,rs,sh
        !          2226: //     011111 rs-rs ra-ra rb-rb 10110 11000 .          srlq[.]         ra,rs,rb        (rb<32)
        !          2227: //     011111 rs-rs ra-ra sh-sh 10111 11000 .          srliq[.]        ra,rs,sh
        !          2228: //     011111 rs-rs ra-ra rb-rb 00110 11001 .          sleq[.]         ra,rs,rb
        !          2229: //     011111 rs-rs ra-ra rb-rb 10110 11001 .          sreq[.]         ra,rs,rb
        !          2230:        lwz             UnimpRB,0(UnimpMQptr)                           // get MQ from context block
        !          2231:        andc    DataTemp,UnimpRB,DataTemp
        !          2232:        or.             MemDataL,MemDataL,DataTemp
        !          2233:        bf              23,EmulateUpdateRA_cr0
        !          2234: EmulateUpdateRA_cr0_mq:
        !          2235: //     011111 rs-rs ra-ra sh-sh 00111 11000 .          slliq[.]        ra,rs,sh
        !          2236: //     011111 rs-rs ra-ra sh-sh 10111 11000 .          srliq[.]        ra,rs,sh
        !          2237: //     011111 rs-rs ra-ra rb-rb 00110 11001 .          sleq[.]         ra,rs,rb
        !          2238: //     011111 rs-rs ra-ra rb-rb 10110 11001 .          sreq[.]         ra,rs,rb
        !          2239:        stw             MemDataH,0(UnimpMQptr)                          // update MQ in context block
        !          2240: EmulateUpdateRA_cr0:
        !          2241:        stwx    MemDataL,KernelDataPtr,UnimpRA          // update RA
        !          2242: EmulateUpdateCR0:
        !          2243:        bf      31,CompleteMemOpDone
        !          2244:        mfcr    DataTemp                                                        // get CR0
        !          2245:        //rlwimi        SavedCR,DataTemp,0,0xF0000000           // update CR0
        !          2246:        rlwimi  SavedCR,DataTemp,0,0,3          // update CR0
        !          2247:        b       CompleteMemOpDone
        !          2248: 
        !          2249: EmulateSHIFT_right:
        !          2250: //     011111 rs-rs ra-ra rb-rb 10100 11000 .  srq[.]          ra,rs,rb
        !          2251: //     011111 rs-rs ra-ra sh-sh 10101 11000 .  sriq[.]         ra,rs,sh
        !          2252: //     011111 rs-rs ra-ra rb-rb 10110 11000 .  srlq[.]         ra,rs,rb(rb<32)
        !          2253: //     011111 rs-rs ra-ra sh-sh 10111 11000 .  srliq[.]        ra,rs,sh
        !          2254: //     011111 rs-rs ra-ra rb-rb 11100 11000 .  sraq[.]         ra,rs,rb
        !          2255: //     011111 rs-rs ra-ra sh-sh 11101 11000 .  sraiq[.]        ra,rs,sh
        !          2256: //     011111 rs-rs ra-ra rb-rb 10100 11001 .  sre[.]          ra,rs,rb
        !          2257: //     011111 rs-rs ra-ra rb-rb 10110 11001 .  sreq[.]         ra,rs,rb
        !          2258: //     011111 rs-rs ra-ra rb-rb 11100 11001 .  srea[.]         ra,rs,rb
        !          2259:        neg             MemDataH,UnimpRB// convert right rotate count to left
        !          2260:        rotlw   MemDataH,UnimpRS,MemDataH// MQ <- RS rotated right by RB bits
        !          2261:        bt              22,EmulateSHIFT_right_arith
        !          2262: EmulateSHIFT_right_logical:
        !          2263: //     011111 rs-rs ra-ra rb-rb 10100 11000 .  srq[.]          ra,rs,rb
        !          2264: //     011111 rs-rs ra-ra sh-sh 10101 11000 .  sriq[.]         ra,rs,sh
        !          2265: //     011111 rs-rs ra-ra rb-rb 10110 11000 .  srlq[.]         ra,rs,rb        (rb<32)
        !          2266: //     011111 rs-rs ra-ra sh-sh 10111 11000 .  srliq[.]        ra,rs,sh
        !          2267: //     011111 rs-rs ra-ra rb-rb 10100 11001 .  sre[.]          ra,rs,rb
        !          2268: //     011111 rs-rs ra-ra rb-rb 10110 11001 .  sreq[.]         ra,rs,rb
        !          2269:        srw.    MemDataL,UnimpRS,UnimpRB// RA <- RS shifted righ by RB bits
        !          2270:        bf              24,EmulateUpdateRA_cr0_mq
        !          2271: //     011111 rs-rs ra-ra rb-rb 10110 11000 .  srlq[.]         ra,rs,rb(rb<32)
        !          2272: //     011111 rs-rs ra-ra sh-sh 10111 11000 .  srliq[.]        ra,rs,sh
        !          2273: //     011111 rs-rs ra-ra rb-rb 10110 11001 .  sreq[.]         ra,rs,rb
        !          2274:        li              DataTemp,-1
        !          2275:        srw             DataTemp,DataTemp,UnimpRB
        !          2276:        b               EmulateUpdateRA_cr0_mq_merge
        !          2277: 
        !          2278: EmulateSHIFT_right_arith:
        !          2279: //     011111 rs-rs ra-ra rb-rb 11100 11000 .  sraq[.]         ra,rs,rb
        !          2280: //     011111 rs-rs ra-ra sh-sh 11101 11000 .  sraiq[.]        ra,rs,sh
        !          2281: //     011111 rs-rs ra-ra rb-rb 11100 11001 .  srea[.]         ra,rs,rb
        !          2282:        sraw.   MemDataL,UnimpRS,UnimpRB        // updates live copy of XER
        !          2283:        b               EmulateUpdateRA_cr0_mq
        !          2284: 
        !          2285: 
        !          2286: EmulateMASKG_MASKIR:
        !          2287: //                1 11111 11112 22222 22223 3
        !          2288: //     012345 67890 12345 67890 12345 67890 1
        !          2289: //     ------ ----- ----- ----- ----- ----- -
        !          2290: //     011111 rs-rs ra-ra rb-rb 00000 11101 .  maskg[.]        ra,rs,rb
        !          2291: //     011111 rs-rs ra-ra rb-rb 10000 11101 .  maskir[.]       ra,rs,rb
        !          2292:        bf              b_EmulatePowerComplex,EmulateDisabledPowerComplex
        !          2293:        lwzx    UnimpRB,KernelDataPtr,UnimpRB   // get RB
        !          2294:        lwzx    UnimpRS,KernelDataPtr,UnimpRS   // get RS
        !          2295:        bt              21,EmulateMASKIR
        !          2296: EmulateMASKG:
        !          2297: //     011111 rs-rs ra-ra rb-rb 00000 11101 .  maskg[.]        ra,rs,rb
        !          2298:        li              MemDataL,-1             // initial mask
        !          2299:        sub             UnimpRB,UnimpRB,UnimpRS // end - start
        !          2300:        not             UnimpRB,UnimpRB         // 31 - (end - start) (number of zeros)
        !          2301:        //rlwinm        UnimpRB,UnimpRB,0,0x1F  // mask to 5 bits
        !          2302:        rlwinm  UnimpRB,UnimpRB,0,27,31         // mask to 5 bits
        !          2303:        neg             UnimpRS,UnimpRS         // setup to right rotate field mask by RS
        !          2304:        slw             MemDataL,MemDataL,UnimpRB// left aligned field mask
        !          2305:        rotlw.  MemDataL,MemDataL,UnimpRS       // position the field mask
        !          2306:        b               EmulateUpdateRA_cr0
        !          2307: 
        !          2308: EmulateMASKIR:
        !          2309: //     011111 rs-rs ra-ra rb-rb 10000 11101 .  maskir[.]       ra,rs,rb
        !          2310:        lwzx    MemDataL,KernelDataPtr,UnimpRA  // get RA
        !          2311:        and             UnimpRS,UnimpRS,UnimpRB // get new bits to insert
        !          2312:        andc    MemDataL,MemDataL,UnimpRB       // clear old bits to be overwritten
        !          2313:        or.             MemDataL,MemDataL,UnimpRS// insert new bits
        !          2314:        b               EmulateUpdateRA_cr0
        !          2315: 
        !          2316: EmulateRLMI:
        !          2317: //     010110 rs-rs ra-ra rb-rb mb-mb me-me .  rlmi[.]         ra,rs,rb,mb,me
        !          2318:        bf              b_EmulatePowerComplex,EmulateDisabledPowerComplex
        !          2319:        lwzx    UnimpRS,KernelDataPtr,UnimpRS   // get RS
        !          2320:        //rlwinm        MemDataH,MemInstr,21+5,0x1F     // get MB
        !          2321:        rlwinm  MemDataH,MemInstr,21+5,27,31    // get MB
        !          2322:        lwzx    UnimpRB,KernelDataPtr,UnimpRB   // get RB
        !          2323:        //rlwinm        MemDataL,MemInstr,21+10,0x1F    // get ME
        !          2324:        rlwinm  MemDataL,MemInstr,21+10,27,31   // get ME
        !          2325:        li      DataTemp,-1                     // initial mask
        !          2326:        sub     MemDataL,MemDataL,MemDataH      // ME - MB
        !          2327:        not     MemDataL,MemDataL               // 31 - (ME - MB)
        !          2328:        //rlwinm        MemDataL,MemDataL,0,0x1F// mask to 5 bits
        !          2329:        rlwinm  MemDataL,MemDataL,0,27,31       // mask to 5 bits
        !          2330:        neg     MemDataH,MemDataH       // setup to right rotate field mask by MB
        !          2331:        slw     DataTemp,DataTemp,MemDataL      // left aligned field mask
        !          2332:        lwzx    MemDataL,KernelDataPtr,UnimpRA  // get RA
        !          2333:        rotlw   DataTemp,DataTemp,MemDataH      // position the field mask
        !          2334:        rotlw   UnimpRS,UnimpRS,UnimpRB // position the RS data to be inserted
        !          2335: EmulateUpdateRA_cr0_insert:
        !          2336:        and     UnimpRS,UnimpRS,DataTemp        // get new bits to insert
        !          2337:        andc    MemDataL,MemDataL,DataTemp      // clear old bits to be overwritten
        !          2338:        or.     MemDataL,MemDataL,UnimpRS       // insert new bits
        !          2339:        b       EmulateUpdateRA_cr0
        !          2340: 
        !          2341: 
        !          2342: EmulatePowerMemoryInvalidForm:
        !          2343: //     011111 rt-rt ra-ra rb-rb 01000 10101 .  lscbx[.]        rt,ra,rb
        !          2344: //     011111 rt-rt ra-ra rb-rb 10000 10101 x  lswx            rt,ra,rb
        !          2345: //     011111 rt-rt ra-ra nb-nb 10010 10101 x  lswi            rt,ra,nb
        !          2346: //     011111 rt-rt ra-ra rb-rb 00001 10111 x  lwzux           rt,ra,rb
        !          2347: //     011111 rt-rt ra-ra rb-rb 00011 10111 x  lbzux           rt,ra,rb
        !          2348: //     011111 rs-rs ra-ra rb-rb 00101 10111 x  stwux           rs,ra,rb
        !          2349: //     011111 rs-rs ra-ra rb-rb 00111 10111 x  stbux           rs,ra,rb
        !          2350: //     011111 rt-rt ra-ra rb-rb 01001 10111 x  lhzux           rt,ra,rb
        !          2351: //     011111 rt-rt ra-ra rb-rb 01011 10111 x  lhaux           rt,ra,rb
        !          2352: //     011111 rs-rs ra-ra rb-rb 01101 10111 x  sthux           rs,ra,rb
        !          2353: //     011111 ft-ft ra-ra rb-rb 10001 10111 x  lfsux           ft,ra,rb
        !          2354: //     011111 ft-ft ra-ra rb-rb 10011 10111 x  lfdux           ft,ra,rb
        !          2355: //     011111 fs-fs ra-ra rb-rb 10101 10111 x  stfsux          fs,ra,rb
        !          2356: //     011111 fs-fs ra-ra rb-rb 10111 10111 x  stfdux          fs,ra,rb
        !          2357: //     100001 rt-rt ra-ra d---d d---d d---d d  lwzu            rt,d(ra)
        !          2358: //     100011 rt-rt ra-ra d---d d---d d---d d  lbzu            rt,d(ra)
        !          2359: //     100101 rs-rs ra-ra d---d d---d d---d d  stwu            rs,d(ra)
        !          2360: //     100111 rs-rs ra-ra d---d d---d d---d d  stbu            rs,d(ra)
        !          2361: //     101001 rt-rt ra-ra d---d d---d d---d d  lhzu            rt,d(ra)
        !          2362: //     101011 rt-rt ra-ra d---d d---d d---d d  lhau            rt,d(ra)
        !          2363: //     101101 rs-rs ra-ra d---d d---d d---d d  sthu            rs,d(ra)
        !          2364: //     101110 rt-rt ra-ra d---d d---d d---d d  lmw             rt,d(ra)
        !          2365: //     110001 ft-ft ra-ra d---d d---d d---d d  lfsu            ft,d(ra)
        !          2366: //     110011 ft-ft ra-ra d---d d---d d---d d  lfdu            ft,d(ra)
        !          2367: //     110101 fs-fs ra-ra d---d d---d d---d d  stfsu           fs,d(ra)
        !          2368: //     110111 fs-fs ra-ra d---d d---d d---d d  stfdu           fs,d(ra)
        !          2369:        bf      b_EmulatePowerMemory,EmulateDisabledPowerMemory
        !          2370:        b       DSI_Decode              // emulate the memory reference
        !          2371: 
        !          2372: 
        !          2373: EmulateUpdateMemOps_STFIWX:
        !          2374: //     011111 rt-rt ra-ra rb-rb 00001 10111 x  lwzux           rt,ra,rb
        !          2375: //     011111 rt-rt ra-ra rb-rb 00011 10111 x  lbzux           rt,ra,rb
        !          2376: //     011111 rs-rs ra-ra rb-rb 00101 10111 x  stwux           rs,ra,rb
        !          2377: //     011111 rs-rs ra-ra rb-rb 00111 10111 x  stbux           rs,ra,rb
        !          2378: //     011111 rt-rt ra-ra rb-rb 01001 10111 x  lhzux           rt,ra,rb
        !          2379: //     011111 rt-rt ra-ra rb-rb 01011 10111 x  lhaux           rt,ra,rb
        !          2380: //     011111 rs-rs ra-ra rb-rb 01101 10111 x  sthux           rs,ra,rb
        !          2381: //     011111 ft-ft ra-ra rb-rb 10001 10111 x  lfsux           ft,ra,rb
        !          2382: //     011111 ft-ft ra-ra rb-rb 10011 10111 x  lfdux           ft,ra,rb
        !          2383: //     011111 fs-fs ra-ra rb-rb 10101 10111 x  stfsux          fs,ra,rb
        !          2384: //     011111 fs-fs ra-ra rb-rb 10111 10111 x  stfdux          fs,ra,rb
        !          2385: //     011111 fs-fs ra-ra rb-rb 11110 10111 x  stfiwx          fs,ra,rb
        !          2386:        bt      25,EmulatePowerMemoryInvalidForm        // update forms may be invalid forms
        !          2387: EmulateSTFIWX:
        !          2388: //     011111 fs-fs ra-ra rb-rb 11110 10111 x  stfiwx          fs,ra,rb
        !          2389:        bf      b_EmulateOptional,EmulateDisabledOptional
        !          2390:        b       DSI_Decode              // emulate the memory reference
        !          2391: 
        !          2392: 
        !          2393: 
        !          2394:        .align  8
        !          2395: MemProcBase:
        !          2396: 
        !          2397: // The Setup routines expect the following register contents:
        !          2398: //
        !          2399: // KernelDataPtr       Points to base of KernelData page, XCP_GPR_0_31 must be first
        !          2400: // SavedSRR0   The address of the instruction that caused the exception
        !          2401: // SavedSRR1   The MSR at the time of the exception (low 16 bits)
        !          2402: // SavedLR     The Link Register at the time of the exception
        !          2403: // SavedCR     The Condition Register at the time of the exception
        !          2404: // SavedVBR    The contents of VectorBaseSPRG at the time of the exception
        !          2405: // MemCmdInfo  6/MemOp,5/RT,5/RA,10/0,5/size,1/RW
        !          2406: // MemUpdateEA The effective address generated by the memory reference
        !          2407: // MemAddress  Don't care
        !          2408: // MemDataH    Don't care
        !          2409: // MemDataL    High 3 bytes must be zero, low byte is don't care
        !          2410: // MemProcPtr  High 22 bits point to MemProcBase, low 10 bits don't care
        !          2411: // MemSetupInfo        Low byte, completion routine index
        !          2412: // MemCtxFlags Copy of ActiveCtxFlags
        !          2413: // MSR_Enabled Data to load into MSR to  enable DR
        !          2414: // MSR_Disabled        Data to load into MSR to disable DR and possibly enable FP
        !          2415: // jMemInstr   The entire instruction that caused the exception (If FlagReadInstr)
        !          2416: // MemByteCount        Don't care
        !          2417: // RegIndex    Don't care
        !          2418: // DataTemp    Don't care
        !          2419: // PTEaddr     unused
        !          2420: // PTEu                unused
        !          2421: // PTEl                unused
        !          2422: // LR          Points to setup routine
        !          2423: // CR          CR3 contains the 4 flag bits
        !          2424: // gpr 0..31   are saved in XCP_GPR_0_31
        !          2425: // gpr 0,2..9  are same as saved copy
        !          2426: 
        !          2427: // The Completion routines expect the following register contents:
        !          2428: //
        !          2429: // KernelDataPtr Points to base of KernelData page, XCP_GPR_0_31 must be first
        !          2430: // SavedSRR0   The address of the instruction that caused the exception
        !          2431: // SavedSRR1   The MSR at the time of the exception (low 16 bits)
        !          2432: // SavedLR     The Link Register at the time of the exception
        !          2433: // SavedCR     The Condition Register at the time of the exception
        !          2434: // SavedVBR    The contents of VectorBaseSPRG at the time of the exception
        !          2435: // MemCmdInfo  6/MemOp,5/RT,5/RA,10/MemOpSpecific,5/size,1/RW
        !          2436: // MemUpdateEA The effective address for updating, or other completion purposes
        !          2437: // MemAddress  Address of byte just past end of data
        !          2438: // MemDataH    High 4 bytes of data that was read/written
        !          2439: // MemDataL    Low  4 bytes of data that was read/written
        !          2440: // MemProcPtr  High 22 bits point to MemProcBase, low 10 bits don't care
        !          2441: // MemSetupInfo        Low byte, completion routine index
        !          2442: // MemCtxFlags Copy of ActiveCtxFlags
        !          2443: // MSR_Enabled Data to load into MSR to  enable DR
        !          2444: // MSR_Disabled        Data to load into MSR to disable DR and possibly enable FP
        !          2445: // MemInstr    Don't care
        !          2446: // MemByteCount        Don't care
        !          2447: // RegIndex    Don't care
        !          2448: // DataTemp    Don't care
        !          2449: // PTEaddr     unused
        !          2450: // PTEu                unused
        !          2451: // PTEl                unused
        !          2452: // LR          Points to completion routine
        !          2453: // CR          CR3 contains the low 2 flag bits
        !          2454: // gpr 0..31   are saved in XCP_GPR_0_31
        !          2455: //gpr 0,2..9 are same as saved copy, iff b_FlagRegModified=0
        !          2456: 
        !          2457: SetupLDAR:
        !          2458: Setup0000010:
        !          2459: Setup0000011:
        !          2460: Setup0000100:
        !          2461: Setup0000101:
        !          2462: Setup0000110:
        !          2463: Setup0000111:
        !          2464: Setup0001000:
        !          2465: Setup0001001:
        !          2466: Setup0001010:
        !          2467: Setup0001011:
        !          2468: Setup0001111:
        !          2469: Setup0010000:
        !          2470: Setup0010001:
        !          2471: Setup0010010:
        !          2472: Setup0010011:
        !          2473: Setup0010100:
        !          2474: Setup0010101:
        !          2475: Setup0010110:
        !          2476: Setup0010111:
        !          2477: Setup0011000:
        !          2478: Setup0011001:
        !          2479: Setup0011010:
        !          2480: Setup0011011:
        !          2481: SetupLMD:
        !          2482: SetupSTMD:
        !          2483: 
        !          2484: Setup0100001:
        !          2485: Setup0100011:
        !          2486: Setup0100110:
        !          2487: Setup0100111:
        !          2488: Setup0101100:
        !          2489: Setup0101101:
        !          2490: Setup0101110:
        !          2491: Setup0101111:
        !          2492: Setup0110001:
        !          2493: Setup0110011:
        !          2494: Setup0110100:
        !          2495: Setup0110110:
        !          2496: Setup0110111:
        !          2497: Setup0111000:
        !          2498: Setup0111001:
        !          2499: Setup0111010:
        !          2500: Setup0111011:
        !          2501: Setup0111100:
        !          2502: Setup0111101:
        !          2503: Setup0111110:
        !          2504: Setup0111111:
        !          2505: 
        !          2506: Setup1000000:
        !          2507: SetupSTDCX:
        !          2508: Setup1000101:
        !          2509: Setup1000110:
        !          2510: SetupDCBI:
        !          2511: SetupSYNC:
        !          2512: Setup1001011:
        !          2513: SetupEIEIO:
        !          2514: SetupCLF:
        !          2515: Setup1010010:
        !          2516: Setup1010101:
        !          2517: SetupCLI:
        !          2518: Setup1011000:
        !          2519: SetupDCLST:
        !          2520: Setup1011010:
        !          2521: Setup1011011:
        !          2522: Setup1011100:
        !          2523: Setup1011101:
        !          2524: Setup1011110:
        !          2525: 
        !          2526: SetupLFQX:
        !          2527: Setup1101101:
        !          2528: SetupSTFQX:
        !          2529: SetupLFQUX:
        !          2530: Setup1111101:
        !          2531: SetupSTFQUX:
        !          2532: Setup1111111:
        !          2533:                        bl              KernelCrash                                     // invalid memory exception opcode
        !          2534: #if    0
        !          2535: Complete0001_00:
        !          2536: Complete0001_11:
        !          2537: Complete0010_00:
        !          2538: Complete0010_11:
        !          2539: Complete0011_00:
        !          2540: Complete0011_01:
        !          2541: CompleteLDAR:
        !          2542: CompleteSTDC_:
        !          2543: Complete0110_00:
        !          2544: Complete0110_01:
        !          2545: CompleteLMD:
        !          2546: Complete0111_00:
        !          2547: Complete0111_01:
        !          2548: CompleteSTMD:
        !          2549: Complete1100_01:
        !          2550: Complete1100_10:
        !          2551: Complete1100_11:
        !          2552: Complete1101_00:
        !          2553: Complete1101_01:
        !          2554: Complete1101_10:
        !          2555: Complete1101_11:
        !          2556: Complete1110_00:
        !          2557: Complete1110_01:
        !          2558: Complete1110_10:
        !          2559: Complete1110_11:
        !          2560: Complete1111_00:
        !          2561: Complete1111_01:
        !          2562: CompleteIllegal:
        !          2563:                        b               CompleteForceEx
        !          2564: 
        !          2565: 
        !          2566: SetupSTFSX:    rlwinm  MemCmdInfo,MemCmdInfo,0,0xFFE0FFFF      // RA <- 0, no update
        !          2567: SetupSTFSUX:crclr      31                                                                      // indicate single precision
        !          2568:                        b               SetupFloatStore
        !          2569: 
        !          2570: SetupSTFDX:
        !          2571: SetupSTFIWX:rlwinm     MemCmdInfo,MemCmdInfo,0,0xFFE0FFFF      // RA <- 0, no update
        !          2572: SetupSTFDUX:crset      31                                                                      // indicate double precision
        !          2573: SetupFloatStore:
        !          2574:                        rlwinm  MemAddress,MemProcPtr,0,0xFFFFFC00      // clear low bits
        !          2575:                        rlwimi  MemAddress,MemCmdInfo,6+5+3,0xF8        // get index of FRS register
        !          2576:                        la              MemAddress,StoreFPreg-MemProcBase(MemAddress)
        !          2577:                        mtlr    MemAddress                                                      // setup to get FRS
        !          2578:                        rlwimi  MSR_Disabled,SavedSRR1,0,msr_fp         // setup to enable FP regs
        !          2579:                        mtmsr   MSR_Disabled                                            // enable FP regs, if they were valid
        !          2580:                        isync
        !          2581:                        blr                                                                                     // FP reg -> DataConvertBuffer
        !          2582: SetupFloatStoreDone:
        !          2583:                        ori             SavedSRR1,SavedSRR1,msr_fp                      // FP regs are now valid
        !          2584:                        lwz             MemDataH,DataConvertBuffer+0(KernelDataPtr)     // get upper half of data
        !          2585:                        lwz             MemDataL,DataConvertBuffer+4(KernelDataPtr)     // get lower half of data
        !          2586:                        bt              31,SetupDone                                            // all done if double prec
        !          2587: 
        !          2588:                        rlwinm  DataTemp,MemDataH,12,0x07FF                     // get DP exponent, test for zero
        !          2589:                        cmpwi   DataTemp,896                                            // check for denorm
        !          2590:                        rlwimi  MemDataH,MemDataH,3,0x3FFFFFF8          // convert dp to sp
        !          2591:                        rlwimi  MemDataH,MemDataL,3,0x00000007          // convert dp to sp
        !          2592:                        mr              MemDataL,MemDataH                                       // setup 32 bits to be stored
        !          2593:                        bgt             SetupDone                                                       // all done if normalized single
        !          2594: 
        !          2595:                        cmpwi   DataTemp,874                                            // check for denorm to zero
        !          2596:                        rlwinm  MemDataL,MemDataH,0,0x80000000          // retain sign, exp/frac <- 0
        !          2597:                        blt             SetupDone                                                       // all done if denorm to zero
        !          2598: 
        !          2599:                        oris    MemDataH,MemDataH,0x0080                        // insert msb
        !          2600:                        neg             DataTemp,DataTemp                                       // shift amount 0
        !          2601: 22 (low 6 bits)
        !          2602:                        rlwinm  MemDataH,MemDataH,0,0x00FFFFFF          // clear high bits
        !          2603:                        srw             MemDataH,MemDataH,DataTemp                      // denormalize the data
        !          2604:                        rlwimi  MemDataL,MemDataH,31,0x007FFFFF         // insert the shifted fraction
        !          2605:                        b               SetupDone                                                       // all done
        !          2606: 
        !          2607: 
        !          2608: SetupSTWBRX:
        !          2609:                        rlwinm  RegIndex,MemCmdInfo,6+5+2,0x7C  // get index of RS register
        !          2610:                        lwbrx   MemDataL,KernelDataPtr,RegIndex // get register RS, data to store
        !          2611:                        b               SetupDoneClearRA
        !          2612: 
        !          2613: SetupSTHBRX:
        !          2614:                        rlwinm  RegIndex,MemCmdInfo,6+5+2,0x7C  // get index of RS register
        !          2615:                        la              MemDataL,2(KernelDataPtr)
        !          2616:                        lhbrx   MemDataL,MemDataL,RegIndex              // get register RS, data to store
        !          2617:                        b               SetupDoneClearRA
        !          2618: 
        !          2619: SetupSTMW:
        !          2620: SetupSTBUX:
        !          2621: SetupSTHUX:
        !          2622: SetupSTWUX:
        !          2623: SetupSTDUX:
        !          2624: SetupSTDU:
        !          2625:                        rlwinm  RegIndex,MemCmdInfo,6+5+2,0x7C  // get index of RS register
        !          2626:                        lwzx    MemDataL,KernelDataPtr,RegIndex // get register RS, data to store
        !          2627:                        b               SetupDone
        !          2628: 
        !          2629: SetupSTBX:
        !          2630: SetupSTHX:
        !          2631: SetupSTWX:
        !          2632: SetupSTWCX_:
        !          2633: SetupSTDX:
        !          2634: SetupSTD:
        !          2635: SetupECOWX:
        !          2636:                        rlwinm  RegIndex,MemCmdInfo,6+5+2,0x7C  // get index of RS register
        !          2637:                        lwzx    MemDataL,KernelDataPtr,RegIndex // get register RS, data to store
        !          2638: SetupLBZX:
        !          2639: SetupLHZX:
        !          2640: SetupLHAX:
        !          2641: SetupLWZX:
        !          2642: SetupLWA:
        !          2643: SetupLWAX:
        !          2644: SetupLWAR:
        !          2645: SetupLFSX:
        !          2646: SetupLD:
        !          2647: SetupLDX:
        !          2648: SetupLFDX:
        !          2649: SetupECIWX:
        !          2650: SetupDoneClearRA:
        !          2651:                        rlwinm  MemCmdInfo,MemCmdInfo,0,0xFFE0FFFF      // RA <- 0, no update
        !          2652: SetupDCBF:
        !          2653: SetupDCBT:
        !          2654: SetupICBI:
        !          2655: SetupDCBST:
        !          2656: SetupDCBTST:
        !          2657: SetupLBZUX:
        !          2658: SetupLHZUX:
        !          2659: SetupLHAUX:
        !          2660: SetupLHBRX:
        !          2661: SetupLWZUX:
        !          2662: SetupLWAUX:
        !          2663: SetupLWBRX:
        !          2664: SetupLMW:
        !          2665: SetupLFSUX:
        !          2666: SetupLDU:
        !          2667: SetupLDUX:
        !          2668: SetupLFDUX:
        !          2669: SetupDone:
        !          2670:                        rlwinm. MemByteCount,MemCmdInfo,31,0x0F         // get byte count, test for zero
        !          2671:                        add             MemAddress,MemUpdateEA,MemByteCount     // point past end of data
        !          2672: RetryStart:
        !          2673:                        rlwinm  MemProcPtr,MemProcPtr,0,0xFFFFFC00      // setup to insert alignment info
        !          2674:                        rlwimi  MemProcPtr,MemAddress,1,0x0E            // insert low 3 bits of end address
        !          2675:                        rlwimi  MemProcPtr,MemCmdInfo,4,0xF0            // insert len, r/w
        !          2676:                        lha             MemByteCount,RetryLookup-MemProcBase(MemProcPtr)
        !          2677:                        la              DataTemp,VectorTableDSI(KernelDataPtr)
        !          2678:                        add             MemByteCount,MemByteCount,MemProcPtr
        !          2679:                        mtlr    MemByteCount
        !          2680:                        mtsprg  VectorBaseSPRG,DataTemp                         // setup to catch nested DSIs
        !          2681:                        mtmsr   MSR_Enabled
        !          2682:                        isync
        !          2683:                        rlwimi  MemProcPtr,MemSetupInfo,2,0x03FC        // insert completion routine index
        !          2684:                        bnelr                                                                           // read/write the bytes if count <> 0
        !          2685:                        b               RetryDone                                                       // nothing to retry if count = 0
        !          2686: 
        !          2687: W4_22:         srwi    DataTemp,MemDataL,16
        !          2688:                        sth             DataTemp,-4(MemAddress)
        !          2689:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          2690:                        sth             MemDataL,-2(MemAddress)
        !          2691:                        b               RetryDone
        !          2692: 
        !          2693: R4_22:         lhz             DataTemp,-4(MemAddress)
        !          2694:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          2695:                        rlwimi  MemDataL,DataTemp,16,0xFFFF0000
        !          2696: R2_2:          lhz             DataTemp,-2(MemAddress)
        !          2697:                        rlwimi  MemDataL,DataTemp, 0,0x0000FFFF
        !          2698: RetryDoneNoData:
        !          2699: RetryDone:     bl              WaitBusIdle
        !          2700:                        rlwinm. RegIndex,MemCmdInfo,16+2,0x7C           // get RA register index, test RA=0
        !          2701:                        mtlr    MemProcPtr                                                      // point to completion routine
        !          2702:                        cror    eq,eq,b_FlagNoUpdate
        !          2703:                        mtsprg  VectorBaseSPRG,SavedVBR                         // restore previous exception vectors
        !          2704:                        beqlr                                                                           // run completion proc if no update
        !          2705:                        crset   b_FlagRegModified                                       // indicate that saved registers are modified
        !          2706:                        stwx    MemUpdateEA,KernelDataPtr,RegIndex      // update RA register
        !          2707:                        blr                                                                                     // run completion proc
        !          2708: 
        !          2709: CompleteLHA:
        !          2710:                        extsh   MemDataL,MemDataL                                       // sign extend the data
        !          2711: CompleteLBZ:
        !          2712: CompleteLHZ:
        !          2713: CompleteLWZ:
        !          2714: CompleteLWA:
        !          2715: CompleteLD:
        !          2716:                        rlwinm  RegIndex,MemCmdInfo,11+2,0x7C           // get RT register index
        !          2717:                        crset   b_FlagRegModified                                       // indicate that saved registers are modified
        !          2718:                        stwx    MemDataL,KernelDataPtr,RegIndex         // update RT register
        !          2719: CompleteSTB:
        !          2720: CompleteSTH:
        !          2721: CompleteSTW:
        !          2722: CompleteSTD:
        !          2723: CompleteMemOpDone:
        !          2724:                        andi.   DataTemp,MemCtxFlags,1<<(31-b_CtxFlagTracePending)      // see if trace pending
        !          2725:                        la              SavedSRR0,4(SavedSRR0)                          // skip over the faulting instr
        !          2726:                        mtsrr0  SavedSRR0
        !          2727:                        mtsrr1  SavedSRR1
        !          2728:                        bne             CompleteTracePending
        !          2729:                        mtlr    SavedLR
        !          2730: // when b_FlagRegModified = 0, gpr 0,2
        !          2731: 9 are still valid, gpr 0
        !          2732: 31 are saved in XCP_GPR_0_31
        !          2733: // when b_FlagRegModified = 1, gpr 0,2
        !          2734: 9 may be invalid,  gpr 0
        !          2735: 31 are saved in XCP_GPR_0_31
        !          2736:                        bf              b_FlagRegModified,CompleteReturnMin
        !          2737: CompleteReturnMax:
        !          2738:                        mtcr    SavedCR
        !          2739:                        lmw             r2,XCP_GPR_0_31+(2*4)(KernelDataPtr)
        !          2740:                        lwz             r0,XCP_GPR_0_31+(0*4)(KernelDataPtr)
        !          2741:                        lwz             r1,XCP_GPR_0_31+(1*4)(KernelDataPtr)
        !          2742:                        rfi
        !          2743: 
        !          2744: CompleteReturnMin:
        !          2745:                        mtcr    SavedCR
        !          2746:                        lmw             r10,XCP_GPR_0_31+(10*4)(KernelDataPtr)
        !          2747:                        lwz             r1,XCP_GPR_0_31+( 1*4)(KernelDataPtr)
        !          2748:                        rfi
        !          2749: 
        !          2750: CompleteTracePending:
        !          2751:                        mfsprg  SavedVBR,VectorBaseSPRG
        !          2752:                        mtsprg  lrSaveSPRG,SavedLR
        !          2753:                        rlwinm  MemCtxFlags,MemCtxFlags,0,~(1<<(31-b_CtxFlagTracePending))
        !          2754:                        lwz             SavedLR,0x0D00>>6(SavedVBR)                     // get the trace handler
        !          2755:                        stw             MemCtxFlags,ActiveCtxFlags(KernelDataPtr)
        !          2756:                        mtcr    SavedCR
        !          2757:                        mtlr    SavedLR
        !          2758:                        lmw             r2,XCP_GPR_0_31+(2*4)(KernelDataPtr)
        !          2759:                        lwz             r0,XCP_GPR_0_31+(0*4)(KernelDataPtr)
        !          2760:                        lwz             r1,XCP_GPR_0_31+(1*4)(KernelDataPtr)
        !          2761:                        mtsprg  r1SaveSPRG,r1
        !          2762:                        blrl
        !          2763: 
        !          2764: 
        !          2765: CompleteLHBR:
        !          2766:                        slwi    MemDataL,MemDataL,16                            // shift bytes into high half, zero fill
        !          2767: CompleteLWBR:
        !          2768:                        rlwinm  RegIndex,MemCmdInfo,11+2,0x7C           // get RT register index
        !          2769:                        crset   b_FlagRegModified                                       // indicate that saved registers are modified
        !          2770:                        stwbrx  MemDataL,KernelDataPtr,RegIndex         // update RT register
        !          2771:                        b               CompleteMemOpDone
        !          2772: 
        !          2773: CompleteLFS:rlwinm     MemDataH,MemDataL,0,0x80000000          // copy the sign bit
        !          2774:                        xor.    MemDataL,MemDataH,MemDataL                      // clear sign, test for +/- zero
        !          2775:                        beq             CompleteLFD                                                     // If all zero, all done
        !          2776:                        rlwinm. DataTemp,MemDataL,16,0x00007F80         // get the exponent, test for zero
        !          2777:                        addi    DataTemp,DataTemp,0x0080                        // setup to extend exp=255
        !          2778:                        rlwimi  MemDataH,MemDataL,32-3,0x07FFFFFF       // convert sp to dp
        !          2779:                        extsh   DataTemp,DataTemp                                       // fill with FFFF if exp=255
        !          2780:                        rlwimi  MemDataH,MemDataL,0,0x40000000          // update bit 1
        !          2781:                        slwi    MemDataL,MemDataL,32-3                          // convert sp to dp
        !          2782:                        subi    DataTemp,DataTemp,0x4080                        // compute bits 2
        !          2783: 4
        !          2784:                        rlwimi  MemDataH,DataTemp,0,0x38000000          // convert sp to dp
        !          2785:                        bne             CompleteLFD                                                     // all done if not denorm
        !          2786:                        srwi    MemDataL,MemDataL,20                            // reassemble fraction
        !          2787:                        rlwimi  MemDataL,MemDataH,12,0xFFFFF000         // reassemble fraction
        !          2788:                        cntlzw  DataTemp,MemDataL                                       // setup to normalize
        !          2789:                        slw             MemDataL,MemDataL,DataTemp                      // normalize fraction
        !          2790:                        neg             DataTemp,DataTemp                                       // setup to compute exponent
        !          2791:                        rlwimi  MemDataH,MemDataL,1+20,0x000FFFFF       // convert sp to dp
        !          2792:                        addi    DataTemp,DataTemp,1023-127                      // compute dp exponent
        !          2793:                        slwi    MemDataL,MemDataL,1+20                          // convert sp to dp
        !          2794:                        rlwimi  MemDataH,DataTemp,20,0x7FF00000         // insert exponent
        !          2795: CompleteLFD:rlwinm     DataTemp,MemProcPtr,0,0xFFFFFC00        // clear low bits
        !          2796:                        rlwimi  DataTemp,MemCmdInfo,6+5+3,0xF8          // get index of FRT register
        !          2797:                        la              DataTemp,LoadFPreg-MemProcBase(DataTemp)
        !          2798:                        mtlr    DataTemp                                                        // setup to get FRT
        !          2799:                        stw             MemDataH,DataConvertBuffer+0(KernelDataPtr)     // save upper half of data
        !          2800:                        stw             MemDataL,DataConvertBuffer+4(KernelDataPtr)     // save lower half of data
        !          2801:                        rlwimi  MSR_Disabled,SavedSRR1,0,msr_fp         // setup to enable FP regs
        !          2802:                        mtmsr   MSR_Disabled                                            // enable FP regs, if they were valid
        !          2803:                        isync
        !          2804:                        ori             SavedSRR1,SavedSRR1,msr_fp                      // FP regs will become valid
        !          2805:                        blr                                                                                     // FP reg <- DataConvertBuffer
        !          2806: 
        !          2807: CompleteLMW:rlwinm.    RegIndex,MemCmdInfo,6+5+2,0x7C          // get RT register index, test zero
        !          2808:                        rlwinm  DataTemp,MemCmdInfo,6+5+5+2,0x7C        // get RA index, to compare to RT
        !          2809:                        cmpw    cr7,RegIndex,DataTemp                           // see if RT=RA
        !          2810:                        addis   MemCmdInfo,MemCmdInfo,1<<5                      // increment RT
        !          2811:                        beq             CompleteLMWupdateRT                                     // always update if RT=0
        !          2812:                        beq             cr7,CompleteLMWskipRT                           // dont update if RT=RA
        !          2813: CompleteLMWupdateRT:
        !          2814:                        stwx    MemDataL,KernelDataPtr,RegIndex         // update RT register
        !          2815: CompleteLMWskipRT:
        !          2816:                        cmpwi   RegIndex,31*4                                           // check RT=31
        !          2817:                        li              MemByteCount,(4<<1)+1                           // read 4 bytes
        !          2818:                        rlwimi  MemCmdInfo,MemByteCount,0,0x3F          // insert byte count, r/w
        !          2819:                        la              MemAddress,4(MemAddress)                        // point past end of data
        !          2820:                        bne             RetryStart                                                      // continue until RT=31
        !          2821:                        b               CompleteMemOpDone                                       // all done when RT=31
        !          2822: 
        !          2823: CompleteSTMW:
        !          2824:                        addis   MemCmdInfo,MemCmdInfo,1<<5                      // increment RS
        !          2825:                        rlwinm. RegIndex,MemCmdInfo,6+5+2,0x7C          // get index of RS register, check wrap
        !          2826:                        beq             CompleteMemOpDone                                       // all done when 31 wraps to 0
        !          2827:                        lwzx    MemDataL,KernelDataPtr,RegIndex         // get register RS, data to store
        !          2828:                        li              MemByteCount,(4<<1)+0                           // write 4 bytes
        !          2829:                        rlwimi  MemCmdInfo,MemByteCount,0,0x3F          // insert byte count, r/w
        !          2830:                        la              MemAddress,4(MemAddress)                        // point past end of data
        !          2831:                        b               RetryStart                                                      // store the next register
        !          2832: 
        !          2833: 
        !          2834: SetupDCBZ:     lhz             MemDataL,PI+DataCacheBlockSize(KernelDataPtr)
        !          2835:                        neg             MemDataL,MemDataL                                       // form mask
        !          2836:                        and             MemAddress,MemUpdateEA,MemDataL         // align address to start of cache block
        !          2837:                        b               CompleteDCBZnext                                        // start zeroing
        !          2838: 
        !          2839: CompleteDCBZ:
        !          2840:                        lhz             MemDataL,PI+DataCacheBlockSize(KernelDataPtr)
        !          2841:                        subi    MemDataL,MemDataL,8                                     // DCBZ size - 8
        !          2842:                        and.    MemByteCount,MemAddress,MemDataL        // check for wrap into next cache block
        !          2843:                        rlwinm  MemAddress,MemAddress,0,-8                      // align address to next 8 bytes
        !          2844:                        beq             CompleteMemOpDone                                       // all done when 31 wraps to 0
        !          2845: CompleteDCBZnext:
        !          2846:                        li              MemByteCount,(8<<1)+0                           // write 8 bytes
        !          2847:                        rlwimi. MemCmdInfo,MemByteCount,0,0x3F          // insert byte count, r/w  force ne for RetryStart
        !          2848:                        la              MemAddress,8(MemAddress)                        // point past end of data
        !          2849:                        li              MemDataH,0                                                      // store 8 bytes of zeros at a time
        !          2850:                        li              MemDataL,0                                                      // store 8 bytes of zeros at a time
        !          2851:                        b               RetryStart                                                      // store the next register
        !          2852: 
        !          2853: CompleteLWAR:
        !          2854:                        rlwinm  RegIndex,MemCmdInfo,11+2,0x7C           // get RT register index
        !          2855:                        crset   b_FlagRegModified                                       // indicate that saved registers are modified
        !          2856:                        stwx    MemDataL,KernelDataPtr,RegIndex         // update RT register
        !          2857:                        stwcx.  MemDataL,KernelDataPtr,RegIndex         // clear the reservation
        !          2858:                        b               CompleteMemOpDone                                       // complete the load
        !          2859: 
        !          2860: CompleteSTWC_:                                                                                 // perform a rd instead of wr to update HTAB
        !          2861:                        stwcx.  r0,0,KernelDataPtr                                      // XCP_GPR_0_31+(0*4)(KernelDataPtr), clear reservation
        !          2862:                        mfcr    DataTemp                                                        // get CR0 (especially updated SO bit)
        !          2863:                        rlwinm  DataTemp,DataTemp,0,0xDFFFFFFF          // clear the EQ bit, indicate store not performed
        !          2864:                        rlwimi  SavedCR,DataTemp,0,0xF0000000           // update saved CR0
        !          2865:                        b               CompleteMemOpDone                                       // complete the operation
        !          2866: 
        !          2867: CompleteTouchRd:
        !          2868:                        rlwinm  MemCtxFlags,MemCtxFlags,0,~((1<<(31-b_CtxFlagTracePending))|(1<<(31-b_CtxFlagMemInfoValid)))
        !          2869:                        la              SavedSRR0,-4(SavedSRR0)                         // re-execute the instruction
        !          2870:                        stw             MemCtxFlags,ActiveCtxFlags(KernelDataPtr)       // clear pending exceptions
        !          2871:                        b               CompleteMemOpDone                                       // retry the operation
        !          2872: 
        !          2873: CompleteForceEx:
        !          2874:                        li              Tmp1,ecDataInvalidAddress                       // there are no legal addresses for this op
        !          2875:                        b               GenerateMemException                            // Invalid Address, Mem Exception
        !          2876: 
        !          2877: SetupSTSWI:    subi    MemByteCount,MemInstr,1<<11                     // get NB field - 1
        !          2878:                        rlwinm  MemByteCount,MemByteCount,21,0x1F       // get count - 1
        !          2879:                        b               SetupSTSW                                                       // join common code
        !          2880: SetupSTSWX:    mfxer   MemByteCount                                            // get byte count
        !          2881:                        andi.   MemByteCount,MemByteCount,0x7F          // test for zero, clear unused bits
        !          2882:                        subi    MemByteCount,MemByteCount,1                     // get count - 1
        !          2883:                        beq             CompleteMemOpDone                                       // all done if count=0
        !          2884: SetupSTSW:     rlwimi  MemCmdInfo,MemByteCount,4,0x07C0        // insert register count
        !          2885:                        not             MemByteCount,MemByteCount                       // compute ending byte number
        !          2886:                        rlwimi  MemCmdInfo,MemByteCount,26,0x0C000000   // modify low 2 bits of memop
        !          2887:                        mr              MemAddress,MemUpdateEA                          // point to start of data
        !          2888:                        b               CompleteSTSWnext                                        // store the next register
        !          2889: 
        !          2890: CompleteSTSW_4:
        !          2891: CompleteSTSW_3:
        !          2892: CompleteSTSW_2:
        !          2893: CompleteSTSW_1:
        !          2894:                        andi.   MemByteCount,MemCmdInfo,0x07C0          // see if all done
        !          2895:                        addis   RegIndex,MemCmdInfo,1<<5                        // increment RS, may wrap around
        !          2896:                        rlwimi  MemCmdInfo,RegIndex,0,0x03E00000        // insert incremented RS field
        !          2897:                        subi    MemCmdInfo,MemCmdInfo,0x0040            // decrement reg count field
        !          2898:                        bne             CompleteSTSWnext                                        // continue if count<>0
        !          2899:                        b               CompleteMemOpDone                                       // all done if count=0
        !          2900: 
        !          2901: 
        !          2902: SetupLSWI:     subi    MemByteCount,MemInstr,1<<11                     // get NB field - 1
        !          2903:                        rlwinm  MemByteCount,MemByteCount,21,0x1F       // get count - 1
        !          2904:                        addis   RegIndex,MemInstr,0x1F<<5                       // get RT field - 1
        !          2905:                        rlwimi  MemCmdInfo,RegIndex,22,0x0000F800       // create RB field = RT-1
        !          2906:                        b               SetupLSW                                                        // join common code
        !          2907: SetupLSWX:     mfxer   MemByteCount                                            // get byte count
        !          2908:                        andi.   MemByteCount,MemByteCount,0x7F          // test for zero, clear unused bits
        !          2909:                        rlwimi  MemCmdInfo,MemInstr,0,0x0000F800        // insert RB field
        !          2910:                        subi    MemByteCount,MemByteCount,1                     // get count - 1
        !          2911:                        beq             CompleteMemOpDone                                       // all done if count=0
        !          2912: SetupLSW:      andis.  DataTemp,MemCmdInfo,0x001F                      // see if RA=0
        !          2913:                        rlwimi  MemCmdInfo,MemByteCount,4,0x07C0        // insert register count
        !          2914:                        not             MemByteCount,MemByteCount                       // compute ending byte number
        !          2915:                        rlwimi  MemCmdInfo,MemByteCount,26,0x0C000000   // modify low 2 bits of memop
        !          2916:                        mr              MemAddress,MemUpdateEA                          // point to start of data
        !          2917:                        bne             CompleteLSWnext                                         // load the next register (RA<>0)
        !          2918:                        rlwimi  MemCmdInfo,MemCmdInfo,5,0x001F0000      // Use RB for RA when RA=0
        !          2919:                        b               CompleteLSWnext                                         // load the next register
        !          2920: 
        !          2921: CompleteLSW_4:
        !          2922: CompleteLSW_3:
        !          2923: CompleteLSW_2:
        !          2924: CompleteLSW_1:
        !          2925:                        andi.   MemByteCount,MemCmdInfo,0x07C0          // see if last register
        !          2926:                        rlwinm  RegIndex,MemCmdInfo,6+5+2,0x7C          // get index of RT register
        !          2927:                        bne             CompleteLSWnoShift                                      // don't shift data unless last register
        !          2928:                        rlwinm  MemByteCount,MemCmdInfo,9,0x18          // get the shift amount
        !          2929:                        slw             MemDataL,MemDataL,MemByteCount          // left align the data
        !          2930:                        b               CompleteLSWnoShift                                      // join common code
        !          2931: 
        !          2932: 
        !          2933: CompleteLSCB_4:
        !          2934: CompleteLSCB_3:
        !          2935: CompleteLSCB_2:
        !          2936: CompleteLSCB_1:
        !          2937: CompleteLSCB__4:
        !          2938: CompleteLSCB__3:
        !          2939: CompleteLSCB__2:
        !          2940: CompleteLSCB__1:
        !          2941:                        rlwinm. MemByteCount,MemCmdInfo,32-4,0x07C      // see if last register
        !          2942:                        rlwinm  RegIndex,MemCmdInfo,6+5+2,0x7C          // get index of RT register
        !          2943:                        bne             CompleteLSCBnoShift                                     // don't shift data unless last register
        !          2944:                        rlwinm  DataTemp,MemCmdInfo,9,0x18                      // get the shift amount
        !          2945:                        slw             MemDataL,MemDataL,DataTemp                      // left align the data
        !          2946:                        b               CompleteLSCBnoShift                                     // join common code
        !          2947: 
        !          2948: SetupLSCBX:    mfxer   MemByteCount                                            // get byte count
        !          2949:                        andi.   MemByteCount,MemByteCount,0x7F          // test for zero, clear unused bits
        !          2950:                        rlwimi  MemCmdInfo,MemInstr,0,0x0000F800        // insert RB field
        !          2951:                        rlwimi  MemCmdInfo,MemInstr,28,0x10000000       // insert RC bit
        !          2952:                        cmpw    cr7,MemInstr,MemByteCount                       // force CR7 to NE condition
        !          2953:                        beq             CompleteLSCBend                                         // all done if count=0
        !          2954:                        subi    MemByteCount,MemByteCount,1                     // get count - 1
        !          2955:                        andis.  DataTemp,MemCmdInfo,0x001F                      // see if RA=0
        !          2956:                        rlwimi  MemCmdInfo,MemByteCount,4,0x07C0        // insert register count
        !          2957:                        not             MemByteCount,MemByteCount                       // compute ending byte number
        !          2958:                        rlwimi  MemCmdInfo,MemByteCount,26,0x0C000000   // modify low 2 bits of memop
        !          2959:                        mr              MemAddress,MemUpdateEA                          // point to start of data
        !          2960:                        bne             CompleteLSCBnext                                        // load the next register (RA<>0)
        !          2961:                        rlwimi  MemCmdInfo,MemCmdInfo,5,0x001F0000      // Use RB for RA when RA=0
        !          2962:                        b               CompleteLSCBnext                                        // load the next register
        !          2963: 
        !          2964: //     NOTE: All of the Setup/Complete entry points must reside in the 1024 byte range
        !          2965: //     starting at MemProcBase. To make sure that they all fit, some of the longer routines
        !          2966: //     have been split up, and are continued here, which can be outside of the 1024 byte range.
        !          2967: 
        !          2968: CompleteSTSWnext:
        !          2969:                        andi.   DataTemp,MemCmdInfo,0x07C0                      // see if last register
        !          2970:                        rlwinm  RegIndex,MemCmdInfo,6+5+2,0x7C          // get index of RS register
        !          2971:                        lwzx    MemDataL,KernelDataPtr,RegIndex         // get register RS, data to store
        !          2972:                        li              MemByteCount,(4<<1)+0                           // write 4 bytes
        !          2973:                        rlwimi  MemCmdInfo,MemByteCount,0,0x3F          // insert byte count, r/w
        !          2974:                        la              MemAddress,4(MemAddress)                        // point past end of data
        !          2975:                        bne             RetryStart                                                      // store the next register
        !          2976: 
        !          2977:                        rlwinm  MemByteCount,MemCmdInfo,9,0x18          // get the shift amount
        !          2978:                        srw             MemDataL,MemDataL,MemByteCount          // right align the data
        !          2979:                        rlwinm  MemByteCount,MemCmdInfo,6,0x03          // get the remaining byte count
        !          2980:                        neg             MemByteCount,MemByteCount                       // setup for subtraction
        !          2981:                        add             MemAddress,MemAddress,MemByteCount      // adjust the ending address
        !          2982:                        addi    MemByteCount,MemByteCount,4                     // compute number of bytes to write
        !          2983:                        rlwimi. MemCmdInfo,MemByteCount,1,0x3E          // insert byte count, force ne for RetryStart
        !          2984:                        b               RetryStart                                                      // store the last register
        !          2985: 
        !          2986: 
        !          2987: CompleteLSWnoShift:
        !          2988:                        rlwinm  DataTemp,MemCmdInfo,6+5+5+2,0x7C        // get RA index, to compare to RT
        !          2989:                        cmpw    cr7,RegIndex,DataTemp                           // see if RT=RA
        !          2990:                        rlwinm  DataTemp,MemCmdInfo,6+5+5+5+2,0x7C      // get RB index, to compare to RT
        !          2991:                        cmpw    cr6,RegIndex,DataTemp                           // see if RT=RB
        !          2992:                        beq             cr7,CompleteLSWupdateDone                       // skip register if RT=RA
        !          2993:                        beq             cr6,CompleteLSWupdateDone                       // skip register if RT=RB
        !          2994:                        stwx    MemDataL,KernelDataPtr,RegIndex         // update register RT
        !          2995: CompleteLSWupdateDone:
        !          2996:                        addis   RegIndex,MemCmdInfo,1<<5                        // increment RT, may wrap around
        !          2997:                        rlwimi  MemCmdInfo,RegIndex,0,0x03E00000        // insert incremented RT field
        !          2998:                        subi    MemCmdInfo,MemCmdInfo,0x0040            // decrement reg count field
        !          2999:                        beq             CompleteMemOpDone                                       // all done if count=0
        !          3000: CompleteLSCBnext:
        !          3001: CompleteLSWnext:
        !          3002:                        andi.   DataTemp,MemCmdInfo,0x07C0                      // see if last register
        !          3003:                        li              MemByteCount,(4<<1)+1                           // read 4 bytes
        !          3004:                        rlwimi  MemCmdInfo,MemByteCount,0,0x3F          // insert byte count, r/w
        !          3005:                        la              MemAddress,4(MemAddress)                        // point past end of data
        !          3006:                        bne             RetryStart                                                      // read the next word
        !          3007: 
        !          3008:                        rlwinm  MemByteCount,MemCmdInfo,6,0x03          // get the remaining byte count
        !          3009:                        neg             MemByteCount,MemByteCount                       // setup for subtraction
        !          3010:                        add             MemAddress,MemAddress,MemByteCount      // adjust the ending address
        !          3011:                        addi    MemByteCount,MemByteCount,4                     // compute number of bytes to read
        !          3012:                        rlwimi. MemCmdInfo,MemByteCount,1,0x3E          // insert byte count, force ne for RetryStart
        !          3013:                        b               RetryStart                                                      // store the last register
        !          3014: 
        !          3015: 
        !          3016: CompleteLSCBnoShift:
        !          3017:                        rlwinm  DataTemp,MemCmdInfo,6+5+5+2,0x7C        // get RA index, to compare to RT
        !          3018:                        cmpw    cr7,RegIndex,DataTemp                           // see if RT=RA
        !          3019:                        rlwinm  DataTemp,MemCmdInfo,6+5+5+5+2,0x7C      // get RB index, to compare to RT
        !          3020:                        cmpw    cr6,RegIndex,DataTemp                           // see if RT=RB
        !          3021:                        beq             cr7,CompleteLSCBupdateDone                      // skip register if RT=RA
        !          3022:                        beq             cr6,CompleteLSCBupdateDone                      // skip register if RT=RB
        !          3023:                        stwx    MemDataL,KernelDataPtr,RegIndex         // update register RT
        !          3024: CompleteLSCBupdateDone:
        !          3025:                        addis   RegIndex,MemCmdInfo,1<<5                        // increment RT, may wrap around
        !          3026:                        rlwimi  MemCmdInfo,RegIndex,0,0x03E00000        // insert incremented RT field
        !          3027:                        subi    MemCmdInfo,MemCmdInfo,0x0040            // decrement reg count field
        !          3028:                        not             MemByteCount,MemByteCount                       // setup to compute negative count
        !          3029:                        rlwimi  MemByteCount,MemCmdInfo,6,0x03          // insert low 2 bits
        !          3030:                        li              RegIndex,1                                                      // setup to increment neg count
        !          3031:                        mfxer   DataTemp                                                        // get byte to compare to
        !          3032:                        rlwinm  DataTemp,DataTemp,32-8,0xFF                     // right align it
        !          3033: 
        !          3034:                        rlwinm  MemDataH,MemDataL,8,0xFF                        // get byte 0
        !          3035:                        cmpw    cr7,MemDataH,DataTemp                           // check for match
        !          3036:                        add.    MemByteCount,MemByteCount,RegIndex      // count the byte, check for end
        !          3037:                        beq             cr7,CompleteLSCBmatch                           // exit if match found
        !          3038:                        beq             CompleteLSCBend                                         // exit if end of string reached
        !          3039: 
        !          3040:                        rlwinm  MemDataH,MemDataL,16,0xFF                       // get byte 1
        !          3041:                        cmpw    cr7,MemDataH,DataTemp                           // check for match
        !          3042:                        add.    MemByteCount,MemByteCount,RegIndex      // count the byte, check for end
        !          3043:                        beq             cr7,CompleteLSCBmatch                           // exit if match found
        !          3044:                        beq             CompleteLSCBend                                         // exit if end of string reached
        !          3045: 
        !          3046:                        rlwinm  MemDataH,MemDataL,24,0xFF                       // get byte 2
        !          3047:                        cmpw    cr7,MemDataH,DataTemp                           // check for match
        !          3048:                        add.    MemByteCount,MemByteCount,RegIndex      // count the byte, check for end
        !          3049:                        beq             cr7,CompleteLSCBmatch                           // exit if match found
        !          3050:                        beq             CompleteLSCBend                                         // exit if end of string reached
        !          3051: 
        !          3052:                        rlwinm  MemDataH,MemDataL,0,0xFF                        // get byte 3
        !          3053:                        cmpw    cr7,MemDataH,DataTemp                           // check for match
        !          3054:                        add.    MemByteCount,MemByteCount,RegIndex      // count the byte, check for end
        !          3055:                        beq             cr7,CompleteLSCBmatch                           // exit if match found
        !          3056:                        bne             CompleteLSCBnext                                        // continue reading if more bytes
        !          3057: CompleteLSCBend:
        !          3058: CompleteLSCBmatch:
        !          3059:                        rlwinm. RegIndex,MemCmdInfo,0,0x10000000        // test the RC bit
        !          3060:                        mfxer   DataTemp                                                        // get string length
        !          3061:                        add             MemByteCount,MemByteCount,DataTemp      // compute number of bytes compared
        !          3062:                        rlwimi  DataTemp,MemByteCount,0,0x7F            // insert into XER
        !          3063:                        mtxer   DataTemp                                                        // restore XER
        !          3064:                        beq             CompleteMemOpDone                                       // all done if RC=0
        !          3065:                        mfcr    DataTemp                                                        // get the match/so bits
        !          3066:                        rlwinm  DataTemp,DataTemp,0,0x03                        // clear the lt/gt bits
        !          3067:                        rlwimi  SavedCR,DataTemp,28,0xF0000000          // update the saved CR0 field
        !          3068:                        b               CompleteMemOpDone                                       // all done
        !          3069: 
        !          3070: 
        !          3071: R8_1241:       lbz             DataTemp,-8(MemAddress)
        !          3072:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3073:                        rlwimi  MemDataH,DataTemp,24,0xFF000000
        !          3074: R7_241:                lhz             DataTemp,-7(MemAddress)
        !          3075:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          3076:                        rlwimi  MemDataH,DataTemp, 8,0x00FFFF00
        !          3077:                        b               R5_41
        !          3078: R6_141:                lbz             DataTemp,-6(MemAddress)
        !          3079:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3080:                        rlwimi  MemDataH,DataTemp, 8,0x0000FF00
        !          3081: R5_41:         lwz             DataTemp,-5(MemAddress)
        !          3082:                        addi    MemCmdInfo,MemCmdInfo,4*MemCmdSizeDec
        !          3083:                        rlwimi  MemDataH,DataTemp, 8,0x000000FF
        !          3084:                        rlwimi  MemDataL,DataTemp, 8,0xFFFFFF00
        !          3085:                        b               R1_1
        !          3086: R8_1421:       lbz             DataTemp,-8(MemAddress)
        !          3087:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3088:                        rlwimi  MemDataH,DataTemp,24,0xFF000000
        !          3089: R7_421:                lwz             DataTemp,-7(MemAddress)
        !          3090:                        addi    MemCmdInfo,MemCmdInfo,4*MemCmdSizeDec
        !          3091:                        rlwimi  MemDataH,DataTemp,24,0x00FFFFFF
        !          3092:                        rlwimi  MemDataL,DataTemp,24,0xFF000000
        !          3093:                        b               R3_21
        !          3094: R6_1221:       lbz             DataTemp,-6(MemAddress)
        !          3095:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3096:                        rlwimi  MemDataH,DataTemp, 8,0x0000FF00
        !          3097: R5_221:                lhz             DataTemp,-5(MemAddress)
        !          3098:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          3099:                        rlwimi  MemDataH,DataTemp,24,0x000000FF
        !          3100:                        rlwimi  MemDataL,DataTemp,24,0xFF000000
        !          3101:                        b               R3_21
        !          3102: R4_121:                lbz             DataTemp,-4(MemAddress)
        !          3103:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3104:                        rlwimi  MemDataL,DataTemp,24,0xFF000000
        !          3105: R3_21:         lhz             DataTemp,-3(MemAddress)
        !          3106:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          3107:                        rlwimi  MemDataL,DataTemp, 8,0x00FFFF00
        !          3108:                        b               R1_1
        !          3109: R2_11:         lbz             DataTemp,-2(MemAddress)
        !          3110:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3111:                        rlwimi  MemDataL,DataTemp, 8,0x0000FF00
        !          3112: R1_1:          lbz             DataTemp,-1(MemAddress)
        !          3113:                        rlwimi  MemDataL,DataTemp, 0,0x000000FF
        !          3114:                        b               RetryDone
        !          3115: 
        !          3116: R8_242:                lhz             DataTemp,-8(MemAddress)
        !          3117:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          3118:                        rlwimi  MemDataH,DataTemp,16,0xFFFF0000
        !          3119:                        b               R6_42
        !          3120: R7_142:                lbz             DataTemp,-7(MemAddress)
        !          3121:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3122:                        rlwimi  MemDataH,DataTemp,16,0x00FF0000
        !          3123: R6_42:         lwz             DataTemp,-6(MemAddress)
        !          3124:                        addi    MemCmdInfo,MemCmdInfo,4*MemCmdSizeDec
        !          3125:                        rlwimi  MemDataH,DataTemp,16,0x0000FFFF
        !          3126:                        rlwimi  MemDataL,DataTemp,16,0xFFFF0000
        !          3127:                        b               R2_2
        !          3128: R5_122:                lbz             DataTemp,-5(MemAddress)
        !          3129:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3130:                        rlwimi  MemDataH,DataTemp, 0,0x000000FF
        !          3131:                        b               R4_22
        !          3132: R3_12:         lbz             DataTemp,-3(MemAddress)
        !          3133:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3134:                        rlwimi  MemDataL,DataTemp,16,0x00FF0000
        !          3135:                        b               R2_2
        !          3136: 
        !          3137: R8_44:         lwz             MemDataH,-8(MemAddress)
        !          3138:                        addi    MemCmdInfo,MemCmdInfo,4*MemCmdSizeDec
        !          3139:                        lwz             MemDataL,-4(MemAddress)
        !          3140:                        b               RetryDone
        !          3141: R7_124:                lbz             DataTemp,-7(MemAddress)
        !          3142:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3143:                        rlwimi  MemDataH,DataTemp,16,0x00FF0000
        !          3144: R6_24:         lhz             DataTemp,-6(MemAddress)
        !          3145:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          3146:                        rlwimi  MemDataH,DataTemp, 0,0x0000FFFF
        !          3147:                        lwz             MemDataL,-4(MemAddress)
        !          3148:                        b               RetryDone
        !          3149: R5_14:         lbz             DataTemp,-5(MemAddress)
        !          3150:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3151:                        rlwimi  MemDataH,DataTemp, 0,0x000000FF
        !          3152: R4_4:          lwz             MemDataL,-4(MemAddress)
        !          3153:                        b               RetryDone
        !          3154: 
        !          3155: R8_8:          lwz             MemDataH,-8(MemAddress)
        !          3156:                        lwz             MemDataL,-4(MemAddress)
        !          3157:                        b               RetryDone
        !          3158: 
        !          3159: 
        !          3160: W8_1241:       srwi    DataTemp,MemDataH,24
        !          3161:                        stb             DataTemp,-8(MemAddress)
        !          3162:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3163: W7_241:                srwi    DataTemp,MemDataH,8
        !          3164:                        sth             DataTemp,-7(MemAddress)
        !          3165:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          3166:                        b               W5_41
        !          3167: W6_141:                srwi    DataTemp,MemDataH,8
        !          3168:                        stb             DataTemp,-6(MemAddress)
        !          3169:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3170: W5_41:         srwi    DataTemp,MemDataL,8
        !          3171:                        rlwimi  DataTemp,MemDataH,24,0xFF000000
        !          3172:                        stw             DataTemp,-5(MemAddress)
        !          3173:                        addi    MemCmdInfo,MemCmdInfo,4*MemCmdSizeDec
        !          3174:                        stb             MemDataL,-1(MemAddress)
        !          3175:                        b               RetryDone
        !          3176: W8_1421:       srwi    DataTemp,MemDataH,24
        !          3177:                        stb             DataTemp,-8(MemAddress)
        !          3178:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3179: W7_421:                srwi    DataTemp,MemDataL,24
        !          3180:                        rlwimi  DataTemp,MemDataH, 8,0xFFFFFF00
        !          3181:                        stw             DataTemp,-7(MemAddress)
        !          3182:                        addi    MemCmdInfo,MemCmdInfo,4*MemCmdSizeDec
        !          3183:                        b               W3_21
        !          3184: W6_1221:       srwi    DataTemp,MemDataH,8
        !          3185:                        stb             DataTemp,-6(MemAddress)
        !          3186:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3187: W5_221:                srwi    DataTemp,MemDataL,24
        !          3188:                        rlwimi  DataTemp,MemDataH, 8,0x0000FF00
        !          3189:                        sth             DataTemp,-5(MemAddress)
        !          3190:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          3191:                        b               W3_21
        !          3192: W4_121:                srwi    DataTemp,MemDataL,24
        !          3193:                        stb             DataTemp,-4(MemAddress)
        !          3194:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3195: W3_21:         srwi    DataTemp,MemDataL,8
        !          3196:                        sth             DataTemp,-3(MemAddress)
        !          3197:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          3198:                        stb             MemDataL,-1(MemAddress)
        !          3199:                        b               RetryDone
        !          3200: W2_11:         srwi    DataTemp,MemDataL,8
        !          3201:                        stb             DataTemp,-2(MemAddress)
        !          3202:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3203: W1_1:          stb             MemDataL,-1(MemAddress)
        !          3204:                        b               RetryDone
        !          3205: 
        !          3206: W8_242:                srwi    DataTemp,MemDataH,16
        !          3207:                        sth             DataTemp,-8(MemAddress)
        !          3208:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          3209:                        b               W6_42
        !          3210: W7_142:                srwi    DataTemp,MemDataH,16
        !          3211:                        stb             DataTemp,-7(MemAddress)
        !          3212:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3213: W6_42:         srwi    DataTemp,MemDataL,16
        !          3214:                        rlwimi  DataTemp,MemDataH,16,0xFFFF0000
        !          3215:                        stw             DataTemp,-6(MemAddress)
        !          3216:                        addi    MemCmdInfo,MemCmdInfo,4*MemCmdSizeDec
        !          3217:                        sth             MemDataL,-2(MemAddress)
        !          3218:                        b               RetryDone
        !          3219: W5_122:                stb             MemDataH,-5(MemAddress)
        !          3220:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3221:                        b               W4_22
        !          3222: W3_12:         srwi    DataTemp,MemDataL,16
        !          3223:                        stb             DataTemp,-3(MemAddress)
        !          3224:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3225: W2_2:          sth             MemDataL,-2(MemAddress)
        !          3226:                        b               RetryDone
        !          3227: 
        !          3228: W8_44:         stw             MemDataH,-8(MemAddress)
        !          3229:                        addi    MemCmdInfo,MemCmdInfo,4*MemCmdSizeDec
        !          3230:                        stw             MemDataL,-4(MemAddress)
        !          3231:                        b               RetryDone
        !          3232: W7_124:                srwi    DataTemp,MemDataH,16
        !          3233:                        stb             DataTemp,-7(MemAddress)
        !          3234:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3235: W6_24:         sth             MemDataH,-6(MemAddress)
        !          3236:                        addi    MemCmdInfo,MemCmdInfo,2*MemCmdSizeDec
        !          3237:                        stw             MemDataL,-4(MemAddress)
        !          3238:                        b               RetryDone
        !          3239: W5_14:         stb             MemDataH,-5(MemAddress)
        !          3240:                        addi    MemCmdInfo,MemCmdInfo,1*MemCmdSizeDec
        !          3241: W4_4:          stw             MemDataL,-4(MemAddress)
        !          3242:                        b               RetryDone
        !          3243: 
        !          3244: W8_8:          stw             MemDataH,-8(MemAddress)
        !          3245:                        stw             MemDataL,-4(MemAddress)
        !          3246:                        b               RetryDone
        !          3247: 
        !          3248: #endif /* 0 */
        !          3249: 
        !          3250: /*
        !          3251: ** HACK!  Assembler fixups!
        !          3252: */
        !          3253: CompleteMemOpDone:
        !          3254: DSI_Decode:
        !          3255: GenerateException:
        !          3256: KernelCrash:
        !          3257:        rfi
        !          3258: #endif
        !          3259: 
        !          3260: /* --------------------------------------------------------------------------- 
        !          3261:        L_MMU(type)
        !          3262: 
        !          3263:        Adopted from Nukernel technology.
        !          3264: 
        !          3265:        This is the exception handling routine branched to by a DSI or ISI
        !          3266:        type of system exception. 
        !          3267: 
        !          3268:        An extension of the data access and instruction access exception handlers
        !          3269:        installed in the hardware vectors.  Satisfies the fault, if possible, from
        !          3270:        the overflow hash table or by generating the PTE from static information.
        !          3271: 
        !          3272:        NOTE: Must be called in the access exception path before data relocation has been
        !          3273:        re-enabled.  Instruction relocation is OK only if these routines are entirely BAT
        !          3274:        mapped.  Avoiding relocated references is a requirement for being able to move
        !          3275:        *any* PTE out to the overflow table.  Otherwise, it would be possible to "overflow
        !          3276:        fault" inside the overflow fault handler.
        !          3277:        
        !          3278:        This routine acts as a safety valve to handle cases when too many virtual 
        !          3279:        addresses fall in a PTE hash class (aka a PTE group or PTEG). Though the PMAP
        !          3280:        support allows pagable entries to be tossed and reconstituted later, wired
        !          3281:        page frames cannot be handled in this manner. This firmware function extends
        !          3282:        the apparent size of the PTEGs by creating a software overflow list that can
        !          3283:        house extra PTEs. When a DSI or ISI is recognized, this function checks the
        !          3284:        overflow list for the related PTE and upon finding it, places it in its
        !          3285:        appropriate PTEG. This may cause a PTE to be vacated into the overflow list.
        !          3286:        Once the PTE is reinstated, control is passed directly back to the interrupted
        !          3287:        instruction. Upon failing to find the related PTE, control is passed to the
        !          3288:        common exit handler to propagate the DSI or ISI to the upper kernel layer for
        !          3289:        the usual page fault resolution.
        !          3290:        
        !          3291:        Other firmware functions replace some of the PMAP equivalent functions to
        !          3292:        ensure searches and/or deletions include the PTEs in the overflow list.
        !          3293:        These functions are accesed via fast path system calls.
        !          3294:        
        !          3295: 
        !          3296:    Entry:      via a system exception handler, thus interrupts off, VM off.
        !          3297:                Entry r1-r3 have been saved in sprg1-3. 
        !          3298:                r2 - byte offset into per_proc_info of this CPU
        !          3299:                r3 - contains the exception number.
        !          3300: 
        !          3301:    Exit:       If the PTE miss is resolved by finding the related PTE in
        !          3302:                the overflow list, control passes directly to the exception
        !          3303:                point. Otherwise, the exception is propagated to the usual
        !          3304:                common exception handler.
        !          3305: */
        !          3306: 
        !          3307: #define        noErr                    0
        !          3308: #define        kernelInUseErr          -1
        !          3309: #define        kernelAlreadyFreeErr    -2
        !          3310: 
        !          3311:        .section __VECTORS, __interrupts
        !          3312:        .align  ALIGNMENT
        !          3313: 
        !          3314: 
        !          3315: 
        !          3316: /*     Globals used by the MMU support functions to manage
        !          3317:        the overflow hash table.
        !          3318: */
        !          3319: .gOverflowHashTable:   .long   0
        !          3320: .gFreeOverflowPTEs:    .long   0
        !          3321: .gOverflowPTEGSeed:    .long   0
        !          3322: .gOverflowTossCount:   .long   0
        !          3323: .gOverflowReloadCount: .long   0
        !          3324: 
        !          3325: /*     Globals used to track autogen capable areas (a nukernel area
        !          3326:        is similar to a mach region). Areas that are autogen capable
        !          3327:        have physically contiguous pages and are resident (wired).
        !          3328: */
        !          3329: .gAutogenAreaList:     .long   0
        !          3330: .gAutogenReloadCount:  .long   0
        !          3331: .gAutogenTossCount:    .long   0
        !          3332: 
        !          3333:                
        !          3334: L_MMU:
        !          3335: 
        !          3336:        /* Save SRR0 and SRR1 plus cr and r3 into PER_PROC structure.
        !          3337:        */
        !          3338:        stw     r3,     PP_SAVE_EXCEPTION_TYPE(r2)
        !          3339:        mfsrr0  r1
        !          3340:        mfsrr1  r3
        !          3341:        stw     r1,     PP_SAVE_SRR0(r2)
        !          3342:        stw     r3,     PP_SAVE_SRR1(r2)
        !          3343:        mfdar   r1
        !          3344:        mfdsisr r3
        !          3345:        stw     r1,     PP_SAVE_DAR(r2)
        !          3346:        stw     r3,     PP_SAVE_DSISR(r2)
        !          3347:        mfcr    r1
        !          3348:        stw     r1,     PP_SAVE_CR(r2)
        !          3349:        
        !          3350:        /* Save registers we'll use into the per-processor buffer.
        !          3351:        */
        !          3352:        stw     r0,     PP_SAVE_R0(r2)
        !          3353:        stw     r4,     PP_SAVE_R4(r2)
        !          3354:        stw     r5,     PP_SAVE_R5(r2)
        !          3355:        stw     r6,     PP_SAVE_R6(r2)
        !          3356:        stw     r7,     PP_SAVE_R7(r2)
        !          3357:        stw     r8,     PP_SAVE_R8(r2)
        !          3358:        stw     r9,     PP_SAVE_R9(r2)
        !          3359:        stw     r10,    PP_SAVE_R10(r2)
        !          3360:        stw     r11,    PP_SAVE_R11(r2)
        !          3361:        stw     r12,    PP_SAVE_R12(r2)
        !          3362: 
        !          3363:        mflr    r0
        !          3364:        lwz     r3,     PP_SAVE_EXCEPTION_TYPE(r2)
        !          3365:        stw     r0,     PP_SAVE_LR(r2)
        !          3366: 
        !          3367: ReloadPTE:
        !          3368: 
        !          3369:        /* Check the OverflowHashTable and AutogenAreaList, 
        !          3370:           reloading if possible.
        !          3371:        */
        !          3372:        cmpwi   r3, EXC_INSTRUCTION_ACCESS
        !          3373:        mfspr   r4, srr0                        // fault address is PC
        !          3374:        beq     HaveFaultAddress
        !          3375:        mfdar   r4                              // fault address is DAR
        !          3376: HaveFaultAddress:
        !          3377:        li              r3, 0                   // pass "current address space"
        !          3378:        bl              LookupPTE
        !          3379: //     EndHashTableSection     r2
        !          3380: 
        !          3381:        /* Check result and restore the registers. If extended PTE lookup worked
        !          3382:           (r4 == noErr), rfi to resume faultee's execution.  If it didn't work,
        !          3383:           continue to process the exception as a page fault.
        !          3384:        */
        !          3385:        cmpwi   r4, noErr                       // check LookupPTE result
        !          3386: 
        !          3387:        lwz     r3,     PP_SAVE_CR(r2)
        !          3388:        lwz     r5,     PP_SAVE_LR(r2)
        !          3389:        lwz     r0,     PP_SAVE_R0(r2)
        !          3390:        mtlr    r5
        !          3391:        lwz     r4,     PP_SAVE_R4(r2)
        !          3392:        lwz     r5,     PP_SAVE_R5(r2)
        !          3393:        lwz     r6,     PP_SAVE_R6(r2)
        !          3394:        lwz     r7,     PP_SAVE_R7(r2)
        !          3395:        lwz     r8,     PP_SAVE_R8(r2)
        !          3396:        lwz     r9,     PP_SAVE_R9(r2)
        !          3397:        lwz     r10,    PP_SAVE_R10(r2)
        !          3398:        lwz     r11,    PP_SAVE_R11(r2)
        !          3399:        lwz     r12,    PP_SAVE_R12(r2)
        !          3400: 
        !          3401:        beq-    DoRFI                           // LookupPTE worked?
        !          3402:        mtcr    r3
        !          3403:        b       .L_Common
        !          3404: 
        !          3405: 
        !          3406:        /* Restore the faultee's r1-r3, then rfi back with the PTE mapped!  Pad (at
        !          3407:           least) the remainder of the rfi instruction's cache line with benign values
        !          3408:           to prevent prefetch enigmas as we transition from instruction relocation off
        !          3409:           back to instruction relocation on. This is a problem on 601s.
        !          3410:        */
        !          3411: DoRFI: mtcr    r3              
        !          3412:        mfsprg  r1, 1
        !          3413:        mfsprg  r2, 2
        !          3414:        mfsprg  r3, 3
        !          3415:        rfi
        !          3416:        .long   0                               // Safety padding
        !          3417:        .long   0                               // Safety padding
        !          3418:        .long   0                               // Safety padding
        !          3419:        .long   0                               // Safety padding
        !          3420:        .long   0                               // Safety padding
        !          3421:        .long   0                               // Safety padding
        !          3422:        .long   0                               // Safety padding
        !          3423:        .long   0                               // Safety padding
        !          3424: 
        !          3425: 
        !          3426: #if 0 /* WIP ================================================================== */
        !          3427: 
        !          3428: /*
        !          3429: -------------------------------------------------------------------------------------
        !          3430:  AllocateOverflowPTE.
        !          3431: 
        !          3432:  Inputs:       r3 == PTEG address
        !          3433:                r4 == PTE hash information word
        !          3434:                r5 == PTE attributes word
        !          3435:  Outputs:      (none)
        !          3436:  Changes:      r3 - r6
        !          3437: 
        !          3438:  Description.
        !          3439: 
        !          3440:  NOTE: This routine is called with interrupts and data relocation disabled.
        !          3441: -------------------------------------------------------------------------------------
        !          3442: */
        !          3443: 
        !          3444: AllocateOverflowPTE:
        !          3445: 
        !          3446:        /* Get an entry from the overflow PTE free list.
        !          3447:        */
        !          3448:        lwz     r6, .gFreeOverflowPTEs(0)
        !          3449:        stw     r3, OverflowPTE.ptegAddress(r6)
        !          3450:        lwz     r3, OverflowPTE.pNextOverflowPTE(r6)
        !          3451:        stw     r3, .gFreeOverflowPTEs(0)
        !          3452: 
        !          3453:        /* Copy thePTEG and thePTEValue into overflow PTE with pteValid set to one.
        !          3454:           r6 == OverflowPTE, r3 == thePTEG, r4 == hash info.
        !          3455:        */
        !          3456:        oris    r4, r4, PTE_validMaskS
        !          3457:        stw     r4, OverflowPTE.pteValue+PTE.hashInfoWord(r6)
        !          3458:        stw     r5, OverflowPTE.pteValue+PTE.attributesWord(r6)
        !          3459: 
        !          3460:        /* Place overflow PTE into proper hash table list head.  
        !          3461:           The hash function is the abbreviated page index (api).
        !          3462:           r6 == OverflowPTE, r4 == hash information word
        !          3463:        */
        !          3464:        rlwinm  r4, r4, PTE_apiShiftOut, PTE_apiMaskOut
        !          3465:        slwi    r4, r4, 2
        !          3466:        addi    r3, r4, .gOverflowHashTable
        !          3467:        lwz     r4, 0(r3)
        !          3468:        stw     r4, OverflowPTE.pNextOverflowPTE(r6)
        !          3469:        stw     r6, 0(r3)
        !          3470: 
        !          3471:        blr
        !          3472: 
        !          3473: /* -----------------------------------------------------------------------------------
        !          3474:  void          DeallocateOverflowPTE      (OverflowPTE *       theOverflowPTE)
        !          3475: 
        !          3476:  Inputs:       r3 == OverflowPTE to deallocate
        !          3477:  Outputs:      (none)
        !          3478:  Changes:      r3 - r5
        !          3479: 
        !          3480:  Description.
        !          3481: -------------------------------------------------------------------------------------
        !          3482: */
        !          3483: DeallocateOverflowPTE:
        !          3484: 
        !          3485:        /* Hash function is the abbreviated page index.
        !          3486:        */
        !          3487:        lwz     r5, OverflowPTE.pteValue+PTE.hashInfoWord(r3)
        !          3488:        rlwinm  r5, r5, PTE_apiShiftOut, PTE_apiMaskOut
        !          3489:        slwi    r5, r5, 2
        !          3490:        addi    r4, r5, .gOverflowHashTable
        !          3491: 
        !          3492:        /* Locate the element previous to the one being deallocated
        !          3493:           r4 == address of current element of which to check link
        !          3494:           r3 == address of target element.
        !          3495:        */
        !          3496: DeallocateLoop:
        !          3497:        lwz     r5, OverflowPTE.pNextOverflowPTE(r4)
        !          3498:        cmplw   r5, r3
        !          3499:        beq     DeallocateFound
        !          3500: 
        !          3501:        mr      r4, r5
        !          3502:        b       DeallocateLoop
        !          3503: 
        !          3504:        /* Delink target element from previous element
        !          3505:           r3 == address of target element
        !          3506:           r4 == address of previous element in list, or the list head itself.
        !          3507:        */
        !          3508: DeallocateFound:
        !          3509:        lwz     r5, OverflowPTE.pNextOverflowPTE(r3)
        !          3510:        stw     r5, OverflowPTE.pNextOverflowPTE(r4)
        !          3511: 
        !          3512:        /* For viewing from the debugger: Make the upper nibble of the 
        !          3513:           ptegAddress be 0xF so we can easily recognize freed elements 
        !          3514:           with all the information intact (PTEG addresses are physical, 
        !          3515:           and are most likely very low so the high 0xF does not disturb anything).
        !          3516:        */
        !          3517: #ifdef  DEBUG
        !          3518:        lwz     r5, OverflowPTE.ptegAddress(r3)
        !          3519:        oris    r5, r5, 0xF000
        !          3520:        stw     r5, OverflowPTE.ptegAddress(r3)
        !          3521: #endif /* DEBUG */
        !          3522: 
        !          3523:        /* Link target element into the free list.  Normally, put it at 
        !          3524:           the head.  For debugger viewing, put it at the end so we have 
        !          3525:           a little history.
        !          3526:           r3 == address of target element.
        !          3527:        */
        !          3528: #ifdef  DEBUG
        !          3529:        lwz     r4, .gFreeOverflowPTEs(0)
        !          3530: FindEnd:
        !          3531:        lwz     r5, OverflowPTE.pNextOverflowPTE(r4)
        !          3532:        cmpwi   r5, 0
        !          3533:        beq     FoundEnd
        !          3534:        mr      r4, r5
        !          3535:        b       FindEnd
        !          3536: FoundEnd:
        !          3537:        stw     r5, OverflowPTE.pNextOverflowPTE(r3)
        !          3538:        stw     r3, OverflowPTE.pNextOverflowPTE(r4)
        !          3539: #else  /* DEBUG */
        !          3540:        lwz     r4, .gFreeOverflowPTEs(0)
        !          3541:        stw     r4, OverflowPTE.pNextOverflowPTE(r3)
        !          3542:        stw     r3, .gFreeOverflowPTEs(0)
        !          3543: #endif /* DEBUG */
        !          3544:        blr
        !          3545: 
        !          3546: /* ----------------------------------------------------------------------------------
        !          3547:  AllocateFromPTEG.
        !          3548: 
        !          3549:  Inputs:       r3 == PTEG address
        !          3550:                        r4 == PTE hash information word
        !          3551:                        r5 == PTE page attributes word
        !          3552:  Outputs:      r3 == PTE address, nil if there was no room
        !          3553:  Changes:      r3 - r6
        !          3554: 
        !          3555:  Description.
        !          3556: 
        !          3557:  NOTE: This routine is called with interrupts and data relocation disabled.
        !          3558: -------------------------------------------------------------------------------------
        !          3559: */
        !          3560: 
        !          3561: AllocateFromPTEG:
        !          3562: 
        !          3563:        /* Loop to find entry with pteValid == 0
        !          3564:        */
        !          3565: AllocateFromPTEGLoop:
        !          3566:        lwz     r6, PTE.hashInfoWord(r3)
        !          3567:        andis.  r6, r6, PTE_validMaskS          // check PTE valid
        !          3568:        beq     FoundFreePTE                    // if clear, go use this PTE
        !          3569:        addi    r3, r3, PTE.sizeof              // else, move to next PTE in PTEG
        !          3570:        andi.   r6, r3, kPTEGSize-1             // off end of PTEG now?
        !          3571:        bne     AllocateFromPTEGLoop            // if not, loop to check PTE
        !          3572: 
        !          3573:        /* No free entry in this PTEG.
        !          3574:        */
        !          3575:        li      r3, 0                           // return nil
        !          3576:        b       AllocateFromPTEGDone            // bye
        !          3577: 
        !          3578:        /* Free PTE found.  r3 == PTE address
        !          3579:        */
        !          3580: FoundFreePTE:
        !          3581:        oris    r4, r4, PTE_validMaskS
        !          3582:        stw     r5, PTE.attributesWord(r3)
        !          3583:        sync
        !          3584:        stw     r4, PTE.hashInfoWord(r3)
        !          3585: 
        !          3586:        /* Common exit path
        !          3587:           r3 == PTE address or nil
        !          3588:        */
        !          3589: AllocateFromPTEGDone:
        !          3590: 
        !          3591:                blr
        !          3592: 
        !          3593: 
        !          3594: /* -----------------------------------------------------------------------------------
        !          3595:  LookupExistingPTEfromVSID.
        !          3596: 
        !          3597:  Inputs:       r3 == VSID.
        !          3598:                        r4 == logical address
        !          3599:  Outputs:      same as LookupExistingPTE
        !          3600: 
        !          3601:  NOTE: This routine is called with interrupts and data relocation disabled.
        !          3602: -------------------------------------------------------------------------------------
        !          3603: */
        !          3604: 
        !          3605: LookupExistingPTEfromVSID:
        !          3606: 
        !          3607: 
        !          3608:        /* Use gSDR1 and specified VSID for theSpace.
        !          3609:           r3 == VSID, r4 == logical address
        !          3610:        */
        !          3611:        lwz     r8, .gSDR1(rtoc)                // r8 = memory system's SDR1
        !          3612:        lwz     r8, 0(r8)
        !          3613:        b       HaveMMUInformation
        !          3614: 
        !          3615: 
        !          3616: 
        !          3617: /* -----------------------------------------------------------------------------------
        !          3618:  LookupExistingPTE.
        !          3619: 
        !          3620:  Inputs:       r3 == address space description or nil (meaning current)
        !          3621:                        r4 == logical address
        !          3622:  Outputs:      r3 == PTE address or nil
        !          3623:                        r4 == Iff r3 is nil: OverflowPTE address, or nil
        !          3624:                        r12 == msr value to restore when out of critical section
        !          3625:  Changes:      r3 - r10, r12
        !          3626:                        Exits in hash table critical section
        !          3627: 
        !          3628:  Return the address of the PageTableEntry or OverflowPTE that map the specified
        !          3629:  logical address.  A nil AddressSpace specifies the current MMU mappings.
        !          3630: 
        !          3631:  NOTE: This routine is called with interrupts and data relocation disabled.
        !          3632:  -------------------------------------------------------------------------------------
        !          3633: */
        !          3634: 
        !          3635: LookupExistingPTE:
        !          3636: 
        !          3637:        /* Check whether caller specified a particular space, or current mappings
        !          3638:        */
        !          3639:        cmpwi   r3, 0                           // theSpace specified?
        !          3640:        bne     UseSpecifiedSpace               // if so, go use it
        !          3641: 
        !          3642:        /* Use gSDR1 and SegmentRegister from current MMU state.
        !          3643:        */
        !          3644:        mfsrin  r3, r4                          // r3 = SegmentRegister value
        !          3645:        mfsdr1  r8                              // r8 = SDR1
        !          3646:        b       HaveMMUInformation
        !          3647: 
        !          3648:        /* Use gSDR1 and SegmentRegister for theSpace.
        !          3649:           r3 == AddressSpace pointer, r4 == logical address.
        !          3650:        */
        !          3651: UseSpecifiedSpace:
        !          3652:        lwz     r3, OpaqueAddressSpacePtr.mmuInfo+MMUSpaceDesc.segmentRegisters(r3)
        !          3653:        rlwinm  r5, r4, EA_segmentNumberShiftOut+2, (EA_segmentNumberMaskOut << 2)      // extract and multiply segment number
        !          3654:        add     r3, r3, r5                      // make byte offset into register file
        !          3655:        lwz     r3, 0(r3)                       // r3 = SegmentRegister value
        !          3656:        lwz     r8, .gSDR1(rtoc)                // r8 = memory system's SDR1
        !          3657:        lwz     r8, 0(r8)
        !          3658: 
        !          3659:        /* Calculate value to match with entry's hashInfoWord
        !          3660:           ((1 << 31) | (segment ID << 7) | (theHashType << 6) | api)
        !          3661:           r3 == SegmentRegister value, r4 == logical address, r8 == SDR1
        !          3662:        */
        !          3663: HaveMMUInformation:
        !          3664:        rlwinm  r6, r3, SR_segmentIDShiftOut+7, (SR_segmentIDMaskOut << 7)              // extract, rotate segment ID
        !          3665:        rlwinm  r5, r4, EA_apiShiftOut, EA_apiMaskOut   // extract abbreviated page index
        !          3666:        or      r5, r6, r5                              // combine segment ID and api
        !          3667:        oris    r10, r5, PTE_validMaskS                 // r10 = hashInfoWord to match
        !          3668: 
        !          3669:        /* Calculate hash values.
        !          3670:        */
        !          3671:        rlwinm  r5, r4, EA_virtualPageShiftOut+kLog2PTEGSize, (EA_virtualPageMaskOut << kLog2PTEGSize)  // calculate (virtual page ID * kPTEGSize)
        !          3672:        rlwinm  r6, r3, SR_VSIDShiftOut+kLog2PTEGSize, (SR_VSIDMaskOut << kLog2PTEGSize)                // calculate (19-bit-VSID * kPTEGSize)
        !          3673:        xor     r3, r5, r6                      // calculate primary hash value
        !          3674:        not     r5, r3                          // calculate secondary hash value
        !          3675: 
        !          3676:        /* Turn off interrupts and data translation
        !          3677:        */
        !          3678:        BeginHashTableSection r4, r6, r7
        !          3679: 
        !          3680:        /* Calculate PTEG address from hash value and SDR1
        !          3681:           r3 == primary hash value, r5 == secondary hash value,
        !          3682:           r8 == SDR1, r10 == hashInfoWord to match.
        !          3683:        */
        !          3684: HaveHashValue:
        !          3685:        rlwinm  r6, r8, SDR1_HTABmaskShiftOut+SDR1_HTABorgShiftIn, (SDR1_HTABmaskMaskOut << SDR1_HTABorgShiftIn)                        // extract table mask and ...
        !          3686:        ori     r6, r6, ((-SDR1_HTABorgMask-1) & -kPTEGSize)    // ... ones-fill to make mask
        !          3687:        and     r3, r3, r6                                      // mask the hash value
        !          3688: 
        !          3689:        rlwinm  r6, r8, 0, SDR1_HTABorgMask     // isolate physical base of hash table
        !          3690:        or      r3, r6, r3                      // sum base and masked hash value to get PTEG
        !          3691: 
        !          3692:        /* Search the PTEG for matching entry
        !          3693:           r3 == PTEG address, r10 == hashInfoWord to match.
        !          3694:        */
        !          3695: SearchPTEGLoop:
        !          3696:        lwz     r6, PTE.hashInfoWord(r3)
        !          3697:        cmplw   r6, r10                         // check this PTE
        !          3698:        beq     PTELookupDone                   // if matched, go return it
        !          3699:        addi    r3, r3, PTE.sizeof              // move to next PTE in PTEG
        !          3700:        andi.   r6, r3, kPTEGSize-1             // off end of PTEG?
        !          3701:        bne     SearchPTEGLoop                  // if not, go check this PTE
        !          3702: 
        !          3703:        andi.   r6, r10, PTE_hashTypeMask       // tried both PTEGs now?
        !          3704:        bne     LookupOverflowPTE               // if so, go try overflow
        !          3705: 
        !          3706:        subi    r9, r3, kPTEGSize               // remember primary PTEG address
        !          3707: 
        !          3708:        /* Calculate secondary hash value
        !          3709:        */
        !          3710:        ori     r10, r10, PTE_hashTypeMask      // switch match for secondary PTEG
        !          3711:        mr      r3, r5                          // get secondary hash value
        !          3712:        b       HaveHashValue                   // and retry
        !          3713: 
        !          3714:        /* PTE not in main hash table, try the overflow table
        !          3715:           r3 == secondary PTEG address + PTEGSize, 
        !          3716:           r9 == primary PTEG address,
        !          3717:           r10 == hashInfoWord to match
        !          3718:        */
        !          3719: LookupOverflowPTE:
        !          3720:        subi    r8, r3, kPTEGSize               // remember secondary PTEG address
        !          3721:        rlwinm  r10, r10, 0, ~PTE_hashTypeMask  // use hash type for primary PTEG
        !          3722:        rlwinm  r6, r10, PTE_apiShiftOut+2, (PTE_apiMaskOut << 2)       // multiply API by sizeof(OverflowPTE *)
        !          3723:        addi    r5, r6, .gOverflowHashTable     // sum base and offset to get list head
        !          3724: TryAgain:
        !          3725:        lwz     r4, 0(r5)                       // get first OverflowPTE in list
        !          3726: SearchOverflowLoop:
        !          3727:        cmpwi   r4, 0                           // nil OverflowPTE pointer?
        !          3728:        beq     OverflowLoopNotFound            // if so, nothing found
        !          3729:        lwz     r6, OverflowPTE.ptegAddress(r4) // get PTEG from OverflowPTE
        !          3730:        cmplw   r6, r9                          // matching PTEG address?
        !          3731:        bne     ContinueOverflowLoop            // if not, continue loop
        !          3732:        lwz     r6, OverflowPTE.pteValue+PTE.hashInfoWord(r4)
        !          3733:        cmplw   r6, r10                         // matching hash information?
        !          3734:        beq     OverflowLoopDone                // if so, found OverflowPTE!
        !          3735: ContinueOverflowLoop:
        !          3736:        lwz     r4, OverflowPTE.pNextOverflowPTE(r4)
        !          3737:        b       SearchOverflowLoop
        !          3738: 
        !          3739: OverflowLoopNotFound:
        !          3740:        cmplw   r8, r9                          // tried secondary already?
        !          3741:        mr      r9, r8                          // switch to secondary PTEG
        !          3742:        ori     r10, r10, PTE_hashTypeMask      // switch match for secondary PTEG
        !          3743:        bne     TryAgain                        // go look again
        !          3744: 
        !          3745:        /* Overflow loop exited one way or the other.
        !          3746:           r4 == OverflowPTE address, or nil.
        !          3747:        */
        !          3748: OverflowLoopDone:
        !          3749: #ifdef  DEBUG
        !          3750:        cmpwi   r4, 0
        !          3751:        beq     DoneIncOverflowReloadCount
        !          3752:        lwz     r3, .gOverflowReloadCount(0)
        !          3753:        addi    r3, r3, 1
        !          3754:        stw     r3, .gOverflowReloadCount(0)
        !          3755: DoneIncOverflowReloadCount:
        !          3756: #endif /* DEBUG */
        !          3757:        li      r3, 0                           // make nil PTE address
        !          3758: 
        !          3759:        /* Common exit.  
        !          3760:           r3 == PTE address, or nil.  
        !          3761:           If nil, r4 == OverflowPTE address, or nil.
        !          3762:        */
        !          3763: PTELookupDone:
        !          3764: 
        !          3765:        blr
        !          3766: 
        !          3767: /* -----------------------------------------------------------------------------------
        !          3768:  GeneratePTE.
        !          3769: 
        !          3770:  Inputs:       r3 == theLogicalAddress
        !          3771:  Outputs:      r3 == primary PTEG address, or nil
        !          3772:                        r4 == primary PTE hash information word (with pteValid == 0)
        !          3773:                        r5 == PTE page attributes word
        !          3774:                        r6 == secondary PTEG address
        !          3775:  Changes:      r3 - r7
        !          3776: 
        !          3777:  Reconstitute a PageTableEntry for the specified logical address in the current
        !          3778:  address space, based on the AutogenArea list.
        !          3779: 
        !          3780:  NOTE: This routine is called with interrupts and data relocation disabled.
        !          3781:  -------------------------------------------------------------------------------------
        !          3782: */
        !          3783: 
        !          3784: GeneratePTE:
        !          3785: 
        !          3786:        /* Locate AutogenArea element for the specified logical address
        !          3787:        */
        !          3788:        lwz     r7, .gAutogenAreaList(0)
        !          3789: GeneratePTELoop:
        !          3790:        cmpwi   r7, 0
        !          3791:        beq     CantGenerate
        !          3792:        lwz     r4, AutogenArea.lowestBackedAddress(r7)
        !          3793:        cmplw   r4, r3                          // lowest <= theLogicalAddress?
        !          3794:        bgt     ContinueGeneratePTELoop         // if not, continue
        !          3795:        lwz     r4, AutogenArea.highestBackedAddress(r7)
        !          3796:        cmplw   r3, r4                          // theLogicalAddress <= highest?
        !          3797:        ble             FoundAutogenArea        // if so, we can generate the PTE
        !          3798: ContinueGeneratePTELoop:
        !          3799:        lwz     r7, AutogenArea.pNextAutogenArea(r7)
        !          3800:        b       GeneratePTELoop
        !          3801: 
        !          3802:        /* Found an autogen area for address.  Carry on.
        !          3803:           r3 == logical address, r7 == address of autogen area
        !          3804:        */
        !          3805: FoundAutogenArea:
        !          3806: 
        !          3807:        /* Generate hash information word
        !          3808:           r3 == logical address
        !          3809:           ((1 << 31) | (segment ID << 7) | (theHashType << 6) | api)
        !          3810:        */
        !          3811:        mfsrin  r4, r3                                          // get segment register value
        !          3812:        rlwinm  r4, r4, PTE_segmentIDShiftIn, PTE_segmentIDMask // extract, rotate segment ID
        !          3813:        rlwinm  r5, r3, EA_apiShiftOut, EA_apiMaskOut           // extract abbreviated page index
        !          3814:        or      r4, r4, r5                                      // combine segment ID and api
        !          3815:        oris    r4, r4, PTE_validMaskS                          // turn on pteValid
        !          3816: 
        !          3817:        /* Generate page attributes word
        !          3818:        */
        !          3819:        lwz     r5, AutogenArea.lowestBackedAddress(r7)
        !          3820:        sub     r5, r3, r5
        !          3821:        rlwinm  r5, r5, 0, kPageAlignMask
        !          3822:        lwz     r6, AutogenArea.physicalBase(r7)
        !          3823:        add     r5, r5, r6
        !          3824:        lwz     r6, AutogenArea.pageProtection(r7)
        !          3825:        rlwimi  r5, r6, PTE_protectionShiftIn, PTE_protectionMask
        !          3826:        lwz     r6, AutogenArea.pageCacheMode(r7)
        !          3827:        rlwimi  r5, r6, PTE_cacheControlShiftIn, PTE_cacheControlMask
        !          3828: 
        !          3829:        /* Calculate PTEG addresses
        !          3830:        */
        !          3831:        mfsrin  r7, r3                          // get segment register value
        !          3832:        rlwinm  r6, r3, EA_virtualPageShiftOut+kLog2PTEGSize, (EA_virtualPageMaskOut << kLog2PTEGSize)  // calculate (virtual page ID * kPTEGSize)
        !          3833:        rlwinm  r7, r7, SR_VSIDShiftOut+kLog2PTEGSize, (SR_VSIDMaskOut << kLog2PTEGSize)                // calculate (19-bit-VSID * kPTEGSize)
        !          3834:        xor     r3, r6, r7                      // calculate primary hash value
        !          3835:        not     r6, r3                          // calculate secondary hash value
        !          3836:        mfsdr1  r7                              // get hash table register
        !          3837:        rlwinm  r7, r7, SDR1_HTABmaskShiftOut+SDR1_HTABorgShiftIn, (SDR1_HTABmaskMaskOut << SDR1_HTABorgShiftIn)                        // extract table mask and ...
        !          3838:        ori     r7, r7, ((-SDR1_HTABorgMask-1) & -kPTEGSize)    // ... ones-fill to make mask
        !          3839:        and     r3, r3, r7                                      // mask the primary hash value
        !          3840:        and     r6, r6, r7                                      // mask the secondary hash value
        !          3841: 
        !          3842:        mfsdr1  r7                              // get hash table register
        !          3843:        rlwinm  r7, r7, 0, SDR1_HTABorgMask     // isolate physical base of hash table
        !          3844:        or      r3, r7, r3                      // r3 = primary PTEG address
        !          3845:        or      r6, r7, r6                      // r6 = secondary PTEG address
        !          3846: #ifdef  DEBUG
        !          3847:        lwz     r7, .gAutogenReloadCount(0)
        !          3848:        addi    r7, r7, 1
        !          3849:        stw     r7, .gAutogenReloadCount(0)
        !          3850: #endif
        !          3851:        b       GeneratePTEDone
        !          3852: 
        !          3853: CantGenerate:
        !          3854:        li      r3, 0
        !          3855: 
        !          3856: GeneratePTEDone:
        !          3857:        blr
        !          3858: 
        !          3859: #endif /* WIP ================================================================== */
        !          3860: 
        !          3861: 
        !          3862: /* -----------------------------------------------------------------------------------
        !          3863:  LookupPTE
        !          3864: 
        !          3865:  Inputs:       r3 == address space description or nil
        !          3866:                r4 == theLogicalAddress
        !          3867:  Outputs:      r3 == thePTE
        !          3868:                r4 == zero iff page was in main hash table
        !          3869:                r12 == value for EndHashTableSection to restore msr
        !          3870:  Changes:      r0, r3 - r12
        !          3871:                msr = hardware interrupts and data translation disabled
        !          3872: 
        !          3873:  Map, if possible, the specified current logical address into the main hash table by
        !          3874:  either bringing it in from the overflow hash table, or generating the PTE on-the-fly.
        !          3875: 
        !          3876:  Exits still inside the hash table critical section so caller can access the returned
        !          3877:  PTE address.  While in the critical section, hardware interrupts and data relocation
        !          3878:  are disabled.  Caller must EndHashTableSection when done with the PTE.
        !          3879: 
        !          3880:  NOTE: When called with r3 == nil, this routine must assume data translation is
        !          3881:  already disabled.
        !          3882:  -------------------------------------------------------------------------------------
        !          3883: */
        !          3884: LookupPTE:
        !          3885: 
        !          3886:        /*      Temp stub. Indicate we didn't find a PTE in the overflow
        !          3887:                list to propagate the exception upward.
        !          3888:        */
        !          3889:        li      r4, kernelInUseErr              // status saying no reload
        !          3890:        blr
        !          3891: 
        !          3892: #if 0 /* WIP ================================================================== */
        !          3893: 
        !          3894:        /* save link register so we can make calls.
        !          3895:        */
        !          3896:        mflr    r0
        !          3897: 
        !          3898:        /* Check the hash table and overflow table.  Return error if the page is
        !          3899:           in the main hash table, because the exception must be for some other
        !          3900:           problem, like access level violation.
        !          3901:        */
        !          3902:        mr      r11, r4                                                                 // r11 = logical address
        !          3903: 
        !          3904:        bl      LookupExistingPTE               // locate PTE or OverflowPTE
        !          3905:        cmpwi   r3, 0                                                                   // found PTE?
        !          3906:        beq     TryOverflow                                                             // no, what about OverflowPTE?
        !          3907: 
        !          3908:        li      r4, kernelInUseErr              // status saying no reload
        !          3909:        b       LookupPTEDone                   // return PTE address and status
        !          3910: 
        !          3911:        /* No overflow means we can try generating the PTE on-the-fly
        !          3912:        */
        !          3913: TryOverflow:
        !          3914:        cmpwi   r4, 0                                                                   // found OverflowPTE?
        !          3915:        beq     TryGeneratingPTE                // if not, go try making PTE
        !          3916: 
        !          3917:        /* Retrieve mapping information from, and free, the OverflowPTE
        !          3918:        */
        !          3919:        lwz     r8, OverflowPTE.ptegAddress(r4)
        !          3920:        lwz     r9, OverflowPTE.pteValue+PTE.hashInfoWord(r4)
        !          3921:        lwz     r10, OverflowPTE.pteValue+PTE.attributesWord(r4)
        !          3922:        mr      r3, r4
        !          3923:        bl      DeallocateOverflowPTE
        !          3924: 
        !          3925:        mr      r7, r8                                                                  // PTEG address for overflow
        !          3926:        mr      r4, r9                                                                  // hash information word
        !          3927:        b       ReloadIt
        !          3928: 
        !          3929:        /* Not in main hash table or in overflow table.  
        !          3930:           Try to generate a PTE.
        !          3931:        */
        !          3932: TryGeneratingPTE:
        !          3933:        mr      r3, r11                                                                 // pass logical address
        !          3934:        bl      GeneratePTE
        !          3935:        cmpwi   r3, 0                                                                   // check result
        !          3936:        bne     GenerateWorked
        !          3937: 
        !          3938:        li      r3, 0                                                                   // nil PTE address
        !          3939:        li      r4, kernelAlreadyFreeErr        // status saying no PTE at all
        !          3940:        b       LookupPTEDone                   // bye
        !          3941: 
        !          3942:        /* PTE was generated.  Try primary PTEG.  Fall back to secondary PTEG.
        !          3943:           r3 == primary PTEG, r4 == hash information, r5 == attributes, 
        !          3944:           r6 == secondary PTEG
        !          3945:        */
        !          3946: GenerateWorked:
        !          3947:        mr      r7, r3                                                                  // keep PTEG address for overflow
        !          3948:        mr      r8, r6                                                                  // keep secondary PTEG address for retry
        !          3949:        mr      r9, r4                                                                  // keep hash information word for retry
        !          3950:        mr      r10, r5                                                                 // keep attributes word for retry
        !          3951:        bl      AllocateFromPTEG
        !          3952:        cmpwi   r3, 0
        !          3953:        bne     ReloadWorked
        !          3954: 
        !          3955:        ori     r4, r9, PTE_hashTypeMask        // hash information word for secondary PTEG
        !          3956:        rlwinm  r9, r9, 0, ~PTE_hashTypeMask    // hash information word for overflow
        !          3957: 
        !          3958:        /* Search specified PTEG.
        !          3959:           r8 == PTEG to check, 
        !          3960:           r4 == PTE hash information word, 
        !          3961:           r10 == PTE page attribute word
        !          3962:           r7 == PTEG address for overflow,
        !          3963:           r9 == PTE hash information word for overflow.
        !          3964:        */
        !          3965: ReloadIt:
        !          3966:        mr      r3, r8                                                                  // pass PTEG address
        !          3967:        mr      r5, r10                                                                 // pass attributes word
        !          3968:        bl      AllocateFromPTEG
        !          3969:        cmpwi   r3, 0                                                                   // check result
        !          3970:        bne     ReloadWorked                    // if it worked, we're done
        !          3971: 
        !          3972:        /* No room in primary or secondary PTEG.
        !          3973:           Select an existing PTE to swap out from the primary PTEG.
        !          3974:        */
        !          3975:        lwz     r4, .gOverflowPTEGSeed(0)       // get current seed value
        !          3976:        addi    r3, r4, 1                                                               // increment it
        !          3977:        cmpwi   r3, kPTEsPerPTEG                // check for wrap
        !          3978:        blt     SetNewSeed                                                              // if none, store value
        !          3979:        li      r3, 0                                                                   // else cut back to zero
        !          3980: SetNewSeed:
        !          3981:        stw     r3, .gOverflowPTEGSeed(0)       // store updated seed value
        !          3982:        slwi    r4, r4, kLog2PTESize            // multiply seed by element size
        !          3983:        add     r8, r7, r4                                                              // r8 = PTE address to swap out
        !          3984: 
        !          3985: #if 0
        !          3986: /*
        !          3987: !!! Don't do this until I/O system agrees with implied restrictions.  !!!
        !          3988: 
        !          3989:  Use the PTE we located.  Don't waste an OverflowPTE on PTE that can be
        !          3990:  regenerated instead.  The address needs to be with an AutogenArea,
        !          3991:  and the page's cache mode must be the same as the area's.
        !          3992:  NOTE: Because the AutogenArea lookup is based on the physical address,
        !          3993:  the cache mode check might be inaccurate if there are more than one
        !          3994:  AutogenArea containing that physical address.  Therefore, SetProcessorCacheMode
        !          3995:  disallows AutogenArea cache mode changes if there are any aliased pages, and
        !          3996:  we are safe.  The idea is that there should be an area per cache mode for
        !          3997:  AutogenArea-type areas.
        !          3998:  r7 == PTEG address, r8 == PTE address
        !          3999: */
        !          4000:  
        !          4001:        lwz     r3, PTE.attributesWord(r8)      // get attributes word
        !          4002:        rlwinm  r3, r3, 0, PTE_pageMask         // mask to physical address
        !          4003:        lwz     r5, .gAutogenAreaList(0)
        !          4004: IsAutogenAddressLoop:
        !          4005:        cmpwi   r5, 0
        !          4006:        beq     SaveInOverflowTable
        !          4007:        lwz     r4, AutogenArea.physicalBase(r5)
        !          4008:        cmplw   r4, r3                                                                  // physical base <= page address?
        !          4009:        bgt     ContinueIsAutogenAddressLoop    // if not, continue
        !          4010:        lwz     r4, AutogenArea.lowestBackedAddress(r5)
        !          4011:        lwz     r6, AutogenArea.highestBackedAddress(r5)
        !          4012:        sub     r6, r6, r4
        !          4013:        lwz     r4, AutogenArea.physicalBase(r5)
        !          4014:        add     r4, r4, r6
        !          4015:        cmplw   r3, r4                                                                  // page address <= highest?
        !          4016:        ble     IsAutogenAddress                // if so, r5 == the AutogenArea
        !          4017: ContinueIsAutogenAddressLoop:
        !          4018:        lwz     r5, AutogenArea.pNextAutogenArea(r5)
        !          4019:        b       IsAutogenAddressLoop
        !          4020: 
        !          4021: IsAutogenAddress:
        !          4022:        lwz     r4, PTE.hashInfoWord(r8)
        !          4023:        rlwinm  r3, r4, PTE_cacheControlShiftOut, PTE_cacheControlMaskOut
        !          4024:        lwz     r5, AutogenArea.pageCacheMode(r5)       // get area's cache mode
        !          4025: #ifdef  DEBUG
        !          4026:        cmplw   r3, r5
        !          4027:        bne     SaveInOverflowTable
        !          4028:        lwz     r4, .gAutogenTossCount(0)
        !          4029:        addi    r4, r4, 1
        !          4030:        stw     r4, .gAutogenTossCount(0)
        !          4031: #endif /* DEBUG */
        !          4032:        cmplw   r3, r5                                                                  // matching cache mode?
        !          4033:        beq     SwapOutPTE                                                              // if so, we can regenerate the PTE
        !          4034: 
        !          4035:        /* Copy the PTE's contents into an element in the overflow table.
        !          4036:           r7 == PTEG address, r8 == PTE address.
        !          4037:        */
        !          4038: SaveInOverflowTable:
        !          4039: #endif /* 0 */
        !          4040: 
        !          4041: #ifdef  DEBUG
        !          4042:        lwz     r3, .gOverflowTossCount(0)
        !          4043:        addi    r3, r3, 1
        !          4044:        stw     r3, .gOverflowTossCount(0)
        !          4045: #endif /* DEBUG */
        !          4046:        mr      r3, r7                                                                  // pass PTEG address
        !          4047:        lwz     r4, PTE.hashInfoWord(r8)        // pass hash information word
        !          4048:        lwz     r5, PTE.attributesWord(r8)      // pass attributes word
        !          4049:        bl      AllocateOverflowPTE
        !          4050: 
        !          4051:        /* Map the new page in place of the old.  A tlbie is not necessary 
        !          4052:           because no effective-to-physical mapping is being undone.  Rather, 
        !          4053:           the PTE is just moving to the overflow list (i.e. the tlb information 
        !          4054:           still applies).  Changes to the tlb entry happen only as a result of a 
        !          4055:           page fault (e.g. setting the "modified" bit), so tlb cast out has no 
        !          4056:           requirement that the PTE be in the main hash table.
        !          4057:           r8 == PTE, 
        !          4058:           r9 == hash information word, 
        !          4059:           r10 == attributes
        !          4060:        */
        !          4061: SwapOutPTE:
        !          4062:        li      r3, 0                                                                   // zero word
        !          4063:        stw     r3, PTE.hashInfoWord(r8)        // invalidate the PTE
        !          4064:        sync                                                                            // synchronize
        !          4065:        stw     r10, PTE.attributesWord(r8)     // store new attributes
        !          4066:        sync                                                                            // synchronize
        !          4067:        stw     r9, PTE.hashInfoWord(r8)        // store new hash information
        !          4068:        mr      r3, r8                                                                  // r3 == PTE address
        !          4069: 
        !          4070:        /* Page was successfully mapped
        !          4071:           r3 == PTE address or nil
        !          4072:        */
        !          4073: ReloadWorked:
        !          4074:        li      r4, noErr                                                               // status saying reload happened
        !          4075: 
        !          4076:        /* r3 == PTE address or nil, 
        !          4077:           r4 == noErr iff reload happened
        !          4078:        */
        !          4079: LookupPTEDone:
        !          4080: 
        !          4081:        mtlr    r0
        !          4082:        blr
        !          4083: 
        !          4084: #endif /* WIP ================================================================== */
        !          4085: 
        !          4086: /* ------------------------------------------------------------------------------
        !          4087: */
        !          4088: 
        !          4089: 
        !          4090: 
        !          4091: 
        !          4092: 
        !          4093:        .globl _ExceptionVectorsEnd
        !          4094: _ExceptionVectorsEnd:  /* Used if relocating the exception vectors */
        !          4095: 
        !          4096: 
        !          4097: 
        !          4098: /*     The entirety of the lowmem area has to fit in the space assigned to it.
        !          4099:        The kernel start point is defined in to places: the makefile.ppc and
        !          4100:        MASTER.ppc files.
        !          4101: */
        !          4102: #if    (_ExceptionVectorsEnd - _ExceptionVectorsStart) > RELOC
        !          4103: #warning **** lowmem overflows into kernel space ****
        !          4104: #endif

unix.superglobalmegacorp.com

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