]>
Commit | Line | Data |
---|---|---|
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 | ||
68 | LEXT(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 | ||
89 | eNoVect: 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 | ||
124 | eZeroBase: lwzx r22,r24,r22 ; Get the index value | |
125 | add r22,r22,r19 ; Get DAR | |
126 | b eFinishUp ; Done, go finish up... | |
127 | ||
128 | eNotIndex: 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 | ||
140 | eFinishUp: 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 | ||
147 | eExit: 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 | 159 | eIFetch: 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 | ||
196 | eRedriveAsISI: | |
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 | ||
230 | LEXT(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 | ||
271 | aaNoVect: 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 |
278 | aaFPis8: 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 |
287 | aaFPload: 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 | ||
299 | aaLdNotDbl: 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 |
318 | aaFPstore: 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 | ||
330 | aaNotstfiwx: | |
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 | ||
343 | aaStNotDbl: 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 | 356 | aaComExit: 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 | |
363 | aaComExNU: 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 | ||
372 | aaComExGo: 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 | ||
391 | aaNotFloat: | |
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 | ||
413 | aaEmTable: | |
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 | ||
440 | aaLmwStmw: | |
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 | 445 | aaLSComm: 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 | ||
456 | aaLmwNxt: 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 | ||
480 | aaLmwB1: 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 | ||
518 | aaLmwNxtH: 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 | ||
535 | aaLmwB2: 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 | |
557 | aaLmwL4: 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 | ||
581 | aaLmwBy: 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 | ||
598 | aaLmwDn: 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 | |
626 | aaLmwCb: 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 | ||
639 | aaStmw: | |
640 | crclr iUpdate ; Make sure we do not think this is an update form | |
641 | ||
642 | aaStmwNxt: 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 | ||
694 | aaStmwB1: 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 | ||
704 | aaStmwNxtH: 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 | ||
735 | aaStmwB2: 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 | ||
742 | aaStmwL4: 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 | |
763 | aaStmwBy1: 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 | ||
768 | aaStmwSt: 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 | ||
787 | aaStmwBy2: 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 | ||
806 | aaStmwDn: 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 | 822 | aaLswx: 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 | ||
837 | aaLswi: 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 | 856 | aaStswx: 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 | ||
872 | aaStswi: 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 | ||
892 | aaLwbrx: | |
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 | ||
927 | aaStwbrx: | |
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 | ||
960 | aaLhbrx: | |
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 | ||
993 | aaSthbrx: | |
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 | ||
1022 | aaDcbz: | |
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 | ||
1050 | aaDcbzXit: 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 |
1064 | aaPassAlongUnMap: |
1065 | bfl+ kernAccess,aaUnSetSegs ; Go set SRs if we are in user and need to | |
1066 | ||
1067 | ||
9bccf70c A |
1068 | aaPassAlong: |
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 | ||
1080 | aaComExitrd: | |
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 | ||
1094 | aaRedriveAsDSI: | |
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 | ||
1126 | LEXT(aaSetSegsX) | |
1127 | ||
1128 | aaSetSegs: 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 | ||
1142 | aaSetS1ok: 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 | ||
1159 | LEXT(aaUnSetSegsX) | |
1160 | ||
1161 | aaUnSetSegs: | |
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 | ||
1174 | aaUnSetS1ok: | |
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 | 1196 | aaFPopTable: |
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 |