linux/arch/powerpc/kvm/fpu.S
<<
>>
Prefs
   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 <asm/reg.h>
  10#include <asm/page.h>
  11#include <asm/mmu.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
  86FPS_ONE_IN(fres)
  87FPS_ONE_IN(frsqrte)
  88FPS_ONE_IN(fsqrts)
  89FPS_TWO_IN(fadds)
  90FPS_TWO_IN(fdivs)
  91FPS_TWO_IN(fmuls)
  92FPS_TWO_IN(fsubs)
  93FPS_THREE_IN(fmadds)
  94FPS_THREE_IN(fmsubs)
  95FPS_THREE_IN(fnmadds)
  96FPS_THREE_IN(fnmsubs)
  97FPS_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 */
 113fpd_load_three:
 114        lfd     2,0(r8)                 /* load param3 */
 115fpd_load_two:
 116        lfd     1,0(r7)                 /* load param2 */
 117fpd_load_one:
 118        lfd     0,0(r6)                 /* load param1 */
 119fpd_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 */
 134fpd_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
 238FPD_ONE_IN(fsqrts)
 239FPD_ONE_IN(frsqrtes)
 240FPD_ONE_IN(fres)
 241FPD_ONE_IN(frsp)
 242FPD_ONE_IN(fctiw)
 243FPD_ONE_IN(fctiwz)
 244FPD_ONE_IN(fsqrt)
 245FPD_ONE_IN(fre)
 246FPD_ONE_IN(frsqrte)
 247FPD_ONE_IN(fneg)
 248FPD_ONE_IN(fabs)
 249FPD_TWO_IN(fadds)
 250FPD_TWO_IN(fsubs)
 251FPD_TWO_IN(fdivs)
 252FPD_TWO_IN(fmuls)
 253FPD_TWO_IN_CR(fcmpu)
 254FPD_TWO_IN(fcpsgn)
 255FPD_TWO_IN(fdiv)
 256FPD_TWO_IN(fadd)
 257FPD_TWO_IN(fmul)
 258FPD_TWO_IN_CR(fcmpo)
 259FPD_TWO_IN(fsub)
 260FPD_THREE_IN(fmsubs)
 261FPD_THREE_IN(fmadds)
 262FPD_THREE_IN(fnmsubs)
 263FPD_THREE_IN(fnmadds)
 264FPD_THREE_IN(fsel)
 265FPD_THREE_IN(fmsub)
 266FPD_THREE_IN(fmadd)
 267FPD_THREE_IN(fnmsub)
 268FPD_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
 279