initramfs: Escape colons in depfile
[cascardo/linux.git] / arch / powerpc / kernel / vector.S
1 #include <asm/processor.h>
2 #include <asm/ppc_asm.h>
3 #include <asm/reg.h>
4 #include <asm/asm-offsets.h>
5 #include <asm/cputable.h>
6 #include <asm/thread_info.h>
7 #include <asm/page.h>
8 #include <asm/ptrace.h>
9 #include <asm/export.h>
10
11 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
12 /* void do_load_up_transact_altivec(struct thread_struct *thread)
13  *
14  * This is similar to load_up_altivec but for the transactional version of the
15  * vector regs.  It doesn't mess with the task MSR or valid flags.
16  * Furthermore, VEC laziness is not supported with TM currently.
17  */
18 _GLOBAL(do_load_up_transact_altivec)
19         mfmsr   r6
20         oris    r5,r6,MSR_VEC@h
21         MTMSRD(r5)
22         isync
23
24         li      r4,1
25         stw     r4,THREAD_USED_VR(r3)
26
27         li      r10,THREAD_TRANSACT_VRSTATE+VRSTATE_VSCR
28         lvx     v0,r10,r3
29         mtvscr  v0
30         addi    r10,r3,THREAD_TRANSACT_VRSTATE
31         REST_32VRS(0,r4,r10)
32
33         blr
34 #endif
35
36 /*
37  * Load state from memory into VMX registers including VSCR.
38  * Assumes the caller has enabled VMX in the MSR.
39  */
40 _GLOBAL(load_vr_state)
41         li      r4,VRSTATE_VSCR
42         lvx     v0,r4,r3
43         mtvscr  v0
44         REST_32VRS(0,r4,r3)
45         blr
46 EXPORT_SYMBOL(load_vr_state)
47
48 /*
49  * Store VMX state into memory, including VSCR.
50  * Assumes the caller has enabled VMX in the MSR.
51  */
52 _GLOBAL(store_vr_state)
53         SAVE_32VRS(0, r4, r3)
54         mfvscr  v0
55         li      r4, VRSTATE_VSCR
56         stvx    v0, r4, r3
57         blr
58 EXPORT_SYMBOL(store_vr_state)
59
60 /*
61  * Disable VMX for the task which had it previously,
62  * and save its vector registers in its thread_struct.
63  * Enables the VMX for use in the kernel on return.
64  * On SMP we know the VMX is free, since we give it up every
65  * switch (ie, no lazy save of the vector registers).
66  *
67  * Note that on 32-bit this can only use registers that will be
68  * restored by fast_exception_return, i.e. r3 - r6, r10 and r11.
69  */
70 _GLOBAL(load_up_altivec)
71         mfmsr   r5                      /* grab the current MSR */
72         oris    r5,r5,MSR_VEC@h
73         MTMSRD(r5)                      /* enable use of AltiVec now */
74         isync
75
76         /*
77          * While userspace in general ignores VRSAVE, glibc uses it as a boolean
78          * to optimise userspace context save/restore. Whenever we take an
79          * altivec unavailable exception we must set VRSAVE to something non
80          * zero. Set it to all 1s. See also the programming note in the ISA.
81          */
82         mfspr   r4,SPRN_VRSAVE
83         cmpwi   0,r4,0
84         bne+    1f
85         li      r4,-1
86         mtspr   SPRN_VRSAVE,r4
87 1:
88         /* enable use of VMX after return */
89 #ifdef CONFIG_PPC32
90         mfspr   r5,SPRN_SPRG_THREAD             /* current task's THREAD (phys) */
91         oris    r9,r9,MSR_VEC@h
92 #else
93         ld      r4,PACACURRENT(r13)
94         addi    r5,r4,THREAD            /* Get THREAD */
95         oris    r12,r12,MSR_VEC@h
96         std     r12,_MSR(r1)
97 #endif
98         /* Don't care if r4 overflows, this is desired behaviour */
99         lbz     r4,THREAD_LOAD_VEC(r5)
100         addi    r4,r4,1
101         stb     r4,THREAD_LOAD_VEC(r5)
102         addi    r6,r5,THREAD_VRSTATE
103         li      r4,1
104         li      r10,VRSTATE_VSCR
105         stw     r4,THREAD_USED_VR(r5)
106         lvx     v0,r10,r6
107         mtvscr  v0
108         REST_32VRS(0,r4,r6)
109         /* restore registers and return */
110         blr
111
112 /*
113  * save_altivec(tsk)
114  * Save the vector registers to its thread_struct
115  */
116 _GLOBAL(save_altivec)
117         addi    r3,r3,THREAD            /* want THREAD of task */
118         PPC_LL  r7,THREAD_VRSAVEAREA(r3)
119         PPC_LL  r5,PT_REGS(r3)
120         PPC_LCMPI       0,r7,0
121         bne     2f
122         addi    r7,r3,THREAD_VRSTATE
123 2:      SAVE_32VRS(0,r4,r7)
124         mfvscr  v0
125         li      r4,VRSTATE_VSCR
126         stvx    v0,r4,r7
127         blr
128
129 #ifdef CONFIG_VSX
130
131 #ifdef CONFIG_PPC32
132 #error This asm code isn't ready for 32-bit kernels
133 #endif
134
135 /*
136  * load_up_vsx(unused, unused, tsk)
137  * Disable VSX for the task which had it previously,
138  * and save its vector registers in its thread_struct.
139  * Reuse the fp and vsx saves, but first check to see if they have
140  * been saved already.
141  */
142 _GLOBAL(load_up_vsx)
143 /* Load FP and VSX registers if they haven't been done yet */
144         andi.   r5,r12,MSR_FP
145         beql+   load_up_fpu             /* skip if already loaded */
146         andis.  r5,r12,MSR_VEC@h
147         beql+   load_up_altivec         /* skip if already loaded */
148
149         ld      r4,PACACURRENT(r13)
150         addi    r4,r4,THREAD            /* Get THREAD */
151         li      r6,1
152         stw     r6,THREAD_USED_VSR(r4) /* ... also set thread used vsr */
153         /* enable use of VSX after return */
154         oris    r12,r12,MSR_VSX@h
155         std     r12,_MSR(r1)
156         b       fast_exception_return
157
158 #endif /* CONFIG_VSX */
159
160
161 /*
162  * The routines below are in assembler so we can closely control the
163  * usage of floating-point registers.  These routines must be called
164  * with preempt disabled.
165  */
166 #ifdef CONFIG_PPC32
167         .data
168 fpzero:
169         .long   0
170 fpone:
171         .long   0x3f800000      /* 1.0 in single-precision FP */
172 fphalf:
173         .long   0x3f000000      /* 0.5 in single-precision FP */
174
175 #define LDCONST(fr, name)       \
176         lis     r11,name@ha;    \
177         lfs     fr,name@l(r11)
178 #else
179
180         .section ".toc","aw"
181 fpzero:
182         .tc     FD_0_0[TC],0
183 fpone:
184         .tc     FD_3ff00000_0[TC],0x3ff0000000000000    /* 1.0 */
185 fphalf:
186         .tc     FD_3fe00000_0[TC],0x3fe0000000000000    /* 0.5 */
187
188 #define LDCONST(fr, name)       \
189         lfd     fr,name@toc(r2)
190 #endif
191
192         .text
193 /*
194  * Internal routine to enable floating point and set FPSCR to 0.
195  * Don't call it from C; it doesn't use the normal calling convention.
196  */
197 fpenable:
198 #ifdef CONFIG_PPC32
199         stwu    r1,-64(r1)
200 #else
201         stdu    r1,-64(r1)
202 #endif
203         mfmsr   r10
204         ori     r11,r10,MSR_FP
205         mtmsr   r11
206         isync
207         stfd    fr0,24(r1)
208         stfd    fr1,16(r1)
209         stfd    fr31,8(r1)
210         LDCONST(fr1, fpzero)
211         mffs    fr31
212         MTFSF_L(fr1)
213         blr
214
215 fpdisable:
216         mtlr    r12
217         MTFSF_L(fr31)
218         lfd     fr31,8(r1)
219         lfd     fr1,16(r1)
220         lfd     fr0,24(r1)
221         mtmsr   r10
222         isync
223         addi    r1,r1,64
224         blr
225
226 /*
227  * Vector add, floating point.
228  */
229 _GLOBAL(vaddfp)
230         mflr    r12
231         bl      fpenable
232         li      r0,4
233         mtctr   r0
234         li      r6,0
235 1:      lfsx    fr0,r4,r6
236         lfsx    fr1,r5,r6
237         fadds   fr0,fr0,fr1
238         stfsx   fr0,r3,r6
239         addi    r6,r6,4
240         bdnz    1b
241         b       fpdisable
242
243 /*
244  * Vector subtract, floating point.
245  */
246 _GLOBAL(vsubfp)
247         mflr    r12
248         bl      fpenable
249         li      r0,4
250         mtctr   r0
251         li      r6,0
252 1:      lfsx    fr0,r4,r6
253         lfsx    fr1,r5,r6
254         fsubs   fr0,fr0,fr1
255         stfsx   fr0,r3,r6
256         addi    r6,r6,4
257         bdnz    1b
258         b       fpdisable
259
260 /*
261  * Vector multiply and add, floating point.
262  */
263 _GLOBAL(vmaddfp)
264         mflr    r12
265         bl      fpenable
266         stfd    fr2,32(r1)
267         li      r0,4
268         mtctr   r0
269         li      r7,0
270 1:      lfsx    fr0,r4,r7
271         lfsx    fr1,r5,r7
272         lfsx    fr2,r6,r7
273         fmadds  fr0,fr0,fr2,fr1
274         stfsx   fr0,r3,r7
275         addi    r7,r7,4
276         bdnz    1b
277         lfd     fr2,32(r1)
278         b       fpdisable
279
280 /*
281  * Vector negative multiply and subtract, floating point.
282  */
283 _GLOBAL(vnmsubfp)
284         mflr    r12
285         bl      fpenable
286         stfd    fr2,32(r1)
287         li      r0,4
288         mtctr   r0
289         li      r7,0
290 1:      lfsx    fr0,r4,r7
291         lfsx    fr1,r5,r7
292         lfsx    fr2,r6,r7
293         fnmsubs fr0,fr0,fr2,fr1
294         stfsx   fr0,r3,r7
295         addi    r7,r7,4
296         bdnz    1b
297         lfd     fr2,32(r1)
298         b       fpdisable
299
300 /*
301  * Vector reciprocal estimate.  We just compute 1.0/x.
302  * r3 -> destination, r4 -> source.
303  */
304 _GLOBAL(vrefp)
305         mflr    r12
306         bl      fpenable
307         li      r0,4
308         LDCONST(fr1, fpone)
309         mtctr   r0
310         li      r6,0
311 1:      lfsx    fr0,r4,r6
312         fdivs   fr0,fr1,fr0
313         stfsx   fr0,r3,r6
314         addi    r6,r6,4
315         bdnz    1b
316         b       fpdisable
317
318 /*
319  * Vector reciprocal square-root estimate, floating point.
320  * We use the frsqrte instruction for the initial estimate followed
321  * by 2 iterations of Newton-Raphson to get sufficient accuracy.
322  * r3 -> destination, r4 -> source.
323  */
324 _GLOBAL(vrsqrtefp)
325         mflr    r12
326         bl      fpenable
327         stfd    fr2,32(r1)
328         stfd    fr3,40(r1)
329         stfd    fr4,48(r1)
330         stfd    fr5,56(r1)
331         li      r0,4
332         LDCONST(fr4, fpone)
333         LDCONST(fr5, fphalf)
334         mtctr   r0
335         li      r6,0
336 1:      lfsx    fr0,r4,r6
337         frsqrte fr1,fr0         /* r = frsqrte(s) */
338         fmuls   fr3,fr1,fr0     /* r * s */
339         fmuls   fr2,fr1,fr5     /* r * 0.5 */
340         fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */
341         fmadds  fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */
342         fmuls   fr3,fr1,fr0     /* r * s */
343         fmuls   fr2,fr1,fr5     /* r * 0.5 */
344         fnmsubs fr3,fr1,fr3,fr4 /* 1 - s * r * r */
345         fmadds  fr1,fr2,fr3,fr1 /* r = r + 0.5 * r * (1 - s * r * r) */
346         stfsx   fr1,r3,r6
347         addi    r6,r6,4
348         bdnz    1b
349         lfd     fr5,56(r1)
350         lfd     fr4,48(r1)
351         lfd     fr3,40(r1)
352         lfd     fr2,32(r1)
353         b       fpdisable