]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/Emulate.s
xnu-344.49.tar.gz
[apple/xnu.git] / osfmk / ppc / Emulate.s
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
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
13 * file.
14 *
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
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.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
26 Emulate.s
27
28 Emulate instructions and traps.
29
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.
32
33*/
34
35#include <cpus.h>
36#include <ppc/asm.h>
37#include <ppc/proc_reg.h>
38#include <ppc/exception.h>
39#include <mach/machine/vm_param.h>
40#include <assym.s>
41
de355530 42#define kernAccess 31
9bccf70c
A
43#define traceInst 30
44#define dssAllDone 29
1c79356b
A
45
46; General stuff what happens here:
47; 1) All general context saved, interrupts off, translation off
48; 2) Vector and floating point disabled, but there may be live context.
49; This code is responsible for saving and restoring what is used. This
50; includes exception states, java mode, etc.
51; 3) No attempt is made to resolve page faults. PTE misses are handled
52; automatically, but actual faults (ala copyin/copyout) are not. If
53; a fault does occur, the exception that caused entry to the emulation
54; routine is remapped to either an instruction or data miss (depending
55; upon the stage detected) and redrived through the exception handler.
56; The only time that an instruction fault can happen is when a different
57; processor removes a mapping between our original fault and when we
58; fetch the assisted instruction. For an assisted instruction, data
59; faults should not occur (except in the MP case). For a purely
60; emulated instruction, faults can occur.
61;
62;
63
64
65 .align 5
66 .globl EXT(Emulate)
67
68LEXT(Emulate)
69
9bccf70c 70
de355530
A
71 mfsprg r31,0 ; Get the per_proc
72 lis r30,hi16(EXT(dgWork)) ; Get the high half of diagnostic work area
73 lwz r12,savesrr1(r13) ; Get the exception info
74 ori r30,r30,lo16(EXT(dgWork)) ; And the low half
9bccf70c 75 rlwinm. r0,r12,0,SRR1_PRG_ILL_INS_BIT,SRR1_PRG_ILL_INS_BIT ; Emulation candidate?
de355530 76 lwz r30,dgFlags(r30) ; Get the flags
9bccf70c
A
77 beq+ eExit ; Nope, do not try to emulate...
78
79 rlwinm. r0,r30,0,enaDiagEMb,enaDiagEMb ; Do we want to try to emulate something?
80 mfsprg r28,2 ; Get the processor features
81 beq+ eExit ; No emulation allowed...
82
83 rlwinm. r28,r28,0,pfAltivecb,pfAltivecb ; Do we have Altivec on this machine?
84 beq eNoVect ; Nope, no Altivec...
85
86 dssall ; We need to kill streams because we are going to flip to problem state
87 sync
88
89eNoVect: bl eIFetch ; Get the instruction image
90 bne- eRedriveAsISI ; Go redrive this as an ISI...
91
92 rlwinm. r0,r10,0,0,5 ; See if we have the "special" op code here
93 rlwinm r20,r10,16,22,31 ; Set rS/rD and rA
94 bne+ eExit ; Not special op, ignore...
95
96 rlwinm r0,r10,31,22,31 ; Extract the sub op code
97 crclr cr1_eq ; Clear
98 rlwimi r20,r10,14,15,16 ; Move bits 29 and 30 of instruction to 15 and 16 of DSISR
99 cmplwi r0,790 ; lhbrx?
100 rlwimi r20,r10,8,17,17 ; Move bit 25 to bit 17
101 cror cr1_eq,cr1_eq,cr0_eq ; Remember
102 cmplwi r0,534 ; lwbrx?
103 rlwimi r20,r10,3,18,21 ; Move bit 21-24 to bit 18-21
104 cror cr1_eq,cr1_eq,cr0_eq ; Remember
105 cmplwi r0,918 ; sthbrx?
106 cror cr1_eq,cr1_eq,cr0_eq ; Remember
107 cmplwi r0,662 ; stwbrx?
108 cror cr1_eq,cr1_eq,cr0_eq ; Remember
109 cmplwi r0,1014 ; dcbz?
110 cror cr1_eq,cr1_eq,cr0_eq ; Remember
111 cmplwi r0,533 ; lswx?
112 cror cr1_eq,cr1_eq,cr0_eq ; Remember
113 cmplwi r0,661 ; stswx?
114 cror cr1_eq,cr1_eq,cr0_eq ; Remember
115 bne cr1_eq,eNotIndex ; Go check non-index forms...
116
de355530
A
117 rlwinm. r21,r10,18,25,29 ; Extract index to rA to build EA
118 rlwinm r22,r10,23,25,29 ; Extract index to rB
119 addi r24,r13,saver0 ; Point to the start of registers
9bccf70c
A
120 li r19,0 ; Assume 0 base
121 beq eZeroBase ; Yes...
122 lwzx r19,r24,r21 ; Get the base register value
123
124eZeroBase: lwzx r22,r24,r22 ; Get the index value
125 add r22,r22,r19 ; Get DAR
126 b eFinishUp ; Done, go finish up...
127
128eNotIndex: cmplwi r0,725 ; stswi?
129 cror cr1_eq,cr1_eq,cr0_eq ; Remember
130 cmplwi r0,597 ; lswi?
131 cror cr1_eq,cr1_eq,cr0_eq ; Remember
132 bne cr1,eExit ; Not one we handle...
133
de355530
A
134 rlwinm. r21,r10,18,25,29 ; Extract index to rA to build EA
135 addi r24,r13,saver0 ; Point to the start of registers
9bccf70c
A
136 li r22,0 ; Assume 0 base
137 beq eFinishUp ; Yes, it is...
138 lwzx r22,r24,r21 ; Get the base register value
139
140eFinishUp: stw r20,savedsisr(r13) ; Set the DSISR
141 li r11,T_ALIGNMENT ; Get the exception code
de355530 142 stw r22,savedar(r13) ; Save the DAR
9bccf70c
A
143 stw r11,saveexception(r13) ; Set the exception code
144 b EXT(AlignAssist) ; Go emulate the handler...
145
146
147eExit: b EXT(EmulExit) ; Just return for now...
148
149
150;
151; Fetch the failing instruction.
152; Image returned in R10 if CR0_EQ is false, otherwise, an ISI should be generated/
153; The cr bit kernAccess is set if this was a kernel access.
154; R1 has the DSISR if access failed.
155;
156
157 .align 5
158
de355530 159eIFetch: lwz r23,savesrr1(r13) ; Get old MSR
9bccf70c
A
160 mflr r28 ; Save return
161
162 rlwinm. r22,r23,0,MSR_PR_BIT,MSR_PR_BIT ; Within kernel?
163
164 mfmsr r30 ; Save the MSR for now
de355530
A
165 lwz r23,savesrr0(r13) ; Get instruction address
166 crmove kernAccess,cr0_eq ; Remember if fault was in kernel
167 li r25,4 ; Set access length
168 or r22,r22,r30 ; Add PR to access MSR
9bccf70c 169
de355530
A
170 bfl+ kernAccess,aaSetSegs ; Go set SRs if we are in user and need to
171
172 ori r22,r22,lo16(MASK(MSR_DR)|MASK(MSR_RI)) ; Set RI onto access MSR
9bccf70c
A
173
174 crset cr0_eq ; Set this to see if we failed
175 mtmsr r22 ; Flip DR, RI, and maybe PR on
176 isync
177
178 lwz r10,0(r23) ; Fetch the instruction
179
de355530
A
180 crmove 28,cr0_eq ; Remember if we failed
181 li r0,loadMSR ; Set the magic "get back to supervisor" SC
182 mr r3,r30 ; Get MSR to load
183 sc ; Get back to supervisor state
184
185 bfl+ kernAccess,aaUnSetSegs ; Go set SRs if we are in user and need to
9bccf70c
A
186
187 mtlr r28 ; Restore the LR
de355530 188 crmove cr0_eq,28 ; Set CR0_EQ if the fetch succeeded
9bccf70c
A
189 blr ; Return with instruction image in R10
190
191
192;
193; Redrive as an ISI
194;
195
196eRedriveAsISI:
de355530 197 lwz r6,savesrr1(r13) ; Get the srr1 value
9bccf70c
A
198 lwz r4,SAVflags(r13) ; Pick up the flags
199 li r11,T_INSTRUCTION_ACCESS ; Set failing instruction fetch code
200 rlwimi r6,r1,0,0,4 ; Move the DSISR bits to the SRR1
201 oris r4,r4,hi16(SAVredrive) ; Set the redrive bit
202 stw r11,saveexception(r13) ; Set the replacement code
203 stw r4,SAVflags(r13) ; Set redrive request
de355530 204 stw r6,savesrr1(r13) ; Set the srr1 value
9bccf70c
A
205 b EXT(EmulExit) ; Bail out to handle ISI...
206
207
208;
209; This code emulates instructions that have failed because of operand
210; alignment. We decode the DSISR to figure out what we need to do.
211;
212; DSISR:
213; 0001FC00 - Instruction designation
214#define iFloat 12
215#define iOptype1 15
216#define iOptype2 16
217#define iOptype3 18
218#define iOptype4 19
219#define iUpdate 17
220#define iStore 20
221#define iDouble 21
222#define iNotify 22
223; 000003E0 - Target/Source register
224; 0000001F - Register to update if update form
225;
226
227 .align 5
228 .globl EXT(AlignAssist)
229
230LEXT(AlignAssist)
de355530
A
231
232#if 0
233 b EXT(EmulExit) ; Just return for now...
234#endif
235
236
9bccf70c 237 mfsprg r31,0 ; Get the per_proc
de355530 238 lwz r20,savedsisr(r13) ; Get the DSISR
9bccf70c 239 lwz r21,spcFlags(r31) ; Grab the special flags
de355530 240 mtcrf 0x1C,r20 ; Put instruction ID in CR for later
9bccf70c 241 rlwinm. r0,r21,0,runningVMbit,runningVMbit ; Are we running a VM?
de355530 242 lwz r22,savesrr1(r13) ; Get the SRR1
9bccf70c 243 bne- aaPassAlong ; We are in a VM, no emulation for alignment exceptions...
de355530 244 rlwinm. r0,r21,0,trapUnalignbit,trapUnalignbit ; Should we trap alignment exceptions?
9bccf70c
A
245 crxor iFloat,iOptype1,iOptype2 ; Set this to 0 if both bits are either 0 or 1
246 mr r26,r20 ; Save the DSISR
de355530 247 bne- aaPassAlong ; No alignment exceptions allowed...
9bccf70c 248 rlwinm. r0,r22,0,MSR_SE_BIT,MSR_SE_BIT ; Were we single stepping?
de355530 249 lwz r23,savedar(r13) ; Pick up the address that we want to access
9bccf70c 250 crnot traceInst,cr0_eq ; Remember if trace is on
de355530
A
251 rlwinm. r0,r21,0,notifyUnalignbit,notifyUnalignbit ; Should we notify that an alignment exception happened?
252 mfsprg r28,2 ; Get the processor features
d7e50217 253 crnot iNotify,cr0_eq ; Remember to tell someone we did this
de355530
A
254 rlwinm. r22,r22,0,MSR_PR_BIT,MSR_PR_BIT ; Did we take the exception in the kernel and isolate PR?
255 mfmsr r30 ; Save the MSR for now
9bccf70c
A
256 li r29,emfp0 ; Point to work area
257 crxor iFloat,iFloat,iOptype3 ; Set true if we have a floating point instruction
de355530 258 or r22,r22,r30 ; Add PR to access MSR
9bccf70c 259 dcbz r29,r31 ; Clear and allocate a cache line for us to work in
de355530 260 rlwinm r24,r20,2,25,29 ; Get displacement to register to update if update form
9bccf70c 261 rlwimi r20,r20,24,28,28 ; Move load/store indication to the bottom of index
de355530
A
262 ori r22,r22,lo16(MASK(MSR_DR)|MASK(MSR_RI)) ; Set RI onto access MSR
263 crmove kernAccess,cr0_eq ; Remember if fault was in kernel
264 rlwinm. r28,r28,0,pfAltivecb,pfAltivecb ; Do we have Altivec on this machine?
9bccf70c 265 rlwimi r20,r20,26,27,27 ; Move single/double indication to just above the bottom
de355530
A
266 beq aaNoVect ; Nope, no Altivec...
267
268 dssall ; We need to kill streams because we are going to flip to problem state
269 sync
270
271aaNoVect: lis r29,hi16(aaFPopTable) ; High part of FP branch table
9bccf70c 272 bf- iFloat,aaNotFloat ; This is not a floating point instruction...
de355530
A
273 li r25,8 ; Assume 8-byte access for now
274 ori r29,r29,lo16(aaFPopTable) ; Low part of FP branch table
275 bt iDouble,aaFPis8 ; So far, we think we are a double...
276 li r25,4 ; Set word access
9bccf70c 277
de355530
A
278aaFPis8: rlwimi r29,r20,0,22,28 ; Index into table based upon register||iDouble||iStore
279 ori r0,r30,lo16(MASK(MSR_FP)) ; Turn on floating point
9bccf70c
A
280 mtctr r29 ; Get set to call the function
281 bt iStore,aaFPstore ; This is an FP store...
282
283;
284; Here we handle floating point loads
285;
286
de355530
A
287aaFPload: bfl+ kernAccess,aaSetSegs ; Go set SRs if we are in user and need to
288
289 crset cr0_eq ; Set this to see if we failed
290 ori r3,r30,lo16(MASK(MSR_FP)) ; We will need FP on in a bit, so turn on when we ditch problem state
291 mtmsr r22 ; Flip DR, RI, and maybe PR on
9bccf70c
A
292 isync
293
294 lwz r10,0(r23) ; Get the first word
295 bf- cr0_eq,aaLdNotDbl ; Jump out if we DSIed...
296 bf iDouble,aaLdNotDbl ; this is not a double...
297 lwz r11,4(r23) ; Get the second half
298
299aaLdNotDbl: mr r4,r0 ; Save the DAR if we failed the access
de355530
A
300 li r0,loadMSR ; Set the magic "get back to supervisor" SC
301 sc ; Get back to supervisor state and turn on FP
9bccf70c
A
302
303 bf- cr0_eq,aaRedriveAsDSI ; Go redrive this as a DSI...
304
305 stw r10,emfp0(r31) ; Save the first half
306 stw r11,emfp0+4(r31) ; Save the second half, just in case we need it
307
308 bctrl ; Go set the target FP register
309
310 b aaComExit ; All done, go exit...
311
312;
313; Here we handle floating point stores
314;
315
316 .align 5
317
de355530
A
318aaFPstore: mtmsr r0 ; We need floating point on for the first phase
319 isync
320
321 bctrl ; Go save the source FP register
9bccf70c
A
322
323 lwz r10,emfp0(r31) ; Get first word
324 crandc iDouble,iDouble,iOptype4 ; Change to 4-byte access if stfiwx
325 lwz r11,emfp0+4(r31) ; and the second
326 bf+ iOptype4,aaNotstfiwx ; This is not a stfiwx...
de355530 327 li r25,4 ; Set this is a word
9bccf70c
A
328 mr r10,r11 ; The stfiwx wants to store the second half
329
330aaNotstfiwx:
de355530
A
331 bfl+ kernAccess,aaSetSegs ; Go set SRs if we are in user and need to
332
9bccf70c 333 crset cr0_eq ; Set this to see if we failed
de355530
A
334 mr r3,r30 ; Set the normal MSR
335 mtmsr r22 ; Flip DR, RI, and maybe PR on
9bccf70c
A
336 isync
337
338 stw r10,0(r23) ; Save the first word
339 bf- cr0_eq,aaStNotDbl ; Jump out if we DSIed...
340 bf iDouble,aaStNotDbl ; this is not a double...
341 stw r11,4(r23) ; Save the second half
342
343aaStNotDbl: mr r4,r0 ; Save the DAR if we failed the access
de355530
A
344 li r0,loadMSR ; Set the magic "get back to supervisor" SC
345 sc ; Get back to supervisor state
346
9bccf70c
A
347
348 bf- cr0_eq,aaRedriveAsDSI ; Go redrive this as a DSI...
de355530
A
349
350
9bccf70c
A
351
352;
353; Common exit routines
354;
355
de355530 356aaComExit: lwz r10,savesrr0(r13) ; Get the failing instruction address
9bccf70c
A
357 add r24,r24,r13 ; Offset to update register
358 li r11,T_IN_VAIN ; Assume we are all done
359 addi r10,r10,4 ; Step to the next instruction
360 bf iUpdate,aaComExNU ; Skip if not an update form...
de355530 361 stw r23,saver0(r24) ; Update the target
9bccf70c
A
362
363aaComExNU: lwz r9,SAVflags(r13) ; Get the flags
de355530 364 stw r10,savesrr0(r13) ; Set new PC
9bccf70c
A
365 bt- traceInst,aaComExitrd ; We are tracing, go emulate trace...
366 bf+ iNotify,aaComExGo ; Nothing special here, go...
de355530
A
367
368 bfl+ kernAccess,aaUnSetSegs ; Go set SRs if we are in user and need to
9bccf70c
A
369
370 li r11,T_ALIGNMENT ; Set the we just did an alignment exception....
371
372aaComExGo: b EXT(EmulExit) ; We are done, no tracing on...
373
374
375;
376; This is not a floating point operation
377;
378; The emulation routines for these are positioned every 64 bytes (16 instructions)
379; in a 1024-byte aligned table. It is indexed by taking the low order 4 bits of
380; the instruction code in the DSISR and subtracting 7. If this comes up negative,
381; the instruction is not to be emulated. Then we add bit 0 of the code * 4. This
382; gives us a fairly compact and almost unique index. Both lwm and stmw map to 0 so
383; that one needs to be further reduced, and we end up with holes at index 6, 8, and 10.
384;
385; If the emulation routine takes more than 16 instructions, it must branch elsewhere
386; to finish up.
387;
388
389 .align 5
390
391aaNotFloat:
392 lis r19,hi16(aaEmTable) ; Point to high part of table address
393 rlwinm r3,r26,24,26,29 ; Isolate last 4 bits of op type * 4
394 rlwimi r19,r26,20,27,27 ; Get bit 0 of instruction code * 4 into bottom of table base
395 addic. r3,r3,-28 ; Subtract 7*4 to adjust index
396 ori r19,r19,lo16(aaEmTable) ; Low part of table address
397 blt- aaPassAlong ; We do not handle any of these (lwarx, stwcx., eciwx, ecowx)...
398 add r19,r19,r3 ; Point to emulation routine
de355530 399 rlwinm r18,r26,29,25,29 ; Get the target/source register displacement
9bccf70c
A
400
401 mtctr r19 ; Set the routine address
402
403 bctr ; Go emulate the instruction...
404
405;
406; This is the table of non-floating point emulation routines.
407; It is indexed by low 4 bits of DSISR op type - 7 + bit 0 of
408; op type * 4
409;
410
411 .align 5
412
413aaEmTable:
414 b aaLmwStmw ; This for lmw/stmw
415 b aaLswx ; This for lwwx
416 b aaLswi ; This for lswi
417 b aaStswx ; This for stswx
418 b aaStswi ; This for stswi
419 b aaLwbrx ; This for lwbrx
420 b aaPassAlong ; This an invalid index (6)
421 b aaStwbrx ; This for stwbrx
422 b aaPassAlong ; This an invalid index (8)
423 b aaLhbrx ; This for lhbrx
424 b aaPassAlong ; This an invalid index (A)
425 b aaSthbrx ; This for sthbrx
426 b aaDcbz ; This for dcbz
427 b aaPassAlong ; This an invalid index (D)
428 b aaPassAlong ; This an invalid index (E)
429 b aaPassAlong ; This an invalid index (F)
430
431
432;
433; Here we handle the set up for the lmw and stmw. After that, we split off to the
434; individual routines.
435;
436; Note also that after some set up, all of the string instructions come through here as well.
437;
438 .align 5
439
440aaLmwStmw:
de355530 441 subfic r25,r18,32*4 ; Calculate the length of the transfer
9bccf70c 442 li r28,0 ; Set no extra bytes to move (used for string instructions)
de355530 443 mr r17,r25 ; Save the word transfer length here
9bccf70c 444
de355530 445aaLSComm: addi r19,r13,saver0 ; Offset to registers in savearea
9bccf70c 446 mr r16,r23 ; Make a hunk pointer
de355530
A
447
448 bfl+ kernAccess,aaSetSegs ; Go set SRs if we are in user and need to
9bccf70c
A
449
450 bt iUpdate,aaStmw ; This is the stmw...
451
452;
453; Load multiple word
454;
455
456aaLmwNxt: cmplwi cr1,r17,8*4 ; Is there enough to move 8?
457 blt- cr1,aaLmwNxtH ; Not enough for a full hunk...
458 subi r17,r17,8*4 ; Back off for another hunk
459
460 crset cr0_eq ; Set this to see if we failed
de355530 461 mtmsr r22 ; Flip DR, RI, and maybe PR on
9bccf70c
A
462 isync
463
464 lwz r2,0(r16) ; Load word 0
465 bf- cr0_eq,aaLmwB1 ; Error, bail...
466 lwz r15,4(r16) ; Load word 1
467 bf- cr0_eq,aaLmwB1 ; Error, bail...
468 lwz r14,8(r16) ; Load word 2
469 bf- cr0_eq,aaLmwB1 ; Error, bail...
470 lwz r5,12(r16) ; Load word 3
471 bf- cr0_eq,aaLmwB1 ; Error, bail...
472 lwz r6,16(r16) ; Load word 4
473 bf- cr0_eq,aaLmwB1 ; Error, bail...
474 lwz r7,20(r16) ; Load word 5
475 bf- cr0_eq,aaLmwB1 ; Error, bail...
476 lwz r8,24(r16) ; Load word 6
477 bf- cr0_eq,aaLmwB1 ; Error, bail...
478 lwz r9,28(r16) ; Load word 7
479
480aaLmwB1: mr r4,r0 ; Remember DAR, jus in case we failed the access
de355530
A
481 mr r3,r30 ; Set the normal MSR
482 li r0,loadMSR ; Set the magic "get back to supervisor" SC
483 sc ; Get back to supervisor state
9bccf70c
A
484
485 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
486
487 addi r16,r16,8*4 ; Point up to next input aread
488
489 stwx r2,r19,r18 ; Store register
de355530
A
490 addi r18,r18,4 ; Next register
491 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 492 stwx r15,r19,r18 ; Store register
de355530
A
493 addi r18,r18,4 ; Next register
494 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 495 stwx r14,r19,r18 ; Store register
de355530
A
496 addi r18,r18,4 ; Next register
497 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 498 stwx r5,r19,r18 ; Store register
de355530
A
499 addi r18,r18,4 ; Next register
500 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 501 stwx r6,r19,r18 ; Store register
de355530
A
502 addi r18,r18,4 ; Next register
503 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 504 stwx r7,r19,r18 ; Store register
de355530
A
505 addi r18,r18,4 ; Next register
506 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 507 stwx r8,r19,r18 ; Store register
de355530
A
508 addi r18,r18,4 ; Next register
509 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 510 stwx r9,r19,r18 ; Store register
de355530
A
511 addi r18,r18,4 ; Next register
512 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c
A
513
514 b aaLmwNxt ; Do the next hunk...
515
516 .align 5
517
518aaLmwNxtH: cmplwi cr1,r17,4*4 ; Do we have 4 left?
519 blt cr1,aaLmwL4 ; Nope...
520
521 subi r17,r17,4*4 ; Set count properly
522
523 crset cr0_eq ; Set this to see if we failed
524 mtmsr r22 ; Flip DR, RI, and maybe PR on
525 isync
526
527 lwz r2,0(r16) ; Load word 0
528 bf- cr0_eq,aaLmwB2 ; Error, bail...
529 lwz r15,4(r16) ; Load word 1
530 bf- cr0_eq,aaLmwB2 ; Error, bail...
531 lwz r14,8(r16) ; Load word 2
532 bf- cr0_eq,aaLmwB2 ; Error, bail...
533 lwz r5,12(r16) ; Load word 3
534
535aaLmwB2: mr r4,r0 ; Remember DAR, jus in case we failed the access
de355530
A
536 mr r3,r30 ; Set the normal MSR
537 li r0,loadMSR ; Set the magic "get back to supervisor" SC
538 sc ; Get back to supervisor state
9bccf70c
A
539
540 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
541
542 addi r16,r16,4*4 ; Point up to next input aread
543
544 stwx r2,r19,r18 ; Store register
de355530
A
545 addi r18,r18,4 ; Next register
546 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 547 stwx r15,r19,r18 ; Store register
de355530
A
548 addi r18,r18,4 ; Next register
549 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 550 stwx r14,r19,r18 ; Store register
de355530
A
551 addi r18,r18,4 ; Next register
552 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 553 stwx r5,r19,r18 ; Store register
de355530
A
554 addi r18,r18,4 ; Next register
555 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c
A
556
557aaLmwL4: or. r5,r17,r28 ; Do we have anything left?
558 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three full words left?
559 cmplwi cr2,r17,0 ; Do we have no full words left?
560 beq aaComExit ; Nothing left...
561
562 crset cr0_eq ; Set this to see if we failed
563 mtmsr r22 ; Flip DR, RI, and maybe PR on
564 isync
565
566 beq- cr2,aaLmwBy ; No full words, get bytes...
567
568 lwz r2,0(r16) ; Pick up first word
569 bf- cr0_eq,aaLmwDn ; Read failed, escape...
570 addi r16,r16,4 ; Next input location
571 blt cr1,aaLmwBy ; We only had one, we are done...
572
573 lwz r15,0(r16) ; Pick up second word
574 bf- cr0_eq,aaLmwDn ; Read failed, escape...
575 addi r16,r16,4 ; Next input location
576 beq cr1,aaLmwBy ; We had two, we are done...
577
578 lwz r14,0(r16) ; Load word 3
579 addi r16,r16,4 ; Next input location
580
581aaLmwBy: cmplwi cr2,r28,0 ; Any trailing bytes to do?
582 li r8,0 ; Clear second trailing byte
583 cmplwi cr1,r28,2 ; Check for 1, 2, or 3
584 li r9,0 ; Clear third trailing byte
585 beq+ cr2,aaLmwDn ; No trailing bytes...
586
587 lbz r5,0(r16) ; Pick up first trailing byte
588 bf- cr0_eq,aaLmwDn ; Read failed, escape...
589 blt cr1,aaLmwDn ; We only had one, we are done...
590
591 lbz r8,1(r16) ; Pick up second trailing byte
592 bf- cr0_eq,aaLmwDn ; Read failed, escape...
593 beq cr1,aaLmwDn ; We had two, we are done...
594
595 lbz r9,2(r16) ; Get last trailing byte
596
597
598aaLmwDn: rlwinm r5,r5,24,0,7 ; Move first byte to top
599 cmplwi cr2,r17,0 ; Any full words to do?
600 mr r4,r0 ; Remember DAR, just in case we failed the access
601 rlwimi r9,r8,8,16,23 ; Move second byte above third byte
602 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three full words left?
603 mr r3,r30 ; Set the normal MSR
604 rlwimi r5,r9,8,8,23 ; Move bytes 1 and 2 after 0
de355530
A
605 li r0,loadMSR ; Set the magic "get back to supervisor" SC
606 sc ; Get back to supervisor state
9bccf70c
A
607
608 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
609
610 beq- cr2,aaLmwCb ; No full words, copy bytes...
611
612 stwx r2,r19,r18 ; Store register
de355530
A
613 addi r18,r18,4 ; Next register
614 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c
A
615 blt cr1,aaLmwCb ; We only had one, we are done...
616
617 stwx r15,r19,r18 ; Store register
de355530
A
618 addi r18,r18,4 ; Next register
619 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c
A
620 beq cr1,aaLmwCb ; We had two, we are done...
621
622 stwx r14,r19,r18 ; Store register
de355530
A
623 addi r18,r18,4 ; Next register
624 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c
A
625
626aaLmwCb: mr. r28,r28 ; Any trailing bytes to do?
627 beq+ aaComExit ; Nope, leave...
628
629 stwx r5,r19,r18 ; Store register
630
631 b aaComExit ; We are done....
632
633;
634; Store multiple word
635;
636
637 .align 5
638
639aaStmw:
640 crclr iUpdate ; Make sure we do not think this is an update form
641
642aaStmwNxt: cmplwi cr1,r17,8*4 ; Is there enough to move 8?
643 blt- cr1,aaStmwNxtH ; Not enough for a full hunk...
644 subi r17,r17,8*4 ; Back off for another hunk
645
646 lwzx r2,r19,r18 ; Store register
de355530
A
647 addi r18,r18,4 ; Next register
648 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 649 lwzx r15,r19,r18 ; Store register
de355530
A
650 addi r18,r18,4 ; Next register
651 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 652 lwzx r14,r19,r18 ; Store register
de355530
A
653 addi r18,r18,4 ; Next register
654 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 655 lwzx r5,r19,r18 ; Store register
de355530
A
656 addi r18,r18,4 ; Next register
657 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 658 lwzx r6,r19,r18 ; Store register
de355530
A
659 addi r18,r18,4 ; Next register
660 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 661 lwzx r7,r19,r18 ; Store register
de355530
A
662 addi r18,r18,4 ; Next register
663 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 664 lwzx r8,r19,r18 ; Store register
de355530
A
665 addi r18,r18,4 ; Next register
666 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 667 lwzx r9,r19,r18 ; Store register
de355530
A
668 addi r18,r18,4 ; Next register
669 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c
A
670
671 crset cr0_eq ; Set this to see if we failed
672 mtmsr r22 ; Flip DR, RI, and maybe PR on
673 isync
674
675 stw r2,0(r16) ; Store word 0
676 bf- cr0_eq,aaStmwB1 ; Error, bail...
677 stw r15,4(r16) ; Store word 1
678 bf- cr0_eq,aaStmwB1 ; Error, bail...
679 stw r14,8(r16) ; Store word 2
680 bf- cr0_eq,aaStmwB1 ; Error, bail...
681 stw r5,12(r16) ; Store word 3
682 bf- cr0_eq,aaStmwB1 ; Error, bail...
683 stw r6,16(r16) ; Store word 4
684 bf- cr0_eq,aaStmwB1 ; Error, bail...
685 stw r7,20(r16) ; Store word 5
686 bf- cr0_eq,aaStmwB1 ; Error, bail...
687 stw r8,24(r16) ; Store word 6
688 bf- cr0_eq,aaStmwB1 ; Error, bail...
689 stw r9,28(r16) ; Store word 7
690
691 addi r16,r16,8*4 ; Point up to next output aread
692
693
694aaStmwB1: mr r4,r0 ; Remember DAR, jus in case we failed the access
de355530
A
695 mr r3,r30 ; Set the normal MSR
696 li r0,loadMSR ; Set the magic "get back to supervisor" SC
697 sc ; Get back to supervisor state
9bccf70c
A
698
699 bt- cr0_eq,aaStmwNxt ; We have more to do and no failed access...
700 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
701
702 .align 5
703
704aaStmwNxtH: cmplwi cr1,r17,(4*4) ; Do we have at least 4 left?
705 blt cr1,aaStmwL4 ; Nope...
706 subi r17,r17,4*4 ; Set count properly
707
708 lwzx r2,r19,r18 ; Store register
de355530
A
709 addi r18,r18,4 ; Next register
710 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 711 lwzx r15,r19,r18 ; Store register
de355530
A
712 addi r18,r18,4 ; Next register
713 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 714 lwzx r14,r19,r18 ; Store register
de355530
A
715 addi r18,r18,4 ; Next register
716 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c 717 lwzx r5,r19,r18 ; Store register
de355530
A
718 addi r18,r18,4 ; Next register
719 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c
A
720
721 crset cr0_eq ; Set this to see if we failed
de355530 722 mtmsr r22 ; Flip DR, RI, and maybe PR on
9bccf70c
A
723 isync
724
725 stw r2,0(r16) ; Store word 0
726 bf- cr0_eq,aaStmwB2 ; Error, bail...
727 stw r15,4(r16) ; Store word 1
728 bf- cr0_eq,aaStmwB2 ; Error, bail...
729 stw r14,8(r16) ; Store word 2
730 bf- cr0_eq,aaStmwB2 ; Error, bail...
731 stw r5,12(r16) ; Store word 3
732
733 addi r16,r16,4*4 ; Point up to next input aread
734
735aaStmwB2: mr r4,r0 ; Remember DAR, jus in case we failed the access
de355530
A
736 mr r3,r30 ; Set the normal MSR
737 li r0,loadMSR ; Set the magic "get back to supervisor" SC
738 sc ; Get back to supervisor state
9bccf70c
A
739
740 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
741
742aaStmwL4: or. r5,r17,r28 ; Do we have anything left to do?
743 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three left?
744 cmplwi cr2,r17,0 ; Do we have no full words left?
745 beq aaComExit ; Nothing left...
746
747 beq- cr2,aaStmwBy1 ; No full words, check out bytes
748
749 lwzx r2,r19,r18 ; Store register
de355530
A
750 addi r18,r18,4 ; Next register
751 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c
A
752 blt cr1,aaStmwBy1 ; We only had one, go save it...
753
754 lwzx r15,r19,r18 ; Store register
de355530
A
755 addi r18,r18,4 ; Next register
756 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c
A
757 beq cr1,aaStmwBy1 ; We had two, go save it...
758
759 lwzx r14,r19,r18 ; Store register
de355530
A
760 addi r18,r18,4 ; Next register
761 rlwinm r18,r18,0,25,29 ; Wrap back to 0 if needed
9bccf70c
A
762
763aaStmwBy1: mr. r28,r28 ; Do we have any trailing bytes?
764 beq+ aaStmwSt ; Nope...
765
766 lwzx r5,r19,r18 ; Yes, pick up one extra register
767
768aaStmwSt: crset cr0_eq ; Set this to see if we failed
de355530 769 mtmsr r22 ; Flip DR, RI, and maybe PR on
9bccf70c
A
770 isync
771
772 beq- cr2,aaStmwBy2 ; No words, check trailing bytes...
773
774 stw r2,0(r16) ; Save first word
de355530 775 bf- cr0_eq,aaStmwDn ; Read failed, escape...
9bccf70c
A
776 addi r16,r16,4 ; Bump sink
777 blt cr1,aaStmwBy2 ; We only had one, we are done...
778
779 stw r15,0(r16) ; Save second word
de355530 780 bf- cr0_eq,aaStmwDn ; Read failed, escape...
9bccf70c
A
781 addi r16,r16,4 ; Bump sink
782 beq cr1,aaStmwBy2 ; We had two, we are done...
783
784 stw r14,0(r16) ; Save third word
785 addi r16,r16,4 ; Bump sink
786
787aaStmwBy2: rlwinm r2,r5,8,24,31 ; Get byte 0
788 cmplwi cr2,r28,0 ; Any trailing bytes to do?
789 rlwinm r14,r5,24,24,31 ; Get byte 3
790 li r8,0 ; Clear second trailing byte
791 cmplwi cr1,r28,2 ; Check for 1, 2, or 3
792 li r9,0 ; Clear third trailing byte
793 beq+ cr2,aaStmwDn ; No trailing bytes...
794 rlwinm r15,r5,16,24,31 ; Get byte 1
795
796 stb r2,0(r16) ; Save first byte
797 bf- cr0_eq,aaStmwDn ; Read failed, escape...
798 blt cr1,aaStmwDn ; We only had one, we are done...
799
800 stb r15,1(r16) ; Save second byte
801 bf- cr0_eq,aaStmwDn ; Read failed, escape...
802 beq cr1,aaStmwDn ; We had two, we are done...
803
804 stb r14,2(r16) ; Save third byte
805
806aaStmwDn: mr r4,r0 ; Remember DAR, jus in case we failed the access
de355530
A
807 mr r3,r30 ; Set the normal MSR
808 li r0,loadMSR ; Set the magic "get back to supervisor" SC
809 sc ; Get back to supervisor state
9bccf70c
A
810
811 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
812
813 b aaComExit ; We are done....
814
815
816;
817; Load String Indexed
818;
819
820 .align 5
821
de355530 822aaLswx: lwz r17,savexer(r13) ; Pick up the XER
9bccf70c
A
823 crclr iUpdate ; Make sure we think this the load form
824 rlwinm. r25,r17,0,25,31 ; Get the number of bytes to load
825 rlwinm r28,r17,0,30,31 ; Get the number of bytes past an even word
826 beq- aaComExit ; Do nothing if 0 length...
827 xor r17,r25,r28 ; Round down to an even word boundary
828 b aaLSComm ; Join up with common load/store code...
829
830
831;
832; Load String Immediate
833;
834
835 .align 5
836
837aaLswi: mr r9,r23 ; Save the DAR
838 bl eIFetch ; Get the instruction image
839 bne- eRedriveAsISI ; Go redrive this as an ISI...
840 rlwinm r25,r10,21,27,31 ; Get the number of bytes to load
841 crclr iUpdate ; Make sure we think this the load form
842 subi r25,r25,1 ; Back off by 1
843 rlwinm r25,r25,0,27,31 ; Clear back down
844 addi r25,r25,1 ; Add back the 1 to convert 0 to 32
845 rlwinm r28,r25,0,30,31 ; Get the number of bytes past an even word
846 xor r17,r25,r28 ; Round down to an even word boundary
847 mr r23,r9 ; Move back the DAR
848 b aaLSComm ; Join up with common load/store code...
849
850;
851; Store String Indexed
852;
853
854 .align 5
855
de355530 856aaStswx: lwz r17,savexer(r13) ; Pick up the XER
9bccf70c
A
857 crclr iUpdate ; Make sure this is clear in case we have 0 length
858 rlwinm. r25,r17,0,25,31 ; Get the number of bytes to load
859 rlwinm r28,r17,0,30,31 ; Get the number of bytes past an even word
860 beq- aaComExit ; Do nothing if 0 length...
861 xor r17,r25,r28 ; Round down to an even word boundary
862 crset iUpdate ; Make sure we think this the store form
863 b aaLSComm ; Join up with common load/store code...
864
865
866;
867; Store String Immediate
868;
869
870 .align 5
871
872aaStswi: mr r9,r23 ; Save the DAR
873 bl eIFetch ; Get the instruction image
874 bne- eRedriveAsISI ; Go redrive this as an ISI...
875 rlwinm r25,r10,21,27,31 ; Get the number of bytes to load
876 crclr iUpdate ; Make sure we think this the load form
877 subi r25,r25,1 ; Back off by 1
878 rlwinm r25,r25,0,27,31 ; Clear back down
879 addi r25,r25,1 ; Add back the 1 to convert 0 to 32
880 rlwinm r28,r25,21,30,31 ; Get the number of bytes past an even word
881 xor r17,r25,r28 ; Round down to an even word boundary
882 mr r23,r9 ; Move back the DAR
883 b aaLSComm ; Join up with common load/store code...
884
885
886;
887; Load byte-reversed word
888;
889
890 .align 5
891
892aaLwbrx:
893 add r18,r18,r13 ; Index to source register
de355530
A
894 li r25,4 ; Set the length
895
896 bfl+ kernAccess,aaSetSegs ; Go set SRs if we are in user and need to
9bccf70c
A
897
898 crset cr0_eq ; Set this to see if we failed
de355530 899 mr r3,r30 ; Set the normal MSR
9bccf70c
A
900 mtmsr r22 ; Flip DR, RI, and maybe PR on
901 isync
902
903 lwz r11,0(r23) ; Load the word
904
905 mr r4,r0 ; Save the DAR if we failed the access
de355530
A
906 li r0,loadMSR ; Set the magic "get back to supervisor" SC
907 sc ; Get back to supervisor state
908
9bccf70c
A
909 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
910
911 rlwinm r10,r11,8,0,31 ; Get byte 0 to 3 and byte 2 to 1
912 rlwimi r10,r11,24,16,23 ; Move byte 1 to byte 2
913 rlwimi r10,r11,24,0,7 ; Move byte 3 to byte 0
914
de355530 915 stw r10,saver0(r18) ; Set the register
9bccf70c
A
916
917 b aaComExit ; All done, go exit...
918
919
920
921;
922; Store byte-reversed word
923;
924
925 .align 5
926
927aaStwbrx:
928 add r18,r18,r13 ; Index to source register
de355530
A
929 li r25,4 ; Set the length
930 lwz r11,saver0(r18) ; Get the register to store
9bccf70c
A
931
932 rlwinm r10,r11,8,0,31 ; Get byte 0 to 3 and byte 2 to 1
933 rlwimi r10,r11,24,16,23 ; Move byte 1 to byte 2
934 rlwimi r10,r11,24,0,7 ; Move byte 3 to byte 0
935
de355530
A
936 bfl+ kernAccess,aaSetSegs ; Go set SRs if we are in user and need to
937
9bccf70c 938 crset cr0_eq ; Set this to see if we failed
de355530 939 mr r3,r30 ; Set the normal MSR
9bccf70c
A
940 mtmsr r22 ; Flip DR, RI, and maybe PR on
941 isync
942
943 stw r10,0(r23) ; Store the reversed halfword
944
945 mr r4,r0 ; Save the DAR if we failed the access
de355530
A
946 li r0,loadMSR ; Set the magic "get back to supervisor" SC
947 sc ; Get back to supervisor state
948
9bccf70c
A
949 bt+ cr0_eq,aaComExit ; All done, go exit...
950 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
951
952
953
954;
955; Load byte-reversed halfword
956;
957
958 .align 5
959
960aaLhbrx:
961 add r18,r18,r13 ; Index to source register
de355530
A
962 li r25,2 ; Set the length
963
964 bfl+ kernAccess,aaSetSegs ; Go set SRs if we are in user and need to
9bccf70c
A
965
966 crset cr0_eq ; Set this to see if we failed
de355530 967 mr r3,r30 ; Set the normal MSR
9bccf70c
A
968 mtmsr r22 ; Flip DR, RI, and maybe PR on
969 isync
970
971 lhz r11,0(r23) ; Load the halfword
972
973 mr r4,r0 ; Save the DAR if we failed the access
de355530
A
974 li r0,loadMSR ; Set the magic "get back to supervisor" SC
975 sc ; Get back to supervisor state
9bccf70c
A
976
977 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
978
979 rlwinm r10,r11,8,16,23 ; Rotate bottom byte up one and clear everything else
980 rlwimi r10,r11,24,24,31 ; Put old second from bottom into bottom
981
de355530 982 stw r10,saver0(r18) ; Set the register
9bccf70c
A
983
984 b aaComExit ; All done, go exit...
985
986
987;
988; Store byte-reversed halfword
989;
990
991 .align 5
992
993aaSthbrx:
994 add r18,r18,r13 ; Index to source register
de355530
A
995 li r25,2 ; Set the length
996 lwz r10,saver0(r18) ; Get the register to store
9bccf70c
A
997 rlwinm r10,r10,8,0,31 ; Rotate bottom byte up one
998 rlwimi r10,r10,16,24,31 ; Put old second from bottom into bottom
999
de355530
A
1000 bfl+ kernAccess,aaSetSegs ; Go set SRs if we are in user and need to
1001
9bccf70c 1002 crset cr0_eq ; Set this to see if we failed
de355530 1003 mr r3,r30 ; Set the normal MSR
9bccf70c
A
1004 mtmsr r22 ; Flip DR, RI, and maybe PR on
1005 isync
1006
1007 sth r10,0(r23) ; Store the reversed halfword
1008
1009 mr r4,r0 ; Save the DAR if we failed the access
de355530
A
1010 li r0,loadMSR ; Set the magic "get back to supervisor" SC
1011 sc ; Get back to supervisor state
9bccf70c
A
1012
1013 bt+ cr0_eq,aaComExit ; All done, go exit...
1014 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
1015
1016;
1017; Data cache block zero
1018;
1019
1020 .align 5
1021
1022aaDcbz:
de355530 1023 li r25,32 ; Set the length
9bccf70c
A
1024 rlwinm r23,r23,0,0,26 ; Round back to a 32-byte boundary
1025
de355530
A
1026 bfl+ kernAccess,aaSetSegs ; Go set SRs if we are in user and need to
1027
9bccf70c 1028 crset cr0_eq ; Set this to see if we failed
de355530 1029 mr r3,r30 ; Set the normal MSR
9bccf70c
A
1030 li r0,0 ; Clear this out
1031 mtmsr r22 ; Flip DR, RI, and maybe PR on
1032 isync
1033
1034 stw r0,0(r23) ; Clear word
1035 bne- aaDcbzXit ; Got DSI, we are stopping...
1036 stw r0,4(r23) ; Clear word
1037 bne- aaDcbzXit ; Got DSI, we are stopping...
1038 stw r0,8(r23) ; Clear word
1039 bne- aaDcbzXit ; Got DSI, we are stopping...
1040 stw r0,12(r23) ; Clear word
1041 bne- aaDcbzXit ; Got DSI, we are stopping...
1042 stw r0,16(r23) ; Clear word
1043 bne- aaDcbzXit ; Got DSI, we are stopping...
1044 stw r0,20(r23) ; Clear word
1045 bne- aaDcbzXit ; Got DSI, we are stopping...
1046 stw r0,24(r23) ; Clear word
1047 bne- aaDcbzXit ; Got DSI, we are stopping...
1048 stw r0,28(r23) ; Clear word
1049
1050aaDcbzXit: mr r4,r0 ; Save the DAR if we failed the access
de355530
A
1051 li r0,loadMSR ; Set the magic "get back to supervisor" SC
1052 sc ; Get back to supervisor state
9bccf70c
A
1053
1054 crclr iUpdate ; Make sure we do not think this is an update form
1055
1056 bt+ cr0_eq,aaComExit ; All done, go exit...
1057 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
1058
1059
1060;
1061; Unhandled alignment exception, pass it along
1062;
1063
de355530
A
1064aaPassAlongUnMap:
1065 bfl+ kernAccess,aaUnSetSegs ; Go set SRs if we are in user and need to
1066
1067
9bccf70c
A
1068aaPassAlong:
1069 b EXT(EmulExit)
1070
1071
1072
1073
1074;
1075; We go here to emulate a trace exception after we have handled alignment error
1076;
1077
1078 .align 5
1079
1080aaComExitrd:
de355530 1081 bfl+ kernAccess,aaUnSetSegs ; Go set SRs back if we need to because we are not going back to user yet
9bccf70c
A
1082 oris r9,r9,hi16(SAVredrive) ; Set the redrive bit
1083 li r11,T_TRACE ; Set trace interrupt
1084 rlwinm r12,r12,0,16,31 ; Clear top half of SRR1
1085 stw r9,SAVflags(r13) ; Set the flags
1086 stw r11,saveexception(r13) ; Set the exception code
1087 b EXT(EmulExit) ; Exit and do trace interrupt...
1088
1089
1090
1091;
1092; Redrive as a DSI
1093
1094aaRedriveAsDSI:
1095 mr r20,r1 ; Save the DSISR
1096 mr r21,r4
de355530 1097 bfl+ kernAccess,aaUnSetSegs ; Go set SRs back if we need to because we are not going back to user yet
9bccf70c
A
1098 lwz r4,SAVflags(r13) ; Pick up the flags
1099 li r11,T_DATA_ACCESS ; Set failing data access code
1100 oris r4,r4,hi16(SAVredrive) ; Set the redrive bit
1101 stw r20,savedsisr(r13) ; Set the DSISR of failed access
de355530 1102 stw r21,savedar(r13) ; Set the address of the failed access
9bccf70c
A
1103 stw r11,saveexception(r13) ; Set the replacement code
1104 stw r4,SAVflags(r13) ; Set redrive request
1105 b EXT(EmulExit) ; Bail out to handle ISI...
1106
de355530
A
1107;
1108; Set segment registers for user access. Do not call this if we are trying to get
1109; supervisor state memory. We do not need this.
1110;
1111; Performance-wise, we will usually be setting one SR here. Most memory will be
1112; allocated before the 1GB mark. Since the kernel maps the first GB, the exception
1113; handler always sets the SRs before we get here. Therefore, we will usually
1114; have to remap it.
1115;
1116; Also, we need to un-do these mapping ONLY if we take a non-standard
1117; exit, e.g., emulate DSI, emulate trace exception, etc. This is because
1118; translation will never be turned on until we return and at that point,
1119; normal exception exit code will restore the first 4 SRs if needed.
1120;
1121
1122 .align 5
1123
1124 .globl EXT(aaSetSegsX)
1125
1126LEXT(aaSetSegsX)
1127
1128aaSetSegs: addi r3,r25,-1 ; Point at last accessed offset in range
1129 lwz r7,PP_USERPMAP(r31) ; Get the current user pmap
1130 lis r0,0x4000 ; This is the address of the first segment outside of the kernel
1131 rlwinm r5,r23,6,26,29 ; Get index into pmap table
1132 add r4,r23,r3 ; Point to the last byte accessed
d12e1678 1133 addi r7,r7,PMAP_SEGS ; Point to the segment slot
de355530
A
1134 cmplw r23,r0 ; See if first segment register needs to be reloaded
1135 cmplw cr2,r4,r0 ; Do we need to set the second (if any) SR?
1136 xor r0,r4,r23 ; See if we are in the same segment as first
1137 bge aaSetS1ok ; Nope, we are in a pure user range
1138
1139 lwzx r6,r5,r7 ; Get the user address space SR value
1140 mtsrin r6,r23 ; Load the corresponding SR register
1141
1142aaSetS1ok: rlwinm. r0,r0,0,0,3 ; Any change in segment?
1143 bgelr- cr2 ; We are in user only space, we do not need to mess with SR
1144 rlwinm r5,r4,6,26,29 ; Get index into pmap table
1145 beqlr+ ; No change in segment, we are done...
1146
1147 lwzx r6,r5,r7 ; Get the user address space SR value
1148 mtsrin r6,r4 ; Load the corresponding SR register
1149 blr ; Leave...
1150
1151;
1152; Unset segment registers for user access. Do not call unless we had a user access.
1153;
1154
1155 .align 5
1156
1157 .globl EXT(aaUnSetSegsX)
1158
1159LEXT(aaUnSetSegsX)
1160
1161aaUnSetSegs:
1162 addi r3,r25,-1 ; Point at last accessed offset in range
1163 lis r0,0x4000 ; This is the address of the first segment outside of the kernel
1164 lis r5,hi16(KERNEL_SEG_REG0_VALUE) ; Get the high half of the kernel SR0 value
1165 add r4,r23,r3 ; Point to the last byte accessed
1166 cmplw r23,r0 ; See if first segment register needs to be reloaded
1167 rlwimi r5,r23,24,8,11 ; Make the correct kernel segment
1168 cmplw cr2,r4,r0 ; Do we need to set the second (if any) SR?
1169 xor r0,r4,r23 ; See if we are in the same segment as first
1170 bge aaUnSetS1ok ; Nope, we are in a pure user range
1171
1172 mtsrin r5,r23 ; Load the corresponding SR register
1173
1174aaUnSetS1ok:
1175 rlwinm. r0,r0,0,0,3 ; Any change in segment?
1176 bgelr cr2 ; We are in user only space, we do not need to mess with SR
1177 rlwimi r5,r4,24,8,11 ; Make the correct kernel segment
1178 beqlr+ ; No change in segment, we are done...
1179
1180 mtsrin r5,r4 ; Load the corresponding SR register
1181 blr ; Leave...
1182
9bccf70c
A
1183
1184
1185;
1186; Table of functions to load or store floating point registers
1187; This table is indexed reg||size||dir. That means that each
1188; like load/store pair (e.g., lfd f31/stfd f31) are within the same
1189; quadword, which is the current ifetch size. We expect most of the
1190; unaligned accesses to be part of copies, therefore, with this
1191; organization, we will save the ifetch of the store after the load.
1192;
1193
1194 .align 10 ; Make sure we are on a 1k boundary
1195
de355530 1196aaFPopTable:
9bccf70c
A
1197 lfs f0,emfp0(r31) ; Load single variant
1198 blr
1199
1200 stfs f0,emfp0(r31) ; Store single variant
1201 blr
1202
1203 lfd f0,emfp0(r31) ; Load double variant
1204 blr
1205
1206 stfd f0,emfp0(r31) ; Store double variant
1207 blr
1208
1209 lfs f1,emfp0(r31) ; Load single variant
1210 blr
1211
1212 stfs f1,emfp0(r31) ; Store single variant
1213 blr
1214
1215 lfd f1,emfp0(r31) ; Load double variant
1216 blr
1217
1218 stfd f1,emfp0(r31) ; Store double variant
1219 blr
1220
1221 lfs f2,emfp0(r31) ; Load single variant
1222 blr
1223
1224 stfs f2,emfp0(r31) ; Store single variant
1225 blr
1226
1227 lfd f2,emfp0(r31) ; Load double variant
1228 blr
1229
1230 stfd f2,emfp0(r31) ; Store double variant
1231 blr
1232
1233 lfs f3,emfp0(r31) ; Load single variant
1234 blr
1235
1236 stfs f3,emfp0(r31) ; Store single variant
1237 blr
1238
1239 lfd f3,emfp0(r31) ; Load double variant
1240 blr
1241
1242 stfd f3,emfp0(r31) ; Store double variant
1243 blr
1244
1245 lfs f4,emfp0(r31) ; Load single variant
1246 blr
1247
1248 stfs f4,emfp0(r31) ; Store single variant
1249 blr
1250
1251 lfd f4,emfp0(r31) ; Load double variant
1252 blr
1253
1254 stfd f4,emfp0(r31) ; Store double variant
1255 blr
1256
1257 lfs f5,emfp0(r31) ; Load single variant
1258 blr
1259
1260 stfs f5,emfp0(r31) ; Store single variant
1261 blr
1262
1263 lfd f5,emfp0(r31) ; Load double variant
1264 blr
1265
1266 stfd f5,emfp0(r31) ; Store double variant
1267 blr
1268
1269 lfs f6,emfp0(r31) ; Load single variant
1270 blr
1271
1272 stfs f6,emfp0(r31) ; Store single variant
1273 blr
1274
1275 lfd f6,emfp0(r31) ; Load double variant
1276 blr
1277
1278 stfd f6,emfp0(r31) ; Store double variant
1279 blr
1280
1281 lfs f7,emfp0(r31) ; Load single variant
1282 blr
1283
1284 stfs f7,emfp0(r31) ; Store single variant
1285 blr
1286
1287 lfd f7,emfp0(r31) ; Load double variant
1288 blr
1289
1290 stfd f7,emfp0(r31) ; Store double variant
1291 blr
1292
1293 lfs f8,emfp0(r31) ; Load single variant
1294 blr
1295
1296 stfs f8,emfp0(r31) ; Store single variant
1297 blr
1298
1299 lfd f8,emfp0(r31) ; Load double variant
1300 blr
1301
1302 stfd f8,emfp0(r31) ; Store double variant
1303 blr
1304
1305 lfs f9,emfp0(r31) ; Load single variant
1306 blr
1307
1308 stfs f9,emfp0(r31) ; Store single variant
1309 blr
1310
1311 lfd f9,emfp0(r31) ; Load double variant
1312 blr
1313
1314 stfd f9,emfp0(r31) ; Store double variant
1315 blr
1316
1317 lfs f10,emfp0(r31) ; Load single variant
1318 blr
1319
1320 stfs f10,emfp0(r31) ; Store single variant
1321 blr
1322
1323 lfd f10,emfp0(r31) ; Load double variant
1324 blr
1325
1326 stfd f10,emfp0(r31) ; Store double variant
1327 blr
1328
1329 lfs f11,emfp0(r31) ; Load single variant
1330 blr
1331
1332 stfs f11,emfp0(r31) ; Store single variant
1333 blr
1334
1335 lfd f11,emfp0(r31) ; Load double variant
1336 blr
1337
1338 stfd f11,emfp0(r31) ; Store double variant
1339 blr
1340
1341 lfs f12,emfp0(r31) ; Load single variant
1342 blr
1343
1344 stfs f12,emfp0(r31) ; Store single variant
1345 blr
1346
1347 lfd f12,emfp0(r31) ; Load double variant
1348 blr
1349
1350 stfd f12,emfp0(r31) ; Store double variant
1351 blr
1352
1353 lfs f13,emfp0(r31) ; Load single variant
1354 blr
1355
1356 stfs f13,emfp0(r31) ; Store single variant
1357 blr
1358
1359 lfd f13,emfp0(r31) ; Load double variant
1360 blr
1361
1362 stfd f13,emfp0(r31) ; Store double variant
1363 blr
1364
1365 lfs f14,emfp0(r31) ; Load single variant
1366 blr
1367
1368 stfs f14,emfp0(r31) ; Store single variant
1369 blr
1370
1371 lfd f14,emfp0(r31) ; Load double variant
1372 blr
1373
1374 stfd f14,emfp0(r31) ; Store double variant
1375 blr
1376
1377 lfs f15,emfp0(r31) ; Load single variant
1378 blr
1379
1380 stfs f15,emfp0(r31) ; Store single variant
1381 blr
1382
1383 lfd f15,emfp0(r31) ; Load double variant
1384 blr
1385
1386 stfd f15,emfp0(r31) ; Store double variant
1387 blr
1388
1389 lfs f16,emfp0(r31) ; Load single variant
1390 blr
1391
1392 stfs f16,emfp0(r31) ; Store single variant
1393 blr
1394
1395 lfd f16,emfp0(r31) ; Load double variant
1396 blr
1397
1398 stfd f16,emfp0(r31) ; Store double variant
1399 blr
1400
1401 lfs f17,emfp0(r31) ; Load single variant
1402 blr
1403
1404 stfs f17,emfp0(r31) ; Store single variant
1405 blr
1406
1407 lfd f17,emfp0(r31) ; Load double variant
1408 blr
1409
1410 stfd f17,emfp0(r31) ; Store double variant
1411 blr
1412
1413 lfs f18,emfp0(r31) ; Load single variant
1414 blr
1415
1416 stfs f18,emfp0(r31) ; Store single variant
1417 blr
1418
1419 lfd f18,emfp0(r31) ; Load double variant
1420 blr
1421
1422 stfd f18,emfp0(r31) ; Store double variant
1423 blr
1424
1425 lfs f19,emfp0(r31) ; Load single variant
1426 blr
1427
1428 stfs f19,emfp0(r31) ; Store single variant
1429 blr
1430
1431 lfd f19,emfp0(r31) ; Load double variant
1432 blr
1433
1434 stfd f19,emfp0(r31) ; Store double variant
1435 blr
1436
1437 lfs f20,emfp0(r31) ; Load single variant
1438 blr
1439
1440 stfs f20,emfp0(r31) ; Store single variant
1441 blr
1442
1443 lfd f20,emfp0(r31) ; Load double variant
1444 blr
1445
1446 stfd f20,emfp0(r31) ; Store double variant
1447 blr
1448
1449 lfs f21,emfp0(r31) ; Load single variant
1450 blr
1451
1452 stfs f21,emfp0(r31) ; Store single variant
1453 blr
1454
1455 lfd f21,emfp0(r31) ; Load double variant
1456 blr
1457
1458 stfd f21,emfp0(r31) ; Store double variant
1459 blr
1460
1461 lfs f22,emfp0(r31) ; Load single variant
1462 blr
1463
1464 stfs f22,emfp0(r31) ; Store single variant
1465 blr
1466
1467 lfd f22,emfp0(r31) ; Load double variant
1468 blr
1469
1470 stfd f22,emfp0(r31) ; Store double variant
1471 blr
1472
1473 lfs f23,emfp0(r31) ; Load single variant
1474 blr
1475
1476 stfs f23,emfp0(r31) ; Store single variant
1477 blr
1478
1479 lfd f23,emfp0(r31) ; Load double variant
1480 blr
1481
1482 stfd f23,emfp0(r31) ; Store double variant
1483 blr
1484
1485 lfs f24,emfp0(r31) ; Load single variant
1486 blr
1487
1488 stfs f24,emfp0(r31) ; Store single variant
1489 blr
1490
1491 lfd f24,emfp0(r31) ; Load double variant
1492 blr
1493
1494 stfd f24,emfp0(r31) ; Store double variant
1495 blr
1496
1497 lfs f25,emfp0(r31) ; Load single variant
1498 blr
1499
1500 stfs f25,emfp0(r31) ; Store single variant
1501 blr
1502
1503 lfd f25,emfp0(r31) ; Load double variant
1504 blr
1505
1506 stfd f25,emfp0(r31) ; Store double variant
1507 blr
1508
1509 lfs f26,emfp0(r31) ; Load single variant
1510 blr
1511
1512 stfs f26,emfp0(r31) ; Store single variant
1513 blr
1514
1515 lfd f26,emfp0(r31) ; Load double variant
1516 blr
1517
1518 stfd f26,emfp0(r31) ; Store double variant
1519 blr
1520
1521 lfs f27,emfp0(r31) ; Load single variant
1522 blr
1523
1524 stfs f27,emfp0(r31) ; Store single variant
1525 blr
1526
1527 lfd f27,emfp0(r31) ; Load double variant
1528 blr
1529
1530 stfd f27,emfp0(r31) ; Store double variant
1531 blr
1532
1533 lfs f28,emfp0(r31) ; Load single variant
1534 blr
1535
1536 stfs f28,emfp0(r31) ; Store single variant
1537 blr
1538
1539 lfd f28,emfp0(r31) ; Load double variant
1540 blr
1541
1542 stfd f28,emfp0(r31) ; Store double variant
1543 blr
1544
1545 lfs f29,emfp0(r31) ; Load single variant
1546 blr
1547
1548 stfs f29,emfp0(r31) ; Store single variant
1549 blr
1550
1551 lfd f29,emfp0(r31) ; Load double variant
1552 blr
1553
1554 stfd f29,emfp0(r31) ; Store double variant
1555 blr
1556
1557 lfs f30,emfp0(r31) ; Load single variant
1558 blr
1559
1560 stfs f30,emfp0(r31) ; Store single variant
1561 blr
1562
1563 lfd f30,emfp0(r31) ; Load double variant
1564 blr
1565
1566 stfd f30,emfp0(r31) ; Store double variant
1567 blr
1568
1569 lfs f31,emfp0(r31) ; Load single variant
1570 blr
1571
1572 stfs f31,emfp0(r31) ; Store single variant
1573 blr
1574
1575 lfd f31,emfp0(r31) ; Load double variant
1576 blr
1577
1578 stfd f31,emfp0(r31) ; Store double variant
1579 blr
1c79356b 1580