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