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