Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/kvm/fpu.S
10818 views
1
/*
2
* FPU helper code to use FPU operations from inside the kernel
3
*
4
* Copyright (C) 2010 Alexander Graf ([email protected])
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
284
285