Skip to content

Commit

Permalink
powerpc/math-emu: Use kernel generic math-emu code
Browse files Browse the repository at this point in the history
The math emulation code is centered around a set of generic macros that
provide the core of the emulation that are shared by the various
architectures and other projects (like glibc).  Each arch implements its
own sfp-machine.h to specific various arch specific details.

For historic reasons that are now lost the powerpc math-emu code had
its own version of the common headers.  This moves us to using the
kernel generic version and thus getting fixes when those are updated.

Also cleaned up exception/error reporting from the FP emulation functions.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
  • Loading branch information
Kumar Gala committed Oct 1, 2008
1 parent a969e76 commit d2b194e
Show file tree
Hide file tree
Showing 45 changed files with 323 additions and 2,266 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,90 +79,51 @@
* #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
*/

#define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(S,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(D,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)

#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y)
#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y)
#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)

/* These macros define what NaN looks like. They're supposed to expand to
* a comma-separated set of 32bit unsigned ints that encode NaN.
*/
#define _FP_NANFRAC_S _FP_QNANBIT_S
#define _FP_NANFRAC_D _FP_QNANBIT_D, 0
#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0
#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
#define _FP_NANSIGN_S 0
#define _FP_NANSIGN_D 0
#define _FP_NANSIGN_Q 0

#define _FP_KEEPNANFRACP 1

/* Exception flags. We use the bit positions of the appropriate bits
in the FPSCR, which also correspond to the FE_* bits. This makes
everything easier ;-). */
#define FP_EX_INVALID (1 << (31 - 2))
#define FP_EX_INVALID_SNAN EFLAG_VXSNAN
#define FP_EX_INVALID_ISI EFLAG_VXISI
#define FP_EX_INVALID_IDI EFLAG_VXIDI
#define FP_EX_INVALID_ZDZ EFLAG_VXZDZ
#define FP_EX_INVALID_IMZ EFLAG_VXIMZ
#define FP_EX_OVERFLOW (1 << (31 - 3))
#define FP_EX_UNDERFLOW (1 << (31 - 4))
#define FP_EX_DIVZERO (1 << (31 - 5))
#define FP_EX_INEXACT (1 << (31 - 6))

/* This macro appears to be called when both X and Y are NaNs, and
* has to choose one and copy it to R. i386 goes for the larger of the
* two, sparc64 just picks Y. I don't understand this at all so I'll
* go with sparc64 because it's shorter :-> -- PMM
*/
#define _FP_CHOOSENAN(fs, wc, R, X, Y) \
#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
do { \
R##_s = Y##_s; \
_FP_FRAC_COPY_##wc(R,Y); \
R##_c = FP_CLS_NAN; \
} while (0)


extern void fp_unpack_d(long *, unsigned long *, unsigned long *,
long *, long *, void *);
extern int fp_pack_d(void *, long, unsigned long, unsigned long, long, long);
extern int fp_pack_ds(void *, long, unsigned long, unsigned long, long, long);

#define __FP_UNPACK_RAW_1(fs, X, val) \
do { \
union _FP_UNION_##fs *_flo = \
(union _FP_UNION_##fs *)val; \
\
X##_f = _flo->bits.frac; \
X##_e = _flo->bits.exp; \
X##_s = _flo->bits.sign; \
} while (0)

#define __FP_UNPACK_RAW_2(fs, X, val) \
do { \
union _FP_UNION_##fs *_flo = \
(union _FP_UNION_##fs *)val; \
\
X##_f0 = _flo->bits.frac0; \
X##_f1 = _flo->bits.frac1; \
X##_e = _flo->bits.exp; \
X##_s = _flo->bits.sign; \
} while (0)

#define __FP_UNPACK_S(X,val) \
do { \
__FP_UNPACK_RAW_1(S,X,val); \
_FP_UNPACK_CANONICAL(S,1,X); \
} while (0)

#define __FP_UNPACK_D(X,val) \
fp_unpack_d(&X##_s, &X##_f1, &X##_f0, &X##_e, &X##_c, val)

#define __FP_PACK_RAW_1(fs, val, X) \
do { \
union _FP_UNION_##fs *_flo = \
(union _FP_UNION_##fs *)val; \
\
_flo->bits.frac = X##_f; \
_flo->bits.exp = X##_e; \
_flo->bits.sign = X##_s; \
} while (0)

#define __FP_PACK_RAW_2(fs, val, X) \
do { \
union _FP_UNION_##fs *_flo = \
(union _FP_UNION_##fs *)val; \
\
_flo->bits.frac0 = X##_f0; \
_flo->bits.frac1 = X##_f1; \
_flo->bits.exp = X##_e; \
_flo->bits.sign = X##_s; \
} while (0)

#include <linux/kernel.h>
#include <linux/sched.h>

Expand All @@ -182,15 +143,30 @@ extern int fp_pack_ds(void *, long, unsigned long, unsigned long, long, long);
#define __FP_PACK_S(val,X) \
({ int __exc = _FP_PACK_CANONICAL(S,1,X); \
if(!__exc || !__FPU_TRAP_P(__exc)) \
__FP_PACK_RAW_1(S,val,X); \
_FP_PACK_RAW_1_P(S,val,X); \
__exc; \
})

#define __FP_PACK_D(val,X) \
fp_pack_d(val, X##_s, X##_f1, X##_f0, X##_e, X##_c)

#define __FP_PACK_DS(val,X) \
fp_pack_ds(val, X##_s, X##_f1, X##_f0, X##_e, X##_c)
do { \
_FP_PACK_CANONICAL(D, 2, X); \
if (!FP_CUR_EXCEPTIONS || !__FPU_TRAP_P(FP_CUR_EXCEPTIONS)) \
_FP_PACK_RAW_2_P(D, val, X); \
} while (0)

#define __FP_PACK_DS(val,X) \
do { \
FP_DECL_S(__X); \
FP_CONV(S, D, 1, 2, __X, X); \
_FP_PACK_CANONICAL(S, 1, __X); \
if (!FP_CUR_EXCEPTIONS || !__FPU_TRAP_P(FP_CUR_EXCEPTIONS)) { \
_FP_UNPACK_CANONICAL(S, 1, __X); \
FP_CONV(D, S, 2, 1, X, __X); \
_FP_PACK_CANONICAL(D, 2, X); \
if (!FP_CUR_EXCEPTIONS || !__FPU_TRAP_P(FP_CUR_EXCEPTIONS)) \
_FP_PACK_RAW_2_P(D, val, X); \
} \
} while (0)

/* Obtain the current rounding mode. */
#define FP_ROUNDMODE \
Expand Down
7 changes: 4 additions & 3 deletions arch/powerpc/math-emu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ obj-y := math.o fmr.o lfd.o stfd.o
obj-$(CONFIG_MATH_EMULATION) += fabs.o fadd.o fadds.o fcmpo.o fcmpu.o \
fctiw.o fctiwz.o fdiv.o fdivs.o \
fmadd.o fmadds.o fmsub.o fmsubs.o \
fmul.o fmuls.o fnabs.o fneg.o types.o \
fmul.o fmuls.o fnabs.o fneg.o \
fnmadd.o fnmadds.o fnmsub.o fnmsubs.o \
fres.o frsp.o frsqrte.o fsel.o lfs.o \
fsqrt.o fsqrts.o fsub.o fsubs.o \
mcrfs.o mffs.o mtfsb0.o mtfsb1.o \
mtfsf.o mtfsfi.o stfiwx.o stfs.o \
udivmodti4.o
mtfsf.o mtfsfi.o stfiwx.o stfs.o

CFLAGS_fabs.o = -fno-builtin-fabs
CFLAGS_math.o = -fno-builtin-fabs

EXTRA_CFLAGS = -I. -Iinclude/math-emu -w
129 changes: 0 additions & 129 deletions arch/powerpc/math-emu/double.h

This file was deleted.

17 changes: 9 additions & 8 deletions arch/powerpc/math-emu/fadd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,38 @@
#include <linux/errno.h>
#include <asm/uaccess.h>

#include "soft-fp.h"
#include "double.h"
#include <asm/sfp-machine.h>
#include <math-emu/soft-fp.h>
#include <math-emu/double.h>

int
fadd(void *frD, void *frA, void *frB)
{
FP_DECL_D(A);
FP_DECL_D(B);
FP_DECL_D(R);
FP_DECL_EX;
int ret = 0;

#ifdef DEBUG
printk("%s: %p %p %p\n", __func__, frD, frA, frB);
#endif

__FP_UNPACK_D(A, frA);
__FP_UNPACK_D(B, frB);
FP_UNPACK_DP(A, frA);
FP_UNPACK_DP(B, frB);

#ifdef DEBUG
printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
#endif

if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
ret |= EFLAG_VXISI;

FP_ADD_D(R, A, B);

#ifdef DEBUG
printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
#endif

return (ret | __FP_PACK_D(frD, R));
__FP_PACK_D(frD, R);

return FP_CUR_EXCEPTIONS;
}
20 changes: 10 additions & 10 deletions arch/powerpc/math-emu/fadds.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,38 @@
#include <linux/errno.h>
#include <asm/uaccess.h>

#include "soft-fp.h"
#include "double.h"
#include "single.h"
#include <asm/sfp-machine.h>
#include <math-emu/soft-fp.h>
#include <math-emu/double.h>
#include <math-emu/single.h>

int
fadds(void *frD, void *frA, void *frB)
{
FP_DECL_D(A);
FP_DECL_D(B);
FP_DECL_D(R);
int ret = 0;
FP_DECL_EX;

#ifdef DEBUG
printk("%s: %p %p %p\n", __func__, frD, frA, frB);
#endif

__FP_UNPACK_D(A, frA);
__FP_UNPACK_D(B, frB);
FP_UNPACK_DP(A, frA);
FP_UNPACK_DP(B, frB);

#ifdef DEBUG
printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
#endif

if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
ret |= EFLAG_VXISI;

FP_ADD_D(R, A, B);

#ifdef DEBUG
printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
#endif

return (ret | __FP_PACK_DS(frD, R));
__FP_PACK_DS(frD, R);

return FP_CUR_EXCEPTIONS;
}
Loading

0 comments on commit d2b194e

Please sign in to comment.