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