[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