]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/Emulate.s
b2b75b1a3f9f9e93ecac45a80da10b3ecd9f6fff
[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 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 Emulate.s
25
26 Emulate instructions and traps.
27
28 Lovingly crafted by Bill Angell using traditional methods and only natural or recycled materials.
29 No animal products are used other than rendered otter bile and deep fried pork lard.
30
31 */
32
33 #include <ppc/asm.h>
34 #include <ppc/proc_reg.h>
35 #include <ppc/exception.h>
36 #include <ppc/cpu_capabilities.h>
37 #include <mach/machine/vm_param.h>
38 #include <assym.s>
39
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 bf-- pf64Bitb,emn64 ; Skip if not 64-bit
68 b EXT(Emulate64) ; Jump to the 64-bit code...
69
70 emn64: mfsprg r31,0 ; Get the per_proc
71 lwz r12,savesrr1+4(r13) ; Get the exception info
72 rlwinm. r0,r12,0,SRR1_PRG_ILL_INS_BIT,SRR1_PRG_ILL_INS_BIT ; Emulation candidate?
73 lwz r30,dgFlags(0) ; 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,19,24,28 ; Extract index to rA to build EA
115 rlwinm r22,r10,24,24,28 ; Extract index to rB
116 addi r24,r13,saver0+4 ; 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,19,24,28 ; Extract index to rA to build EA
132 addi r24,r13,saver0+4 ; 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+4(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+4(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+4(r13) ; Get instruction address
163
164 ori r22,r30,lo16(MASK(MSR_DR)|MASK(MSR_RI)) ; Set RI and DR onto access MSR
165
166 crset cr0_eq ; Set this to see if we failed
167 mtmsr r22 ; Flip DR, RI, and maybe PR on
168 isync
169
170 lwz r10,0(r23) ; Fetch the instruction
171
172 mtmsr r30 ; Trans and RI off
173 isync
174
175 mtlr r28 ; Restore the LR
176 blr ; Return with instruction image in R10
177
178
179 ;
180 ; Redrive as an ISI
181 ;
182
183 eRedriveAsISI:
184 lwz r6,savesrr1+4(r13) ; Get the srr1 value
185 lwz r4,SAVflags(r13) ; Pick up the flags
186 li r11,T_INSTRUCTION_ACCESS ; Set failing instruction fetch code
187 rlwimi r6,r1,0,0,4 ; Move the DSISR bits to the SRR1
188 oris r4,r4,hi16(SAVredrive) ; Set the redrive bit
189 stw r11,saveexception(r13) ; Set the replacement code
190 stw r4,SAVflags(r13) ; Set redrive request
191 stw r6,savesrr1+4(r13) ; Set the srr1 value
192 b EXT(EmulExit) ; Bail out to handle ISI...
193
194
195 ;
196 ; This code emulates instructions that have failed because of operand
197 ; alignment. We decode the DSISR to figure out what we need to do.
198 ;
199 ; DSISR:
200 ; 0001FC00 - Instruction designation
201 #define iFloat 12
202 #define iOptype1 15
203 #define iOptype2 16
204 #define iOptype3 18
205 #define iOptype4 19
206 #define iUpdate 17
207 #define iStore 20
208 #define iDouble 21
209 #define iNotify 22
210 ; 000003E0 - Target/Source register
211 ; 0000001F - Register to update if update form
212 ;
213
214 .align 5
215 .globl EXT(AlignAssist)
216
217 LEXT(AlignAssist)
218 bf-- pf64Bitb,aan64 ; Skip if not 64-bit
219 b EXT(AlignAssist64) ; Jump to the 64-bit code...
220
221 aan64: lwz r20,savedsisr(r13) ; Get the DSISR
222 li r0,0 ; Assume we emulate
223 mfsprg r31,0 ; Get the per_proc
224 mtcrf 0x10,r20 ; Put instruction ID in CR for later
225 lwz r21,spcFlags(r31) ; Grab the special flags
226 stw r0,savemisc3(r13) ; Assume that we emulate ok
227 mtcrf 0x08,r20 ; Put instruction ID in CR for later
228 rlwinm. r0,r21,0,runningVMbit,runningVMbit ; Are we running a VM?
229 mtcrf 0x04,r20 ; Put instruction ID in CR for later
230 lwz r22,savesrr1+4(r13) ; Get the SRR1
231 bne- aaPassAlong ; We are in a VM, no emulation for alignment exceptions...
232 lwz r19,dgFlags(0) ; Get the diagnostics flags
233 crxor iFloat,iOptype1,iOptype2 ; Set this to 0 if both bits are either 0 or 1
234 mr r26,r20 ; Save the DSISR
235 rlwinm. r0,r22,0,MSR_SE_BIT,MSR_SE_BIT ; Were we single stepping?
236 lwz r23,savedar+4(r13) ; Pick up the address that we want to access
237 crnot traceInst,cr0_eq ; Remember if trace is on
238
239 rlwinm. r0,r19,0,enaNotifyEMb,enaNotifyEMb ; Should we notify that an alignment exception happened?
240 mfmsr r30 ; Save the MSR for now
241 crnot iNotify,cr0_eq ; Remember to tell someone we did this
242 li r29,emfp0 ; Point to work area
243 crxor iFloat,iFloat,iOptype3 ; Set true if we have a floating point instruction
244 dcbz r29,r31 ; Clear and allocate a cache line for us to work in
245 rlwinm r24,r20,3,24,28 ; Get displacement to register to update if update form
246 rlwimi r20,r20,24,28,28 ; Move load/store indication to the bottom of index
247 ori r22,r30,lo16(MASK(MSR_DR)|MASK(MSR_RI)) ; Set RI onto access MSR
248 rlwimi r20,r20,26,27,27 ; Move single/double indication to just above the bottom
249 lis r29,hi16(EXT(aaFPopTable)) ; High part of FP branch table
250 bf- iFloat,aaNotFloat ; This is not a floating point instruction...
251 ori r29,r29,lo16(EXT(aaFPopTable)) ; Low part of FP branch table
252
253 rlwimi r29,r20,0,22,28 ; Index into table based upon register||iDouble||iStore
254 mtctr r29 ; Get set to call the function
255 bt iStore,aaFPstore ; This is an FP store...
256
257 ;
258 ; Here we handle floating point loads
259 ;
260
261 aaFPload: crset cr0_eq ; Set this to see if we failed
262 mtmsr r22 ; Flip DR, RI
263 isync
264
265 lwz r10,0(r23) ; Get the first word
266 bf- cr0_eq,aaLdNotDbl ; Jump out if we DSIed...
267 bf iDouble,aaLdNotDbl ; this is not a double...
268 lwz r11,4(r23) ; Get the second half
269
270 aaLdNotDbl: mr r4,r0 ; Save the DAR if we failed the access
271
272 mtmsr r30 ; Turn off translation again
273 isync
274
275 bf- cr0_eq,aaRedriveAsDSI ; Go redrive this as a DSI...
276
277 stw r10,emfp0(r31) ; Save the first half
278 stw r11,emfp0+4(r31) ; Save the second half, just in case we need it
279
280 bctrl ; Go set the target FP register
281
282 b aaComExit ; All done, go exit...
283
284 ;
285 ; Here we handle floating point stores
286 ;
287
288 .align 5
289
290 aaFPstore: bctrl ; Go save the source FP register
291
292 lwz r10,emfp0(r31) ; Get first word
293 crandc iDouble,iDouble,iOptype4 ; Change to 4-byte access if stfiwx
294 lwz r11,emfp0+4(r31) ; and the second
295 bf+ iOptype4,aaNotstfiwx ; This is not a stfiwx...
296 mr r10,r11 ; The stfiwx wants to store the second half
297
298 aaNotstfiwx:
299 crset cr0_eq ; Set this to see if we failed
300 mtmsr r22 ; Flip DR, RI
301 isync
302
303 stw r10,0(r23) ; Save the first word
304 bf- cr0_eq,aaStNotDbl ; Jump out if we DSIed...
305 bf iDouble,aaStNotDbl ; this is not a double...
306 stw r11,4(r23) ; Save the second half
307
308 aaStNotDbl: mr r4,r0 ; Save the DAR if we failed the access
309 mtmsr r30 ; Turn off
310 isync
311
312 bf- cr0_eq,aaRedriveAsDSI ; Go redrive this as a DSI...
313
314 ;
315 ; Common exit routines
316 ;
317
318 aaComExit: lwz r10,savesrr0+4(r13) ; Get the failing instruction address
319 add r24,r24,r13 ; Offset to update register
320 li r11,T_IN_VAIN ; Assume we are all done
321 addi r10,r10,4 ; Step to the next instruction
322 bf iUpdate,aaComExNU ; Skip if not an update form...
323 stw r23,saver0+4(r24) ; Update the target
324
325 aaComExNU: lwz r9,SAVflags(r13) ; Get the flags
326 stw r10,savesrr0+4(r13) ; Set new PC
327 bt- traceInst,aaComExitrd ; We are tracing, go emulate trace...
328 bf+ iNotify,aaComExGo ; Nothing special here, go...
329
330 li r11,T_ALIGNMENT ; Set the we just did an alignment exception....
331
332 aaComExGo: b EXT(EmulExit) ; We are done, no tracing on...
333
334
335 ;
336 ; This is not a floating point operation
337 ;
338 ; The table of these emulation routines is indexed by taking the low order 4 bits of
339 ; the instruction code in the DSISR and subtracting 7. If this comes up negative,
340 ; the instruction is not to be emulated. Then we add bit 0 of the code * 4. This
341 ; gives us a fairly compact and almost unique index. Both lwm and stmw map to 0 so
342 ; that one needs to be further reduced, and we end up with holes at a few indexes.
343 ;
344
345 .align 5
346
347 aaNotFloat:
348 lis r19,hi16(aaEmTable) ; Point to high part of table address
349 rlwinm r3,r26,24,26,29 ; Isolate last 4 bits of op type * 4
350 rlwimi r19,r26,20,27,27 ; Get bit 0 of instruction code * 4 into bottom of table base
351 addic. r3,r3,-28 ; Subtract 7*4 to adjust index
352 ori r19,r19,lo16(aaEmTable) ; Low part of table address
353 blt- aaPassAlong ; We do not handle any of these (lwarx, stwcx., eciwx, ecowx)...
354 add r19,r19,r3 ; Point to emulation routine
355 rlwinm r18,r26,30,24,28 ; Get the target/source register displacement
356
357 mtctr r19 ; Set the routine address
358
359 bctr ; Go emulate the instruction...
360
361 ;
362 ; This is the table of non-floating point emulation routines.
363 ; It is indexed by the code immediately above.
364
365 .align 5
366
367 aaEmTable:
368 b aaLmwStmw ; This for lmw/stmw
369 b aaLswx ; This for lwwx
370 b aaLswi ; This for lswi
371 b aaStswx ; This for stswx
372 b aaStswi ; This for stswi
373 b aaLwbrx ; This for lwbrx
374 b aaPassAlong ; This an invalid index (6)
375 b aaStwbrx ; This for stwbrx
376 b aaPassAlong ; This an invalid index (8)
377 b aaLhbrx ; This for lhbrx
378 b aaPassAlong ; This an invalid index (A)
379 b aaSthbrx ; This for sthbrx
380 b aaDcbz ; This for dcbz
381 b aaPassAlong ; This an invalid index (D)
382 b aaPassAlong ; This an invalid index (E)
383 b aaPassAlong ; This an invalid index (F)
384
385
386 ;
387 ; Here we handle the set up for the lmw and stmw. After that, we split off to the
388 ; individual routines.
389 ;
390 ; Note also that after some set up, all of the string instructions come through here as well.
391 ;
392 .align 5
393
394 aaLmwStmw:
395 rlwinm r17,r18,31,1,29 ; Convert doublword based index to words
396 li r28,0 ; Set no extra bytes to move (used for string instructions)
397 subfic r17,r17,32*4 ; Calculate the length of the transfer
398
399 aaLSComm: addi r19,r13,saver0+4 ; Offset to registers in savearea
400 mr r16,r23 ; Make a hunk pointer
401
402 bt iUpdate,aaStmw ; This is the stmw...
403
404 ;
405 ; Load multiple word
406 ;
407
408 aaLmwNxt: cmplwi cr1,r17,8*4 ; Is there enough to move 8?
409 blt- cr1,aaLmwNxtH ; Not enough for a full hunk...
410 subi r17,r17,8*4 ; Back off for another hunk
411
412 crset cr0_eq ; Set this to see if we failed
413 mtmsr r22 ; Flip DR, RI
414 isync
415
416 lwz r2,0(r16) ; Load word 0
417 bf- cr0_eq,aaLmwB1 ; Error, bail...
418 lwz r15,4(r16) ; Load word 1
419 bf- cr0_eq,aaLmwB1 ; Error, bail...
420 lwz r14,8(r16) ; Load word 2
421 bf- cr0_eq,aaLmwB1 ; Error, bail...
422 lwz r5,12(r16) ; Load word 3
423 bf- cr0_eq,aaLmwB1 ; Error, bail...
424 lwz r6,16(r16) ; Load word 4
425 bf- cr0_eq,aaLmwB1 ; Error, bail...
426 lwz r7,20(r16) ; Load word 5
427 bf- cr0_eq,aaLmwB1 ; Error, bail...
428 lwz r8,24(r16) ; Load word 6
429 bf- cr0_eq,aaLmwB1 ; Error, bail...
430 lwz r9,28(r16) ; Load word 7
431
432 aaLmwB1: mr r4,r0 ; Remember DAR, jus in case we failed the access
433 mtmsr r30 ; Turn off DR, RI
434 isync
435
436 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
437
438 addi r16,r16,8*4 ; Point up to next input aread
439
440 stwx r2,r19,r18 ; Store register
441 addi r18,r18,8 ; Next register
442 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
443 stwx r15,r19,r18 ; Store register
444 addi r18,r18,8 ; Next register
445 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
446 stwx r14,r19,r18 ; Store register
447 addi r18,r18,8 ; Next register
448 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
449 stwx r5,r19,r18 ; Store register
450 addi r18,r18,8 ; Next register
451 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
452 stwx r6,r19,r18 ; Store register
453 addi r18,r18,8 ; Next register
454 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
455 stwx r7,r19,r18 ; Store register
456 addi r18,r18,8 ; Next register
457 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
458 stwx r8,r19,r18 ; Store register
459 addi r18,r18,8 ; Next register
460 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
461 stwx r9,r19,r18 ; Store register
462 addi r18,r18,8 ; Next register
463 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
464
465 b aaLmwNxt ; Do the next hunk...
466
467 .align 5
468
469 aaLmwNxtH: cmplwi cr1,r17,4*4 ; Do we have 4 left?
470 blt cr1,aaLmwL4 ; Nope...
471
472 subi r17,r17,4*4 ; Set count properly
473
474 crset cr0_eq ; Set this to see if we failed
475 mtmsr r22 ; Flip DR, RI, and maybe PR on
476 isync
477
478 lwz r2,0(r16) ; Load word 0
479 bf- cr0_eq,aaLmwB2 ; Error, bail...
480 lwz r15,4(r16) ; Load word 1
481 bf- cr0_eq,aaLmwB2 ; Error, bail...
482 lwz r14,8(r16) ; Load word 2
483 bf- cr0_eq,aaLmwB2 ; Error, bail...
484 lwz r5,12(r16) ; Load word 3
485
486 aaLmwB2: mr r4,r0 ; Remember DAR, jus in case we failed the access
487 mtmsr r30 ; Turn off DR, RI
488 isync
489
490 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
491
492 addi r16,r16,4*4 ; Point up to next input aread
493
494 stwx r2,r19,r18 ; Store register
495 addi r18,r18,8 ; Next register
496 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
497 stwx r15,r19,r18 ; Store register
498 addi r18,r18,8 ; Next register
499 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
500 stwx r14,r19,r18 ; Store register
501 addi r18,r18,8 ; Next register
502 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
503 stwx r5,r19,r18 ; Store register
504 addi r18,r18,8 ; Next register
505 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
506
507 aaLmwL4: or. r5,r17,r28 ; Do we have anything left?
508 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three full words left?
509 cmplwi cr2,r17,0 ; Do we have no full words left?
510 beq aaComExit ; Nothing left...
511
512 crset cr0_eq ; Set this to see if we failed
513 mtmsr r22 ; Flip DR, RI, and maybe PR on
514 isync
515
516 beq- cr2,aaLmwBy ; No full words, get bytes...
517
518 lwz r2,0(r16) ; Pick up first word
519 bf- cr0_eq,aaLmwDn ; Read failed, escape...
520 addi r16,r16,4 ; Next input location
521 blt cr1,aaLmwBy ; We only had one, we are done...
522
523 lwz r15,0(r16) ; Pick up second word
524 bf- cr0_eq,aaLmwDn ; Read failed, escape...
525 addi r16,r16,4 ; Next input location
526 beq cr1,aaLmwBy ; We had two, we are done...
527
528 lwz r14,0(r16) ; Load word 3
529 addi r16,r16,4 ; Next input location
530
531 aaLmwBy: cmplwi cr2,r28,0 ; Any trailing bytes to do?
532 li r8,0 ; Clear second trailing byte
533 cmplwi cr1,r28,2 ; Check for 1, 2, or 3
534 li r9,0 ; Clear third trailing byte
535 beq+ cr2,aaLmwDn ; No trailing bytes...
536
537 lbz r5,0(r16) ; Pick up first trailing byte
538 bf- cr0_eq,aaLmwDn ; Read failed, escape...
539 blt cr1,aaLmwDn ; We only had one, we are done...
540
541 lbz r8,1(r16) ; Pick up second trailing byte
542 bf- cr0_eq,aaLmwDn ; Read failed, escape...
543 beq cr1,aaLmwDn ; We had two, we are done...
544
545 lbz r9,2(r16) ; Get last trailing byte
546
547
548 aaLmwDn: rlwinm r5,r5,24,0,7 ; Move first byte to top
549 cmplwi cr2,r17,0 ; Any full words to do?
550 mr r4,r0 ; Remember DAR, just in case we failed the access
551 rlwimi r9,r8,8,16,23 ; Move second byte above third byte
552 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three full words left?
553 mr r3,r30 ; Set the normal MSR
554 rlwimi r5,r9,8,8,23 ; Move bytes 1 and 2 after 0
555
556 mtmsr r30 ; Turn off DR, RI
557 isync
558
559 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
560
561 beq- cr2,aaLmwCb ; No full words, copy bytes...
562
563 stwx r2,r19,r18 ; Store register
564 addi r18,r18,8 ; Next register
565 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
566 blt cr1,aaLmwCb ; We only had one, we are done...
567
568 stwx r15,r19,r18 ; Store register
569 addi r18,r18,8 ; Next register
570 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
571 beq cr1,aaLmwCb ; We had two, we are done...
572
573 stwx r14,r19,r18 ; Store register
574 addi r18,r18,8 ; Next register
575 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
576
577 aaLmwCb: mr. r28,r28 ; Any trailing bytes to do?
578 beq+ aaComExit ; Nope, leave...
579
580 stwx r5,r19,r18 ; Store register
581
582 b aaComExit ; We are done....
583
584 ;
585 ; Store multiple word
586 ;
587
588 .align 5
589
590 aaStmw:
591 crclr iUpdate ; Make sure we do not think this is an update form
592
593 aaStmwNxt: cmplwi cr1,r17,8*4 ; Is there enough to move 8?
594 blt- cr1,aaStmwNxtH ; Not enough for a full hunk...
595 subi r17,r17,8*4 ; Back off for another hunk
596
597 lwzx r2,r19,r18 ; Store register
598 addi r18,r18,8 ; Next register
599 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
600 lwzx r15,r19,r18 ; Store register
601 addi r18,r18,8 ; Next register
602 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
603 lwzx r14,r19,r18 ; Store register
604 addi r18,r18,8 ; Next register
605 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
606 lwzx r5,r19,r18 ; Store register
607 addi r18,r18,8 ; Next register
608 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
609 lwzx r6,r19,r18 ; Store register
610 addi r18,r18,8 ; Next register
611 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
612 lwzx r7,r19,r18 ; Store register
613 addi r18,r18,8 ; Next register
614 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
615 lwzx r8,r19,r18 ; Store register
616 addi r18,r18,8 ; Next register
617 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
618 lwzx r9,r19,r18 ; Store register
619 addi r18,r18,8 ; Next register
620 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
621
622 crset cr0_eq ; Set this to see if we failed
623 mtmsr r22 ; Flip DR, RI, and maybe PR on
624 isync
625
626 stw r2,0(r16) ; Store word 0
627 bf- cr0_eq,aaStmwB1 ; Error, bail...
628 stw r15,4(r16) ; Store word 1
629 bf- cr0_eq,aaStmwB1 ; Error, bail...
630 stw r14,8(r16) ; Store word 2
631 bf- cr0_eq,aaStmwB1 ; Error, bail...
632 stw r5,12(r16) ; Store word 3
633 bf- cr0_eq,aaStmwB1 ; Error, bail...
634 stw r6,16(r16) ; Store word 4
635 bf- cr0_eq,aaStmwB1 ; Error, bail...
636 stw r7,20(r16) ; Store word 5
637 bf- cr0_eq,aaStmwB1 ; Error, bail...
638 stw r8,24(r16) ; Store word 6
639 bf- cr0_eq,aaStmwB1 ; Error, bail...
640 stw r9,28(r16) ; Store word 7
641
642 addi r16,r16,8*4 ; Point up to next output aread
643
644
645 aaStmwB1: mr r4,r0 ; Remember DAR, jus in case we failed the access
646 mtmsr r30 ; Normal MSR
647 isync
648
649 bt- cr0_eq,aaStmwNxt ; We have more to do and no failed access...
650 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
651
652 .align 5
653
654 aaStmwNxtH: cmplwi cr1,r17,(4*4) ; Do we have at least 4 left?
655 blt cr1,aaStmwL4 ; Nope...
656 subi r17,r17,4*4 ; Set count properly
657
658 lwzx r2,r19,r18 ; Store register
659 addi r18,r18,8 ; Next register
660 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
661 lwzx r15,r19,r18 ; Store register
662 addi r18,r18,8 ; Next register
663 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
664 lwzx r14,r19,r18 ; Store register
665 addi r18,r18,8 ; Next register
666 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
667 lwzx r5,r19,r18 ; Store register
668 addi r18,r18,8 ; Next register
669 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
670
671 crset cr0_eq ; Set this to see if we failed
672 mtmsr r22 ; Flip DR, RI
673 isync
674
675 stw r2,0(r16) ; Store word 0
676 bf- cr0_eq,aaStmwB2 ; Error, bail...
677 stw r15,4(r16) ; Store word 1
678 bf- cr0_eq,aaStmwB2 ; Error, bail...
679 stw r14,8(r16) ; Store word 2
680 bf- cr0_eq,aaStmwB2 ; Error, bail...
681 stw r5,12(r16) ; Store word 3
682
683 addi r16,r16,4*4 ; Point up to next input aread
684
685 aaStmwB2: mr r4,r0 ; Remember DAR, jus in case we failed the access
686 mtmsr r30 ; Normal MSR
687 isync
688
689 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
690
691 aaStmwL4: or. r5,r17,r28 ; Do we have anything left to do?
692 cmplwi cr1,r17,(2*4) ; Do we have one, two, or three left?
693 cmplwi cr2,r17,0 ; Do we have no full words left?
694 beq aaComExit ; Nothing left...
695
696 beq- cr2,aaStmwBy1 ; No full words, check out bytes
697
698 lwzx r2,r19,r18 ; Store register
699 addi r18,r18,8 ; Next register
700 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
701 blt cr1,aaStmwBy1 ; We only had one, go save it...
702
703 lwzx r15,r19,r18 ; Store register
704 addi r18,r18,8 ; Next register
705 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
706 beq cr1,aaStmwBy1 ; We had two, go save it...
707
708 lwzx r14,r19,r18 ; Store register
709 addi r18,r18,8 ; Next register
710 rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed
711
712 aaStmwBy1: mr. r28,r28 ; Do we have any trailing bytes?
713 beq+ aaStmwSt ; Nope...
714
715 lwzx r5,r19,r18 ; Yes, pick up one extra register
716
717 aaStmwSt: crset cr0_eq ; Set this to see if we failed
718 mtmsr r22 ; Flip DR, RI
719 isync
720
721 beq- cr2,aaStmwBy2 ; No words, check trailing bytes...
722
723 stw r2,0(r16) ; Save first word
724 bf- cr0_eq,aaStmwDn ; Store failed, escape...
725 addi r16,r16,4 ; Bump sink
726 blt cr1,aaStmwBy2 ; We only had one, we are done...
727
728 stw r15,0(r16) ; Save second word
729 bf- cr0_eq,aaStmwDn ; Store failed, escape...
730 addi r16,r16,4 ; Bump sink
731 beq cr1,aaStmwBy2 ; We had two, we are done...
732
733 stw r14,0(r16) ; Save third word
734 bf- cr0_eq,aaStmwDn ; Store failed, escape...
735 addi r16,r16,4 ; Bump sink
736
737 aaStmwBy2: rlwinm r2,r5,8,24,31 ; Get byte 0
738 cmplwi cr2,r28,0 ; Any trailing bytes to do?
739 rlwinm r14,r5,24,24,31 ; Get byte 3
740 li r8,0 ; Clear second trailing byte
741 cmplwi cr1,r28,2 ; Check for 1, 2, or 3
742 li r9,0 ; Clear third trailing byte
743 beq+ cr2,aaStmwDn ; No trailing bytes...
744 rlwinm r15,r5,16,24,31 ; Get byte 1
745
746 stb r2,0(r16) ; Save first byte
747 bf- cr0_eq,aaStmwDn ; Read failed, escape...
748 blt cr1,aaStmwDn ; We only had one, we are done...
749
750 stb r15,1(r16) ; Save second byte
751 bf- cr0_eq,aaStmwDn ; Read failed, escape...
752 beq cr1,aaStmwDn ; We had two, we are done...
753
754 stb r14,2(r16) ; Save third byte
755
756 aaStmwDn: mr r4,r0 ; Remember DAR, jus in case we failed the access
757 mtmsr r30 ; Normal MSR
758 isync
759
760 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
761
762 b aaComExit ; We are done....
763
764
765 ;
766 ; Load String Indexed
767 ;
768
769 .align 5
770
771 aaLswx: lwz r17,savexer+4(r13) ; Pick up the XER
772 crclr iUpdate ; Make sure we think this the load form
773 rlwinm. r25,r17,0,25,31 ; Get the number of bytes to load
774 rlwinm r28,r17,0,30,31 ; Get the number of bytes past an even word
775 beq- aaComExit ; Do nothing if 0 length...
776 xor r17,r25,r28 ; Round down to an even word boundary
777 b aaLSComm ; Join up with common load/store code...
778
779
780 ;
781 ; Load String Immediate
782 ;
783
784 .align 5
785
786 aaLswi: mr r9,r23 ; Save the DAR
787 bl eIFetch ; Get the instruction image
788 bne- eRedriveAsISI ; Go redrive this as an ISI...
789 rlwinm r25,r10,21,27,31 ; Get the number of bytes to load
790 crclr iUpdate ; Make sure we think this the load form
791 subi r25,r25,1 ; Back off by 1
792 rlwinm r25,r25,0,27,31 ; Clear back down
793 addi r25,r25,1 ; Add back the 1 to convert 0 to 32
794 rlwinm r28,r25,0,30,31 ; Get the number of bytes past an even word
795 xor r17,r25,r28 ; Round down to an even word boundary
796 mr r23,r9 ; Move back the DAR
797 b aaLSComm ; Join up with common load/store code...
798
799 ;
800 ; Store String Indexed
801 ;
802
803 .align 5
804
805 aaStswx: lwz r17,savexer+4(r13) ; Pick up the XER
806 crclr iUpdate ; Make sure this is clear in case we have 0 length
807 rlwinm. r25,r17,0,25,31 ; Get the number of bytes to load
808 rlwinm r28,r17,0,30,31 ; Get the number of bytes past an even word
809 beq- aaComExit ; Do nothing if 0 length...
810 xor r17,r25,r28 ; Round down to an even word boundary
811 crset iUpdate ; Make sure we think this the store form
812 b aaLSComm ; Join up with common load/store code...
813
814
815 ;
816 ; Store String Immediate
817 ;
818
819 .align 5
820
821 aaStswi: mr r9,r23 ; Save the DAR
822 bl eIFetch ; Get the instruction image
823 bne- eRedriveAsISI ; Go redrive this as an ISI...
824 rlwinm r25,r10,21,27,31 ; Get the number of bytes to load
825 crclr iUpdate ; Make sure we think this the load form
826 subi r25,r25,1 ; Back off by 1
827 rlwinm r25,r25,0,27,31 ; Clear back down
828 addi r25,r25,1 ; Add back the 1 to convert 0 to 32
829 rlwinm r28,r25,21,30,31 ; Get the number of bytes past an even word
830 xor r17,r25,r28 ; Round down to an even word boundary
831 mr r23,r9 ; Move back the DAR
832 b aaLSComm ; Join up with common load/store code...
833
834
835 ;
836 ; Load byte-reversed word
837 ;
838
839 .align 5
840
841 aaLwbrx:
842 add r18,r18,r13 ; Index to source register
843
844 crset cr0_eq ; Set this to see if we failed
845 mtmsr r22 ; Flip DR, RI, and maybe PR on
846 isync
847
848 lwz r11,0(r23) ; Load the word
849
850 mr r4,r0 ; Save the DAR if we failed the access
851 mtmsr r30 ; Restore normal MSR
852 isync
853
854 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
855
856 rlwinm r10,r11,8,0,31 ; Get byte 0 to 3 and byte 2 to 1
857 rlwimi r10,r11,24,16,23 ; Move byte 1 to byte 2
858 rlwimi r10,r11,24,0,7 ; Move byte 3 to byte 0
859
860 stw r10,saver0+4(r18) ; Set the register
861
862 b aaComExit ; All done, go exit...
863
864
865
866 ;
867 ; Store byte-reversed word
868 ;
869
870 .align 5
871
872 aaStwbrx:
873 add r18,r18,r13 ; Index to source register
874 lwz r11,saver0+4(r18) ; Get the register to store
875
876 rlwinm r10,r11,8,0,31 ; Get byte 0 to 3 and byte 2 to 1
877 rlwimi r10,r11,24,16,23 ; Move byte 1 to byte 2
878 rlwimi r10,r11,24,0,7 ; Move byte 3 to byte 0
879
880 crset cr0_eq ; Set this to see if we failed
881 mtmsr r22 ; Flip DR, RI, and maybe PR on
882 isync
883
884 stw r10,0(r23) ; Store the reversed halfword
885
886 mr r4,r0 ; Save the DAR if we failed the access
887 mtmsr r30 ; Restore normal MSR
888 isync
889
890 bt+ cr0_eq,aaComExit ; All done, go exit...
891 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
892
893
894
895 ;
896 ; Load byte-reversed halfword
897 ;
898
899 .align 5
900
901 aaLhbrx:
902 add r18,r18,r13 ; Index to source register
903
904 crset cr0_eq ; Set this to see if we failed
905 mtmsr r22 ; Flip DR, RI, and maybe PR on
906 isync
907
908 lhz r11,0(r23) ; Load the halfword
909
910 mr r4,r0 ; Save the DAR if we failed the access
911 mtmsr r30 ; Restore normal MSR
912 isync
913
914 bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI...
915
916 rlwinm r10,r11,8,16,23 ; Rotate bottom byte up one and clear everything else
917 rlwimi r10,r11,24,24,31 ; Put old second from bottom into bottom
918
919 stw r10,saver0+4(r18) ; Set the register
920
921 b aaComExit ; All done, go exit...
922
923
924 ;
925 ; Store byte-reversed halfword
926 ;
927
928 .align 5
929
930 aaSthbrx:
931 add r18,r18,r13 ; Index to source register
932 lwz r10,saver0+4(r18) ; Get the register to store
933 rlwinm r10,r10,8,0,31 ; Rotate bottom byte up one
934 rlwimi r10,r10,16,24,31 ; Put old second from bottom into bottom
935
936 crset cr0_eq ; Set this to see if we failed
937 mtmsr r22 ; Flip DR, RI, and maybe PR on
938 isync
939
940 sth r10,0(r23) ; Store the reversed halfword
941
942 mr r4,r0 ; Save the DAR if we failed the access
943 mtmsr r30 ; Restore normal MSR
944 isync
945
946 bt+ cr0_eq,aaComExit ; All done, go exit...
947 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
948
949 ;
950 ; Data cache block zero
951 ;
952
953 .align 5
954
955 aaDcbz:
956 lwz r0,savesrr0+4(r13) ; get instruction address
957 li r4,_COMM_PAGE_BASE_ADDRESS
958 rlwinm r23,r23,0,0,26 ; Round EA back to a 32-byte boundary
959 sub r4,r0,r4 ; compute instruction offset from base of commpage
960 cmplwi r4,_COMM_PAGE_AREA_USED ; did fault occur in commpage?
961 bge+ aaDcbz1 ; skip if not in commpage
962 lwz r4,savecr(r13) ; if we take a dcbz in the commpage...
963 rlwinm r4,r4,0,0,27 ; ...clear users cr7 as a flag for commpage code
964 stw r4,savecr(r13)
965 aaDcbz1:
966 crset cr0_eq ; Set this to see if we failed
967 li r0,0 ; Clear this out
968 mtmsr r22 ; Flip DR, RI, and maybe PR on
969 isync
970
971 stw r0,0(r23) ; Clear word
972 bne- aaDcbzXit ; Got DSI, we are stopping...
973 stw r0,4(r23) ; Clear word
974 bne- aaDcbzXit ; Got DSI, we are stopping...
975 stw r0,8(r23) ; Clear word
976 bne- aaDcbzXit ; Got DSI, we are stopping...
977 stw r0,12(r23) ; Clear word
978 bne- aaDcbzXit ; Got DSI, we are stopping...
979 stw r0,16(r23) ; Clear word
980 bne- aaDcbzXit ; Got DSI, we are stopping...
981 stw r0,20(r23) ; Clear word
982 bne- aaDcbzXit ; Got DSI, we are stopping...
983 stw r0,24(r23) ; Clear word
984 bne- aaDcbzXit ; Got DSI, we are stopping...
985 stw r0,28(r23) ; Clear word
986
987 aaDcbzXit: mr r4,r0 ; Save the DAR if we failed the access
988 mtmsr r30 ; Restore normal MSR
989 isync
990
991 crclr iUpdate ; Make sure we do not think this is an update form
992
993 bt+ cr0_eq,aaComExit ; All done, go exit...
994 b aaRedriveAsDSI ; We failed, go redrive this as a DSI...
995
996
997 ;
998 ; Unhandled alignment exception, pass it along
999 ;
1000
1001 aaPassAlong:
1002 li r0,1 ; Indicate that we failed to emulate
1003 stw r0,savemisc3(r13) ; Assume that we emulate ok
1004 b EXT(EmulExit)
1005
1006
1007
1008
1009 ;
1010 ; We go here to emulate a trace exception after we have handled alignment error
1011 ;
1012
1013 .align 5
1014
1015 aaComExitrd:
1016 oris r9,r9,hi16(SAVredrive) ; Set the redrive bit
1017 li r11,T_TRACE ; Set trace interrupt
1018 rlwinm r12,r12,0,16,31 ; Clear top half of SRR1
1019 stw r9,SAVflags(r13) ; Set the flags
1020 stw r11,saveexception(r13) ; Set the exception code
1021 b EXT(EmulExit) ; Exit and do trace interrupt...
1022
1023
1024
1025 ;
1026 ; Redrive as a DSI
1027
1028 aaRedriveAsDSI:
1029 mr r20,r1 ; Save the DSISR
1030 mr r21,r4
1031 lwz r4,SAVflags(r13) ; Pick up the flags
1032 li r11,T_DATA_ACCESS ; Set failing data access code
1033 oris r4,r4,hi16(SAVredrive) ; Set the redrive bit
1034 stw r20,savedsisr(r13) ; Set the DSISR of failed access
1035 stw r21,savedar+4(r13) ; Set the address of the failed access
1036 stw r11,saveexception(r13) ; Set the replacement code
1037 stw r4,SAVflags(r13) ; Set redrive request
1038 b EXT(EmulExit) ; Bail out to handle ISI...
1039
1040
1041
1042 ;
1043 ; Table of functions to load or store floating point registers
1044 ; This table is indexed reg||size||dir. That means that each
1045 ; like load/store pair (e.g., lfd f31/stfd f31) are within the same
1046 ; quadword, which is the current ifetch size. We expect most of the
1047 ; unaligned accesses to be part of copies, therefore, with this
1048 ; organization, we will save the ifetch of the store after the load.
1049 ;
1050
1051 .align 10 ; Make sure we are on a 1k boundary
1052 .globl EXT(aaFPopTable)
1053
1054 LEXT(aaFPopTable)
1055 lfs f0,emfp0(r31) ; Load single variant
1056 blr
1057
1058 stfs f0,emfp0(r31) ; Store single variant
1059 blr
1060
1061 lfd f0,emfp0(r31) ; Load double variant
1062 blr
1063
1064 stfd f0,emfp0(r31) ; Store double variant
1065 blr
1066
1067 lfs f1,emfp0(r31) ; Load single variant
1068 blr
1069
1070 stfs f1,emfp0(r31) ; Store single variant
1071 blr
1072
1073 lfd f1,emfp0(r31) ; Load double variant
1074 blr
1075
1076 stfd f1,emfp0(r31) ; Store double variant
1077 blr
1078
1079 lfs f2,emfp0(r31) ; Load single variant
1080 blr
1081
1082 stfs f2,emfp0(r31) ; Store single variant
1083 blr
1084
1085 lfd f2,emfp0(r31) ; Load double variant
1086 blr
1087
1088 stfd f2,emfp0(r31) ; Store double variant
1089 blr
1090
1091 lfs f3,emfp0(r31) ; Load single variant
1092 blr
1093
1094 stfs f3,emfp0(r31) ; Store single variant
1095 blr
1096
1097 lfd f3,emfp0(r31) ; Load double variant
1098 blr
1099
1100 stfd f3,emfp0(r31) ; Store double variant
1101 blr
1102
1103 lfs f4,emfp0(r31) ; Load single variant
1104 blr
1105
1106 stfs f4,emfp0(r31) ; Store single variant
1107 blr
1108
1109 lfd f4,emfp0(r31) ; Load double variant
1110 blr
1111
1112 stfd f4,emfp0(r31) ; Store double variant
1113 blr
1114
1115 lfs f5,emfp0(r31) ; Load single variant
1116 blr
1117
1118 stfs f5,emfp0(r31) ; Store single variant
1119 blr
1120
1121 lfd f5,emfp0(r31) ; Load double variant
1122 blr
1123
1124 stfd f5,emfp0(r31) ; Store double variant
1125 blr
1126
1127 lfs f6,emfp0(r31) ; Load single variant
1128 blr
1129
1130 stfs f6,emfp0(r31) ; Store single variant
1131 blr
1132
1133 lfd f6,emfp0(r31) ; Load double variant
1134 blr
1135
1136 stfd f6,emfp0(r31) ; Store double variant
1137 blr
1138
1139 lfs f7,emfp0(r31) ; Load single variant
1140 blr
1141
1142 stfs f7,emfp0(r31) ; Store single variant
1143 blr
1144
1145 lfd f7,emfp0(r31) ; Load double variant
1146 blr
1147
1148 stfd f7,emfp0(r31) ; Store double variant
1149 blr
1150
1151 lfs f8,emfp0(r31) ; Load single variant
1152 blr
1153
1154 stfs f8,emfp0(r31) ; Store single variant
1155 blr
1156
1157 lfd f8,emfp0(r31) ; Load double variant
1158 blr
1159
1160 stfd f8,emfp0(r31) ; Store double variant
1161 blr
1162
1163 lfs f9,emfp0(r31) ; Load single variant
1164 blr
1165
1166 stfs f9,emfp0(r31) ; Store single variant
1167 blr
1168
1169 lfd f9,emfp0(r31) ; Load double variant
1170 blr
1171
1172 stfd f9,emfp0(r31) ; Store double variant
1173 blr
1174
1175 lfs f10,emfp0(r31) ; Load single variant
1176 blr
1177
1178 stfs f10,emfp0(r31) ; Store single variant
1179 blr
1180
1181 lfd f10,emfp0(r31) ; Load double variant
1182 blr
1183
1184 stfd f10,emfp0(r31) ; Store double variant
1185 blr
1186
1187 lfs f11,emfp0(r31) ; Load single variant
1188 blr
1189
1190 stfs f11,emfp0(r31) ; Store single variant
1191 blr
1192
1193 lfd f11,emfp0(r31) ; Load double variant
1194 blr
1195
1196 stfd f11,emfp0(r31) ; Store double variant
1197 blr
1198
1199 lfs f12,emfp0(r31) ; Load single variant
1200 blr
1201
1202 stfs f12,emfp0(r31) ; Store single variant
1203 blr
1204
1205 lfd f12,emfp0(r31) ; Load double variant
1206 blr
1207
1208 stfd f12,emfp0(r31) ; Store double variant
1209 blr
1210
1211 lfs f13,emfp0(r31) ; Load single variant
1212 blr
1213
1214 stfs f13,emfp0(r31) ; Store single variant
1215 blr
1216
1217 lfd f13,emfp0(r31) ; Load double variant
1218 blr
1219
1220 stfd f13,emfp0(r31) ; Store double variant
1221 blr
1222
1223 lfs f14,emfp0(r31) ; Load single variant
1224 blr
1225
1226 stfs f14,emfp0(r31) ; Store single variant
1227 blr
1228
1229 lfd f14,emfp0(r31) ; Load double variant
1230 blr
1231
1232 stfd f14,emfp0(r31) ; Store double variant
1233 blr
1234
1235 lfs f15,emfp0(r31) ; Load single variant
1236 blr
1237
1238 stfs f15,emfp0(r31) ; Store single variant
1239 blr
1240
1241 lfd f15,emfp0(r31) ; Load double variant
1242 blr
1243
1244 stfd f15,emfp0(r31) ; Store double variant
1245 blr
1246
1247 lfs f16,emfp0(r31) ; Load single variant
1248 blr
1249
1250 stfs f16,emfp0(r31) ; Store single variant
1251 blr
1252
1253 lfd f16,emfp0(r31) ; Load double variant
1254 blr
1255
1256 stfd f16,emfp0(r31) ; Store double variant
1257 blr
1258
1259 lfs f17,emfp0(r31) ; Load single variant
1260 blr
1261
1262 stfs f17,emfp0(r31) ; Store single variant
1263 blr
1264
1265 lfd f17,emfp0(r31) ; Load double variant
1266 blr
1267
1268 stfd f17,emfp0(r31) ; Store double variant
1269 blr
1270
1271 lfs f18,emfp0(r31) ; Load single variant
1272 blr
1273
1274 stfs f18,emfp0(r31) ; Store single variant
1275 blr
1276
1277 lfd f18,emfp0(r31) ; Load double variant
1278 blr
1279
1280 stfd f18,emfp0(r31) ; Store double variant
1281 blr
1282
1283 lfs f19,emfp0(r31) ; Load single variant
1284 blr
1285
1286 stfs f19,emfp0(r31) ; Store single variant
1287 blr
1288
1289 lfd f19,emfp0(r31) ; Load double variant
1290 blr
1291
1292 stfd f19,emfp0(r31) ; Store double variant
1293 blr
1294
1295 lfs f20,emfp0(r31) ; Load single variant
1296 blr
1297
1298 stfs f20,emfp0(r31) ; Store single variant
1299 blr
1300
1301 lfd f20,emfp0(r31) ; Load double variant
1302 blr
1303
1304 stfd f20,emfp0(r31) ; Store double variant
1305 blr
1306
1307 lfs f21,emfp0(r31) ; Load single variant
1308 blr
1309
1310 stfs f21,emfp0(r31) ; Store single variant
1311 blr
1312
1313 lfd f21,emfp0(r31) ; Load double variant
1314 blr
1315
1316 stfd f21,emfp0(r31) ; Store double variant
1317 blr
1318
1319 lfs f22,emfp0(r31) ; Load single variant
1320 blr
1321
1322 stfs f22,emfp0(r31) ; Store single variant
1323 blr
1324
1325 lfd f22,emfp0(r31) ; Load double variant
1326 blr
1327
1328 stfd f22,emfp0(r31) ; Store double variant
1329 blr
1330
1331 lfs f23,emfp0(r31) ; Load single variant
1332 blr
1333
1334 stfs f23,emfp0(r31) ; Store single variant
1335 blr
1336
1337 lfd f23,emfp0(r31) ; Load double variant
1338 blr
1339
1340 stfd f23,emfp0(r31) ; Store double variant
1341 blr
1342
1343 lfs f24,emfp0(r31) ; Load single variant
1344 blr
1345
1346 stfs f24,emfp0(r31) ; Store single variant
1347 blr
1348
1349 lfd f24,emfp0(r31) ; Load double variant
1350 blr
1351
1352 stfd f24,emfp0(r31) ; Store double variant
1353 blr
1354
1355 lfs f25,emfp0(r31) ; Load single variant
1356 blr
1357
1358 stfs f25,emfp0(r31) ; Store single variant
1359 blr
1360
1361 lfd f25,emfp0(r31) ; Load double variant
1362 blr
1363
1364 stfd f25,emfp0(r31) ; Store double variant
1365 blr
1366
1367 lfs f26,emfp0(r31) ; Load single variant
1368 blr
1369
1370 stfs f26,emfp0(r31) ; Store single variant
1371 blr
1372
1373 lfd f26,emfp0(r31) ; Load double variant
1374 blr
1375
1376 stfd f26,emfp0(r31) ; Store double variant
1377 blr
1378
1379 lfs f27,emfp0(r31) ; Load single variant
1380 blr
1381
1382 stfs f27,emfp0(r31) ; Store single variant
1383 blr
1384
1385 lfd f27,emfp0(r31) ; Load double variant
1386 blr
1387
1388 stfd f27,emfp0(r31) ; Store double variant
1389 blr
1390
1391 lfs f28,emfp0(r31) ; Load single variant
1392 blr
1393
1394 stfs f28,emfp0(r31) ; Store single variant
1395 blr
1396
1397 lfd f28,emfp0(r31) ; Load double variant
1398 blr
1399
1400 stfd f28,emfp0(r31) ; Store double variant
1401 blr
1402
1403 lfs f29,emfp0(r31) ; Load single variant
1404 blr
1405
1406 stfs f29,emfp0(r31) ; Store single variant
1407 blr
1408
1409 lfd f29,emfp0(r31) ; Load double variant
1410 blr
1411
1412 stfd f29,emfp0(r31) ; Store double variant
1413 blr
1414
1415 lfs f30,emfp0(r31) ; Load single variant
1416 blr
1417
1418 stfs f30,emfp0(r31) ; Store single variant
1419 blr
1420
1421 lfd f30,emfp0(r31) ; Load double variant
1422 blr
1423
1424 stfd f30,emfp0(r31) ; Store double variant
1425 blr
1426
1427 lfs f31,emfp0(r31) ; Load single variant
1428 blr
1429
1430 stfs f31,emfp0(r31) ; Store single variant
1431 blr
1432
1433 lfd f31,emfp0(r31) ; Load double variant
1434 blr
1435
1436 stfd f31,emfp0(r31) ; Store double variant
1437 blr
1438