]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - arch/powerpc/kvm/fpu.S
3dfae0cb62280b99e28dfe2bc96614eddaedd68e
[mirror_ubuntu-jammy-kernel.git] / arch / powerpc / kvm / fpu.S
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * FPU helper code to use FPU operations from inside the kernel
4 *
5 * Copyright (C) 2010 Alexander Graf (agraf@suse.de)
6 */
7
8 #include <asm/reg.h>
9 #include <asm/page.h>
10 #include <asm/mmu.h>
11 #include <asm/pgtable.h>
12 #include <asm/cputable.h>
13 #include <asm/cache.h>
14 #include <asm/thread_info.h>
15 #include <asm/ppc_asm.h>
16 #include <asm/asm-offsets.h>
17
18 /* Instructions operating on single parameters */
19
20 /*
21 * Single operation with one input operand
22 *
23 * R3 = (double*)&fpscr
24 * R4 = (short*)&result
25 * R5 = (short*)&param1
26 */
27 #define FPS_ONE_IN(name) \
28 _GLOBAL(fps_ ## name); \
29 lfd 0,0(r3); /* load up fpscr value */ \
30 MTFSF_L(0); \
31 lfs 0,0(r5); \
32 \
33 name 0,0; \
34 \
35 stfs 0,0(r4); \
36 mffs 0; \
37 stfd 0,0(r3); /* save new fpscr value */ \
38 blr
39
40 /*
41 * Single operation with two input operands
42 *
43 * R3 = (double*)&fpscr
44 * R4 = (short*)&result
45 * R5 = (short*)&param1
46 * R6 = (short*)&param2
47 */
48 #define FPS_TWO_IN(name) \
49 _GLOBAL(fps_ ## name); \
50 lfd 0,0(r3); /* load up fpscr value */ \
51 MTFSF_L(0); \
52 lfs 0,0(r5); \
53 lfs 1,0(r6); \
54 \
55 name 0,0,1; \
56 \
57 stfs 0,0(r4); \
58 mffs 0; \
59 stfd 0,0(r3); /* save new fpscr value */ \
60 blr
61
62 /*
63 * Single operation with three input operands
64 *
65 * R3 = (double*)&fpscr
66 * R4 = (short*)&result
67 * R5 = (short*)&param1
68 * R6 = (short*)&param2
69 * R7 = (short*)&param3
70 */
71 #define FPS_THREE_IN(name) \
72 _GLOBAL(fps_ ## name); \
73 lfd 0,0(r3); /* load up fpscr value */ \
74 MTFSF_L(0); \
75 lfs 0,0(r5); \
76 lfs 1,0(r6); \
77 lfs 2,0(r7); \
78 \
79 name 0,0,1,2; \
80 \
81 stfs 0,0(r4); \
82 mffs 0; \
83 stfd 0,0(r3); /* save new fpscr value */ \
84 blr
85
86 FPS_ONE_IN(fres)
87 FPS_ONE_IN(frsqrte)
88 FPS_ONE_IN(fsqrts)
89 FPS_TWO_IN(fadds)
90 FPS_TWO_IN(fdivs)
91 FPS_TWO_IN(fmuls)
92 FPS_TWO_IN(fsubs)
93 FPS_THREE_IN(fmadds)
94 FPS_THREE_IN(fmsubs)
95 FPS_THREE_IN(fnmadds)
96 FPS_THREE_IN(fnmsubs)
97 FPS_THREE_IN(fsel)
98
99
100 /* Instructions operating on double parameters */
101
102 /*
103 * Beginning of double instruction processing
104 *
105 * R3 = (double*)&fpscr
106 * R4 = (u32*)&cr
107 * R5 = (double*)&result
108 * R6 = (double*)&param1
109 * R7 = (double*)&param2 [load_two]
110 * R8 = (double*)&param3 [load_three]
111 * LR = instruction call function
112 */
113 fpd_load_three:
114 lfd 2,0(r8) /* load param3 */
115 fpd_load_two:
116 lfd 1,0(r7) /* load param2 */
117 fpd_load_one:
118 lfd 0,0(r6) /* load param1 */
119 fpd_load_none:
120 lfd 3,0(r3) /* load up fpscr value */
121 MTFSF_L(3)
122 lwz r6, 0(r4) /* load cr */
123 mtcr r6
124 blr
125
126 /*
127 * End of double instruction processing
128 *
129 * R3 = (double*)&fpscr
130 * R4 = (u32*)&cr
131 * R5 = (double*)&result
132 * LR = caller of instruction call function
133 */
134 fpd_return:
135 mfcr r6
136 stfd 0,0(r5) /* save result */
137 mffs 0
138 stfd 0,0(r3) /* save new fpscr value */
139 stw r6,0(r4) /* save new cr value */
140 blr
141
142 /*
143 * Double operation with no input operand
144 *
145 * R3 = (double*)&fpscr
146 * R4 = (u32*)&cr
147 * R5 = (double*)&result
148 */
149 #define FPD_NONE_IN(name) \
150 _GLOBAL(fpd_ ## name); \
151 mflr r12; \
152 bl fpd_load_none; \
153 mtlr r12; \
154 \
155 name. 0; /* call instruction */ \
156 b fpd_return
157
158 /*
159 * Double operation with one input operand
160 *
161 * R3 = (double*)&fpscr
162 * R4 = (u32*)&cr
163 * R5 = (double*)&result
164 * R6 = (double*)&param1
165 */
166 #define FPD_ONE_IN(name) \
167 _GLOBAL(fpd_ ## name); \
168 mflr r12; \
169 bl fpd_load_one; \
170 mtlr r12; \
171 \
172 name. 0,0; /* call instruction */ \
173 b fpd_return
174
175 /*
176 * Double operation with two input operands
177 *
178 * R3 = (double*)&fpscr
179 * R4 = (u32*)&cr
180 * R5 = (double*)&result
181 * R6 = (double*)&param1
182 * R7 = (double*)&param2
183 * R8 = (double*)&param3
184 */
185 #define FPD_TWO_IN(name) \
186 _GLOBAL(fpd_ ## name); \
187 mflr r12; \
188 bl fpd_load_two; \
189 mtlr r12; \
190 \
191 name. 0,0,1; /* call instruction */ \
192 b fpd_return
193
194 /*
195 * CR Double operation with two input operands
196 *
197 * R3 = (double*)&fpscr
198 * R4 = (u32*)&cr
199 * R5 = (double*)&param1
200 * R6 = (double*)&param2
201 * R7 = (double*)&param3
202 */
203 #define FPD_TWO_IN_CR(name) \
204 _GLOBAL(fpd_ ## name); \
205 lfd 1,0(r6); /* load param2 */ \
206 lfd 0,0(r5); /* load param1 */ \
207 lfd 3,0(r3); /* load up fpscr value */ \
208 MTFSF_L(3); \
209 lwz r6, 0(r4); /* load cr */ \
210 mtcr r6; \
211 \
212 name 0,0,1; /* call instruction */ \
213 mfcr r6; \
214 mffs 0; \
215 stfd 0,0(r3); /* save new fpscr value */ \
216 stw r6,0(r4); /* save new cr value */ \
217 blr
218
219 /*
220 * Double operation with three input operands
221 *
222 * R3 = (double*)&fpscr
223 * R4 = (u32*)&cr
224 * R5 = (double*)&result
225 * R6 = (double*)&param1
226 * R7 = (double*)&param2
227 * R8 = (double*)&param3
228 */
229 #define FPD_THREE_IN(name) \
230 _GLOBAL(fpd_ ## name); \
231 mflr r12; \
232 bl fpd_load_three; \
233 mtlr r12; \
234 \
235 name. 0,0,1,2; /* call instruction */ \
236 b fpd_return
237
238 FPD_ONE_IN(fsqrts)
239 FPD_ONE_IN(frsqrtes)
240 FPD_ONE_IN(fres)
241 FPD_ONE_IN(frsp)
242 FPD_ONE_IN(fctiw)
243 FPD_ONE_IN(fctiwz)
244 FPD_ONE_IN(fsqrt)
245 FPD_ONE_IN(fre)
246 FPD_ONE_IN(frsqrte)
247 FPD_ONE_IN(fneg)
248 FPD_ONE_IN(fabs)
249 FPD_TWO_IN(fadds)
250 FPD_TWO_IN(fsubs)
251 FPD_TWO_IN(fdivs)
252 FPD_TWO_IN(fmuls)
253 FPD_TWO_IN_CR(fcmpu)
254 FPD_TWO_IN(fcpsgn)
255 FPD_TWO_IN(fdiv)
256 FPD_TWO_IN(fadd)
257 FPD_TWO_IN(fmul)
258 FPD_TWO_IN_CR(fcmpo)
259 FPD_TWO_IN(fsub)
260 FPD_THREE_IN(fmsubs)
261 FPD_THREE_IN(fmadds)
262 FPD_THREE_IN(fnmsubs)
263 FPD_THREE_IN(fnmadds)
264 FPD_THREE_IN(fsel)
265 FPD_THREE_IN(fmsub)
266 FPD_THREE_IN(fmadd)
267 FPD_THREE_IN(fnmsub)
268 FPD_THREE_IN(fnmadd)
269
270 _GLOBAL(kvm_cvt_fd)
271 lfs 0,0(r3)
272 stfd 0,0(r4)
273 blr
274
275 _GLOBAL(kvm_cvt_df)
276 lfd 0,0(r3)
277 stfs 0,0(r4)
278 blr