1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * FPU helper code to use FPU operations from inside the kernel
8 #include <linux/pgtable.h>
9 #include <linux/linkage.h>
14 #include <asm/cputable.h>
15 #include <asm/cache.h>
16 #include <asm/thread_info.h>
17 #include <asm/ppc_asm.h>
18 #include <asm/asm-offsets.h>
20 /* Instructions operating on single parameters */
23 * Single operation with one input operand
25 * R3 = (double*)&fpscr
26 * R4 = (short*)&result
27 * R5 = (short*)¶m1
29 #define FPS_ONE_IN(name) \
30 _GLOBAL(fps_ ## name); \
31 lfd 0,0(r3); /* load up fpscr value */ \
39 stfd 0,0(r3); /* save new fpscr value */ \
43 * Single operation with two input operands
45 * R3 = (double*)&fpscr
46 * R4 = (short*)&result
47 * R5 = (short*)¶m1
48 * R6 = (short*)¶m2
50 #define FPS_TWO_IN(name) \
51 _GLOBAL(fps_ ## name); \
52 lfd 0,0(r3); /* load up fpscr value */ \
61 stfd 0,0(r3); /* save new fpscr value */ \
65 * Single operation with three input operands
67 * R3 = (double*)&fpscr
68 * R4 = (short*)&result
69 * R5 = (short*)¶m1
70 * R6 = (short*)¶m2
71 * R7 = (short*)¶m3
73 #define FPS_THREE_IN(name) \
74 _GLOBAL(fps_ ## name); \
75 lfd 0,0(r3); /* load up fpscr value */ \
85 stfd 0,0(r3); /* save new fpscr value */ \
102 /* Instructions operating on double parameters */
105 * Beginning of double instruction processing
107 * R3 = (double*)&fpscr
109 * R5 = (double*)&result
110 * R6 = (double*)¶m1
111 * R7 = (double*)¶m2 [load_two]
112 * R8 = (double*)¶m3 [load_three]
113 * LR = instruction call function
115 SYM_FUNC_START_LOCAL(fpd_load_three)
116 lfd 2,0(r8) /* load param3 */
117 SYM_FUNC_START_LOCAL(fpd_load_two)
118 lfd 1,0(r7) /* load param2 */
119 SYM_FUNC_START_LOCAL(fpd_load_one)
120 lfd 0,0(r6) /* load param1 */
121 SYM_FUNC_START_LOCAL(fpd_load_none)
122 lfd 3,0(r3) /* load up fpscr value */
124 lwz r6, 0(r4) /* load cr */
127 SYM_FUNC_END(fpd_load_none)
128 SYM_FUNC_END(fpd_load_one)
129 SYM_FUNC_END(fpd_load_two)
130 SYM_FUNC_END(fpd_load_three)
133 * End of double instruction processing
135 * R3 = (double*)&fpscr
137 * R5 = (double*)&result
138 * LR = caller of instruction call function
140 SYM_FUNC_START_LOCAL(fpd_return)
142 stfd 0,0(r5) /* save result */
144 stfd 0,0(r3) /* save new fpscr value */
145 stw r6,0(r4) /* save new cr value */
147 SYM_FUNC_END(fpd_return)
150 * Double operation with no input operand
152 * R3 = (double*)&fpscr
154 * R5 = (double*)&result
156 #define FPD_NONE_IN(name) \
157 _GLOBAL(fpd_ ## name); \
162 name. 0; /* call instruction */ \
166 * Double operation with one input operand
168 * R3 = (double*)&fpscr
170 * R5 = (double*)&result
171 * R6 = (double*)¶m1
173 #define FPD_ONE_IN(name) \
174 _GLOBAL(fpd_ ## name); \
179 name. 0,0; /* call instruction */ \
183 * Double operation with two input operands
185 * R3 = (double*)&fpscr
187 * R5 = (double*)&result
188 * R6 = (double*)¶m1
189 * R7 = (double*)¶m2
190 * R8 = (double*)¶m3
192 #define FPD_TWO_IN(name) \
193 _GLOBAL(fpd_ ## name); \
198 name. 0,0,1; /* call instruction */ \
202 * CR Double operation with two input operands
204 * R3 = (double*)&fpscr
206 * R5 = (double*)¶m1
207 * R6 = (double*)¶m2
208 * R7 = (double*)¶m3
210 #define FPD_TWO_IN_CR(name) \
211 _GLOBAL(fpd_ ## name); \
212 lfd 1,0(r6); /* load param2 */ \
213 lfd 0,0(r5); /* load param1 */ \
214 lfd 3,0(r3); /* load up fpscr value */ \
216 lwz r6, 0(r4); /* load cr */ \
219 name 0,0,1; /* call instruction */ \
222 stfd 0,0(r3); /* save new fpscr value */ \
223 stw r6,0(r4); /* save new cr value */ \
227 * Double operation with three input operands
229 * R3 = (double*)&fpscr
231 * R5 = (double*)&result
232 * R6 = (double*)¶m1
233 * R7 = (double*)¶m2
234 * R8 = (double*)¶m3
236 #define FPD_THREE_IN(name) \
237 _GLOBAL(fpd_ ## name); \
242 name. 0,0,1,2; /* call instruction */ \
269 FPD_THREE_IN(fnmsubs)
270 FPD_THREE_IN(fnmadds)