Linux 4.11-rc5
[linux/fpc-iii.git] / arch / powerpc / lib / ldstfp.S
bloba58777c1b2cba79605290f7375412d16b0e9b516
1 /*
2  * Floating-point, VMX/Altivec and VSX loads and stores
3  * for use in instruction emulation.
4  *
5  * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
6  *
7  *  This program is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU General Public License
9  *  as published by the Free Software Foundation; either version
10  *  2 of the License, or (at your option) any later version.
11  */
13 #include <asm/processor.h>
14 #include <asm/ppc_asm.h>
15 #include <asm/ppc-opcode.h>
16 #include <asm/reg.h>
17 #include <asm/asm-offsets.h>
18 #include <linux/errno.h>
20 #ifdef CONFIG_PPC_FPU
22 #define STKFRM  (PPC_MIN_STKFRM + 16)
24         .macro  inst32  op
25 reg = 0
26         .rept   32
27 20:     \op     reg,0,r4
28         b       3f
29         EX_TABLE(20b,99f)
30 reg = reg + 1
31         .endr
32         .endm
34 /* Get the contents of frN into fr0; N is in r3. */
35 _GLOBAL(get_fpr)
36         mflr    r0
37         rlwinm  r3,r3,3,0xf8
38         bcl     20,31,1f
39         blr                     /* fr0 is already in fr0 */
40         nop
41 reg = 1
42         .rept   31
43         fmr     fr0,reg
44         blr
45 reg = reg + 1
46         .endr
47 1:      mflr    r5
48         add     r5,r3,r5
49         mtctr   r5
50         mtlr    r0
51         bctr
53 /* Put the contents of fr0 into frN; N is in r3. */
54 _GLOBAL(put_fpr)
55         mflr    r0
56         rlwinm  r3,r3,3,0xf8
57         bcl     20,31,1f
58         blr                     /* fr0 is already in fr0 */
59         nop
60 reg = 1
61         .rept   31
62         fmr     reg,fr0
63         blr
64 reg = reg + 1
65         .endr
66 1:      mflr    r5
67         add     r5,r3,r5
68         mtctr   r5
69         mtlr    r0
70         bctr
72 /* Load FP reg N from float at *p.  N is in r3, p in r4. */
73 _GLOBAL(do_lfs)
74         PPC_STLU r1,-STKFRM(r1)
75         mflr    r0
76         PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
77         mfmsr   r6
78         ori     r7,r6,MSR_FP
79         cmpwi   cr7,r3,0
80         MTMSRD(r7)
81         isync
82         beq     cr7,1f
83         stfd    fr0,STKFRM-16(r1)
84 1:      li      r9,-EFAULT
85 2:      lfs     fr0,0(r4)
86         li      r9,0
87 3:      bl      put_fpr
88         beq     cr7,4f
89         lfd     fr0,STKFRM-16(r1)
90 4:      PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
91         mtlr    r0
92         MTMSRD(r6)
93         isync
94         mr      r3,r9
95         addi    r1,r1,STKFRM
96         blr
97         EX_TABLE(2b,3b)
99 /* Load FP reg N from double at *p.  N is in r3, p in r4. */
100 _GLOBAL(do_lfd)
101         PPC_STLU r1,-STKFRM(r1)
102         mflr    r0
103         PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
104         mfmsr   r6
105         ori     r7,r6,MSR_FP
106         cmpwi   cr7,r3,0
107         MTMSRD(r7)
108         isync
109         beq     cr7,1f
110         stfd    fr0,STKFRM-16(r1)
111 1:      li      r9,-EFAULT
112 2:      lfd     fr0,0(r4)
113         li      r9,0
114 3:      beq     cr7,4f
115         bl      put_fpr
116         lfd     fr0,STKFRM-16(r1)
117 4:      PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
118         mtlr    r0
119         MTMSRD(r6)
120         isync
121         mr      r3,r9
122         addi    r1,r1,STKFRM
123         blr
124         EX_TABLE(2b,3b)
126 /* Store FP reg N to float at *p.  N is in r3, p in r4. */
127 _GLOBAL(do_stfs)
128         PPC_STLU r1,-STKFRM(r1)
129         mflr    r0
130         PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
131         mfmsr   r6
132         ori     r7,r6,MSR_FP
133         cmpwi   cr7,r3,0
134         MTMSRD(r7)
135         isync
136         beq     cr7,1f
137         stfd    fr0,STKFRM-16(r1)
138         bl      get_fpr
139 1:      li      r9,-EFAULT
140 2:      stfs    fr0,0(r4)
141         li      r9,0
142 3:      beq     cr7,4f
143         lfd     fr0,STKFRM-16(r1)
144 4:      PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
145         mtlr    r0
146         MTMSRD(r6)
147         isync
148         mr      r3,r9
149         addi    r1,r1,STKFRM
150         blr
151         EX_TABLE(2b,3b)
153 /* Store FP reg N to double at *p.  N is in r3, p in r4. */
154 _GLOBAL(do_stfd)
155         PPC_STLU r1,-STKFRM(r1)
156         mflr    r0
157         PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
158         mfmsr   r6
159         ori     r7,r6,MSR_FP
160         cmpwi   cr7,r3,0
161         MTMSRD(r7)
162         isync
163         beq     cr7,1f
164         stfd    fr0,STKFRM-16(r1)
165         bl      get_fpr
166 1:      li      r9,-EFAULT
167 2:      stfd    fr0,0(r4)
168         li      r9,0
169 3:      beq     cr7,4f
170         lfd     fr0,STKFRM-16(r1)
171 4:      PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
172         mtlr    r0
173         MTMSRD(r6)
174         isync
175         mr      r3,r9
176         addi    r1,r1,STKFRM
177         blr
178         EX_TABLE(2b,3b)
180 #ifdef CONFIG_ALTIVEC
181 /* Get the contents of vrN into v0; N is in r3. */
182 _GLOBAL(get_vr)
183         mflr    r0
184         rlwinm  r3,r3,3,0xf8
185         bcl     20,31,1f
186         blr                     /* v0 is already in v0 */
187         nop
188 reg = 1
189         .rept   31
190         vor     v0,reg,reg      /* assembler doesn't know vmr? */
191         blr
192 reg = reg + 1
193         .endr
194 1:      mflr    r5
195         add     r5,r3,r5
196         mtctr   r5
197         mtlr    r0
198         bctr
200 /* Put the contents of v0 into vrN; N is in r3. */
201 _GLOBAL(put_vr)
202         mflr    r0
203         rlwinm  r3,r3,3,0xf8
204         bcl     20,31,1f
205         blr                     /* v0 is already in v0 */
206         nop
207 reg = 1
208         .rept   31
209         vor     reg,v0,v0
210         blr
211 reg = reg + 1
212         .endr
213 1:      mflr    r5
214         add     r5,r3,r5
215         mtctr   r5
216         mtlr    r0
217         bctr
219 /* Load vector reg N from *p.  N is in r3, p in r4. */
220 _GLOBAL(do_lvx)
221         PPC_STLU r1,-STKFRM(r1)
222         mflr    r0
223         PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
224         mfmsr   r6
225         oris    r7,r6,MSR_VEC@h
226         cmpwi   cr7,r3,0
227         li      r8,STKFRM-16
228         MTMSRD(r7)
229         isync
230         beq     cr7,1f
231         stvx    v0,r1,r8
232 1:      li      r9,-EFAULT
233 2:      lvx     v0,0,r4
234         li      r9,0
235 3:      beq     cr7,4f
236         bl      put_vr
237         lvx     v0,r1,r8
238 4:      PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
239         mtlr    r0
240         MTMSRD(r6)
241         isync
242         mr      r3,r9
243         addi    r1,r1,STKFRM
244         blr
245         EX_TABLE(2b,3b)
247 /* Store vector reg N to *p.  N is in r3, p in r4. */
248 _GLOBAL(do_stvx)
249         PPC_STLU r1,-STKFRM(r1)
250         mflr    r0
251         PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
252         mfmsr   r6
253         oris    r7,r6,MSR_VEC@h
254         cmpwi   cr7,r3,0
255         li      r8,STKFRM-16
256         MTMSRD(r7)
257         isync
258         beq     cr7,1f
259         stvx    v0,r1,r8
260         bl      get_vr
261 1:      li      r9,-EFAULT
262 2:      stvx    v0,0,r4
263         li      r9,0
264 3:      beq     cr7,4f
265         lvx     v0,r1,r8
266 4:      PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
267         mtlr    r0
268         MTMSRD(r6)
269         isync
270         mr      r3,r9
271         addi    r1,r1,STKFRM
272         blr
273         EX_TABLE(2b,3b)
274 #endif /* CONFIG_ALTIVEC */
276 #ifdef CONFIG_VSX
277 /* Get the contents of vsN into vs0; N is in r3. */
278 _GLOBAL(get_vsr)
279         mflr    r0
280         rlwinm  r3,r3,3,0x1f8
281         bcl     20,31,1f
282         blr                     /* vs0 is already in vs0 */
283         nop
284 reg = 1
285         .rept   63
286         XXLOR(0,reg,reg)
287         blr
288 reg = reg + 1
289         .endr
290 1:      mflr    r5
291         add     r5,r3,r5
292         mtctr   r5
293         mtlr    r0
294         bctr
296 /* Put the contents of vs0 into vsN; N is in r3. */
297 _GLOBAL(put_vsr)
298         mflr    r0
299         rlwinm  r3,r3,3,0x1f8
300         bcl     20,31,1f
301         blr                     /* v0 is already in v0 */
302         nop
303 reg = 1
304         .rept   63
305         XXLOR(reg,0,0)
306         blr
307 reg = reg + 1
308         .endr
309 1:      mflr    r5
310         add     r5,r3,r5
311         mtctr   r5
312         mtlr    r0
313         bctr
315 /* Load VSX reg N from vector doubleword *p.  N is in r3, p in r4. */
316 _GLOBAL(do_lxvd2x)
317         PPC_STLU r1,-STKFRM(r1)
318         mflr    r0
319         PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
320         mfmsr   r6
321         oris    r7,r6,MSR_VSX@h
322         cmpwi   cr7,r3,0
323         li      r8,STKFRM-16
324         MTMSRD(r7)
325         isync
326         beq     cr7,1f
327         STXVD2X(0,R1,R8)
328 1:      li      r9,-EFAULT
329 2:      LXVD2X(0,R0,R4)
330         li      r9,0
331 3:      beq     cr7,4f
332         bl      put_vsr
333         LXVD2X(0,R1,R8)
334 4:      PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
335         mtlr    r0
336         MTMSRD(r6)
337         isync
338         mr      r3,r9
339         addi    r1,r1,STKFRM
340         blr
341         EX_TABLE(2b,3b)
343 /* Store VSX reg N to vector doubleword *p.  N is in r3, p in r4. */
344 _GLOBAL(do_stxvd2x)
345         PPC_STLU r1,-STKFRM(r1)
346         mflr    r0
347         PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
348         mfmsr   r6
349         oris    r7,r6,MSR_VSX@h
350         cmpwi   cr7,r3,0
351         li      r8,STKFRM-16
352         MTMSRD(r7)
353         isync
354         beq     cr7,1f
355         STXVD2X(0,R1,R8)
356         bl      get_vsr
357 1:      li      r9,-EFAULT
358 2:      STXVD2X(0,R0,R4)
359         li      r9,0
360 3:      beq     cr7,4f
361         LXVD2X(0,R1,R8)
362 4:      PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
363         mtlr    r0
364         MTMSRD(r6)
365         isync
366         mr      r3,r9
367         addi    r1,r1,STKFRM
368         blr
369         EX_TABLE(2b,3b)
371 #endif /* CONFIG_VSX */
373 #endif  /* CONFIG_PPC_FPU */