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