Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  *  FPU helper code to use FPU operations from inside the kernel
0004  *
0005  *    Copyright (C) 2010 Alexander Graf (agraf@suse.de)
0006  */
0007 
0008 #include <linux/pgtable.h>
0009 #include <asm/reg.h>
0010 #include <asm/page.h>
0011 #include <asm/mmu.h>
0012 #include <asm/cputable.h>
0013 #include <asm/cache.h>
0014 #include <asm/thread_info.h>
0015 #include <asm/ppc_asm.h>
0016 #include <asm/asm-offsets.h>
0017 
0018 /* Instructions operating on single parameters */
0019 
0020 /*
0021  * Single operation with one input operand
0022  *
0023  * R3 = (double*)&fpscr
0024  * R4 = (short*)&result
0025  * R5 = (short*)&param1
0026  */
0027 #define FPS_ONE_IN(name)                    \
0028 _GLOBAL(fps_ ## name);                          \
0029     lfd 0,0(r3);        /* load up fpscr value */   \
0030     MTFSF_L(0);                         \
0031     lfs 0,0(r5);                        \
0032                                     \
0033     name    0,0;                            \
0034                                     \
0035     stfs    0,0(r4);                        \
0036     mffs    0;                          \
0037     stfd    0,0(r3);    /* save new fpscr value */  \
0038     blr
0039 
0040 /*
0041  * Single operation with two input operands
0042  *
0043  * R3 = (double*)&fpscr
0044  * R4 = (short*)&result
0045  * R5 = (short*)&param1
0046  * R6 = (short*)&param2
0047  */
0048 #define FPS_TWO_IN(name)                    \
0049 _GLOBAL(fps_ ## name);                          \
0050     lfd 0,0(r3);        /* load up fpscr value */   \
0051     MTFSF_L(0);                         \
0052     lfs 0,0(r5);                        \
0053     lfs 1,0(r6);                        \
0054                                     \
0055     name    0,0,1;                          \
0056                                     \
0057     stfs    0,0(r4);                        \
0058     mffs    0;                          \
0059     stfd    0,0(r3);        /* save new fpscr value */  \
0060     blr
0061 
0062 /*
0063  * Single operation with three input operands
0064  *
0065  * R3 = (double*)&fpscr
0066  * R4 = (short*)&result
0067  * R5 = (short*)&param1
0068  * R6 = (short*)&param2
0069  * R7 = (short*)&param3
0070  */
0071 #define FPS_THREE_IN(name)                  \
0072 _GLOBAL(fps_ ## name);                          \
0073     lfd 0,0(r3);        /* load up fpscr value */   \
0074     MTFSF_L(0);                         \
0075     lfs 0,0(r5);                        \
0076     lfs 1,0(r6);                        \
0077     lfs 2,0(r7);                        \
0078                                     \
0079     name    0,0,1,2;                        \
0080                                     \
0081     stfs    0,0(r4);                        \
0082     mffs    0;                          \
0083     stfd    0,0(r3);        /* save new fpscr value */  \
0084     blr
0085 
0086 FPS_ONE_IN(fres)
0087 FPS_ONE_IN(frsqrte)
0088 FPS_ONE_IN(fsqrts)
0089 FPS_TWO_IN(fadds)
0090 FPS_TWO_IN(fdivs)
0091 FPS_TWO_IN(fmuls)
0092 FPS_TWO_IN(fsubs)
0093 FPS_THREE_IN(fmadds)
0094 FPS_THREE_IN(fmsubs)
0095 FPS_THREE_IN(fnmadds)
0096 FPS_THREE_IN(fnmsubs)
0097 FPS_THREE_IN(fsel)
0098 
0099 
0100 /* Instructions operating on double parameters */
0101 
0102 /*
0103  * Beginning of double instruction processing
0104  *
0105  * R3 = (double*)&fpscr
0106  * R4 = (u32*)&cr
0107  * R5 = (double*)&result
0108  * R6 = (double*)&param1
0109  * R7 = (double*)&param2 [load_two]
0110  * R8 = (double*)&param3 [load_three]
0111  * LR = instruction call function
0112  */
0113 fpd_load_three:
0114     lfd 2,0(r8)         /* load param3 */
0115 fpd_load_two:
0116     lfd 1,0(r7)         /* load param2 */
0117 fpd_load_one:
0118     lfd 0,0(r6)         /* load param1 */
0119 fpd_load_none:
0120     lfd 3,0(r3)         /* load up fpscr value */
0121     MTFSF_L(3)
0122     lwz r6, 0(r4)       /* load cr */
0123     mtcr    r6
0124     blr
0125 
0126 /*
0127  * End of double instruction processing
0128  *
0129  * R3 = (double*)&fpscr
0130  * R4 = (u32*)&cr
0131  * R5 = (double*)&result
0132  * LR = caller of instruction call function
0133  */
0134 fpd_return:
0135     mfcr    r6
0136     stfd    0,0(r5)         /* save result */
0137     mffs    0
0138     stfd    0,0(r3)         /* save new fpscr value */
0139     stw r6,0(r4)        /* save new cr value */
0140     blr
0141 
0142 /*
0143  * Double operation with no input operand
0144  *
0145  * R3 = (double*)&fpscr
0146  * R4 = (u32*)&cr
0147  * R5 = (double*)&result
0148  */
0149 #define FPD_NONE_IN(name)                       \
0150 _GLOBAL(fpd_ ## name);                          \
0151     mflr    r12;                            \
0152     bl  fpd_load_none;                      \
0153     mtlr    r12;                            \
0154                                     \
0155     name.   0;          /* call instruction */      \
0156     b   fpd_return
0157 
0158 /*
0159  * Double operation with one input operand
0160  *
0161  * R3 = (double*)&fpscr
0162  * R4 = (u32*)&cr
0163  * R5 = (double*)&result
0164  * R6 = (double*)&param1
0165  */
0166 #define FPD_ONE_IN(name)                        \
0167 _GLOBAL(fpd_ ## name);                          \
0168     mflr    r12;                            \
0169     bl  fpd_load_one;                       \
0170     mtlr    r12;                            \
0171                                     \
0172     name.   0,0;            /* call instruction */      \
0173     b   fpd_return
0174 
0175 /*
0176  * Double operation with two input operands
0177  *
0178  * R3 = (double*)&fpscr
0179  * R4 = (u32*)&cr
0180  * R5 = (double*)&result
0181  * R6 = (double*)&param1
0182  * R7 = (double*)&param2
0183  * R8 = (double*)&param3
0184  */
0185 #define FPD_TWO_IN(name)                        \
0186 _GLOBAL(fpd_ ## name);                          \
0187     mflr    r12;                            \
0188     bl  fpd_load_two;                       \
0189     mtlr    r12;                            \
0190                                     \
0191     name.   0,0,1;          /* call instruction */      \
0192     b   fpd_return
0193 
0194 /*
0195  * CR Double operation with two input operands
0196  *
0197  * R3 = (double*)&fpscr
0198  * R4 = (u32*)&cr
0199  * R5 = (double*)&param1
0200  * R6 = (double*)&param2
0201  * R7 = (double*)&param3
0202  */
0203 #define FPD_TWO_IN_CR(name)                     \
0204 _GLOBAL(fpd_ ## name);                          \
0205     lfd 1,0(r6);        /* load param2 */       \
0206     lfd 0,0(r5);        /* load param1 */       \
0207     lfd 3,0(r3);        /* load up fpscr value */   \
0208     MTFSF_L(3);                         \
0209     lwz r6, 0(r4);      /* load cr */           \
0210     mtcr    r6;                         \
0211                                     \
0212     name    0,0,1;          /* call instruction */      \
0213     mfcr    r6;                         \
0214     mffs    0;                          \
0215     stfd    0,0(r3);        /* save new fpscr value */  \
0216     stw r6,0(r4);       /* save new cr value */     \
0217     blr
0218 
0219 /*
0220  * Double operation with three input operands
0221  *
0222  * R3 = (double*)&fpscr
0223  * R4 = (u32*)&cr
0224  * R5 = (double*)&result
0225  * R6 = (double*)&param1
0226  * R7 = (double*)&param2
0227  * R8 = (double*)&param3
0228  */
0229 #define FPD_THREE_IN(name)                      \
0230 _GLOBAL(fpd_ ## name);                          \
0231     mflr    r12;                            \
0232     bl  fpd_load_three;                     \
0233     mtlr    r12;                            \
0234                                     \
0235     name.   0,0,1,2;        /* call instruction */      \
0236     b   fpd_return
0237 
0238 FPD_ONE_IN(fsqrts)
0239 FPD_ONE_IN(frsqrtes)
0240 FPD_ONE_IN(fres)
0241 FPD_ONE_IN(frsp)
0242 FPD_ONE_IN(fctiw)
0243 FPD_ONE_IN(fctiwz)
0244 FPD_ONE_IN(fsqrt)
0245 FPD_ONE_IN(fre)
0246 FPD_ONE_IN(frsqrte)
0247 FPD_ONE_IN(fneg)
0248 FPD_ONE_IN(fabs)
0249 FPD_TWO_IN(fadds)
0250 FPD_TWO_IN(fsubs)
0251 FPD_TWO_IN(fdivs)
0252 FPD_TWO_IN(fmuls)
0253 FPD_TWO_IN_CR(fcmpu)
0254 FPD_TWO_IN(fcpsgn)
0255 FPD_TWO_IN(fdiv)
0256 FPD_TWO_IN(fadd)
0257 FPD_TWO_IN(fmul)
0258 FPD_TWO_IN_CR(fcmpo)
0259 FPD_TWO_IN(fsub)
0260 FPD_THREE_IN(fmsubs)
0261 FPD_THREE_IN(fmadds)
0262 FPD_THREE_IN(fnmsubs)
0263 FPD_THREE_IN(fnmadds)
0264 FPD_THREE_IN(fsel)
0265 FPD_THREE_IN(fmsub)
0266 FPD_THREE_IN(fmadd)
0267 FPD_THREE_IN(fnmsub)
0268 FPD_THREE_IN(fnmadd)
0269 
0270 _GLOBAL(kvm_cvt_fd)
0271     lfs 0,0(r3)
0272     stfd    0,0(r4)
0273     blr
0274 
0275 _GLOBAL(kvm_cvt_df)
0276     lfd 0,0(r3)
0277     stfs    0,0(r4)
0278     blr