xref: /OK3568_Linux_fs/kernel/arch/powerpc/lib/ldstfp.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun/*
3*4882a593Smuzhiyun * Floating-point, VMX/Altivec and VSX loads and stores
4*4882a593Smuzhiyun * for use in instruction emulation.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun#include <asm/processor.h>
10*4882a593Smuzhiyun#include <asm/ppc_asm.h>
11*4882a593Smuzhiyun#include <asm/ppc-opcode.h>
12*4882a593Smuzhiyun#include <asm/reg.h>
13*4882a593Smuzhiyun#include <asm/asm-offsets.h>
14*4882a593Smuzhiyun#include <asm/asm-compat.h>
15*4882a593Smuzhiyun#include <linux/errno.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun#define STKFRM	(PPC_MIN_STKFRM + 16)
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun/* Get the contents of frN into *p; N is in r3 and p is in r4. */
20*4882a593Smuzhiyun_GLOBAL(get_fpr)
21*4882a593Smuzhiyun	mflr	r0
22*4882a593Smuzhiyun	mfmsr	r6
23*4882a593Smuzhiyun	ori	r7, r6, MSR_FP
24*4882a593Smuzhiyun	MTMSRD(r7)
25*4882a593Smuzhiyun	isync
26*4882a593Smuzhiyun	rlwinm	r3,r3,3,0xf8
27*4882a593Smuzhiyun	bcl	20,31,1f
28*4882a593Smuzhiyunreg = 0
29*4882a593Smuzhiyun	.rept	32
30*4882a593Smuzhiyun	stfd	reg, 0(r4)
31*4882a593Smuzhiyun	b	2f
32*4882a593Smuzhiyunreg = reg + 1
33*4882a593Smuzhiyun	.endr
34*4882a593Smuzhiyun1:	mflr	r5
35*4882a593Smuzhiyun	add	r5,r3,r5
36*4882a593Smuzhiyun	mtctr	r5
37*4882a593Smuzhiyun	mtlr	r0
38*4882a593Smuzhiyun	bctr
39*4882a593Smuzhiyun2:	MTMSRD(r6)
40*4882a593Smuzhiyun	isync
41*4882a593Smuzhiyun	blr
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun/* Put the contents of *p into frN; N is in r3 and p is in r4. */
44*4882a593Smuzhiyun_GLOBAL(put_fpr)
45*4882a593Smuzhiyun	mflr	r0
46*4882a593Smuzhiyun	mfmsr	r6
47*4882a593Smuzhiyun	ori	r7, r6, MSR_FP
48*4882a593Smuzhiyun	MTMSRD(r7)
49*4882a593Smuzhiyun	isync
50*4882a593Smuzhiyun	rlwinm	r3,r3,3,0xf8
51*4882a593Smuzhiyun	bcl	20,31,1f
52*4882a593Smuzhiyunreg = 0
53*4882a593Smuzhiyun	.rept	32
54*4882a593Smuzhiyun	lfd	reg, 0(r4)
55*4882a593Smuzhiyun	b	2f
56*4882a593Smuzhiyunreg = reg + 1
57*4882a593Smuzhiyun	.endr
58*4882a593Smuzhiyun1:	mflr	r5
59*4882a593Smuzhiyun	add	r5,r3,r5
60*4882a593Smuzhiyun	mtctr	r5
61*4882a593Smuzhiyun	mtlr	r0
62*4882a593Smuzhiyun	bctr
63*4882a593Smuzhiyun2:	MTMSRD(r6)
64*4882a593Smuzhiyun	isync
65*4882a593Smuzhiyun	blr
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun#ifdef CONFIG_ALTIVEC
68*4882a593Smuzhiyun/* Get the contents of vrN into *p; N is in r3 and p is in r4. */
69*4882a593Smuzhiyun_GLOBAL(get_vr)
70*4882a593Smuzhiyun	mflr	r0
71*4882a593Smuzhiyun	mfmsr	r6
72*4882a593Smuzhiyun	oris	r7, r6, MSR_VEC@h
73*4882a593Smuzhiyun	MTMSRD(r7)
74*4882a593Smuzhiyun	isync
75*4882a593Smuzhiyun	rlwinm	r3,r3,3,0xf8
76*4882a593Smuzhiyun	bcl	20,31,1f
77*4882a593Smuzhiyunreg = 0
78*4882a593Smuzhiyun	.rept	32
79*4882a593Smuzhiyun	stvx	reg, 0, r4
80*4882a593Smuzhiyun	b	2f
81*4882a593Smuzhiyunreg = reg + 1
82*4882a593Smuzhiyun	.endr
83*4882a593Smuzhiyun1:	mflr	r5
84*4882a593Smuzhiyun	add	r5,r3,r5
85*4882a593Smuzhiyun	mtctr	r5
86*4882a593Smuzhiyun	mtlr	r0
87*4882a593Smuzhiyun	bctr
88*4882a593Smuzhiyun2:	MTMSRD(r6)
89*4882a593Smuzhiyun	isync
90*4882a593Smuzhiyun	blr
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun/* Put the contents of *p into vrN; N is in r3 and p is in r4. */
93*4882a593Smuzhiyun_GLOBAL(put_vr)
94*4882a593Smuzhiyun	mflr	r0
95*4882a593Smuzhiyun	mfmsr	r6
96*4882a593Smuzhiyun	oris	r7, r6, MSR_VEC@h
97*4882a593Smuzhiyun	MTMSRD(r7)
98*4882a593Smuzhiyun	isync
99*4882a593Smuzhiyun	rlwinm	r3,r3,3,0xf8
100*4882a593Smuzhiyun	bcl	20,31,1f
101*4882a593Smuzhiyunreg = 0
102*4882a593Smuzhiyun	.rept	32
103*4882a593Smuzhiyun	lvx	reg, 0, r4
104*4882a593Smuzhiyun	b	2f
105*4882a593Smuzhiyunreg = reg + 1
106*4882a593Smuzhiyun	.endr
107*4882a593Smuzhiyun1:	mflr	r5
108*4882a593Smuzhiyun	add	r5,r3,r5
109*4882a593Smuzhiyun	mtctr	r5
110*4882a593Smuzhiyun	mtlr	r0
111*4882a593Smuzhiyun	bctr
112*4882a593Smuzhiyun2:	MTMSRD(r6)
113*4882a593Smuzhiyun	isync
114*4882a593Smuzhiyun	blr
115*4882a593Smuzhiyun#endif /* CONFIG_ALTIVEC */
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun#ifdef CONFIG_VSX
118*4882a593Smuzhiyun/* Get the contents of vsN into vs0; N is in r3. */
119*4882a593Smuzhiyun_GLOBAL(get_vsr)
120*4882a593Smuzhiyun	mflr	r0
121*4882a593Smuzhiyun	rlwinm	r3,r3,3,0x1f8
122*4882a593Smuzhiyun	bcl	20,31,1f
123*4882a593Smuzhiyun	blr			/* vs0 is already in vs0 */
124*4882a593Smuzhiyun	nop
125*4882a593Smuzhiyunreg = 1
126*4882a593Smuzhiyun	.rept	63
127*4882a593Smuzhiyun	XXLOR(0,reg,reg)
128*4882a593Smuzhiyun	blr
129*4882a593Smuzhiyunreg = reg + 1
130*4882a593Smuzhiyun	.endr
131*4882a593Smuzhiyun1:	mflr	r5
132*4882a593Smuzhiyun	add	r5,r3,r5
133*4882a593Smuzhiyun	mtctr	r5
134*4882a593Smuzhiyun	mtlr	r0
135*4882a593Smuzhiyun	bctr
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun/* Put the contents of vs0 into vsN; N is in r3. */
138*4882a593Smuzhiyun_GLOBAL(put_vsr)
139*4882a593Smuzhiyun	mflr	r0
140*4882a593Smuzhiyun	rlwinm	r3,r3,3,0x1f8
141*4882a593Smuzhiyun	bcl	20,31,1f
142*4882a593Smuzhiyun	blr			/* v0 is already in v0 */
143*4882a593Smuzhiyun	nop
144*4882a593Smuzhiyunreg = 1
145*4882a593Smuzhiyun	.rept	63
146*4882a593Smuzhiyun	XXLOR(reg,0,0)
147*4882a593Smuzhiyun	blr
148*4882a593Smuzhiyunreg = reg + 1
149*4882a593Smuzhiyun	.endr
150*4882a593Smuzhiyun1:	mflr	r5
151*4882a593Smuzhiyun	add	r5,r3,r5
152*4882a593Smuzhiyun	mtctr	r5
153*4882a593Smuzhiyun	mtlr	r0
154*4882a593Smuzhiyun	bctr
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun/* Load VSX reg N from vector doubleword *p.  N is in r3, p in r4. */
157*4882a593Smuzhiyun_GLOBAL(load_vsrn)
158*4882a593Smuzhiyun	PPC_STLU r1,-STKFRM(r1)
159*4882a593Smuzhiyun	mflr	r0
160*4882a593Smuzhiyun	PPC_STL	r0,STKFRM+PPC_LR_STKOFF(r1)
161*4882a593Smuzhiyun	mfmsr	r6
162*4882a593Smuzhiyun	oris	r7,r6,MSR_VSX@h
163*4882a593Smuzhiyun	cmpwi	cr7,r3,0
164*4882a593Smuzhiyun	li	r8,STKFRM-16
165*4882a593Smuzhiyun	MTMSRD(r7)
166*4882a593Smuzhiyun	isync
167*4882a593Smuzhiyun	beq	cr7,1f
168*4882a593Smuzhiyun	STXVD2X(0,R1,R8)
169*4882a593Smuzhiyun1:	LXVD2X(0,R0,R4)
170*4882a593Smuzhiyun#ifdef __LITTLE_ENDIAN__
171*4882a593Smuzhiyun	XXSWAPD(0,0)
172*4882a593Smuzhiyun#endif
173*4882a593Smuzhiyun	beq	cr7,4f
174*4882a593Smuzhiyun	bl	put_vsr
175*4882a593Smuzhiyun	LXVD2X(0,R1,R8)
176*4882a593Smuzhiyun4:	PPC_LL	r0,STKFRM+PPC_LR_STKOFF(r1)
177*4882a593Smuzhiyun	mtlr	r0
178*4882a593Smuzhiyun	MTMSRD(r6)
179*4882a593Smuzhiyun	isync
180*4882a593Smuzhiyun	addi	r1,r1,STKFRM
181*4882a593Smuzhiyun	blr
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun/* Store VSX reg N to vector doubleword *p.  N is in r3, p in r4. */
184*4882a593Smuzhiyun_GLOBAL(store_vsrn)
185*4882a593Smuzhiyun	PPC_STLU r1,-STKFRM(r1)
186*4882a593Smuzhiyun	mflr	r0
187*4882a593Smuzhiyun	PPC_STL	r0,STKFRM+PPC_LR_STKOFF(r1)
188*4882a593Smuzhiyun	mfmsr	r6
189*4882a593Smuzhiyun	oris	r7,r6,MSR_VSX@h
190*4882a593Smuzhiyun	li	r8,STKFRM-16
191*4882a593Smuzhiyun	MTMSRD(r7)
192*4882a593Smuzhiyun	isync
193*4882a593Smuzhiyun	STXVD2X(0,R1,R8)
194*4882a593Smuzhiyun	bl	get_vsr
195*4882a593Smuzhiyun#ifdef __LITTLE_ENDIAN__
196*4882a593Smuzhiyun	XXSWAPD(0,0)
197*4882a593Smuzhiyun#endif
198*4882a593Smuzhiyun	STXVD2X(0,R0,R4)
199*4882a593Smuzhiyun	LXVD2X(0,R1,R8)
200*4882a593Smuzhiyun	PPC_LL	r0,STKFRM+PPC_LR_STKOFF(r1)
201*4882a593Smuzhiyun	mtlr	r0
202*4882a593Smuzhiyun	MTMSRD(r6)
203*4882a593Smuzhiyun	isync
204*4882a593Smuzhiyun	mr	r3,r9
205*4882a593Smuzhiyun	addi	r1,r1,STKFRM
206*4882a593Smuzhiyun	blr
207*4882a593Smuzhiyun#endif /* CONFIG_VSX */
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun/* Convert single-precision to double, without disturbing FPRs. */
210*4882a593Smuzhiyun/* conv_sp_to_dp(float *sp, double *dp) */
211*4882a593Smuzhiyun_GLOBAL(conv_sp_to_dp)
212*4882a593Smuzhiyun	mfmsr	r6
213*4882a593Smuzhiyun	ori	r7, r6, MSR_FP
214*4882a593Smuzhiyun	MTMSRD(r7)
215*4882a593Smuzhiyun	isync
216*4882a593Smuzhiyun	stfd	fr0, -16(r1)
217*4882a593Smuzhiyun	lfs	fr0, 0(r3)
218*4882a593Smuzhiyun	stfd	fr0, 0(r4)
219*4882a593Smuzhiyun	lfd	fr0, -16(r1)
220*4882a593Smuzhiyun	MTMSRD(r6)
221*4882a593Smuzhiyun	isync
222*4882a593Smuzhiyun	blr
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun/* Convert single-precision to double, without disturbing FPRs. */
225*4882a593Smuzhiyun/* conv_sp_to_dp(double *dp, float *sp) */
226*4882a593Smuzhiyun_GLOBAL(conv_dp_to_sp)
227*4882a593Smuzhiyun	mfmsr	r6
228*4882a593Smuzhiyun	ori	r7, r6, MSR_FP
229*4882a593Smuzhiyun	MTMSRD(r7)
230*4882a593Smuzhiyun	isync
231*4882a593Smuzhiyun	stfd	fr0, -16(r1)
232*4882a593Smuzhiyun	lfd	fr0, 0(r3)
233*4882a593Smuzhiyun	stfs	fr0, 0(r4)
234*4882a593Smuzhiyun	lfd	fr0, -16(r1)
235*4882a593Smuzhiyun	MTMSRD(r6)
236*4882a593Smuzhiyun	isync
237*4882a593Smuzhiyun	blr
238