|
|
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.