[PATCH] powerpc/math-emu: Use kernel generic math-emu code
Liu Yu-B13201
Yu.Liu at freescale.com
Wed Sep 24 14:28:48 EST 2008
>
> diff --git a/arch/powerpc/include/asm/sfp-machine.h
> b/arch/powerpc/include/asm/sfp-machine.h
> new file mode 100644
> index 0000000..ced34f1
> --- /dev/null
> +++ b/arch/powerpc/include/asm/sfp-machine.h
> @@ -0,0 +1,353 @@
> +/* Machine-dependent software floating-point definitions.
> PPC version.
> + Copyright (C) 1997 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Library General
> Public License as
> + published by the Free Software Foundation; either version 2 of the
> + License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will
> be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Library General Public License for more details.
> +
> + You should have received a copy of the GNU Library General Public
> + License along with the GNU C Library; see the file
> COPYING.LIB. If
> + not, write to the Free Software Foundation, Inc.,
> + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> +
> + Actually, this is a PPC (32bit) version, written based on the
> + i386, sparc, and sparc64 versions, by me,
> + Peter Maydell (pmaydell at chiark.greenend.org.uk).
> + Comments are by and large also mine, although they may be
> inaccurate.
> +
> + In picking out asm fragments I've gone with the lowest common
> + denominator, which also happens to be the hardware I have :->
> + That is, a SPARC without hardware multiply and divide.
> + */
> +
> +/* basic word size definitions */
> +#define _FP_W_TYPE_SIZE 32
> +#define _FP_W_TYPE unsigned long
> +#define _FP_WS_TYPE signed long
> +#define _FP_I_TYPE long
> +
> +#define __ll_B ((UWtype) 1 <<
> (W_TYPE_SIZE / 2))
> +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
> +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
> +
> +/* You can optionally code some things like addition in asm. For
> + * example, i386 defines __FP_FRAC_ADD_2 as asm. If you don't
> + * then you get a fragment of C code [if you change an #ifdef 0
> + * in op-2.h] or a call to add_ssaaaa (see below).
> + * Good places to look for asm fragments to use are gcc and glibc.
> + * gcc's longlong.h is useful.
> + */
> +
> +/* We need to know how to multiply and divide. If the host word size
> + * is >= 2*fracbits you can use FP_MUL_MEAT_n_imm(t,R,X,Y) which
> + * codes the multiply with whatever gcc does to 'a * b'.
> + * _FP_MUL_MEAT_n_wide(t,R,X,Y,f) is used when you have an asm
> + * function that can multiply two 1W values and get a 2W result.
> + * Otherwise you're stuck with _FP_MUL_MEAT_n_hard(t,R,X,Y) which
> + * does bitshifting to avoid overflow.
> + * For division there is FP_DIV_MEAT_n_imm(t,R,X,Y,f) for word size
> + * >= 2*fracbits, where f is either _FP_DIV_HELP_imm or
> + * _FP_DIV_HELP_ldiv (see op-1.h).
> + * _FP_DIV_MEAT_udiv() is if you have asm to do 2W/1W => (1W, 1W).
> + * [GCC and glibc have longlong.h which has the asm macro udiv_qrnnd
> + * to do this.]
> + * In general, 'n' is the number of words required to hold the type,
> + * and 't' is either S, D or Q for single/double/quad.
> + * -- PMM
> + */
> +/* Example: SPARC64:
> + * #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_imm(S,R,X,Y)
> + * #define _FP_MUL_MEAT_D(R,X,Y)
> _FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm)
> + * #define _FP_MUL_MEAT_Q(R,X,Y)
> _FP_MUL_MEAT_2_wide(Q,R,X,Y,umul_ppmm)
> + *
> + * #define _FP_DIV_MEAT_S(R,X,Y)
> _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
> + * #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv(D,R,X,Y)
> + * #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv_64(Q,R,X,Y)
> + *
> + * Example: i386:
> + * #define _FP_MUL_MEAT_S(R,X,Y)
> _FP_MUL_MEAT_1_wide(S,R,X,Y,_i386_mul_32_64)
> + * #define _FP_MUL_MEAT_D(R,X,Y)
> _FP_MUL_MEAT_2_wide(D,R,X,Y,_i386_mul_32_64)
> + *
> + * #define _FP_DIV_MEAT_S(R,X,Y)
> _FP_DIV_MEAT_1_udiv(S,R,X,Y,_i386_div_64_32)
> + * #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(_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)
It seems _FP_DIV_MEAT_S() should be defined to
_FP_DIV_MEAT_1_udiv_norm().
I can't remember very clear, but it seems single point float need to be
normalized before calling udiv_qrnnd.
More information about the Linuxppc-dev
mailing list