2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
28 Emulate instructions and traps.
30 Lovingly crafted by Bill Angell using traditional methods and only natural or recycled materials.
31 No animal products are used other than rendered otter bile and deep fried pork lard.
37 #include <ppc/proc_reg.h>
38 #include <ppc/exception.h>
39 #include <mach/machine/vm_param.h>
45 ; General stuff what happens here:
46 ; 1) All general context saved, interrupts off, translation off
47 ; 2) Vector and floating point disabled, but there may be live context.
48 ; This code is responsible for saving and restoring what is used. This
49 ; includes exception states, java mode, etc.
50 ; 3) No attempt is made to resolve page faults. PTE misses are handled
51 ; automatically, but actual faults (ala copyin/copyout) are not. If
52 ; a fault does occur, the exception that caused entry to the emulation
53 ; routine is remapped to either an instruction or data miss (depending
54 ; upon the stage detected) and redrived through the exception handler.
55 ; The only time that an instruction fault can happen is when a different
56 ; processor removes a mapping between our original fault and when we
57 ; fetch the assisted instruction. For an assisted instruction, data
58 ; faults should not occur (except in the MP case). For a purely
59 ; emulated instruction, faults can occur.
69 bf-- pf64Bitb,emn64 ; Skip if not 64-bit
70 b EXT(Emulate64) ; Jump to the 64-bit code...
72 emn64: mfsprg r31,0 ; Get the per_proc
73 lwz r12,savesrr1+4(r13) ; Get the exception info
74 rlwinm. r0,r12,0,SRR1_PRG_ILL_INS_BIT,SRR1_PRG_ILL_INS_BIT ; Emulation candidate?
75 lwz r30,dgFlags(0) ; Get the flags
76 beq+ eExit ; Nope, do not try to emulate...
78 rlwinm. r0,r30,0,enaDiagEMb,enaDiagEMb ; Do we want to try to emulate something?
79 mfsprg r28,2 ; Get the processor features
80 beq+ eExit ; No emulation allowed...
82 rlwinm. r28,r28,0,pfAltivecb,pfAltivecb ; Do we have Altivec on this machine?
83 beq eNoVect ; Nope, no Altivec...
85 dssall ; We need to kill streams because we are going to flip to problem state
88 eNoVect: bl eIFetch ; Get the instruction image
89 bne- eRedriveAsISI ; Go redrive this as an ISI...
91 rlwinm. r0,r10,0,0,5 ; See if we have the "special" op code here
92 rlwinm r20,r10,16,22,31 ; Set rS/rD and rA
93 bne+ eExit ; Not special op, ignore...
95 rlwinm r0,r10,31,22,31 ; Extract the sub op code
97 rlwimi r20,r10,14,15,16 ; Move bits 29 and 30 of instruction to 15 and 16 of DSISR
98 cmplwi r0,790 ; lhbrx?
99 rlwimi r20,r10,8,17,17 ; Move bit 25 to bit 17
100 cror cr1_eq,cr1_eq,cr0_eq ; Remember
101 cmplwi r0,534 ; lwbrx?
102 rlwimi r20,r10,3,18,21 ; Move bit 21-24 to bit 18-21
103 cror cr1_eq,cr1_eq,cr0_eq ; Remember
104 cmplwi r0,918 ; sthbrx?
105 cror cr1_eq,cr1_eq,cr0_eq ; Remember
106 cmplwi r0,662 ; stwbrx?
107 cror cr1_eq,cr1_eq,cr0_eq ; Remember
108 cmplwi r0,1014 ; dcbz?
109 cror cr1_eq,cr1_eq,cr0_eq ; Remember
110 cmplwi r0,533 ; lswx?
111 cror cr1_eq,cr1_eq,cr0_eq ; Remember
112 cmplwi r0,661 ; stswx?
113 cror cr1_eq,cr1_eq,cr0_eq ; Remember
114 bne cr1_eq,eNotIndex ; Go check non-index forms...
116 rlwinm. r21,r10,19,24,28 ; Extract index to rA to build EA
117 rlwinm r22,r10,24,24,28 ; Extract index to rB
118 addi r24,r13,saver0+4 ; Point to the start of registers
119 li r19,0 ; Assume 0 base
120 beq eZeroBase ; Yes...
121 lwzx r19,r24,r21 ; Get the base register value
123 eZeroBase: lwzx r22,r24,r22 ; Get the index value
124 add r22,r22,r19 ; Get DAR
125 b eFinishUp ; Done, go finish up...
127 eNotIndex: cmplwi r0,725 ; stswi?
128 cror cr1_eq,cr1_eq,cr0_eq ; Remember
129 cmplwi r0,597 ; lswi?
130 cror cr1_eq,cr1_eq,cr0_eq ; Remember
131 bne cr1,eExit ; Not one we handle...
133 rlwinm. r21,r10,19,24,28 ; Extract index to rA to build EA
134 addi r24,r13,saver0+4 ; Point to the start of registers
135 li r22,0 ; Assume 0 base
136 beq eFinishUp ; Yes, it is...
137 lwzx r22,r24,r21 ; Get the base register value
139 eFinishUp: stw r20,savedsisr(r13) ; Set the DSISR
140 li r11,T_ALIGNMENT ; Get the exception code
141 stw r22,savedar+4(r13) ; Save the DAR
142 stw r11,saveexception(r13) ; Set the exception code
143 b EXT(AlignAssist) ; Go emulate the handler...
146 eExit: b EXT(EmulExit) ; Just return for now...
150 ; Fetch the failing instruction.
151 ; Image returned in R10 if CR0_EQ is false, otherwise, an ISI should be generated/
152 ; The cr bit kernAccess is set if this was a kernel access.
153 ; R1 has the DSISR if access failed.
158 eIFetch: lwz r23,savesrr1+4(r13) ; Get old MSR
159 mflr r28 ; Save return
161 rlwinm. r22,r23,0,MSR_PR_BIT,MSR_PR_BIT ; Within kernel?
163 mfmsr r30 ; Save the MSR for now
164 lwz r23,savesrr0+4(r13) ; Get instruction address
166 ori r22,r30,lo16(MASK(MSR_DR)|MASK(MSR_RI)) ; Set RI and DR onto access MSR
168 crset cr0_eq ; Set this to see if we failed
169 mtmsr r22 ; Flip DR, RI, and maybe PR on
172 lwz r10,0(r23) ; Fetch the instruction
174 mtmsr r30 ; Trans and RI off
177 mtlr r28 ; Restore the LR
178 blr ; Return with instruction image in R10
186 lwz r6,savesrr1+4(r13) ; Get the srr1 value
187 lwz r4,SAVflags(r13) ; Pick up the flags
188 li r11,T_INSTRUCTION_ACCESS ; Set failing instruction fetch code
189 rlwimi r6,r1,0,0,4 ; Move the DSISR bits to the SRR1
190 oris r4,r4,hi16(SAVredrive) ; Set the redrive bit
191 stw r11,saveexception(r13) ; Set the replacement code
192 stw r4,SAVflags(r13) ; Set redrive request
193 stw r6,savesrr1+4(r13) ; Set the srr1 value
194 b EXT(EmulExit) ; Bail out to handle ISI...
198 ; This code emulates instructions that have failed because of operand
199 ; alignment. We decode the DSISR to figure out what we need to do.
202 ; 0001FC00 - Instruction designation
212 ; 000003E0 - Target/Source register
213 ; 0000001F - Register to update if update form
217 .globl EXT(AlignAssist)
220 bf-- pf64Bitb,aan64 ; Skip if not 64-bit
221 b EXT(AlignAssist64) ; Jump to the 64-bit code...
223 aan64: lwz r20,savedsisr(r13) ; Get the DSISR
224 mfsprg r31,0 ; Get the per_proc
225 mtcrf 0x10,r20 ; Put instruction ID in CR for later
226 lwz r21,spcFlags(r31) ; Grab the special flags
227 mtcrf 0x08,r20 ; Put instruction ID in CR for later
228 rlwinm. r0,r21,0,runningVMbit,runningVMbit ; Are we running a VM?
229 mtcrf 0x04,r20 ; Put instruction ID in CR for later
230 lwz r22,savesrr1+4(r13) ; Get the SRR1
231 bne- aaPassAlong ; We are in a VM, no emulation for alignment exceptions...
232 lwz r19,dgFlags(0) ; Get the diagnostics flags
233 crxor iFloat,iOptype1,iOptype2 ; Set this to 0 if both bits are either 0 or 1
234 mr r26,r20 ; Save the DSISR
235 rlwinm. r0,r22,0,MSR_SE_BIT,MSR_SE_BIT ; Were we single stepping?
236 lwz r23,savedar+4(r13) ; Pick up the address that we want to access
237 crnot traceInst,cr0_eq ; Remember if trace is on
239 rlwinm. r0,r19,0,enaNotifyEMb,enaNotifyEMb ; Should we notify that an alignment exception happened?
240 mfmsr r30 ; Save the MSR for now
241 crnot iNotify,cr0_eq ; Remember to tell someone we did this
242 li r29,emfp0 ; Point to work area
243 crxor iFloat,iFloat,iOptype3 ; Set true if we have a floating point instruction
244 dcbz r29,r31 ; Clear and allocate a cache line for us to work in
245 rlwinm r24,r20,3,24,28 ; Get displacement to register to update if update form
246 rlwimi r20,r20,24,28,28 ; Move load/store indication to the bottom of index
247 ori r22,r30,lo16(MASK(MSR_DR)|MASK(MSR_RI)) ; Set RI onto access MSR
248 rlwimi r20,r20,26,27,27 ; Move single/double indication to just above the bottom
249 lis r29,hi16(EXT(aaFPopTable)) ; High part of FP branch table
250 bf- iFloat,aaNotFloat ; This is not a floating point instruction...
251 ori r29,r29,lo16(EXT(aaFPopTable)) ; Low part of FP branch table
253 rlwimi r29,r20,0,22,28 ; Index into table based upon register||iDouble||iStore
254 mtctr r29 ; Get set to call the function
255 bt iStore,aaFPstore ; This is an FP store...
258 ; Here we handle floating point loads
261 aaFPload: crset cr0_eq ; Set this to see if we failed
262 mtmsr r22 ; Flip DR, RI
265 lwz r10,0(r23) ; Get the first word
266 bf- cr0_eq,aaLdNotDbl ; Jump out if we DSIed...
267 bf iDouble,aaLdNotDbl ; this is not a double...
268 lwz r11,4(r23) ; Get the second half
270 aaLdNotDbl: mr r4,r0 ; Save the DAR if we failed the access
272 mtmsr r30 ; Turn off translation again
275 bf- cr0_eq,aaRedriveAsDSI ; Go redrive this as a DSI...
277 stw r10,emfp0(r31) ; Save the first half
278 stw r11,emfp0+4(r31) ; Save the second half, just in case we need it
280 bctrl ; Go set the target FP register
282 b aaComExit ; All done, go exit...
285 ; Here we handle floating point stores
290 aaFPstore: bctrl ; Go save the source FP register
292 lwz r10,emfp0(r31) ; Get first word
293 crandc iDouble,iDouble,iOptype4 ; Change to 4-byte access if stfiwx
294 lwz r11,emfp0+4(r31) ; and the second
295 bf+ iOptype4,aaNotstfiwx ; This is not a stfiwx...
296 mr r10,r11 ; The stfiwx wants to store the second half
299 crset cr0_eq ; Set this to see if we failed
300 mtmsr r22 ; Flip DR, RI
303 stw r10,0(r23) ; Save the first word
304 bf- cr0_eq,aaStNotDbl ; Jump out if we DSIed...
305 bf iDouble,aaStNotDbl ; this is not a double...
306 stw r11,4(r23) ; Save the second half
308 aaStNotDbl: mr r4,r0 ; Save the DAR if we failed the access
312 bf- cr0_eq,aaRedriveAsDSI ; Go redrive this as a DSI...
315 ; Common exit routines
318 aaComExit: lwz r10,savesrr0+4(r13) ; Get the failing instruction address
319 add r24,r24,r13 ; Offset to update register
320 li r11,T_IN_VAIN ; Assume we are all done
321 addi r10,r10,4 ; Step to the next instruction
322 bf iUpdate,aaComExNU ; Skip if not an update form...
323 stw r23,saver0+4(r24) ; Update the target
325 aaComExNU: lwz r9,SAVflags(r13) ; Get the flags
326 stw r10,savesrr0+4(r13) ; Set new PC
327 bt- traceInst,aaComExitrd ; We are tracing, go emulate trace...
328 bf+ iNotify,aaComExGo ; Nothing special here, go...
330 li r11,T_ALIGNMENT ; Set the we just did an alignment exception....
332 aaComExGo: b EXT(EmulExit) ; We are done, no tracing on...
336 ; This is not a floating point operation
338 ; The emulation routines for these are positioned every 64 bytes (16 instructions)
339 ; in a 1024-byte aligned table. It is indexed by taking the low order 4 bits of
340 ; the instruction code in the DSISR and subtracting 7. If this comes up negative,
341 ; the instruction is not to be emulated. Then we add bit 0 of the code * 4. This
342 ; gives us a fairly compact and almost unique index. Both lwm and stmw map to 0 so
343 ; that one needs to be further reduced, and we end up with holes at index 6, 8, and 10.
345 ; If the emulation routine takes more than 16 instructions, it must branch elsewhere
352 lis r19,hi16(aaEmTable) ; Point to high part of table address
353 rlwinm r3,r26,24,26,29 ; Isolate last 4 bits of op type * 4
354 rlwimi r19,r26,20,27,27 ; Get bit 0 of instruction code * 4 into bottom of table base
355 addic. r3,r3,-28 ; Subtract 7*4 to adjust index
356 ori r19,r19,lo16(aaEmTable) ; Low part of table address
357 blt- aaPassAlong ; We do not handle any of these (lwarx, stwcx., eciwx, ecowx)...
358 add r19,r19,r3 ; Point to emulation routine
359 rlwinm r18,r26,30,24,28 ; Get the target/source register displacement
361 mtctr r19 ; Set the routine address
363 bctr ; Go emulate the instruction...
366 ; This is the table of non-floating point emulation routines.
367 ; It is indexed by low 4 bits of DSISR op type - 7 + bit 0 of
374 b aaLmwStmw ; This for lmw/stmw
375 b aaLswx ; This for lwwx
376 b aaLswi ; This for lswi
377 b aaStswx ; This for stswx
378 b aaStswi ; This for stswi
379 b aaLwbrx ; This for lwbrx
380 b aaPassAlong ; This an invalid index (6)
381 b aaStwbrx ; This for stwbrx
382 b aaPassAlong ; This an invalid index (8)
383 b aaLhbrx ; This for lhbrx
384 b aaPassAlong ; This an invalid index (A)
385 b aaSthbrx ; This for sthbrx
386 b aaDcbz ; This for dcbz
387 b aaPassAlong ; This an invalid index (D)
388 b aaPassAlong ; This an invalid index (E)
389 b aaPassAlong ; This an invalid index (F)
393 ; Here we handle the set up for the lmw and stmw. After that, we split off to the
394 ; individual routines.
396 ; Note also that after some set up, all of the string instructions come through here as well.
401 rlwinm r17,r18,31,1,29 ; Convert doublword based index to words
402 li r28,0 ; Set no extra bytes to move (used for string instructions)
403 subfic r17,r17,32*4 ; Calculate the length of the transfer
405 aaLSComm: addi r19,r13,saver0+4 ; Offset to registers in savearea
406 mr r16,r23 ; Make a hunk pointer
408 bt iUpdate,aaStmw ; This is the stmw...
414 aaLmwNxt: cmplwi cr1,r17,8*4 ; Is there enough to move 8?
415 blt- cr1,aaLmwNxtH ; Not enough for a full hunk...
416 subi r17,r17,8*4 ; Back off for another hunk
418 crset cr0_eq ; Set this to see if we failed
419 mtmsr r22 ; Flip DR, RI
422 lwz r2,0(r16) ; Load word 0
423 bf- cr0_eq,aaLmwB1 ; Error, bail...
424 lwz r15,4(r16) ; Load word 1
425 bf- cr0_eq,aaLmwB1 ; Error, bail...
426 lwz r14,8(r16) ; Load word 2
427 bf- cr0_eq,aaLmwB1 ; Error, bail...
428 lwz r5,12(r16) ; Load word 3
429 bf- cr0_eq,aaLmwB1 ; Error, bail...
430 lwz r6,16(r16) ; Load word 4
431 bf- cr0_eq,aaLmwB1 ; Error, bail...
432 lwz r7,20(r16) ; Load word 5
433 bf- cr0_eq,aaLmwB1 ; Error, bail...
434 lwz r8,24(r16) ; Load word 6
435 bf- cr0_eq,aaLmwB1 ; Error, bail...
436 lwz r9,28(r16) ; Load word 7
438 aaLmwB1: mr r4,r0 ; Remember DAR, jus in case we failed the access
439 mtmsr r30 ; Turn off DR, RI
442 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
444 addi r16,r16,8*4 ; Point up to next input aread
446 stwx r2,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 r15,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 r14,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 r5,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 r6,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 r7,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 r8,r19,r18 ; Store register
465 addi r18,r18,8 ; Next register
466 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
467 stwx r9,r19,r18 ; Store register
468 addi r18,r18,8 ; Next register
469 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
471 b aaLmwNxt ; Do the next hunk...
475 aaLmwNxtH: cmplwi cr1,r17,4*4 ; Do we have 4 left?
476 blt cr1,aaLmwL4 ; Nope...
478 subi r17,r17,4*4 ; Set count properly
480 crset cr0_eq ; Set this to see if we failed
481 mtmsr r22 ; Flip DR, RI, and maybe PR on
484 lwz r2,0(r16) ; Load word 0
485 bf- cr0_eq,aaLmwB2 ; Error, bail...
486 lwz r15,4(r16) ; Load word 1
487 bf- cr0_eq,aaLmwB2 ; Error, bail...
488 lwz r14,8(r16) ; Load word 2
489 bf- cr0_eq,aaLmwB2 ; Error, bail...
490 lwz r5,12(r16) ; Load word 3
492 aaLmwB2: mr r4,r0 ; Remember DAR, jus in case we failed the access
493 mtmsr r30 ; Turn off DR, RI
496 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
498 addi r16,r16,4*4 ; Point up to next input aread
500 stwx r2,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 r15,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 r14,r19,r18 ; Store register
507 addi r18,r18,8 ; Next register
508 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
509 stwx r5,r19,r18 ; Store register
510 addi r18,r18,8 ; Next register
511 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
513 aaLmwL4: or. r5,r17,r28 ; Do we have anything left?
514 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three full words left?
515 cmplwi cr2,r17,0 ; Do we have no full words left?
516 beq aaComExit ; Nothing left...
518 crset cr0_eq ; Set this to see if we failed
519 mtmsr r22 ; Flip DR, RI, and maybe PR on
522 beq- cr2,aaLmwBy ; No full words, get bytes...
524 lwz r2,0(r16) ; Pick up first word
525 bf- cr0_eq,aaLmwDn ; Read failed, escape...
526 addi r16,r16,4 ; Next input location
527 blt cr1,aaLmwBy ; We only had one, we are done...
529 lwz r15,0(r16) ; Pick up second word
530 bf- cr0_eq,aaLmwDn ; Read failed, escape...
531 addi r16,r16,4 ; Next input location
532 beq cr1,aaLmwBy ; We had two, we are done...
534 lwz r14,0(r16) ; Load word 3
535 addi r16,r16,4 ; Next input location
537 aaLmwBy: cmplwi cr2,r28,0 ; Any trailing bytes to do?
538 li r8,0 ; Clear second trailing byte
539 cmplwi cr1,r28,2 ; Check for 1, 2, or 3
540 li r9,0 ; Clear third trailing byte
541 beq+ cr2,aaLmwDn ; No trailing bytes...
543 lbz r5,0(r16) ; Pick up first trailing byte
544 bf- cr0_eq,aaLmwDn ; Read failed, escape...
545 blt cr1,aaLmwDn ; We only had one, we are done...
547 lbz r8,1(r16) ; Pick up second trailing byte
548 bf- cr0_eq,aaLmwDn ; Read failed, escape...
549 beq cr1,aaLmwDn ; We had two, we are done...
551 lbz r9,2(r16) ; Get last trailing byte
554 aaLmwDn: rlwinm r5,r5,24,0,7 ; Move first byte to top
555 cmplwi cr2,r17,0 ; Any full words to do?
556 mr r4,r0 ; Remember DAR, just in case we failed the access
557 rlwimi r9,r8,8,16,23 ; Move second byte above third byte
558 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three full words left?
559 mr r3,r30 ; Set the normal MSR
560 rlwimi r5,r9,8,8,23 ; Move bytes 1 and 2 after 0
562 mtmsr r30 ; Turn off DR, RI
565 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
567 beq- cr2,aaLmwCb ; No full words, copy bytes...
569 stwx r2,r19,r18 ; Store register
570 addi r18,r18,8 ; Next register
571 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
572 blt cr1,aaLmwCb ; We only had one, we are done...
574 stwx r15,r19,r18 ; Store register
575 addi r18,r18,8 ; Next register
576 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
577 beq cr1,aaLmwCb ; We had two, we are done...
579 stwx r14,r19,r18 ; Store register
580 addi r18,r18,8 ; Next register
581 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
583 aaLmwCb: mr. r28,r28 ; Any trailing bytes to do?
584 beq+ aaComExit ; Nope, leave...
586 stwx r5,r19,r18 ; Store register
588 b aaComExit ; We are done....
591 ; Store multiple word
597 crclr iUpdate ; Make sure we do not think this is an update form
599 aaStmwNxt: cmplwi cr1,r17,8*4 ; Is there enough to move 8?
600 blt- cr1,aaStmwNxtH ; Not enough for a full hunk...
601 subi r17,r17,8*4 ; Back off for another hunk
603 lwzx r2,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 r15,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 r14,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 r5,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 r6,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 r7,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 r8,r19,r18 ; Store register
622 addi r18,r18,8 ; Next register
623 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
624 lwzx r9,r19,r18 ; Store register
625 addi r18,r18,8 ; Next register
626 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
628 crset cr0_eq ; Set this to see if we failed
629 mtmsr r22 ; Flip DR, RI, and maybe PR on
632 stw r2,0(r16) ; Store word 0
633 bf- cr0_eq,aaStmwB1 ; Error, bail...
634 stw r15,4(r16) ; Store word 1
635 bf- cr0_eq,aaStmwB1 ; Error, bail...
636 stw r14,8(r16) ; Store word 2
637 bf- cr0_eq,aaStmwB1 ; Error, bail...
638 stw r5,12(r16) ; Store word 3
639 bf- cr0_eq,aaStmwB1 ; Error, bail...
640 stw r6,16(r16) ; Store word 4
641 bf- cr0_eq,aaStmwB1 ; Error, bail...
642 stw r7,20(r16) ; Store word 5
643 bf- cr0_eq,aaStmwB1 ; Error, bail...
644 stw r8,24(r16) ; Store word 6
645 bf- cr0_eq,aaStmwB1 ; Error, bail...
646 stw r9,28(r16) ; Store word 7
648 addi r16,r16,8*4 ; Point up to next output aread
651 aaStmwB1: mr r4,r0 ; Remember DAR, jus in case we failed the access
652 mtmsr r30 ; Normal MSR
655 bt- cr0_eq,aaStmwNxt ; We have more to do and no failed access...
656 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
660 aaStmwNxtH: cmplwi cr1,r17,(4*4) ; Do we have at least 4 left?
661 blt cr1,aaStmwL4 ; Nope...
662 subi r17,r17,4*4 ; Set count properly
664 lwzx r2,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 r15,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 r14,r19,r18 ; Store register
671 addi r18,r18,8 ; Next register
672 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
673 lwzx r5,r19,r18 ; Store register
674 addi r18,r18,8 ; Next register
675 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
677 crset cr0_eq ; Set this to see if we failed
678 mtmsr r22 ; Flip DR, RI
681 stw r2,0(r16) ; Store word 0
682 bf- cr0_eq,aaStmwB2 ; Error, bail...
683 stw r15,4(r16) ; Store word 1
684 bf- cr0_eq,aaStmwB2 ; Error, bail...
685 stw r14,8(r16) ; Store word 2
686 bf- cr0_eq,aaStmwB2 ; Error, bail...
687 stw r5,12(r16) ; Store word 3
689 addi r16,r16,4*4 ; Point up to next input aread
691 aaStmwB2: mr r4,r0 ; Remember DAR, jus in case we failed the access
692 mtmsr r30 ; Normal MSR
695 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
697 aaStmwL4: or. r5,r17,r28 ; Do we have anything left to do?
698 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three left?
699 cmplwi cr2,r17,0 ; Do we have no full words left?
700 beq aaComExit ; Nothing left...
702 beq- cr2,aaStmwBy1 ; No full words, check out bytes
704 lwzx r2,r19,r18 ; Store register
705 addi r18,r18,8 ; Next register
706 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
707 blt cr1,aaStmwBy1 ; We only had one, go save it...
709 lwzx r15,r19,r18 ; Store register
710 addi r18,r18,8 ; Next register
711 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
712 beq cr1,aaStmwBy1 ; We had two, go save it...
714 lwzx r14,r19,r18 ; Store register
715 addi r18,r18,8 ; Next register
716 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
718 aaStmwBy1: mr. r28,r28 ; Do we have any trailing bytes?
719 beq+ aaStmwSt ; Nope...
721 lwzx r5,r19,r18 ; Yes, pick up one extra register
723 aaStmwSt: crset cr0_eq ; Set this to see if we failed
724 mtmsr r22 ; Flip DR, RI
727 beq- cr2,aaStmwBy2 ; No words, check trailing bytes...
729 stw r2,0(r16) ; Save first word
730 bf- cr0_eq,aaStmwDn ; Store failed, escape...
731 addi r16,r16,4 ; Bump sink
732 blt cr1,aaStmwBy2 ; We only had one, we are done...
734 stw r15,0(r16) ; Save second word
735 bf- cr0_eq,aaStmwDn ; Store failed, escape...
736 addi r16,r16,4 ; Bump sink
737 beq cr1,aaStmwBy2 ; We had two, we are done...
739 stw r14,0(r16) ; Save third word
740 bf- cr0_eq,aaStmwDn ; Store failed, escape...
741 addi r16,r16,4 ; Bump sink
743 aaStmwBy2: rlwinm r2,r5,8,24,31 ; Get byte 0
744 cmplwi cr2,r28,0 ; Any trailing bytes to do?
745 rlwinm r14,r5,24,24,31 ; Get byte 3
746 li r8,0 ; Clear second trailing byte
747 cmplwi cr1,r28,2 ; Check for 1, 2, or 3
748 li r9,0 ; Clear third trailing byte
749 beq+ cr2,aaStmwDn ; No trailing bytes...
750 rlwinm r15,r5,16,24,31 ; Get byte 1
752 stb r2,0(r16) ; Save first byte
753 bf- cr0_eq,aaStmwDn ; Read failed, escape...
754 blt cr1,aaStmwDn ; We only had one, we are done...
756 stb r15,1(r16) ; Save second byte
757 bf- cr0_eq,aaStmwDn ; Read failed, escape...
758 beq cr1,aaStmwDn ; We had two, we are done...
760 stb r14,2(r16) ; Save third byte
762 aaStmwDn: mr r4,r0 ; Remember DAR, jus in case we failed the access
763 mtmsr r30 ; Normal MSR
766 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
768 b aaComExit ; We are done....
772 ; Load String Indexed
777 aaLswx: lwz r17,savexer+4(r13) ; Pick up the XER
778 crclr iUpdate ; Make sure we think this the load form
779 rlwinm. r25,r17,0,25,31 ; Get the number of bytes to load
780 rlwinm r28,r17,0,30,31 ; Get the number of bytes past an even word
781 beq- aaComExit ; Do nothing if 0 length...
782 xor r17,r25,r28 ; Round down to an even word boundary
783 b aaLSComm ; Join up with common load/store code...
787 ; Load String Immediate
792 aaLswi: mr r9,r23 ; Save the DAR
793 bl eIFetch ; Get the instruction image
794 bne- eRedriveAsISI ; Go redrive this as an ISI...
795 rlwinm r25,r10,21,27,31 ; Get the number of bytes to load
796 crclr iUpdate ; Make sure we think this the load form
797 subi r25,r25,1 ; Back off by 1
798 rlwinm r25,r25,0,27,31 ; Clear back down
799 addi r25,r25,1 ; Add back the 1 to convert 0 to 32
800 rlwinm r28,r25,0,30,31 ; Get the number of bytes past an even word
801 xor r17,r25,r28 ; Round down to an even word boundary
802 mr r23,r9 ; Move back the DAR
803 b aaLSComm ; Join up with common load/store code...
806 ; Store String Indexed
811 aaStswx: lwz r17,savexer+4(r13) ; Pick up the XER
812 crclr iUpdate ; Make sure this is clear in case we have 0 length
813 rlwinm. r25,r17,0,25,31 ; Get the number of bytes to load
814 rlwinm r28,r17,0,30,31 ; Get the number of bytes past an even word
815 beq- aaComExit ; Do nothing if 0 length...
816 xor r17,r25,r28 ; Round down to an even word boundary
817 crset iUpdate ; Make sure we think this the store form
818 b aaLSComm ; Join up with common load/store code...
822 ; Store String Immediate
827 aaStswi: mr r9,r23 ; Save the DAR
828 bl eIFetch ; Get the instruction image
829 bne- eRedriveAsISI ; Go redrive this as an ISI...
830 rlwinm r25,r10,21,27,31 ; Get the number of bytes to load
831 crclr iUpdate ; Make sure we think this the load form
832 subi r25,r25,1 ; Back off by 1
833 rlwinm r25,r25,0,27,31 ; Clear back down
834 addi r25,r25,1 ; Add back the 1 to convert 0 to 32
835 rlwinm r28,r25,21,30,31 ; Get the number of bytes past an even word
836 xor r17,r25,r28 ; Round down to an even word boundary
837 mr r23,r9 ; Move back the DAR
838 b aaLSComm ; Join up with common load/store code...
842 ; Load byte-reversed word
848 add r18,r18,r13 ; Index to source register
850 crset cr0_eq ; Set this to see if we failed
851 mtmsr r22 ; Flip DR, RI, and maybe PR on
854 lwz r11,0(r23) ; Load the word
856 mr r4,r0 ; Save the DAR if we failed the access
857 mtmsr r30 ; Restore normal MSR
860 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
862 rlwinm r10,r11,8,0,31 ; Get byte 0 to 3 and byte 2 to 1
863 rlwimi r10,r11,24,16,23 ; Move byte 1 to byte 2
864 rlwimi r10,r11,24,0,7 ; Move byte 3 to byte 0
866 stw r10,saver0+4(r18) ; Set the register
868 b aaComExit ; All done, go exit...
873 ; Store byte-reversed word
879 add r18,r18,r13 ; Index to source register
880 lwz r11,saver0+4(r18) ; Get the register to store
882 rlwinm r10,r11,8,0,31 ; Get byte 0 to 3 and byte 2 to 1
883 rlwimi r10,r11,24,16,23 ; Move byte 1 to byte 2
884 rlwimi r10,r11,24,0,7 ; Move byte 3 to byte 0
886 crset cr0_eq ; Set this to see if we failed
887 mtmsr r22 ; Flip DR, RI, and maybe PR on
890 stw r10,0(r23) ; Store the reversed halfword
892 mr r4,r0 ; Save the DAR if we failed the access
893 mtmsr r30 ; Restore normal MSR
896 bt+ cr0_eq,aaComExit ; All done, go exit...
897 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
902 ; Load byte-reversed halfword
908 add r18,r18,r13 ; Index to source register
910 crset cr0_eq ; Set this to see if we failed
911 mtmsr r22 ; Flip DR, RI, and maybe PR on
914 lhz r11,0(r23) ; Load the halfword
916 mr r4,r0 ; Save the DAR if we failed the access
917 mtmsr r30 ; Restore normal MSR
920 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
922 rlwinm r10,r11,8,16,23 ; Rotate bottom byte up one and clear everything else
923 rlwimi r10,r11,24,24,31 ; Put old second from bottom into bottom
925 stw r10,saver0+4(r18) ; Set the register
927 b aaComExit ; All done, go exit...
931 ; Store byte-reversed halfword
937 add r18,r18,r13 ; Index to source register
938 lwz r10,saver0+4(r18) ; Get the register to store
939 rlwinm r10,r10,8,0,31 ; Rotate bottom byte up one
940 rlwimi r10,r10,16,24,31 ; Put old second from bottom into bottom
942 crset cr0_eq ; Set this to see if we failed
943 mtmsr r22 ; Flip DR, RI, and maybe PR on
946 sth r10,0(r23) ; Store the reversed halfword
948 mr r4,r0 ; Save the DAR if we failed the access
949 mtmsr r30 ; Restore normal MSR
952 bt+ cr0_eq,aaComExit ; All done, go exit...
953 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
956 ; Data cache block zero
962 rlwinm r23,r23,0,0,26 ; Round back to a 32-byte boundary
964 crset cr0_eq ; Set this to see if we failed
965 li r0,0 ; Clear this out
966 mtmsr r22 ; Flip DR, RI, and maybe PR on
969 stw r0,0(r23) ; Clear word
970 bne- aaDcbzXit ; Got DSI, we are stopping...
971 stw r0,4(r23) ; Clear word
972 bne- aaDcbzXit ; Got DSI, we are stopping...
973 stw r0,8(r23) ; Clear word
974 bne- aaDcbzXit ; Got DSI, we are stopping...
975 stw r0,12(r23) ; Clear word
976 bne- aaDcbzXit ; Got DSI, we are stopping...
977 stw r0,16(r23) ; Clear word
978 bne- aaDcbzXit ; Got DSI, we are stopping...
979 stw r0,20(r23) ; Clear word
980 bne- aaDcbzXit ; Got DSI, we are stopping...
981 stw r0,24(r23) ; Clear word
982 bne- aaDcbzXit ; Got DSI, we are stopping...
983 stw r0,28(r23) ; Clear word
985 aaDcbzXit: mr r4,r0 ; Save the DAR if we failed the access
986 mtmsr r30 ; Restore normal MSR
989 crclr iUpdate ; Make sure we do not think this is an update form
991 bt+ cr0_eq,aaComExit ; All done, go exit...
992 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
996 ; Unhandled alignment exception, pass it along
1006 ; We go here to emulate a trace exception after we have handled alignment error
1012 oris r9,r9,hi16(SAVredrive) ; Set the redrive bit
1013 li r11,T_TRACE ; Set trace interrupt
1014 rlwinm r12,r12,0,16,31 ; Clear top half of SRR1
1015 stw r9,SAVflags(r13) ; Set the flags
1016 stw r11,saveexception(r13) ; Set the exception code
1017 b EXT(EmulExit) ; Exit and do trace interrupt...
1025 mr r20,r1 ; Save the DSISR
1027 lwz r4,SAVflags(r13) ; Pick up the flags
1028 li r11,T_DATA_ACCESS ; Set failing data access code
1029 oris r4,r4,hi16(SAVredrive) ; Set the redrive bit
1030 stw r20,savedsisr(r13) ; Set the DSISR of failed access
1031 stw r21,savedar+4(r13) ; Set the address of the failed access
1032 stw r11,saveexception(r13) ; Set the replacement code
1033 stw r4,SAVflags(r13) ; Set redrive request
1034 b EXT(EmulExit) ; Bail out to handle ISI...
1039 ; Table of functions to load or store floating point registers
1040 ; This table is indexed reg||size||dir. That means that each
1041 ; like load/store pair (e.g., lfd f31/stfd f31) are within the same
1042 ; quadword, which is the current ifetch size. We expect most of the
1043 ; unaligned accesses to be part of copies, therefore, with this
1044 ; organization, we will save the ifetch of the store after the load.
1047 .align 10 ; Make sure we are on a 1k boundary
1048 .globl EXT(aaFPopTable)
1051 lfs f0,emfp0(r31) ; Load single variant
1054 stfs f0,emfp0(r31) ; Store single variant
1057 lfd f0,emfp0(r31) ; Load double variant
1060 stfd f0,emfp0(r31) ; Store double variant
1063 lfs f1,emfp0(r31) ; Load single variant
1066 stfs f1,emfp0(r31) ; Store single variant
1069 lfd f1,emfp0(r31) ; Load double variant
1072 stfd f1,emfp0(r31) ; Store double variant
1075 lfs f2,emfp0(r31) ; Load single variant
1078 stfs f2,emfp0(r31) ; Store single variant
1081 lfd f2,emfp0(r31) ; Load double variant
1084 stfd f2,emfp0(r31) ; Store double variant
1087 lfs f3,emfp0(r31) ; Load single variant
1090 stfs f3,emfp0(r31) ; Store single variant
1093 lfd f3,emfp0(r31) ; Load double variant
1096 stfd f3,emfp0(r31) ; Store double variant
1099 lfs f4,emfp0(r31) ; Load single variant
1102 stfs f4,emfp0(r31) ; Store single variant
1105 lfd f4,emfp0(r31) ; Load double variant
1108 stfd f4,emfp0(r31) ; Store double variant
1111 lfs f5,emfp0(r31) ; Load single variant
1114 stfs f5,emfp0(r31) ; Store single variant
1117 lfd f5,emfp0(r31) ; Load double variant
1120 stfd f5,emfp0(r31) ; Store double variant
1123 lfs f6,emfp0(r31) ; Load single variant
1126 stfs f6,emfp0(r31) ; Store single variant
1129 lfd f6,emfp0(r31) ; Load double variant
1132 stfd f6,emfp0(r31) ; Store double variant
1135 lfs f7,emfp0(r31) ; Load single variant
1138 stfs f7,emfp0(r31) ; Store single variant
1141 lfd f7,emfp0(r31) ; Load double variant
1144 stfd f7,emfp0(r31) ; Store double variant
1147 lfs f8,emfp0(r31) ; Load single variant
1150 stfs f8,emfp0(r31) ; Store single variant
1153 lfd f8,emfp0(r31) ; Load double variant
1156 stfd f8,emfp0(r31) ; Store double variant
1159 lfs f9,emfp0(r31) ; Load single variant
1162 stfs f9,emfp0(r31) ; Store single variant
1165 lfd f9,emfp0(r31) ; Load double variant
1168 stfd f9,emfp0(r31) ; Store double variant
1171 lfs f10,emfp0(r31) ; Load single variant
1174 stfs f10,emfp0(r31) ; Store single variant
1177 lfd f10,emfp0(r31) ; Load double variant
1180 stfd f10,emfp0(r31) ; Store double variant
1183 lfs f11,emfp0(r31) ; Load single variant
1186 stfs f11,emfp0(r31) ; Store single variant
1189 lfd f11,emfp0(r31) ; Load double variant
1192 stfd f11,emfp0(r31) ; Store double variant
1195 lfs f12,emfp0(r31) ; Load single variant
1198 stfs f12,emfp0(r31) ; Store single variant
1201 lfd f12,emfp0(r31) ; Load double variant
1204 stfd f12,emfp0(r31) ; Store double variant
1207 lfs f13,emfp0(r31) ; Load single variant
1210 stfs f13,emfp0(r31) ; Store single variant
1213 lfd f13,emfp0(r31) ; Load double variant
1216 stfd f13,emfp0(r31) ; Store double variant
1219 lfs f14,emfp0(r31) ; Load single variant
1222 stfs f14,emfp0(r31) ; Store single variant
1225 lfd f14,emfp0(r31) ; Load double variant
1228 stfd f14,emfp0(r31) ; Store double variant
1231 lfs f15,emfp0(r31) ; Load single variant
1234 stfs f15,emfp0(r31) ; Store single variant
1237 lfd f15,emfp0(r31) ; Load double variant
1240 stfd f15,emfp0(r31) ; Store double variant
1243 lfs f16,emfp0(r31) ; Load single variant
1246 stfs f16,emfp0(r31) ; Store single variant
1249 lfd f16,emfp0(r31) ; Load double variant
1252 stfd f16,emfp0(r31) ; Store double variant
1255 lfs f17,emfp0(r31) ; Load single variant
1258 stfs f17,emfp0(r31) ; Store single variant
1261 lfd f17,emfp0(r31) ; Load double variant
1264 stfd f17,emfp0(r31) ; Store double variant
1267 lfs f18,emfp0(r31) ; Load single variant
1270 stfs f18,emfp0(r31) ; Store single variant
1273 lfd f18,emfp0(r31) ; Load double variant
1276 stfd f18,emfp0(r31) ; Store double variant
1279 lfs f19,emfp0(r31) ; Load single variant
1282 stfs f19,emfp0(r31) ; Store single variant
1285 lfd f19,emfp0(r31) ; Load double variant
1288 stfd f19,emfp0(r31) ; Store double variant
1291 lfs f20,emfp0(r31) ; Load single variant
1294 stfs f20,emfp0(r31) ; Store single variant
1297 lfd f20,emfp0(r31) ; Load double variant
1300 stfd f20,emfp0(r31) ; Store double variant
1303 lfs f21,emfp0(r31) ; Load single variant
1306 stfs f21,emfp0(r31) ; Store single variant
1309 lfd f21,emfp0(r31) ; Load double variant
1312 stfd f21,emfp0(r31) ; Store double variant
1315 lfs f22,emfp0(r31) ; Load single variant
1318 stfs f22,emfp0(r31) ; Store single variant
1321 lfd f22,emfp0(r31) ; Load double variant
1324 stfd f22,emfp0(r31) ; Store double variant
1327 lfs f23,emfp0(r31) ; Load single variant
1330 stfs f23,emfp0(r31) ; Store single variant
1333 lfd f23,emfp0(r31) ; Load double variant
1336 stfd f23,emfp0(r31) ; Store double variant
1339 lfs f24,emfp0(r31) ; Load single variant
1342 stfs f24,emfp0(r31) ; Store single variant
1345 lfd f24,emfp0(r31) ; Load double variant
1348 stfd f24,emfp0(r31) ; Store double variant
1351 lfs f25,emfp0(r31) ; Load single variant
1354 stfs f25,emfp0(r31) ; Store single variant
1357 lfd f25,emfp0(r31) ; Load double variant
1360 stfd f25,emfp0(r31) ; Store double variant
1363 lfs f26,emfp0(r31) ; Load single variant
1366 stfs f26,emfp0(r31) ; Store single variant
1369 lfd f26,emfp0(r31) ; Load double variant
1372 stfd f26,emfp0(r31) ; Store double variant
1375 lfs f27,emfp0(r31) ; Load single variant
1378 stfs f27,emfp0(r31) ; Store single variant
1381 lfd f27,emfp0(r31) ; Load double variant
1384 stfd f27,emfp0(r31) ; Store double variant
1387 lfs f28,emfp0(r31) ; Load single variant
1390 stfs f28,emfp0(r31) ; Store single variant
1393 lfd f28,emfp0(r31) ; Load double variant
1396 stfd f28,emfp0(r31) ; Store double variant
1399 lfs f29,emfp0(r31) ; Load single variant
1402 stfs f29,emfp0(r31) ; Store single variant
1405 lfd f29,emfp0(r31) ; Load double variant
1408 stfd f29,emfp0(r31) ; Store double variant
1411 lfs f30,emfp0(r31) ; Load single variant
1414 stfs f30,emfp0(r31) ; Store single variant
1417 lfd f30,emfp0(r31) ; Load double variant
1420 stfd f30,emfp0(r31) ; Store double variant
1423 lfs f31,emfp0(r31) ; Load single variant
1426 stfs f31,emfp0(r31) ; Store single variant
1429 lfd f31,emfp0(r31) ; Load double variant
1432 stfd f31,emfp0(r31) ; Store double variant