Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003     NetWinder Floating Point Emulator
0004     (c) Rebel.com, 1998-1999
0005     (c) Philip Blundell, 1998, 2001
0006 
0007     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
0008 
0009 */
0010 
0011 #include "fpa11.h"
0012 #include "softfloat.h"
0013 #include "fpopcode.h"
0014 #include "fpmodule.h"
0015 #include "fpmodule.inl"
0016 
0017 #include <linux/uaccess.h>
0018 
0019 static inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem)
0020 {
0021     FPA11 *fpa11 = GET_FPA11();
0022     fpa11->fType[Fn] = typeSingle;
0023     get_user(fpa11->fpreg[Fn].fSingle, pMem);
0024 }
0025 
0026 static inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem)
0027 {
0028     FPA11 *fpa11 = GET_FPA11();
0029     unsigned int *p;
0030     p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
0031     fpa11->fType[Fn] = typeDouble;
0032 #ifdef __ARMEB__
0033     get_user(p[0], &pMem[0]);   /* sign & exponent */
0034     get_user(p[1], &pMem[1]);
0035 #else
0036     get_user(p[0], &pMem[1]);
0037     get_user(p[1], &pMem[0]);   /* sign & exponent */
0038 #endif
0039 }
0040 
0041 #ifdef CONFIG_FPE_NWFPE_XP
0042 static inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem)
0043 {
0044     FPA11 *fpa11 = GET_FPA11();
0045     unsigned int *p;
0046     p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
0047     fpa11->fType[Fn] = typeExtended;
0048     get_user(p[0], &pMem[0]);   /* sign & exponent */
0049 #ifdef __ARMEB__
0050     get_user(p[1], &pMem[1]);   /* ms bits */
0051     get_user(p[2], &pMem[2]);   /* ls bits */
0052 #else
0053     get_user(p[1], &pMem[2]);   /* ls bits */
0054     get_user(p[2], &pMem[1]);   /* ms bits */
0055 #endif
0056 }
0057 #endif
0058 
0059 static inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem)
0060 {
0061     FPA11 *fpa11 = GET_FPA11();
0062     register unsigned int *p;
0063     unsigned long x;
0064 
0065     p = (unsigned int *) &(fpa11->fpreg[Fn]);
0066     get_user(x, &pMem[0]);
0067     fpa11->fType[Fn] = (x >> 14) & 0x00000003;
0068 
0069     switch (fpa11->fType[Fn]) {
0070     case typeSingle:
0071     case typeDouble:
0072         {
0073             get_user(p[0], &pMem[2]);   /* Single */
0074             get_user(p[1], &pMem[1]);   /* double msw */
0075             p[2] = 0;           /* empty */
0076         }
0077         break;
0078 
0079 #ifdef CONFIG_FPE_NWFPE_XP
0080     case typeExtended:
0081         {
0082             get_user(p[1], &pMem[2]);
0083             get_user(p[2], &pMem[1]);   /* msw */
0084             p[0] = (x & 0x80003fff);
0085         }
0086         break;
0087 #endif
0088     }
0089 }
0090 
0091 static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
0092 {
0093     FPA11 *fpa11 = GET_FPA11();
0094     union {
0095         float32 f;
0096         unsigned int i[1];
0097     } val;
0098 
0099     switch (fpa11->fType[Fn]) {
0100     case typeDouble:
0101         val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
0102         break;
0103 
0104 #ifdef CONFIG_FPE_NWFPE_XP
0105     case typeExtended:
0106         val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
0107         break;
0108 #endif
0109 
0110     default:
0111         val.f = fpa11->fpreg[Fn].fSingle;
0112     }
0113 
0114     put_user(val.i[0], pMem);
0115 }
0116 
0117 static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
0118 {
0119     FPA11 *fpa11 = GET_FPA11();
0120     union {
0121         float64 f;
0122         unsigned int i[2];
0123     } val;
0124 
0125     switch (fpa11->fType[Fn]) {
0126     case typeSingle:
0127         val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
0128         break;
0129 
0130 #ifdef CONFIG_FPE_NWFPE_XP
0131     case typeExtended:
0132         val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
0133         break;
0134 #endif
0135 
0136     default:
0137         val.f = fpa11->fpreg[Fn].fDouble;
0138     }
0139 
0140 #ifdef __ARMEB__
0141     put_user(val.i[0], &pMem[0]);   /* msw */
0142     put_user(val.i[1], &pMem[1]);   /* lsw */
0143 #else
0144     put_user(val.i[1], &pMem[0]);   /* msw */
0145     put_user(val.i[0], &pMem[1]);   /* lsw */
0146 #endif
0147 }
0148 
0149 #ifdef CONFIG_FPE_NWFPE_XP
0150 static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem)
0151 {
0152     FPA11 *fpa11 = GET_FPA11();
0153     union {
0154         floatx80 f;
0155         unsigned int i[3];
0156     } val;
0157 
0158     switch (fpa11->fType[Fn]) {
0159     case typeSingle:
0160         val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
0161         break;
0162 
0163     case typeDouble:
0164         val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
0165         break;
0166 
0167     default:
0168         val.f = fpa11->fpreg[Fn].fExtended;
0169     }
0170 
0171     put_user(val.i[0], &pMem[0]);   /* sign & exp */
0172 #ifdef __ARMEB__
0173     put_user(val.i[1], &pMem[1]);   /* msw */
0174     put_user(val.i[2], &pMem[2]);
0175 #else
0176     put_user(val.i[1], &pMem[2]);
0177     put_user(val.i[2], &pMem[1]);   /* msw */
0178 #endif
0179 }
0180 #endif
0181 
0182 static inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem)
0183 {
0184     FPA11 *fpa11 = GET_FPA11();
0185     register unsigned int nType, *p;
0186 
0187     p = (unsigned int *) &(fpa11->fpreg[Fn]);
0188     nType = fpa11->fType[Fn];
0189 
0190     switch (nType) {
0191     case typeSingle:
0192     case typeDouble:
0193         {
0194             put_user(p[0], &pMem[2]);   /* single */
0195             put_user(p[1], &pMem[1]);   /* double msw */
0196             put_user(nType << 14, &pMem[0]);
0197         }
0198         break;
0199 
0200 #ifdef CONFIG_FPE_NWFPE_XP
0201     case typeExtended:
0202         {
0203             put_user(p[2], &pMem[1]);   /* msw */
0204             put_user(p[1], &pMem[2]);
0205             put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
0206         }
0207         break;
0208 #endif
0209     }
0210 }
0211 
0212 unsigned int PerformLDF(const unsigned int opcode)
0213 {
0214     unsigned int __user *pBase, *pAddress, *pFinal;
0215     unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
0216 
0217     pBase = (unsigned int __user *) readRegister(getRn(opcode));
0218     if (REG_PC == getRn(opcode)) {
0219         pBase += 2;
0220         write_back = 0;
0221     }
0222 
0223     pFinal = pBase;
0224     if (BIT_UP_SET(opcode))
0225         pFinal += getOffset(opcode);
0226     else
0227         pFinal -= getOffset(opcode);
0228 
0229     if (PREINDEXED(opcode))
0230         pAddress = pFinal;
0231     else
0232         pAddress = pBase;
0233 
0234     switch (opcode & MASK_TRANSFER_LENGTH) {
0235     case TRANSFER_SINGLE:
0236         loadSingle(getFd(opcode), pAddress);
0237         break;
0238     case TRANSFER_DOUBLE:
0239         loadDouble(getFd(opcode), pAddress);
0240         break;
0241 #ifdef CONFIG_FPE_NWFPE_XP
0242     case TRANSFER_EXTENDED:
0243         loadExtended(getFd(opcode), pAddress);
0244         break;
0245 #endif
0246     default:
0247         nRc = 0;
0248     }
0249 
0250     if (write_back)
0251         writeRegister(getRn(opcode), (unsigned long) pFinal);
0252     return nRc;
0253 }
0254 
0255 unsigned int PerformSTF(const unsigned int opcode)
0256 {
0257     unsigned int __user *pBase, *pAddress, *pFinal;
0258     unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
0259     struct roundingData roundData;
0260 
0261     roundData.mode = SetRoundingMode(opcode);
0262     roundData.precision = SetRoundingPrecision(opcode);
0263     roundData.exception = 0;
0264 
0265     pBase = (unsigned int __user *) readRegister(getRn(opcode));
0266     if (REG_PC == getRn(opcode)) {
0267         pBase += 2;
0268         write_back = 0;
0269     }
0270 
0271     pFinal = pBase;
0272     if (BIT_UP_SET(opcode))
0273         pFinal += getOffset(opcode);
0274     else
0275         pFinal -= getOffset(opcode);
0276 
0277     if (PREINDEXED(opcode))
0278         pAddress = pFinal;
0279     else
0280         pAddress = pBase;
0281 
0282     switch (opcode & MASK_TRANSFER_LENGTH) {
0283     case TRANSFER_SINGLE:
0284         storeSingle(&roundData, getFd(opcode), pAddress);
0285         break;
0286     case TRANSFER_DOUBLE:
0287         storeDouble(&roundData, getFd(opcode), pAddress);
0288         break;
0289 #ifdef CONFIG_FPE_NWFPE_XP
0290     case TRANSFER_EXTENDED:
0291         storeExtended(getFd(opcode), pAddress);
0292         break;
0293 #endif
0294     default:
0295         nRc = 0;
0296     }
0297 
0298     if (roundData.exception)
0299         float_raise(roundData.exception);
0300 
0301     if (write_back)
0302         writeRegister(getRn(opcode), (unsigned long) pFinal);
0303     return nRc;
0304 }
0305 
0306 unsigned int PerformLFM(const unsigned int opcode)
0307 {
0308     unsigned int __user *pBase, *pAddress, *pFinal;
0309     unsigned int i, Fd, write_back = WRITE_BACK(opcode);
0310 
0311     pBase = (unsigned int __user *) readRegister(getRn(opcode));
0312     if (REG_PC == getRn(opcode)) {
0313         pBase += 2;
0314         write_back = 0;
0315     }
0316 
0317     pFinal = pBase;
0318     if (BIT_UP_SET(opcode))
0319         pFinal += getOffset(opcode);
0320     else
0321         pFinal -= getOffset(opcode);
0322 
0323     if (PREINDEXED(opcode))
0324         pAddress = pFinal;
0325     else
0326         pAddress = pBase;
0327 
0328     Fd = getFd(opcode);
0329     for (i = getRegisterCount(opcode); i > 0; i--) {
0330         loadMultiple(Fd, pAddress);
0331         pAddress += 3;
0332         Fd++;
0333         if (Fd == 8)
0334             Fd = 0;
0335     }
0336 
0337     if (write_back)
0338         writeRegister(getRn(opcode), (unsigned long) pFinal);
0339     return 1;
0340 }
0341 
0342 unsigned int PerformSFM(const unsigned int opcode)
0343 {
0344     unsigned int __user *pBase, *pAddress, *pFinal;
0345     unsigned int i, Fd, write_back = WRITE_BACK(opcode);
0346 
0347     pBase = (unsigned int __user *) readRegister(getRn(opcode));
0348     if (REG_PC == getRn(opcode)) {
0349         pBase += 2;
0350         write_back = 0;
0351     }
0352 
0353     pFinal = pBase;
0354     if (BIT_UP_SET(opcode))
0355         pFinal += getOffset(opcode);
0356     else
0357         pFinal -= getOffset(opcode);
0358 
0359     if (PREINDEXED(opcode))
0360         pAddress = pFinal;
0361     else
0362         pAddress = pBase;
0363 
0364     Fd = getFd(opcode);
0365     for (i = getRegisterCount(opcode); i > 0; i--) {
0366         storeMultiple(Fd, pAddress);
0367         pAddress += 3;
0368         Fd++;
0369         if (Fd == 8)
0370             Fd = 0;
0371     }
0372 
0373     if (write_back)
0374         writeRegister(getRn(opcode), (unsigned long) pFinal);
0375     return 1;
0376 }
0377 
0378 unsigned int EmulateCPDT(const unsigned int opcode)
0379 {
0380     unsigned int nRc = 0;
0381 
0382     if (LDF_OP(opcode)) {
0383         nRc = PerformLDF(opcode);
0384     } else if (LFM_OP(opcode)) {
0385         nRc = PerformLFM(opcode);
0386     } else if (STF_OP(opcode)) {
0387         nRc = PerformSTF(opcode);
0388     } else if (SFM_OP(opcode)) {
0389         nRc = PerformSFM(opcode);
0390     } else {
0391         nRc = 0;
0392     }
0393 
0394     return nRc;
0395 }