Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include "fpa11.h"
#include "softfloat.h"
#include "fpopcode.h"
#include <asm/uaccess.h>
-static inline void loadSingle(const unsigned int Fn, const unsigned int *pMem)
+static inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
fpa11->fType[Fn] = typeSingle;
get_user(fpa11->fpreg[Fn].fSingle, pMem);
}
-static inline void loadDouble(const unsigned int Fn, const unsigned int *pMem)
+static inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
unsigned int *p;
p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
fpa11->fType[Fn] = typeDouble;
+#ifdef __ARMEB__
+ get_user(p[0], &pMem[0]); /* sign & exponent */
+ get_user(p[1], &pMem[1]);
+#else
get_user(p[0], &pMem[1]);
get_user(p[1], &pMem[0]); /* sign & exponent */
+#endif
}
#ifdef CONFIG_FPE_NWFPE_XP
-static inline void loadExtended(const unsigned int Fn, const unsigned int *pMem)
+static inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
unsigned int *p;
p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
fpa11->fType[Fn] = typeExtended;
get_user(p[0], &pMem[0]); /* sign & exponent */
+#ifdef __ARMEB__
+ get_user(p[1], &pMem[1]); /* ms bits */
+ get_user(p[2], &pMem[2]); /* ls bits */
+#else
get_user(p[1], &pMem[2]); /* ls bits */
get_user(p[2], &pMem[1]); /* ms bits */
+#endif
}
#endif
-static inline void loadMultiple(const unsigned int Fn, const unsigned int *pMem)
+static inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
register unsigned int *p;
}
}
-static inline void storeSingle(const unsigned int Fn, unsigned int *pMem)
+static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union {
switch (fpa11->fType[Fn]) {
case typeDouble:
- val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
+ val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
- val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
+ val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
break;
#endif
put_user(val.i[0], pMem);
}
-static inline void storeDouble(const unsigned int Fn, unsigned int *pMem)
+static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union {
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
- val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
+ val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
break;
#endif
val.f = fpa11->fpreg[Fn].fDouble;
}
+#ifdef __ARMEB__
+ put_user(val.i[0], &pMem[0]); /* msw */
+ put_user(val.i[1], &pMem[1]); /* lsw */
+#else
put_user(val.i[1], &pMem[0]); /* msw */
put_user(val.i[0], &pMem[1]); /* lsw */
+#endif
}
#ifdef CONFIG_FPE_NWFPE_XP
-static inline void storeExtended(const unsigned int Fn, unsigned int *pMem)
+static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union {
}
put_user(val.i[0], &pMem[0]); /* sign & exp */
+#ifdef __ARMEB__
+ put_user(val.i[1], &pMem[1]); /* msw */
+ put_user(val.i[2], &pMem[2]);
+#else
put_user(val.i[1], &pMem[2]);
put_user(val.i[2], &pMem[1]); /* msw */
+#endif
}
#endif
-static inline void storeMultiple(const unsigned int Fn, unsigned int *pMem)
+static inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
register unsigned int nType, *p;
unsigned int PerformLDF(const unsigned int opcode)
{
- unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
- write_back = WRITE_BACK(opcode);
+ unsigned int __user *pBase, *pAddress, *pFinal;
+ unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
- pBase = (unsigned int *) readRegister(getRn(opcode));
+ pBase = (unsigned int __user *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
if (write_back)
- writeRegister(getRn(opcode), (unsigned int) pFinal);
+ writeRegister(getRn(opcode), (unsigned long) pFinal);
return nRc;
}
unsigned int PerformSTF(const unsigned int opcode)
{
- unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
- write_back = WRITE_BACK(opcode);
+ unsigned int __user *pBase, *pAddress, *pFinal;
+ unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
+ struct roundingData roundData;
- SetRoundingMode(ROUND_TO_NEAREST);
+ roundData.mode = SetRoundingMode(opcode);
+ roundData.precision = SetRoundingPrecision(opcode);
+ roundData.exception = 0;
- pBase = (unsigned int *) readRegister(getRn(opcode));
+ pBase = (unsigned int __user *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
switch (opcode & MASK_TRANSFER_LENGTH) {
case TRANSFER_SINGLE:
- storeSingle(getFd(opcode), pAddress);
+ storeSingle(&roundData, getFd(opcode), pAddress);
break;
case TRANSFER_DOUBLE:
- storeDouble(getFd(opcode), pAddress);
+ storeDouble(&roundData, getFd(opcode), pAddress);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case TRANSFER_EXTENDED:
nRc = 0;
}
+ if (roundData.exception)
+ float_raise(roundData.exception);
+
if (write_back)
- writeRegister(getRn(opcode), (unsigned int) pFinal);
+ writeRegister(getRn(opcode), (unsigned long) pFinal);
return nRc;
}
unsigned int PerformLFM(const unsigned int opcode)
{
- unsigned int i, Fd, *pBase, *pAddress, *pFinal,
- write_back = WRITE_BACK(opcode);
+ unsigned int __user *pBase, *pAddress, *pFinal;
+ unsigned int i, Fd, write_back = WRITE_BACK(opcode);
- pBase = (unsigned int *) readRegister(getRn(opcode));
+ pBase = (unsigned int __user *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
if (write_back)
- writeRegister(getRn(opcode), (unsigned int) pFinal);
+ writeRegister(getRn(opcode), (unsigned long) pFinal);
return 1;
}
unsigned int PerformSFM(const unsigned int opcode)
{
- unsigned int i, Fd, *pBase, *pAddress, *pFinal,
- write_back = WRITE_BACK(opcode);
+ unsigned int __user *pBase, *pAddress, *pFinal;
+ unsigned int i, Fd, write_back = WRITE_BACK(opcode);
- pBase = (unsigned int *) readRegister(getRn(opcode));
+ pBase = (unsigned int __user *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
if (write_back)
- writeRegister(getRn(opcode), (unsigned int) pFinal);
+ writeRegister(getRn(opcode), (unsigned long) pFinal);
return 1;
}