]>
Commit | Line | Data |
---|---|---|
0016a4cf PM |
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 | ||
cd64d169 SM |
20 | #ifdef CONFIG_PPC_FPU |
21 | ||
0016a4cf PM |
22 | #define STKFRM (PPC_MIN_STKFRM + 16) |
23 | ||
0016a4cf PM |
24 | .macro inst32 op |
25 | reg = 0 | |
26 | .rept 32 | |
27 | 20: \op reg,0,r4 | |
28 | b 3f | |
24bfa6a9 | 29 | EX_TABLE(20b,99f) |
0016a4cf PM |
30 | reg = reg + 1 |
31 | .endr | |
32 | .endm | |
33 | ||
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 | |
52 | ||
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 | |
71 | ||
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 | |
cd64d169 | 80 | MTMSRD(r7) |
0016a4cf PM |
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 | |
cd64d169 | 92 | MTMSRD(r6) |
0016a4cf PM |
93 | isync |
94 | mr r3,r9 | |
95 | addi r1,r1,STKFRM | |
96 | blr | |
24bfa6a9 | 97 | EX_TABLE(2b,3b) |
0016a4cf PM |
98 | |
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 | |
cd64d169 | 107 | MTMSRD(r7) |
0016a4cf PM |
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 | |
cd64d169 | 119 | MTMSRD(r6) |
0016a4cf PM |
120 | isync |
121 | mr r3,r9 | |
122 | addi r1,r1,STKFRM | |
123 | blr | |
24bfa6a9 | 124 | EX_TABLE(2b,3b) |
0016a4cf PM |
125 | |
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 | |
cd64d169 | 134 | MTMSRD(r7) |
0016a4cf PM |
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 | |
cd64d169 | 146 | MTMSRD(r6) |
0016a4cf PM |
147 | isync |
148 | mr r3,r9 | |
149 | addi r1,r1,STKFRM | |
150 | blr | |
24bfa6a9 | 151 | EX_TABLE(2b,3b) |
0016a4cf PM |
152 | |
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 | |
cd64d169 | 161 | MTMSRD(r7) |
0016a4cf PM |
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 | |
cd64d169 | 173 | MTMSRD(r6) |
0016a4cf PM |
174 | isync |
175 | mr r3,r9 | |
176 | addi r1,r1,STKFRM | |
177 | blr | |
24bfa6a9 | 178 | EX_TABLE(2b,3b) |
0016a4cf PM |
179 | |
180 | #ifdef CONFIG_ALTIVEC | |
c2ce6f9f | 181 | /* Get the contents of vrN into v0; N is in r3. */ |
0016a4cf PM |
182 | _GLOBAL(get_vr) |
183 | mflr r0 | |
184 | rlwinm r3,r3,3,0xf8 | |
185 | bcl 20,31,1f | |
c2ce6f9f | 186 | blr /* v0 is already in v0 */ |
0016a4cf PM |
187 | nop |
188 | reg = 1 | |
189 | .rept 31 | |
c2ce6f9f | 190 | vor v0,reg,reg /* assembler doesn't know vmr? */ |
0016a4cf PM |
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 | |
199 | ||
c2ce6f9f | 200 | /* Put the contents of v0 into vrN; N is in r3. */ |
0016a4cf PM |
201 | _GLOBAL(put_vr) |
202 | mflr r0 | |
203 | rlwinm r3,r3,3,0xf8 | |
204 | bcl 20,31,1f | |
c2ce6f9f | 205 | blr /* v0 is already in v0 */ |
0016a4cf PM |
206 | nop |
207 | reg = 1 | |
208 | .rept 31 | |
c2ce6f9f | 209 | vor reg,v0,v0 |
0016a4cf PM |
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 | |
218 | ||
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 | |
cd64d169 | 228 | MTMSRD(r7) |
0016a4cf PM |
229 | isync |
230 | beq cr7,1f | |
c2ce6f9f | 231 | stvx v0,r1,r8 |
0016a4cf | 232 | 1: li r9,-EFAULT |
c2ce6f9f | 233 | 2: lvx v0,0,r4 |
0016a4cf PM |
234 | li r9,0 |
235 | 3: beq cr7,4f | |
236 | bl put_vr | |
c2ce6f9f | 237 | lvx v0,r1,r8 |
0016a4cf PM |
238 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
239 | mtlr r0 | |
cd64d169 | 240 | MTMSRD(r6) |
0016a4cf PM |
241 | isync |
242 | mr r3,r9 | |
243 | addi r1,r1,STKFRM | |
244 | blr | |
24bfa6a9 | 245 | EX_TABLE(2b,3b) |
0016a4cf PM |
246 | |
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 | |
cd64d169 | 256 | MTMSRD(r7) |
0016a4cf PM |
257 | isync |
258 | beq cr7,1f | |
c2ce6f9f | 259 | stvx v0,r1,r8 |
0016a4cf PM |
260 | bl get_vr |
261 | 1: li r9,-EFAULT | |
c2ce6f9f | 262 | 2: stvx v0,0,r4 |
0016a4cf PM |
263 | li r9,0 |
264 | 3: beq cr7,4f | |
c2ce6f9f | 265 | lvx v0,r1,r8 |
0016a4cf PM |
266 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
267 | mtlr r0 | |
cd64d169 | 268 | MTMSRD(r6) |
0016a4cf PM |
269 | isync |
270 | mr r3,r9 | |
271 | addi r1,r1,STKFRM | |
272 | blr | |
24bfa6a9 | 273 | EX_TABLE(2b,3b) |
0016a4cf PM |
274 | #endif /* CONFIG_ALTIVEC */ |
275 | ||
276 | #ifdef CONFIG_VSX | |
df99e6eb | 277 | /* Get the contents of vsN into vs0; N is in r3. */ |
0016a4cf PM |
278 | _GLOBAL(get_vsr) |
279 | mflr r0 | |
280 | rlwinm r3,r3,3,0x1f8 | |
281 | bcl 20,31,1f | |
df99e6eb | 282 | blr /* vs0 is already in vs0 */ |
0016a4cf PM |
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 | |
295 | ||
df99e6eb | 296 | /* Put the contents of vs0 into vsN; N is in r3. */ |
0016a4cf PM |
297 | _GLOBAL(put_vsr) |
298 | mflr r0 | |
299 | rlwinm r3,r3,3,0x1f8 | |
300 | bcl 20,31,1f | |
c2ce6f9f | 301 | blr /* v0 is already in v0 */ |
0016a4cf PM |
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 | |
314 | ||
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 | |
cd64d169 | 324 | MTMSRD(r7) |
0016a4cf PM |
325 | isync |
326 | beq cr7,1f | |
c75df6f9 | 327 | STXVD2X(0,R1,R8) |
0016a4cf | 328 | 1: li r9,-EFAULT |
e55174e9 | 329 | 2: LXVD2X(0,R0,R4) |
0016a4cf PM |
330 | li r9,0 |
331 | 3: beq cr7,4f | |
332 | bl put_vsr | |
c75df6f9 | 333 | LXVD2X(0,R1,R8) |
0016a4cf PM |
334 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
335 | mtlr r0 | |
cd64d169 | 336 | MTMSRD(r6) |
0016a4cf PM |
337 | isync |
338 | mr r3,r9 | |
339 | addi r1,r1,STKFRM | |
340 | blr | |
24bfa6a9 | 341 | EX_TABLE(2b,3b) |
0016a4cf PM |
342 | |
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 | |
cd64d169 | 352 | MTMSRD(r7) |
0016a4cf PM |
353 | isync |
354 | beq cr7,1f | |
c75df6f9 | 355 | STXVD2X(0,R1,R8) |
0016a4cf PM |
356 | bl get_vsr |
357 | 1: li r9,-EFAULT | |
e55174e9 | 358 | 2: STXVD2X(0,R0,R4) |
0016a4cf PM |
359 | li r9,0 |
360 | 3: beq cr7,4f | |
c75df6f9 | 361 | LXVD2X(0,R1,R8) |
0016a4cf PM |
362 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
363 | mtlr r0 | |
cd64d169 | 364 | MTMSRD(r6) |
0016a4cf PM |
365 | isync |
366 | mr r3,r9 | |
367 | addi r1,r1,STKFRM | |
368 | blr | |
24bfa6a9 | 369 | EX_TABLE(2b,3b) |
0016a4cf PM |
370 | |
371 | #endif /* CONFIG_VSX */ | |
cd64d169 SM |
372 | |
373 | #endif /* CONFIG_PPC_FPU */ |