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