[ARM] 3118/1: fix and reenable nwfpe extended precision emulation for big-endian
Patch from Lennert Buytenhek nwfpe extended precision emulation used to be broken on big-endian and was therefore disabled. This patch fixes nwfpe so that it copies extended precision floats to/from userspace in the proper word order (similar to patch #2046, see the description of that patch for an explanation) and reenables the Kconfig option. Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
committed by
Russell King
parent
06c03cac94
commit
bedf142b8b
@@ -585,7 +585,7 @@ config FPE_NWFPE
|
|||||||
|
|
||||||
config FPE_NWFPE_XP
|
config FPE_NWFPE_XP
|
||||||
bool "Support extended precision"
|
bool "Support extended precision"
|
||||||
depends on FPE_NWFPE && !CPU_BIG_ENDIAN
|
depends on FPE_NWFPE
|
||||||
help
|
help
|
||||||
Say Y to include 80-bit support in the kernel floating-point
|
Say Y to include 80-bit support in the kernel floating-point
|
||||||
emulator. Otherwise, only 32 and 64-bit support is compiled in.
|
emulator. Otherwise, only 32 and 64-bit support is compiled in.
|
||||||
|
@@ -60,7 +60,7 @@ typedef union tagFPREG {
|
|||||||
#ifdef CONFIG_FPE_NWFPE_XP
|
#ifdef CONFIG_FPE_NWFPE_XP
|
||||||
floatx80 fExtended;
|
floatx80 fExtended;
|
||||||
#else
|
#else
|
||||||
int padding[3];
|
u32 padding[3];
|
||||||
#endif
|
#endif
|
||||||
} FPREG;
|
} FPREG;
|
||||||
|
|
||||||
|
@@ -59,8 +59,13 @@ static inline void loadExtended(const unsigned int Fn, const unsigned int __user
|
|||||||
p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
|
p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
|
||||||
fpa11->fType[Fn] = typeExtended;
|
fpa11->fType[Fn] = typeExtended;
|
||||||
get_user(p[0], &pMem[0]); /* sign & exponent */
|
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[1], &pMem[2]); /* ls bits */
|
||||||
get_user(p[2], &pMem[1]); /* ms bits */
|
get_user(p[2], &pMem[1]); /* ms bits */
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -177,8 +182,13 @@ static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMe
|
|||||||
}
|
}
|
||||||
|
|
||||||
put_user(val.i[0], &pMem[0]); /* sign & exp */
|
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[1], &pMem[2]);
|
||||||
put_user(val.i[2], &pMem[1]); /* msw */
|
put_user(val.i[2], &pMem[1]); /* msw */
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -51,12 +51,17 @@ input or output the `floatx80' type will be defined.
|
|||||||
Software IEC/IEEE floating-point types.
|
Software IEC/IEEE floating-point types.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
typedef unsigned long int float32;
|
typedef u32 float32;
|
||||||
typedef unsigned long long float64;
|
typedef u64 float64;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned short high;
|
#ifdef __ARMEB__
|
||||||
unsigned short __padding;
|
u16 __padding;
|
||||||
unsigned long long low;
|
u16 high;
|
||||||
|
#else
|
||||||
|
u16 high;
|
||||||
|
u16 __padding;
|
||||||
|
#endif
|
||||||
|
u64 low;
|
||||||
} floatx80;
|
} floatx80;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user