Annotation of kernel/machdep/ppc/lowmem_vectors.s, revision 1.1.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.