root/arch/powerpc/kvm/fpu.S

/* [<][>][^][v][top][bottom][index][help] */
   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

/* [<][>][^][v][top][bottom][index][help] */