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