2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
25 Emulate instructions and traps.
27 Lovingly crafted by Bill Angell using traditional methods and only natural or recycled materials.
28 No animal products are used other than rendered otter bile and deep fried pork lard.
34 #include <ppc/proc_reg.h>
35 #include <ppc/exception.h>
36 #include <mach/machine/vm_param.h>
42 ; General stuff what happens here:
43 ; 1) All general context saved, interrupts off, translation off
44 ; 2) Vector and floating point disabled, but there may be live context.
45 ; This code is responsible for saving and restoring what is used. This
46 ; includes exception states, java mode, etc.
47 ; 3) No attempt is made to resolve page faults. PTE misses are handled
48 ; automatically, but actual faults (ala copyin/copyout) are not. If
49 ; a fault does occur, the exception that caused entry to the emulation
50 ; routine is remapped to either an instruction or data miss (depending
51 ; upon the stage detected) and redrived through the exception handler.
52 ; The only time that an instruction fault can happen is when a different
53 ; processor removes a mapping between our original fault and when we
54 ; fetch the assisted instruction. For an assisted instruction, data
55 ; faults should not occur (except in the MP case). For a purely
56 ; emulated instruction, faults can occur.
66 bf-- pf64Bitb,emn64 ; Skip if not 64-bit
67 b EXT(Emulate64) ; Jump to the 64-bit code...
69 emn64: mfsprg r31,0 ; Get the per_proc
70 lwz r12,savesrr1+4(r13) ; Get the exception info
71 rlwinm. r0,r12,0,SRR1_PRG_ILL_INS_BIT,SRR1_PRG_ILL_INS_BIT ; Emulation candidate?
72 lwz r30,dgFlags(0) ; Get the flags
73 beq+ eExit ; Nope, do not try to emulate...
75 rlwinm. r0,r30,0,enaDiagEMb,enaDiagEMb ; Do we want to try to emulate something?
76 mfsprg r28,2 ; Get the processor features
77 beq+ eExit ; No emulation allowed...
79 rlwinm. r28,r28,0,pfAltivecb,pfAltivecb ; Do we have Altivec on this machine?
80 beq eNoVect ; Nope, no Altivec...
82 dssall ; We need to kill streams because we are going to flip to problem state
85 eNoVect: bl eIFetch ; Get the instruction image
86 bne- eRedriveAsISI ; Go redrive this as an ISI...
88 rlwinm. r0,r10,0,0,5 ; See if we have the "special" op code here
89 rlwinm r20,r10,16,22,31 ; Set rS/rD and rA
90 bne+ eExit ; Not special op, ignore...
92 rlwinm r0,r10,31,22,31 ; Extract the sub op code
94 rlwimi r20,r10,14,15,16 ; Move bits 29 and 30 of instruction to 15 and 16 of DSISR
95 cmplwi r0,790 ; lhbrx?
96 rlwimi r20,r10,8,17,17 ; Move bit 25 to bit 17
97 cror cr1_eq,cr1_eq,cr0_eq ; Remember
98 cmplwi r0,534 ; lwbrx?
99 rlwimi r20,r10,3,18,21 ; Move bit 21-24 to bit 18-21
100 cror cr1_eq,cr1_eq,cr0_eq ; Remember
101 cmplwi r0,918 ; sthbrx?
102 cror cr1_eq,cr1_eq,cr0_eq ; Remember
103 cmplwi r0,662 ; stwbrx?
104 cror cr1_eq,cr1_eq,cr0_eq ; Remember
105 cmplwi r0,1014 ; dcbz?
106 cror cr1_eq,cr1_eq,cr0_eq ; Remember
107 cmplwi r0,533 ; lswx?
108 cror cr1_eq,cr1_eq,cr0_eq ; Remember
109 cmplwi r0,661 ; stswx?
110 cror cr1_eq,cr1_eq,cr0_eq ; Remember
111 bne cr1_eq,eNotIndex ; Go check non-index forms...
113 rlwinm. r21,r10,19,24,28 ; Extract index to rA to build EA
114 rlwinm r22,r10,24,24,28 ; Extract index to rB
115 addi r24,r13,saver0+4 ; Point to the start of registers
116 li r19,0 ; Assume 0 base
117 beq eZeroBase ; Yes...
118 lwzx r19,r24,r21 ; Get the base register value
120 eZeroBase: lwzx r22,r24,r22 ; Get the index value
121 add r22,r22,r19 ; Get DAR
122 b eFinishUp ; Done, go finish up...
124 eNotIndex: cmplwi r0,725 ; stswi?
125 cror cr1_eq,cr1_eq,cr0_eq ; Remember
126 cmplwi r0,597 ; lswi?
127 cror cr1_eq,cr1_eq,cr0_eq ; Remember
128 bne cr1,eExit ; Not one we handle...
130 rlwinm. r21,r10,19,24,28 ; Extract index to rA to build EA
131 addi r24,r13,saver0+4 ; Point to the start of registers
132 li r22,0 ; Assume 0 base
133 beq eFinishUp ; Yes, it is...
134 lwzx r22,r24,r21 ; Get the base register value
136 eFinishUp: stw r20,savedsisr(r13) ; Set the DSISR
137 li r11,T_ALIGNMENT ; Get the exception code
138 stw r22,savedar+4(r13) ; Save the DAR
139 stw r11,saveexception(r13) ; Set the exception code
140 b EXT(AlignAssist) ; Go emulate the handler...
143 eExit: b EXT(EmulExit) ; Just return for now...
147 ; Fetch the failing instruction.
148 ; Image returned in R10 if CR0_EQ is false, otherwise, an ISI should be generated/
149 ; The cr bit kernAccess is set if this was a kernel access.
150 ; R1 has the DSISR if access failed.
155 eIFetch: lwz r23,savesrr1+4(r13) ; Get old MSR
156 mflr r28 ; Save return
158 rlwinm. r22,r23,0,MSR_PR_BIT,MSR_PR_BIT ; Within kernel?
160 mfmsr r30 ; Save the MSR for now
161 lwz r23,savesrr0+4(r13) ; Get instruction address
163 ori r22,r30,lo16(MASK(MSR_DR)|MASK(MSR_RI)) ; Set RI and DR onto access MSR
165 crset cr0_eq ; Set this to see if we failed
166 mtmsr r22 ; Flip DR, RI, and maybe PR on
169 lwz r10,0(r23) ; Fetch the instruction
171 mtmsr r30 ; Trans and RI off
174 mtlr r28 ; Restore the LR
175 blr ; Return with instruction image in R10
183 lwz r6,savesrr1+4(r13) ; Get the srr1 value
184 lwz r4,SAVflags(r13) ; Pick up the flags
185 li r11,T_INSTRUCTION_ACCESS ; Set failing instruction fetch code
186 rlwimi r6,r1,0,0,4 ; Move the DSISR bits to the SRR1
187 oris r4,r4,hi16(SAVredrive) ; Set the redrive bit
188 stw r11,saveexception(r13) ; Set the replacement code
189 stw r4,SAVflags(r13) ; Set redrive request
190 stw r6,savesrr1+4(r13) ; Set the srr1 value
191 b EXT(EmulExit) ; Bail out to handle ISI...
195 ; This code emulates instructions that have failed because of operand
196 ; alignment. We decode the DSISR to figure out what we need to do.
199 ; 0001FC00 - Instruction designation
209 ; 000003E0 - Target/Source register
210 ; 0000001F - Register to update if update form
214 .globl EXT(AlignAssist)
217 bf-- pf64Bitb,aan64 ; Skip if not 64-bit
218 b EXT(AlignAssist64) ; Jump to the 64-bit code...
220 aan64: lwz r20,savedsisr(r13) ; Get the DSISR
221 mfsprg r31,0 ; Get the per_proc
222 mtcrf 0x10,r20 ; Put instruction ID in CR for later
223 lwz r21,spcFlags(r31) ; Grab the special flags
224 mtcrf 0x08,r20 ; Put instruction ID in CR for later
225 rlwinm. r0,r21,0,runningVMbit,runningVMbit ; Are we running a VM?
226 mtcrf 0x04,r20 ; Put instruction ID in CR for later
227 lwz r22,savesrr1+4(r13) ; Get the SRR1
228 bne- aaPassAlong ; We are in a VM, no emulation for alignment exceptions...
229 lwz r19,dgFlags(0) ; Get the diagnostics flags
230 crxor iFloat,iOptype1,iOptype2 ; Set this to 0 if both bits are either 0 or 1
231 mr r26,r20 ; Save the DSISR
232 rlwinm. r0,r22,0,MSR_SE_BIT,MSR_SE_BIT ; Were we single stepping?
233 lwz r23,savedar+4(r13) ; Pick up the address that we want to access
234 crnot traceInst,cr0_eq ; Remember if trace is on
236 rlwinm. r0,r19,0,enaNotifyEMb,enaNotifyEMb ; Should we notify that an alignment exception happened?
237 mfmsr r30 ; Save the MSR for now
238 crnot iNotify,cr0_eq ; Remember to tell someone we did this
239 li r29,emfp0 ; Point to work area
240 crxor iFloat,iFloat,iOptype3 ; Set true if we have a floating point instruction
241 dcbz r29,r31 ; Clear and allocate a cache line for us to work in
242 rlwinm r24,r20,3,24,28 ; Get displacement to register to update if update form
243 rlwimi r20,r20,24,28,28 ; Move load/store indication to the bottom of index
244 ori r22,r30,lo16(MASK(MSR_DR)|MASK(MSR_RI)) ; Set RI onto access MSR
245 rlwimi r20,r20,26,27,27 ; Move single/double indication to just above the bottom
246 lis r29,hi16(EXT(aaFPopTable)) ; High part of FP branch table
247 bf- iFloat,aaNotFloat ; This is not a floating point instruction...
248 ori r29,r29,lo16(EXT(aaFPopTable)) ; Low part of FP branch table
250 rlwimi r29,r20,0,22,28 ; Index into table based upon register||iDouble||iStore
251 mtctr r29 ; Get set to call the function
252 bt iStore,aaFPstore ; This is an FP store...
255 ; Here we handle floating point loads
258 aaFPload: crset cr0_eq ; Set this to see if we failed
259 mtmsr r22 ; Flip DR, RI
262 lwz r10,0(r23) ; Get the first word
263 bf- cr0_eq,aaLdNotDbl ; Jump out if we DSIed...
264 bf iDouble,aaLdNotDbl ; this is not a double...
265 lwz r11,4(r23) ; Get the second half
267 aaLdNotDbl: mr r4,r0 ; Save the DAR if we failed the access
269 mtmsr r30 ; Turn off translation again
272 bf- cr0_eq,aaRedriveAsDSI ; Go redrive this as a DSI...
274 stw r10,emfp0(r31) ; Save the first half
275 stw r11,emfp0+4(r31) ; Save the second half, just in case we need it
277 bctrl ; Go set the target FP register
279 b aaComExit ; All done, go exit...
282 ; Here we handle floating point stores
287 aaFPstore: bctrl ; Go save the source FP register
289 lwz r10,emfp0(r31) ; Get first word
290 crandc iDouble,iDouble,iOptype4 ; Change to 4-byte access if stfiwx
291 lwz r11,emfp0+4(r31) ; and the second
292 bf+ iOptype4,aaNotstfiwx ; This is not a stfiwx...
293 mr r10,r11 ; The stfiwx wants to store the second half
296 crset cr0_eq ; Set this to see if we failed
297 mtmsr r22 ; Flip DR, RI
300 stw r10,0(r23) ; Save the first word
301 bf- cr0_eq,aaStNotDbl ; Jump out if we DSIed...
302 bf iDouble,aaStNotDbl ; this is not a double...
303 stw r11,4(r23) ; Save the second half
305 aaStNotDbl: mr r4,r0 ; Save the DAR if we failed the access
309 bf- cr0_eq,aaRedriveAsDSI ; Go redrive this as a DSI...
312 ; Common exit routines
315 aaComExit: lwz r10,savesrr0+4(r13) ; Get the failing instruction address
316 add r24,r24,r13 ; Offset to update register
317 li r11,T_IN_VAIN ; Assume we are all done
318 addi r10,r10,4 ; Step to the next instruction
319 bf iUpdate,aaComExNU ; Skip if not an update form...
320 stw r23,saver0+4(r24) ; Update the target
322 aaComExNU: lwz r9,SAVflags(r13) ; Get the flags
323 stw r10,savesrr0+4(r13) ; Set new PC
324 bt- traceInst,aaComExitrd ; We are tracing, go emulate trace...
325 bf+ iNotify,aaComExGo ; Nothing special here, go...
327 li r11,T_ALIGNMENT ; Set the we just did an alignment exception....
329 aaComExGo: b EXT(EmulExit) ; We are done, no tracing on...
333 ; This is not a floating point operation
335 ; The emulation routines for these are positioned every 64 bytes (16 instructions)
336 ; in a 1024-byte aligned table. It is indexed by taking the low order 4 bits of
337 ; the instruction code in the DSISR and subtracting 7. If this comes up negative,
338 ; the instruction is not to be emulated. Then we add bit 0 of the code * 4. This
339 ; gives us a fairly compact and almost unique index. Both lwm and stmw map to 0 so
340 ; that one needs to be further reduced, and we end up with holes at index 6, 8, and 10.
342 ; If the emulation routine takes more than 16 instructions, it must branch elsewhere
349 lis r19,hi16(aaEmTable) ; Point to high part of table address
350 rlwinm r3,r26,24,26,29 ; Isolate last 4 bits of op type * 4
351 rlwimi r19,r26,20,27,27 ; Get bit 0 of instruction code * 4 into bottom of table base
352 addic. r3,r3,-28 ; Subtract 7*4 to adjust index
353 ori r19,r19,lo16(aaEmTable) ; Low part of table address
354 blt- aaPassAlong ; We do not handle any of these (lwarx, stwcx., eciwx, ecowx)...
355 add r19,r19,r3 ; Point to emulation routine
356 rlwinm r18,r26,30,24,28 ; Get the target/source register displacement
358 mtctr r19 ; Set the routine address
360 bctr ; Go emulate the instruction...
363 ; This is the table of non-floating point emulation routines.
364 ; It is indexed by low 4 bits of DSISR op type - 7 + bit 0 of
371 b aaLmwStmw ; This for lmw/stmw
372 b aaLswx ; This for lwwx
373 b aaLswi ; This for lswi
374 b aaStswx ; This for stswx
375 b aaStswi ; This for stswi
376 b aaLwbrx ; This for lwbrx
377 b aaPassAlong ; This an invalid index (6)
378 b aaStwbrx ; This for stwbrx
379 b aaPassAlong ; This an invalid index (8)
380 b aaLhbrx ; This for lhbrx
381 b aaPassAlong ; This an invalid index (A)
382 b aaSthbrx ; This for sthbrx
383 b aaDcbz ; This for dcbz
384 b aaPassAlong ; This an invalid index (D)
385 b aaPassAlong ; This an invalid index (E)
386 b aaPassAlong ; This an invalid index (F)
390 ; Here we handle the set up for the lmw and stmw. After that, we split off to the
391 ; individual routines.
393 ; Note also that after some set up, all of the string instructions come through here as well.
398 rlwinm r17,r18,31,1,29 ; Convert doublword based index to words
399 li r28,0 ; Set no extra bytes to move (used for string instructions)
400 subfic r17,r17,32*4 ; Calculate the length of the transfer
402 aaLSComm: addi r19,r13,saver0+4 ; Offset to registers in savearea
403 mr r16,r23 ; Make a hunk pointer
405 bt iUpdate,aaStmw ; This is the stmw...
411 aaLmwNxt: cmplwi cr1,r17,8*4 ; Is there enough to move 8?
412 blt- cr1,aaLmwNxtH ; Not enough for a full hunk...
413 subi r17,r17,8*4 ; Back off for another hunk
415 crset cr0_eq ; Set this to see if we failed
416 mtmsr r22 ; Flip DR, RI
419 lwz r2,0(r16) ; Load word 0
420 bf- cr0_eq,aaLmwB1 ; Error, bail...
421 lwz r15,4(r16) ; Load word 1
422 bf- cr0_eq,aaLmwB1 ; Error, bail...
423 lwz r14,8(r16) ; Load word 2
424 bf- cr0_eq,aaLmwB1 ; Error, bail...
425 lwz r5,12(r16) ; Load word 3
426 bf- cr0_eq,aaLmwB1 ; Error, bail...
427 lwz r6,16(r16) ; Load word 4
428 bf- cr0_eq,aaLmwB1 ; Error, bail...
429 lwz r7,20(r16) ; Load word 5
430 bf- cr0_eq,aaLmwB1 ; Error, bail...
431 lwz r8,24(r16) ; Load word 6
432 bf- cr0_eq,aaLmwB1 ; Error, bail...
433 lwz r9,28(r16) ; Load word 7
435 aaLmwB1: mr r4,r0 ; Remember DAR, jus in case we failed the access
436 mtmsr r30 ; Turn off DR, RI
439 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
441 addi r16,r16,8*4 ; Point up to next input aread
443 stwx r2,r19,r18 ; Store register
444 addi r18,r18,8 ; Next register
445 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
446 stwx r15,r19,r18 ; Store register
447 addi r18,r18,8 ; Next register
448 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
449 stwx r14,r19,r18 ; Store register
450 addi r18,r18,8 ; Next register
451 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
452 stwx r5,r19,r18 ; Store register
453 addi r18,r18,8 ; Next register
454 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
455 stwx r6,r19,r18 ; Store register
456 addi r18,r18,8 ; Next register
457 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
458 stwx r7,r19,r18 ; Store register
459 addi r18,r18,8 ; Next register
460 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
461 stwx r8,r19,r18 ; Store register
462 addi r18,r18,8 ; Next register
463 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
464 stwx r9,r19,r18 ; Store register
465 addi r18,r18,8 ; Next register
466 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
468 b aaLmwNxt ; Do the next hunk...
472 aaLmwNxtH: cmplwi cr1,r17,4*4 ; Do we have 4 left?
473 blt cr1,aaLmwL4 ; Nope...
475 subi r17,r17,4*4 ; Set count properly
477 crset cr0_eq ; Set this to see if we failed
478 mtmsr r22 ; Flip DR, RI, and maybe PR on
481 lwz r2,0(r16) ; Load word 0
482 bf- cr0_eq,aaLmwB2 ; Error, bail...
483 lwz r15,4(r16) ; Load word 1
484 bf- cr0_eq,aaLmwB2 ; Error, bail...
485 lwz r14,8(r16) ; Load word 2
486 bf- cr0_eq,aaLmwB2 ; Error, bail...
487 lwz r5,12(r16) ; Load word 3
489 aaLmwB2: mr r4,r0 ; Remember DAR, jus in case we failed the access
490 mtmsr r30 ; Turn off DR, RI
493 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
495 addi r16,r16,4*4 ; Point up to next input aread
497 stwx r2,r19,r18 ; Store register
498 addi r18,r18,8 ; Next register
499 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
500 stwx r15,r19,r18 ; Store register
501 addi r18,r18,8 ; Next register
502 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
503 stwx r14,r19,r18 ; Store register
504 addi r18,r18,8 ; Next register
505 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
506 stwx r5,r19,r18 ; Store register
507 addi r18,r18,8 ; Next register
508 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
510 aaLmwL4: or. r5,r17,r28 ; Do we have anything left?
511 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three full words left?
512 cmplwi cr2,r17,0 ; Do we have no full words left?
513 beq aaComExit ; Nothing left...
515 crset cr0_eq ; Set this to see if we failed
516 mtmsr r22 ; Flip DR, RI, and maybe PR on
519 beq- cr2,aaLmwBy ; No full words, get bytes...
521 lwz r2,0(r16) ; Pick up first word
522 bf- cr0_eq,aaLmwDn ; Read failed, escape...
523 addi r16,r16,4 ; Next input location
524 blt cr1,aaLmwBy ; We only had one, we are done...
526 lwz r15,0(r16) ; Pick up second word
527 bf- cr0_eq,aaLmwDn ; Read failed, escape...
528 addi r16,r16,4 ; Next input location
529 beq cr1,aaLmwBy ; We had two, we are done...
531 lwz r14,0(r16) ; Load word 3
532 addi r16,r16,4 ; Next input location
534 aaLmwBy: cmplwi cr2,r28,0 ; Any trailing bytes to do?
535 li r8,0 ; Clear second trailing byte
536 cmplwi cr1,r28,2 ; Check for 1, 2, or 3
537 li r9,0 ; Clear third trailing byte
538 beq+ cr2,aaLmwDn ; No trailing bytes...
540 lbz r5,0(r16) ; Pick up first trailing byte
541 bf- cr0_eq,aaLmwDn ; Read failed, escape...
542 blt cr1,aaLmwDn ; We only had one, we are done...
544 lbz r8,1(r16) ; Pick up second trailing byte
545 bf- cr0_eq,aaLmwDn ; Read failed, escape...
546 beq cr1,aaLmwDn ; We had two, we are done...
548 lbz r9,2(r16) ; Get last trailing byte
551 aaLmwDn: rlwinm r5,r5,24,0,7 ; Move first byte to top
552 cmplwi cr2,r17,0 ; Any full words to do?
553 mr r4,r0 ; Remember DAR, just in case we failed the access
554 rlwimi r9,r8,8,16,23 ; Move second byte above third byte
555 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three full words left?
556 mr r3,r30 ; Set the normal MSR
557 rlwimi r5,r9,8,8,23 ; Move bytes 1 and 2 after 0
559 mtmsr r30 ; Turn off DR, RI
562 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
564 beq- cr2,aaLmwCb ; No full words, copy bytes...
566 stwx r2,r19,r18 ; Store register
567 addi r18,r18,8 ; Next register
568 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
569 blt cr1,aaLmwCb ; We only had one, we are done...
571 stwx r15,r19,r18 ; Store register
572 addi r18,r18,8 ; Next register
573 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
574 beq cr1,aaLmwCb ; We had two, we are done...
576 stwx r14,r19,r18 ; Store register
577 addi r18,r18,8 ; Next register
578 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
580 aaLmwCb: mr. r28,r28 ; Any trailing bytes to do?
581 beq+ aaComExit ; Nope, leave...
583 stwx r5,r19,r18 ; Store register
585 b aaComExit ; We are done....
588 ; Store multiple word
594 crclr iUpdate ; Make sure we do not think this is an update form
596 aaStmwNxt: cmplwi cr1,r17,8*4 ; Is there enough to move 8?
597 blt- cr1,aaStmwNxtH ; Not enough for a full hunk...
598 subi r17,r17,8*4 ; Back off for another hunk
600 lwzx r2,r19,r18 ; Store register
601 addi r18,r18,8 ; Next register
602 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
603 lwzx r15,r19,r18 ; Store register
604 addi r18,r18,8 ; Next register
605 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
606 lwzx r14,r19,r18 ; Store register
607 addi r18,r18,8 ; Next register
608 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
609 lwzx r5,r19,r18 ; Store register
610 addi r18,r18,8 ; Next register
611 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
612 lwzx r6,r19,r18 ; Store register
613 addi r18,r18,8 ; Next register
614 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
615 lwzx r7,r19,r18 ; Store register
616 addi r18,r18,8 ; Next register
617 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
618 lwzx r8,r19,r18 ; Store register
619 addi r18,r18,8 ; Next register
620 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
621 lwzx r9,r19,r18 ; Store register
622 addi r18,r18,8 ; Next register
623 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
625 crset cr0_eq ; Set this to see if we failed
626 mtmsr r22 ; Flip DR, RI, and maybe PR on
629 stw r2,0(r16) ; Store word 0
630 bf- cr0_eq,aaStmwB1 ; Error, bail...
631 stw r15,4(r16) ; Store word 1
632 bf- cr0_eq,aaStmwB1 ; Error, bail...
633 stw r14,8(r16) ; Store word 2
634 bf- cr0_eq,aaStmwB1 ; Error, bail...
635 stw r5,12(r16) ; Store word 3
636 bf- cr0_eq,aaStmwB1 ; Error, bail...
637 stw r6,16(r16) ; Store word 4
638 bf- cr0_eq,aaStmwB1 ; Error, bail...
639 stw r7,20(r16) ; Store word 5
640 bf- cr0_eq,aaStmwB1 ; Error, bail...
641 stw r8,24(r16) ; Store word 6
642 bf- cr0_eq,aaStmwB1 ; Error, bail...
643 stw r9,28(r16) ; Store word 7
645 addi r16,r16,8*4 ; Point up to next output aread
648 aaStmwB1: mr r4,r0 ; Remember DAR, jus in case we failed the access
649 mtmsr r30 ; Normal MSR
652 bt- cr0_eq,aaStmwNxt ; We have more to do and no failed access...
653 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
657 aaStmwNxtH: cmplwi cr1,r17,(4*4) ; Do we have at least 4 left?
658 blt cr1,aaStmwL4 ; Nope...
659 subi r17,r17,4*4 ; Set count properly
661 lwzx r2,r19,r18 ; Store register
662 addi r18,r18,8 ; Next register
663 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
664 lwzx r15,r19,r18 ; Store register
665 addi r18,r18,8 ; Next register
666 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
667 lwzx r14,r19,r18 ; Store register
668 addi r18,r18,8 ; Next register
669 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
670 lwzx r5,r19,r18 ; Store register
671 addi r18,r18,8 ; Next register
672 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
674 crset cr0_eq ; Set this to see if we failed
675 mtmsr r22 ; Flip DR, RI
678 stw r2,0(r16) ; Store word 0
679 bf- cr0_eq,aaStmwB2 ; Error, bail...
680 stw r15,4(r16) ; Store word 1
681 bf- cr0_eq,aaStmwB2 ; Error, bail...
682 stw r14,8(r16) ; Store word 2
683 bf- cr0_eq,aaStmwB2 ; Error, bail...
684 stw r5,12(r16) ; Store word 3
686 addi r16,r16,4*4 ; Point up to next input aread
688 aaStmwB2: mr r4,r0 ; Remember DAR, jus in case we failed the access
689 mtmsr r30 ; Normal MSR
692 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
694 aaStmwL4: or. r5,r17,r28 ; Do we have anything left to do?
695 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three left?
696 cmplwi cr2,r17,0 ; Do we have no full words left?
697 beq aaComExit ; Nothing left...
699 beq- cr2,aaStmwBy1 ; No full words, check out bytes
701 lwzx r2,r19,r18 ; Store register
702 addi r18,r18,8 ; Next register
703 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
704 blt cr1,aaStmwBy1 ; We only had one, go save it...
706 lwzx r15,r19,r18 ; Store register
707 addi r18,r18,8 ; Next register
708 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
709 beq cr1,aaStmwBy1 ; We had two, go save it...
711 lwzx r14,r19,r18 ; Store register
712 addi r18,r18,8 ; Next register
713 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
715 aaStmwBy1: mr. r28,r28 ; Do we have any trailing bytes?
716 beq+ aaStmwSt ; Nope...
718 lwzx r5,r19,r18 ; Yes, pick up one extra register
720 aaStmwSt: crset cr0_eq ; Set this to see if we failed
721 mtmsr r22 ; Flip DR, RI
724 beq- cr2,aaStmwBy2 ; No words, check trailing bytes...
726 stw r2,0(r16) ; Save first word
727 bf- cr0_eq,aaStmwDn ; Store failed, escape...
728 addi r16,r16,4 ; Bump sink
729 blt cr1,aaStmwBy2 ; We only had one, we are done...
731 stw r15,0(r16) ; Save second word
732 bf- cr0_eq,aaStmwDn ; Store failed, escape...
733 addi r16,r16,4 ; Bump sink
734 beq cr1,aaStmwBy2 ; We had two, we are done...
736 stw r14,0(r16) ; Save third word
737 bf- cr0_eq,aaStmwDn ; Store failed, escape...
738 addi r16,r16,4 ; Bump sink
740 aaStmwBy2: rlwinm r2,r5,8,24,31 ; Get byte 0
741 cmplwi cr2,r28,0 ; Any trailing bytes to do?
742 rlwinm r14,r5,24,24,31 ; Get byte 3
743 li r8,0 ; Clear second trailing byte
744 cmplwi cr1,r28,2 ; Check for 1, 2, or 3
745 li r9,0 ; Clear third trailing byte
746 beq+ cr2,aaStmwDn ; No trailing bytes...
747 rlwinm r15,r5,16,24,31 ; Get byte 1
749 stb r2,0(r16) ; Save first byte
750 bf- cr0_eq,aaStmwDn ; Read failed, escape...
751 blt cr1,aaStmwDn ; We only had one, we are done...
753 stb r15,1(r16) ; Save second byte
754 bf- cr0_eq,aaStmwDn ; Read failed, escape...
755 beq cr1,aaStmwDn ; We had two, we are done...
757 stb r14,2(r16) ; Save third byte
759 aaStmwDn: mr r4,r0 ; Remember DAR, jus in case we failed the access
760 mtmsr r30 ; Normal MSR
763 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
765 b aaComExit ; We are done....
769 ; Load String Indexed
774 aaLswx: lwz r17,savexer+4(r13) ; Pick up the XER
775 crclr iUpdate ; Make sure we think this the load form
776 rlwinm. r25,r17,0,25,31 ; Get the number of bytes to load
777 rlwinm r28,r17,0,30,31 ; Get the number of bytes past an even word
778 beq- aaComExit ; Do nothing if 0 length...
779 xor r17,r25,r28 ; Round down to an even word boundary
780 b aaLSComm ; Join up with common load/store code...
784 ; Load String Immediate
789 aaLswi: mr r9,r23 ; Save the DAR
790 bl eIFetch ; Get the instruction image
791 bne- eRedriveAsISI ; Go redrive this as an ISI...
792 rlwinm r25,r10,21,27,31 ; Get the number of bytes to load
793 crclr iUpdate ; Make sure we think this the load form
794 subi r25,r25,1 ; Back off by 1
795 rlwinm r25,r25,0,27,31 ; Clear back down
796 addi r25,r25,1 ; Add back the 1 to convert 0 to 32
797 rlwinm r28,r25,0,30,31 ; Get the number of bytes past an even word
798 xor r17,r25,r28 ; Round down to an even word boundary
799 mr r23,r9 ; Move back the DAR
800 b aaLSComm ; Join up with common load/store code...
803 ; Store String Indexed
808 aaStswx: lwz r17,savexer+4(r13) ; Pick up the XER
809 crclr iUpdate ; Make sure this is clear in case we have 0 length
810 rlwinm. r25,r17,0,25,31 ; Get the number of bytes to load
811 rlwinm r28,r17,0,30,31 ; Get the number of bytes past an even word
812 beq- aaComExit ; Do nothing if 0 length...
813 xor r17,r25,r28 ; Round down to an even word boundary
814 crset iUpdate ; Make sure we think this the store form
815 b aaLSComm ; Join up with common load/store code...
819 ; Store String Immediate
824 aaStswi: mr r9,r23 ; Save the DAR
825 bl eIFetch ; Get the instruction image
826 bne- eRedriveAsISI ; Go redrive this as an ISI...
827 rlwinm r25,r10,21,27,31 ; Get the number of bytes to load
828 crclr iUpdate ; Make sure we think this the load form
829 subi r25,r25,1 ; Back off by 1
830 rlwinm r25,r25,0,27,31 ; Clear back down
831 addi r25,r25,1 ; Add back the 1 to convert 0 to 32
832 rlwinm r28,r25,21,30,31 ; Get the number of bytes past an even word
833 xor r17,r25,r28 ; Round down to an even word boundary
834 mr r23,r9 ; Move back the DAR
835 b aaLSComm ; Join up with common load/store code...
839 ; Load byte-reversed word
845 add r18,r18,r13 ; Index to source register
847 crset cr0_eq ; Set this to see if we failed
848 mtmsr r22 ; Flip DR, RI, and maybe PR on
851 lwz r11,0(r23) ; Load the word
853 mr r4,r0 ; Save the DAR if we failed the access
854 mtmsr r30 ; Restore normal MSR
857 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
859 rlwinm r10,r11,8,0,31 ; Get byte 0 to 3 and byte 2 to 1
860 rlwimi r10,r11,24,16,23 ; Move byte 1 to byte 2
861 rlwimi r10,r11,24,0,7 ; Move byte 3 to byte 0
863 stw r10,saver0+4(r18) ; Set the register
865 b aaComExit ; All done, go exit...
870 ; Store byte-reversed word
876 add r18,r18,r13 ; Index to source register
877 lwz r11,saver0+4(r18) ; Get the register to store
879 rlwinm r10,r11,8,0,31 ; Get byte 0 to 3 and byte 2 to 1
880 rlwimi r10,r11,24,16,23 ; Move byte 1 to byte 2
881 rlwimi r10,r11,24,0,7 ; Move byte 3 to byte 0
883 crset cr0_eq ; Set this to see if we failed
884 mtmsr r22 ; Flip DR, RI, and maybe PR on
887 stw r10,0(r23) ; Store the reversed halfword
889 mr r4,r0 ; Save the DAR if we failed the access
890 mtmsr r30 ; Restore normal MSR
893 bt+ cr0_eq,aaComExit ; All done, go exit...
894 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
899 ; Load byte-reversed halfword
905 add r18,r18,r13 ; Index to source register
907 crset cr0_eq ; Set this to see if we failed
908 mtmsr r22 ; Flip DR, RI, and maybe PR on
911 lhz r11,0(r23) ; Load the halfword
913 mr r4,r0 ; Save the DAR if we failed the access
914 mtmsr r30 ; Restore normal MSR
917 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
919 rlwinm r10,r11,8,16,23 ; Rotate bottom byte up one and clear everything else
920 rlwimi r10,r11,24,24,31 ; Put old second from bottom into bottom
922 stw r10,saver0+4(r18) ; Set the register
924 b aaComExit ; All done, go exit...
928 ; Store byte-reversed halfword
934 add r18,r18,r13 ; Index to source register
935 lwz r10,saver0+4(r18) ; Get the register to store
936 rlwinm r10,r10,8,0,31 ; Rotate bottom byte up one
937 rlwimi r10,r10,16,24,31 ; Put old second from bottom into bottom
939 crset cr0_eq ; Set this to see if we failed
940 mtmsr r22 ; Flip DR, RI, and maybe PR on
943 sth r10,0(r23) ; Store the reversed halfword
945 mr r4,r0 ; Save the DAR if we failed the access
946 mtmsr r30 ; Restore normal MSR
949 bt+ cr0_eq,aaComExit ; All done, go exit...
950 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
953 ; Data cache block zero
959 rlwinm r23,r23,0,0,26 ; Round back to a 32-byte boundary
961 crset cr0_eq ; Set this to see if we failed
962 li r0,0 ; Clear this out
963 mtmsr r22 ; Flip DR, RI, and maybe PR on
966 stw r0,0(r23) ; Clear word
967 bne- aaDcbzXit ; Got DSI, we are stopping...
968 stw r0,4(r23) ; Clear word
969 bne- aaDcbzXit ; Got DSI, we are stopping...
970 stw r0,8(r23) ; Clear word
971 bne- aaDcbzXit ; Got DSI, we are stopping...
972 stw r0,12(r23) ; Clear word
973 bne- aaDcbzXit ; Got DSI, we are stopping...
974 stw r0,16(r23) ; Clear word
975 bne- aaDcbzXit ; Got DSI, we are stopping...
976 stw r0,20(r23) ; Clear word
977 bne- aaDcbzXit ; Got DSI, we are stopping...
978 stw r0,24(r23) ; Clear word
979 bne- aaDcbzXit ; Got DSI, we are stopping...
980 stw r0,28(r23) ; Clear word
982 aaDcbzXit: mr r4,r0 ; Save the DAR if we failed the access
983 mtmsr r30 ; Restore normal MSR
986 crclr iUpdate ; Make sure we do not think this is an update form
988 bt+ cr0_eq,aaComExit ; All done, go exit...
989 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
993 ; Unhandled alignment exception, pass it along
1003 ; We go here to emulate a trace exception after we have handled alignment error
1009 oris r9,r9,hi16(SAVredrive) ; Set the redrive bit
1010 li r11,T_TRACE ; Set trace interrupt
1011 rlwinm r12,r12,0,16,31 ; Clear top half of SRR1
1012 stw r9,SAVflags(r13) ; Set the flags
1013 stw r11,saveexception(r13) ; Set the exception code
1014 b EXT(EmulExit) ; Exit and do trace interrupt...
1022 mr r20,r1 ; Save the DSISR
1024 lwz r4,SAVflags(r13) ; Pick up the flags
1025 li r11,T_DATA_ACCESS ; Set failing data access code
1026 oris r4,r4,hi16(SAVredrive) ; Set the redrive bit
1027 stw r20,savedsisr(r13) ; Set the DSISR of failed access
1028 stw r21,savedar+4(r13) ; Set the address of the failed access
1029 stw r11,saveexception(r13) ; Set the replacement code
1030 stw r4,SAVflags(r13) ; Set redrive request
1031 b EXT(EmulExit) ; Bail out to handle ISI...
1036 ; Table of functions to load or store floating point registers
1037 ; This table is indexed reg||size||dir. That means that each
1038 ; like load/store pair (e.g., lfd f31/stfd f31) are within the same
1039 ; quadword, which is the current ifetch size. We expect most of the
1040 ; unaligned accesses to be part of copies, therefore, with this
1041 ; organization, we will save the ifetch of the store after the load.
1044 .align 10 ; Make sure we are on a 1k boundary
1045 .globl EXT(aaFPopTable)
1048 lfs f0,emfp0(r31) ; Load single variant
1051 stfs f0,emfp0(r31) ; Store single variant
1054 lfd f0,emfp0(r31) ; Load double variant
1057 stfd f0,emfp0(r31) ; Store double variant
1060 lfs f1,emfp0(r31) ; Load single variant
1063 stfs f1,emfp0(r31) ; Store single variant
1066 lfd f1,emfp0(r31) ; Load double variant
1069 stfd f1,emfp0(r31) ; Store double variant
1072 lfs f2,emfp0(r31) ; Load single variant
1075 stfs f2,emfp0(r31) ; Store single variant
1078 lfd f2,emfp0(r31) ; Load double variant
1081 stfd f2,emfp0(r31) ; Store double variant
1084 lfs f3,emfp0(r31) ; Load single variant
1087 stfs f3,emfp0(r31) ; Store single variant
1090 lfd f3,emfp0(r31) ; Load double variant
1093 stfd f3,emfp0(r31) ; Store double variant
1096 lfs f4,emfp0(r31) ; Load single variant
1099 stfs f4,emfp0(r31) ; Store single variant
1102 lfd f4,emfp0(r31) ; Load double variant
1105 stfd f4,emfp0(r31) ; Store double variant
1108 lfs f5,emfp0(r31) ; Load single variant
1111 stfs f5,emfp0(r31) ; Store single variant
1114 lfd f5,emfp0(r31) ; Load double variant
1117 stfd f5,emfp0(r31) ; Store double variant
1120 lfs f6,emfp0(r31) ; Load single variant
1123 stfs f6,emfp0(r31) ; Store single variant
1126 lfd f6,emfp0(r31) ; Load double variant
1129 stfd f6,emfp0(r31) ; Store double variant
1132 lfs f7,emfp0(r31) ; Load single variant
1135 stfs f7,emfp0(r31) ; Store single variant
1138 lfd f7,emfp0(r31) ; Load double variant
1141 stfd f7,emfp0(r31) ; Store double variant
1144 lfs f8,emfp0(r31) ; Load single variant
1147 stfs f8,emfp0(r31) ; Store single variant
1150 lfd f8,emfp0(r31) ; Load double variant
1153 stfd f8,emfp0(r31) ; Store double variant
1156 lfs f9,emfp0(r31) ; Load single variant
1159 stfs f9,emfp0(r31) ; Store single variant
1162 lfd f9,emfp0(r31) ; Load double variant
1165 stfd f9,emfp0(r31) ; Store double variant
1168 lfs f10,emfp0(r31) ; Load single variant
1171 stfs f10,emfp0(r31) ; Store single variant
1174 lfd f10,emfp0(r31) ; Load double variant
1177 stfd f10,emfp0(r31) ; Store double variant
1180 lfs f11,emfp0(r31) ; Load single variant
1183 stfs f11,emfp0(r31) ; Store single variant
1186 lfd f11,emfp0(r31) ; Load double variant
1189 stfd f11,emfp0(r31) ; Store double variant
1192 lfs f12,emfp0(r31) ; Load single variant
1195 stfs f12,emfp0(r31) ; Store single variant
1198 lfd f12,emfp0(r31) ; Load double variant
1201 stfd f12,emfp0(r31) ; Store double variant
1204 lfs f13,emfp0(r31) ; Load single variant
1207 stfs f13,emfp0(r31) ; Store single variant
1210 lfd f13,emfp0(r31) ; Load double variant
1213 stfd f13,emfp0(r31) ; Store double variant
1216 lfs f14,emfp0(r31) ; Load single variant
1219 stfs f14,emfp0(r31) ; Store single variant
1222 lfd f14,emfp0(r31) ; Load double variant
1225 stfd f14,emfp0(r31) ; Store double variant
1228 lfs f15,emfp0(r31) ; Load single variant
1231 stfs f15,emfp0(r31) ; Store single variant
1234 lfd f15,emfp0(r31) ; Load double variant
1237 stfd f15,emfp0(r31) ; Store double variant
1240 lfs f16,emfp0(r31) ; Load single variant
1243 stfs f16,emfp0(r31) ; Store single variant
1246 lfd f16,emfp0(r31) ; Load double variant
1249 stfd f16,emfp0(r31) ; Store double variant
1252 lfs f17,emfp0(r31) ; Load single variant
1255 stfs f17,emfp0(r31) ; Store single variant
1258 lfd f17,emfp0(r31) ; Load double variant
1261 stfd f17,emfp0(r31) ; Store double variant
1264 lfs f18,emfp0(r31) ; Load single variant
1267 stfs f18,emfp0(r31) ; Store single variant
1270 lfd f18,emfp0(r31) ; Load double variant
1273 stfd f18,emfp0(r31) ; Store double variant
1276 lfs f19,emfp0(r31) ; Load single variant
1279 stfs f19,emfp0(r31) ; Store single variant
1282 lfd f19,emfp0(r31) ; Load double variant
1285 stfd f19,emfp0(r31) ; Store double variant
1288 lfs f20,emfp0(r31) ; Load single variant
1291 stfs f20,emfp0(r31) ; Store single variant
1294 lfd f20,emfp0(r31) ; Load double variant
1297 stfd f20,emfp0(r31) ; Store double variant
1300 lfs f21,emfp0(r31) ; Load single variant
1303 stfs f21,emfp0(r31) ; Store single variant
1306 lfd f21,emfp0(r31) ; Load double variant
1309 stfd f21,emfp0(r31) ; Store double variant
1312 lfs f22,emfp0(r31) ; Load single variant
1315 stfs f22,emfp0(r31) ; Store single variant
1318 lfd f22,emfp0(r31) ; Load double variant
1321 stfd f22,emfp0(r31) ; Store double variant
1324 lfs f23,emfp0(r31) ; Load single variant
1327 stfs f23,emfp0(r31) ; Store single variant
1330 lfd f23,emfp0(r31) ; Load double variant
1333 stfd f23,emfp0(r31) ; Store double variant
1336 lfs f24,emfp0(r31) ; Load single variant
1339 stfs f24,emfp0(r31) ; Store single variant
1342 lfd f24,emfp0(r31) ; Load double variant
1345 stfd f24,emfp0(r31) ; Store double variant
1348 lfs f25,emfp0(r31) ; Load single variant
1351 stfs f25,emfp0(r31) ; Store single variant
1354 lfd f25,emfp0(r31) ; Load double variant
1357 stfd f25,emfp0(r31) ; Store double variant
1360 lfs f26,emfp0(r31) ; Load single variant
1363 stfs f26,emfp0(r31) ; Store single variant
1366 lfd f26,emfp0(r31) ; Load double variant
1369 stfd f26,emfp0(r31) ; Store double variant
1372 lfs f27,emfp0(r31) ; Load single variant
1375 stfs f27,emfp0(r31) ; Store single variant
1378 lfd f27,emfp0(r31) ; Load double variant
1381 stfd f27,emfp0(r31) ; Store double variant
1384 lfs f28,emfp0(r31) ; Load single variant
1387 stfs f28,emfp0(r31) ; Store single variant
1390 lfd f28,emfp0(r31) ; Load double variant
1393 stfd f28,emfp0(r31) ; Store double variant
1396 lfs f29,emfp0(r31) ; Load single variant
1399 stfs f29,emfp0(r31) ; Store single variant
1402 lfd f29,emfp0(r31) ; Load double variant
1405 stfd f29,emfp0(r31) ; Store double variant
1408 lfs f30,emfp0(r31) ; Load single variant
1411 stfs f30,emfp0(r31) ; Store single variant
1414 lfd f30,emfp0(r31) ; Load double variant
1417 stfd f30,emfp0(r31) ; Store double variant
1420 lfs f31,emfp0(r31) ; Load single variant
1423 stfs f31,emfp0(r31) ; Store single variant
1426 lfd f31,emfp0(r31) ; Load double variant
1429 stfd f31,emfp0(r31) ; Store double variant