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