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