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 <linux/pgtable.h> 9 #include <linux/linkage.h> 10 11 #include <asm/reg.h> 12 #include <asm/page.h> 13 #include <asm/mmu.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> 19 20 /* Instructions operating on single parameters */ 21 22 /* 23 * Single operation with one input operand 24 * 25 * R3 = (double*)&fpscr 26 * R4 = (short*)&result 27 * R5 = (short*)¶m1 28 */ 29 #define FPS_ONE_IN(name) \ 30 _GLOBAL(fps_ ## name); \ 31 lfd 0,0(r3); /* load up fpscr value */ \ 32 MTFSF_L(0); \ 33 lfs 0,0(r5); \ 34 \ 35 name 0,0; \ 36 \ 37 stfs 0,0(r4); \ 38 mffs 0; \ 39 stfd 0,0(r3); /* save new fpscr value */ \ 40 blr 41 42 /* 43 * Single operation with two input operands 44 * 45 * R3 = (double*)&fpscr 46 * R4 = (short*)&result 47 * R5 = (short*)¶m1 48 * R6 = (short*)¶m2 49 */ 50 #define FPS_TWO_IN(name) \ 51 _GLOBAL(fps_ ## name); \ 52 lfd 0,0(r3); /* load up fpscr value */ \ 53 MTFSF_L(0); \ 54 lfs 0,0(r5); \ 55 lfs 1,0(r6); \ 56 \ 57 name 0,0,1; \ 58 \ 59 stfs 0,0(r4); \ 60 mffs 0; \ 61 stfd 0,0(r3); /* save new fpscr value */ \ 62 blr 63 64 /* 65 * Single operation with three input operands 66 * 67 * R3 = (double*)&fpscr 68 * R4 = (short*)&result 69 * R5 = (short*)¶m1 70 * R6 = (short*)¶m2 71 * R7 = (short*)¶m3 72 */ 73 #define FPS_THREE_IN(name) \ 74 _GLOBAL(fps_ ## name); \ 75 lfd 0,0(r3); /* load up fpscr value */ \ 76 MTFSF_L(0); \ 77 lfs 0,0(r5); \ 78 lfs 1,0(r6); \ 79 lfs 2,0(r7); \ 80 \ 81 name 0,0,1,2; \ 82 \ 83 stfs 0,0(r4); \ 84 mffs 0; \ 85 stfd 0,0(r3); /* save new fpscr value */ \ 86 blr 87 88 FPS_ONE_IN(fres) 89 FPS_ONE_IN(frsqrte) 90 FPS_ONE_IN(fsqrts) 91 FPS_TWO_IN(fadds) 92 FPS_TWO_IN(fdivs) 93 FPS_TWO_IN(fmuls) 94 FPS_TWO_IN(fsubs) 95 FPS_THREE_IN(fmadds) 96 FPS_THREE_IN(fmsubs) 97 FPS_THREE_IN(fnmadds) 98 FPS_THREE_IN(fnmsubs) 99 FPS_THREE_IN(fsel) 100 101 102 /* Instructions operating on double parameters */ 103 104 /* 105 * Beginning of double instruction processing 106 * 107 * R3 = (double*)&fpscr 108 * R4 = (u32*)&cr 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 114 */ 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 */ 123 MTFSF_L(3) 124 lwz r6, 0(r4) /* load cr */ 125 mtcr r6 126 blr 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) 131 132 /* 133 * End of double instruction processing 134 * 135 * R3 = (double*)&fpscr 136 * R4 = (u32*)&cr 137 * R5 = (double*)&result 138 * LR = caller of instruction call function 139 */ 140 SYM_FUNC_START_LOCAL(fpd_return) 141 mfcr r6 142 stfd 0,0(r5) /* save result */ 143 mffs 0 144 stfd 0,0(r3) /* save new fpscr value */ 145 stw r6,0(r4) /* save new cr value */ 146 blr 147 SYM_FUNC_END(fpd_return) 148 149 /* 150 * Double operation with no input operand 151 * 152 * R3 = (double*)&fpscr 153 * R4 = (u32*)&cr 154 * R5 = (double*)&result 155 */ 156 #define FPD_NONE_IN(name) \ 157 _GLOBAL(fpd_ ## name); \ 158 mflr r12; \ 159 bl fpd_load_none; \ 160 mtlr r12; \ 161 \ 162 name. 0; /* call instruction */ \ 163 b fpd_return 164 165 /* 166 * Double operation with one input operand 167 * 168 * R3 = (double*)&fpscr 169 * R4 = (u32*)&cr 170 * R5 = (double*)&result 171 * R6 = (double*)¶m1 172 */ 173 #define FPD_ONE_IN(name) \ 174 _GLOBAL(fpd_ ## name); \ 175 mflr r12; \ 176 bl fpd_load_one; \ 177 mtlr r12; \ 178 \ 179 name. 0,0; /* call instruction */ \ 180 b fpd_return 181 182 /* 183 * Double operation with two input operands 184 * 185 * R3 = (double*)&fpscr 186 * R4 = (u32*)&cr 187 * R5 = (double*)&result 188 * R6 = (double*)¶m1 189 * R7 = (double*)¶m2 190 * R8 = (double*)¶m3 191 */ 192 #define FPD_TWO_IN(name) \ 193 _GLOBAL(fpd_ ## name); \ 194 mflr r12; \ 195 bl fpd_load_two; \ 196 mtlr r12; \ 197 \ 198 name. 0,0,1; /* call instruction */ \ 199 b fpd_return 200 201 /* 202 * CR Double operation with two input operands 203 * 204 * R3 = (double*)&fpscr 205 * R4 = (u32*)&cr 206 * R5 = (double*)¶m1 207 * R6 = (double*)¶m2 208 * R7 = (double*)¶m3 209 */ 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 */ \ 215 MTFSF_L(3); \ 216 lwz r6, 0(r4); /* load cr */ \ 217 mtcr r6; \ 218 \ 219 name 0,0,1; /* call instruction */ \ 220 mfcr r6; \ 221 mffs 0; \ 222 stfd 0,0(r3); /* save new fpscr value */ \ 223 stw r6,0(r4); /* save new cr value */ \ 224 blr 225 226 /* 227 * Double operation with three input operands 228 * 229 * R3 = (double*)&fpscr 230 * R4 = (u32*)&cr 231 * R5 = (double*)&result 232 * R6 = (double*)¶m1 233 * R7 = (double*)¶m2 234 * R8 = (double*)¶m3 235 */ 236 #define FPD_THREE_IN(name) \ 237 _GLOBAL(fpd_ ## name); \ 238 mflr r12; \ 239 bl fpd_load_three; \ 240 mtlr r12; \ 241 \ 242 name. 0,0,1,2; /* call instruction */ \ 243 b fpd_return 244 245 FPD_ONE_IN(fsqrts) 246 FPD_ONE_IN(frsqrtes) 247 FPD_ONE_IN(fres) 248 FPD_ONE_IN(frsp) 249 FPD_ONE_IN(fctiw) 250 FPD_ONE_IN(fctiwz) 251 FPD_ONE_IN(fsqrt) 252 FPD_ONE_IN(fre) 253 FPD_ONE_IN(frsqrte) 254 FPD_ONE_IN(fneg) 255 FPD_ONE_IN(fabs) 256 FPD_TWO_IN(fadds) 257 FPD_TWO_IN(fsubs) 258 FPD_TWO_IN(fdivs) 259 FPD_TWO_IN(fmuls) 260 FPD_TWO_IN_CR(fcmpu) 261 FPD_TWO_IN(fcpsgn) 262 FPD_TWO_IN(fdiv) 263 FPD_TWO_IN(fadd) 264 FPD_TWO_IN(fmul) 265 FPD_TWO_IN_CR(fcmpo) 266 FPD_TWO_IN(fsub) 267 FPD_THREE_IN(fmsubs) 268 FPD_THREE_IN(fmadds) 269 FPD_THREE_IN(fnmsubs) 270 FPD_THREE_IN(fnmadds) 271 FPD_THREE_IN(fsel) 272 FPD_THREE_IN(fmsub) 273 FPD_THREE_IN(fmadd) 274 FPD_THREE_IN(fnmsub) 275 FPD_THREE_IN(fnmadd) 276 277 _GLOBAL(kvm_cvt_fd) 278 lfs 0,0(r3) 279 stfd 0,0(r4) 280 blr 281 282 _GLOBAL(kvm_cvt_df) 283 lfd 0,0(r3) 284 stfs 0,0(r4) 285 blr
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.