root/arch/arm/nwfpe/fpa11_cpdt.c

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

DEFINITIONS

This source file includes following definitions.
  1. loadSingle
  2. loadDouble
  3. loadExtended
  4. loadMultiple
  5. storeSingle
  6. storeDouble
  7. storeExtended
  8. storeMultiple
  9. PerformLDF
  10. PerformSTF
  11. PerformLFM
  12. PerformSFM
  13. EmulateCPDT

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3     NetWinder Floating Point Emulator
   4     (c) Rebel.com, 1998-1999
   5     (c) Philip Blundell, 1998, 2001
   6 
   7     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
   8 
   9 */
  10 
  11 #include "fpa11.h"
  12 #include "softfloat.h"
  13 #include "fpopcode.h"
  14 #include "fpmodule.h"
  15 #include "fpmodule.inl"
  16 
  17 #include <linux/uaccess.h>
  18 
  19 static inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem)
  20 {
  21         FPA11 *fpa11 = GET_FPA11();
  22         fpa11->fType[Fn] = typeSingle;
  23         get_user(fpa11->fpreg[Fn].fSingle, pMem);
  24 }
  25 
  26 static inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem)
  27 {
  28         FPA11 *fpa11 = GET_FPA11();
  29         unsigned int *p;
  30         p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
  31         fpa11->fType[Fn] = typeDouble;
  32 #ifdef __ARMEB__
  33         get_user(p[0], &pMem[0]);       /* sign & exponent */
  34         get_user(p[1], &pMem[1]);
  35 #else
  36         get_user(p[0], &pMem[1]);
  37         get_user(p[1], &pMem[0]);       /* sign & exponent */
  38 #endif
  39 }
  40 
  41 #ifdef CONFIG_FPE_NWFPE_XP
  42 static inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem)
  43 {
  44         FPA11 *fpa11 = GET_FPA11();
  45         unsigned int *p;
  46         p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
  47         fpa11->fType[Fn] = typeExtended;
  48         get_user(p[0], &pMem[0]);       /* sign & exponent */
  49 #ifdef __ARMEB__
  50         get_user(p[1], &pMem[1]);       /* ms bits */
  51         get_user(p[2], &pMem[2]);       /* ls bits */
  52 #else
  53         get_user(p[1], &pMem[2]);       /* ls bits */
  54         get_user(p[2], &pMem[1]);       /* ms bits */
  55 #endif
  56 }
  57 #endif
  58 
  59 static inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem)
  60 {
  61         FPA11 *fpa11 = GET_FPA11();
  62         register unsigned int *p;
  63         unsigned long x;
  64 
  65         p = (unsigned int *) &(fpa11->fpreg[Fn]);
  66         get_user(x, &pMem[0]);
  67         fpa11->fType[Fn] = (x >> 14) & 0x00000003;
  68 
  69         switch (fpa11->fType[Fn]) {
  70         case typeSingle:
  71         case typeDouble:
  72                 {
  73                         get_user(p[0], &pMem[2]);       /* Single */
  74                         get_user(p[1], &pMem[1]);       /* double msw */
  75                         p[2] = 0;                       /* empty */
  76                 }
  77                 break;
  78 
  79 #ifdef CONFIG_FPE_NWFPE_XP
  80         case typeExtended:
  81                 {
  82                         get_user(p[1], &pMem[2]);
  83                         get_user(p[2], &pMem[1]);       /* msw */
  84                         p[0] = (x & 0x80003fff);
  85                 }
  86                 break;
  87 #endif
  88         }
  89 }
  90 
  91 static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
  92 {
  93         FPA11 *fpa11 = GET_FPA11();
  94         union {
  95                 float32 f;
  96                 unsigned int i[1];
  97         } val;
  98 
  99         switch (fpa11->fType[Fn]) {
 100         case typeDouble:
 101                 val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
 102                 break;
 103 
 104 #ifdef CONFIG_FPE_NWFPE_XP
 105         case typeExtended:
 106                 val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
 107                 break;
 108 #endif
 109 
 110         default:
 111                 val.f = fpa11->fpreg[Fn].fSingle;
 112         }
 113 
 114         put_user(val.i[0], pMem);
 115 }
 116 
 117 static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
 118 {
 119         FPA11 *fpa11 = GET_FPA11();
 120         union {
 121                 float64 f;
 122                 unsigned int i[2];
 123         } val;
 124 
 125         switch (fpa11->fType[Fn]) {
 126         case typeSingle:
 127                 val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
 128                 break;
 129 
 130 #ifdef CONFIG_FPE_NWFPE_XP
 131         case typeExtended:
 132                 val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
 133                 break;
 134 #endif
 135 
 136         default:
 137                 val.f = fpa11->fpreg[Fn].fDouble;
 138         }
 139 
 140 #ifdef __ARMEB__
 141         put_user(val.i[0], &pMem[0]);   /* msw */
 142         put_user(val.i[1], &pMem[1]);   /* lsw */
 143 #else
 144         put_user(val.i[1], &pMem[0]);   /* msw */
 145         put_user(val.i[0], &pMem[1]);   /* lsw */
 146 #endif
 147 }
 148 
 149 #ifdef CONFIG_FPE_NWFPE_XP
 150 static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem)
 151 {
 152         FPA11 *fpa11 = GET_FPA11();
 153         union {
 154                 floatx80 f;
 155                 unsigned int i[3];
 156         } val;
 157 
 158         switch (fpa11->fType[Fn]) {
 159         case typeSingle:
 160                 val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
 161                 break;
 162 
 163         case typeDouble:
 164                 val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
 165                 break;
 166 
 167         default:
 168                 val.f = fpa11->fpreg[Fn].fExtended;
 169         }
 170 
 171         put_user(val.i[0], &pMem[0]);   /* sign & exp */
 172 #ifdef __ARMEB__
 173         put_user(val.i[1], &pMem[1]);   /* msw */
 174         put_user(val.i[2], &pMem[2]);
 175 #else
 176         put_user(val.i[1], &pMem[2]);
 177         put_user(val.i[2], &pMem[1]);   /* msw */
 178 #endif
 179 }
 180 #endif
 181 
 182 static inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem)
 183 {
 184         FPA11 *fpa11 = GET_FPA11();
 185         register unsigned int nType, *p;
 186 
 187         p = (unsigned int *) &(fpa11->fpreg[Fn]);
 188         nType = fpa11->fType[Fn];
 189 
 190         switch (nType) {
 191         case typeSingle:
 192         case typeDouble:
 193                 {
 194                         put_user(p[0], &pMem[2]);       /* single */
 195                         put_user(p[1], &pMem[1]);       /* double msw */
 196                         put_user(nType << 14, &pMem[0]);
 197                 }
 198                 break;
 199 
 200 #ifdef CONFIG_FPE_NWFPE_XP
 201         case typeExtended:
 202                 {
 203                         put_user(p[2], &pMem[1]);       /* msw */
 204                         put_user(p[1], &pMem[2]);
 205                         put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
 206                 }
 207                 break;
 208 #endif
 209         }
 210 }
 211 
 212 unsigned int PerformLDF(const unsigned int opcode)
 213 {
 214         unsigned int __user *pBase, *pAddress, *pFinal;
 215         unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
 216 
 217         pBase = (unsigned int __user *) readRegister(getRn(opcode));
 218         if (REG_PC == getRn(opcode)) {
 219                 pBase += 2;
 220                 write_back = 0;
 221         }
 222 
 223         pFinal = pBase;
 224         if (BIT_UP_SET(opcode))
 225                 pFinal += getOffset(opcode);
 226         else
 227                 pFinal -= getOffset(opcode);
 228 
 229         if (PREINDEXED(opcode))
 230                 pAddress = pFinal;
 231         else
 232                 pAddress = pBase;
 233 
 234         switch (opcode & MASK_TRANSFER_LENGTH) {
 235         case TRANSFER_SINGLE:
 236                 loadSingle(getFd(opcode), pAddress);
 237                 break;
 238         case TRANSFER_DOUBLE:
 239                 loadDouble(getFd(opcode), pAddress);
 240                 break;
 241 #ifdef CONFIG_FPE_NWFPE_XP
 242         case TRANSFER_EXTENDED:
 243                 loadExtended(getFd(opcode), pAddress);
 244                 break;
 245 #endif
 246         default:
 247                 nRc = 0;
 248         }
 249 
 250         if (write_back)
 251                 writeRegister(getRn(opcode), (unsigned long) pFinal);
 252         return nRc;
 253 }
 254 
 255 unsigned int PerformSTF(const unsigned int opcode)
 256 {
 257         unsigned int __user *pBase, *pAddress, *pFinal;
 258         unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
 259         struct roundingData roundData;
 260 
 261         roundData.mode = SetRoundingMode(opcode);
 262         roundData.precision = SetRoundingPrecision(opcode);
 263         roundData.exception = 0;
 264 
 265         pBase = (unsigned int __user *) readRegister(getRn(opcode));
 266         if (REG_PC == getRn(opcode)) {
 267                 pBase += 2;
 268                 write_back = 0;
 269         }
 270 
 271         pFinal = pBase;
 272         if (BIT_UP_SET(opcode))
 273                 pFinal += getOffset(opcode);
 274         else
 275                 pFinal -= getOffset(opcode);
 276 
 277         if (PREINDEXED(opcode))
 278                 pAddress = pFinal;
 279         else
 280                 pAddress = pBase;
 281 
 282         switch (opcode & MASK_TRANSFER_LENGTH) {
 283         case TRANSFER_SINGLE:
 284                 storeSingle(&roundData, getFd(opcode), pAddress);
 285                 break;
 286         case TRANSFER_DOUBLE:
 287                 storeDouble(&roundData, getFd(opcode), pAddress);
 288                 break;
 289 #ifdef CONFIG_FPE_NWFPE_XP
 290         case TRANSFER_EXTENDED:
 291                 storeExtended(getFd(opcode), pAddress);
 292                 break;
 293 #endif
 294         default:
 295                 nRc = 0;
 296         }
 297 
 298         if (roundData.exception)
 299                 float_raise(roundData.exception);
 300 
 301         if (write_back)
 302                 writeRegister(getRn(opcode), (unsigned long) pFinal);
 303         return nRc;
 304 }
 305 
 306 unsigned int PerformLFM(const unsigned int opcode)
 307 {
 308         unsigned int __user *pBase, *pAddress, *pFinal;
 309         unsigned int i, Fd, write_back = WRITE_BACK(opcode);
 310 
 311         pBase = (unsigned int __user *) readRegister(getRn(opcode));
 312         if (REG_PC == getRn(opcode)) {
 313                 pBase += 2;
 314                 write_back = 0;
 315         }
 316 
 317         pFinal = pBase;
 318         if (BIT_UP_SET(opcode))
 319                 pFinal += getOffset(opcode);
 320         else
 321                 pFinal -= getOffset(opcode);
 322 
 323         if (PREINDEXED(opcode))
 324                 pAddress = pFinal;
 325         else
 326                 pAddress = pBase;
 327 
 328         Fd = getFd(opcode);
 329         for (i = getRegisterCount(opcode); i > 0; i--) {
 330                 loadMultiple(Fd, pAddress);
 331                 pAddress += 3;
 332                 Fd++;
 333                 if (Fd == 8)
 334                         Fd = 0;
 335         }
 336 
 337         if (write_back)
 338                 writeRegister(getRn(opcode), (unsigned long) pFinal);
 339         return 1;
 340 }
 341 
 342 unsigned int PerformSFM(const unsigned int opcode)
 343 {
 344         unsigned int __user *pBase, *pAddress, *pFinal;
 345         unsigned int i, Fd, write_back = WRITE_BACK(opcode);
 346 
 347         pBase = (unsigned int __user *) readRegister(getRn(opcode));
 348         if (REG_PC == getRn(opcode)) {
 349                 pBase += 2;
 350                 write_back = 0;
 351         }
 352 
 353         pFinal = pBase;
 354         if (BIT_UP_SET(opcode))
 355                 pFinal += getOffset(opcode);
 356         else
 357                 pFinal -= getOffset(opcode);
 358 
 359         if (PREINDEXED(opcode))
 360                 pAddress = pFinal;
 361         else
 362                 pAddress = pBase;
 363 
 364         Fd = getFd(opcode);
 365         for (i = getRegisterCount(opcode); i > 0; i--) {
 366                 storeMultiple(Fd, pAddress);
 367                 pAddress += 3;
 368                 Fd++;
 369                 if (Fd == 8)
 370                         Fd = 0;
 371         }
 372 
 373         if (write_back)
 374                 writeRegister(getRn(opcode), (unsigned long) pFinal);
 375         return 1;
 376 }
 377 
 378 unsigned int EmulateCPDT(const unsigned int opcode)
 379 {
 380         unsigned int nRc = 0;
 381 
 382         if (LDF_OP(opcode)) {
 383                 nRc = PerformLDF(opcode);
 384         } else if (LFM_OP(opcode)) {
 385                 nRc = PerformLFM(opcode);
 386         } else if (STF_OP(opcode)) {
 387                 nRc = PerformSTF(opcode);
 388         } else if (SFM_OP(opcode)) {
 389                 nRc = PerformSFM(opcode);
 390         } else {
 391                 nRc = 0;
 392         }
 393 
 394         return nRc;
 395 }

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