From fdd524d4ccd2bb0c6f67401e938dabf773eb0372 Mon Sep 17 00:00:00 2001 From: matt Date: Thu, 14 Jul 2016 01:59:18 +0000 Subject: [PATCH] Library which implements the softfloat primitives using FP instructions Currently contains only untested MIPS routines. XXX move arm libc_vfp to here. --- lib/libc_fp/Makefile | 26 +++ lib/libc_fp/arch/mips/Makefile.inc | 8 + lib/libc_fp/arch/mips/fpdf.S | 245 ++++++++++++++++++++++++++++ lib/libc_fp/arch/mips/fpsf.S | 243 +++++++++++++++++++++++++++ lib/libc_fp/arch/mips/shlib_version | 5 + lib/libc_fp/gcc-softfloat.c | 217 ++++++++++++++++++++++++ 6 files changed, 744 insertions(+) create mode 100644 lib/libc_fp/Makefile create mode 100644 lib/libc_fp/arch/mips/Makefile.inc create mode 100644 lib/libc_fp/arch/mips/fpdf.S create mode 100644 lib/libc_fp/arch/mips/fpsf.S create mode 100644 lib/libc_fp/arch/mips/shlib_version create mode 100644 lib/libc_fp/gcc-softfloat.c diff --git a/lib/libc_fp/Makefile b/lib/libc_fp/Makefile new file mode 100644 index 000000000000..d3ca9fd9dc69 --- /dev/null +++ b/lib/libc_fp/Makefile @@ -0,0 +1,26 @@ +# $NetBSD: Makefile,v 1.1 2016/07/14 01:59:18 matt Exp $ +# + +USE_SHLIBDIR= yes + +.include + +LIBC_MACHINE_CPU?= ${MACHINE_CPU} + +.if exists(arch/${LIBC_MACHINE_CPU}) +.include "arch/${LIBC_MACHINE_CPU}/Makefile.inc" +.PATH: ${.CURDIR}/arch/${LIBC_MACHINE_CPU} +.elif exists(arch/${MACHINE_ARCH}) +.include "arch/${MACHINE_ARCH}/Makefile.inc" +.PATH: ${.CURDIR}/arch/${MACHINE_ARCH} +.elif exists(arch/${MACHINE} +.include "arch/${MACHINE}/Makefile.inc" +.PATH: ${.CURDIR}/arch/${MACHINE} +.endif + +.if !empty(SRCS) + +LIB?= c_fp + +.include +.endif diff --git a/lib/libc_fp/arch/mips/Makefile.inc b/lib/libc_fp/arch/mips/Makefile.inc new file mode 100644 index 000000000000..befafed6949c --- /dev/null +++ b/lib/libc_fp/arch/mips/Makefile.inc @@ -0,0 +1,8 @@ +# $NetBSD: Makefile.inc,v 1.1 2016/07/14 01:59:18 matt Exp $ +# + +CPUFLAGS+= -mhard-float + +SRCS= fpsf.S fpdf.S +AFLAGS.vfpsf.S+= -mhard-float +AFLAGS.vfpdf.S+= -mhard-float diff --git a/lib/libc_fp/arch/mips/fpdf.S b/lib/libc_fp/arch/mips/fpdf.S new file mode 100644 index 000000000000..bb740bab0de2 --- /dev/null +++ b/lib/libc_fp/arch/mips/fpdf.S @@ -0,0 +1,245 @@ +/*- + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas of 3am Software Foundry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: fpdf.S,v 1.1 2016/07/14 01:59:18 matt Exp $") + +/* + * This file provides softfloat compatible routines which use FP instructions + * to do the actual work. This should give near hard-float performance while + * being compatible with soft-float code. + * + * This file implements the double precision floating point routines. + */ + +#ifdef MIPS3 +#define COP1_SYNC nop +#else +#define COP1_SYNC +#endif + +LEAF_NOPROFILE(__adddf3) + dmtc1 a0, $f12 + dmtc1 a1, $f14 + COP1_SYNC + add.d $f0, $f12, $f14 + dmfc1 v0, $f0 + jr ra +END(__adddf3) + +LEAF_NOPROFILE(__subdf3) + dmtc1 a0, $f12 + dmtc1 a1, $f14 + COP1_SYNC + sub.d $f0, $f12, $f14 + dmfc1 v0, $f0 + jr ra +END(__subdf3) + +LEAF_NOPROFILE(__muldf3) + dmtc1 a0, $f12 + dmtc1 a1, $f14 + COP1_SYNC + mul.d $f0, $f12, $f14 + dmfc1 v0, $f0 + jr ra +END(__muldf3) + +LEAF_NOPROFILE(__divdf3) + dmtc1 a0, $f12 + dmtc1 a1, $f14 + COP1_SYNC + div.d $f0, $f12, $f14 + dmfc1 v0, $f0 + jr ra +END(__divdf3) + +LEAF_NOPROFILE(__negdf2) + dmtc1 a0, $f12 + COP1_SYNC + neg.d $f0, $f12 + dmfc1 v0, $f0 + jr ra +END(__negdf2) + +LEAF_NOPROFILE(__extendsfdf2) + dmtc1 a0, $f12 + COP1_SYNC + cvt.d.s $f0, $f12 + dmfc1 v0, $f0 + jr ra +END(__extendsfdf2) + +LEAF_NOPROFILE(__fixdfdi) + dmtc1 a0, $f12 + COP1_SYNC + trunc.l.d $f0, $f12 + dmfc1 v0, $f0 + jr ra +END(__fixdfdi) + +LEAF_NOPROFILE(__fixdfsi) + dmtc1 a0, $f12 + COP1_SYNC + trunc.w.d $f0, $f12 + mfc1 v0, $f0 + jr ra +END(__fixdfsi) + +LEAF_NOPROFILE(__fixunsdfdi) + lui t0, 0x43e0 # 9223372036854775808.0 + dsll t0, t0, 32 + mtc1 t0, $f0 + mtc1 a0, $f12 + COP1_SYNC + sub.d $f0, $f12, $f0 # convert to signed + trunc.l.d $f0, $f0 + dmfc1 v0, $f0 + li v1, 1 + dsll v1, v1, 63 + add v0, v0, v1 # convert to unsigned + jr ra +END(__fixunsdfdi) + +LEAF_NOPROFILE(__fixunsdfsi) + lui t0, 0x41e0 # 2147483648.0 + dsll t0, t0, 32 + mtc1 t0, $f0 + mtc1 a0, $f12 + COP1_SYNC + sub.d $f0, $f12, $f0 # convert to signed + trunc.w.d $f0, $f0 + lui v1, 0x8000 # 0xffffffff80000000 + mfc1 v0, $f0 + add v0, v0, v1 # convert to unsigned + jr ra +END(__fixunsdfsi) + +LEAF_NOPROFILE(__floatdidf) + dmtc1 a0, $f12 + COP1_SYNC + cvt.d.l $f0, $f12 + dmfc1 v0, $f0 + jr ra +END(__floatdidf) + +LEAF_NOPROFILE(__floatsidf) + mtc1 a0, $f12 + COP1_SYNC + cvt.d.w $f0, $f12 + dmfc1 v0, $f0 + jr ra +END(__floatsidf) + +LEAF_NOPROFILE(__floatundidf) + li t0, 1 + dsll t0, t0, 63 + dsub a0, a0, t0 + dmtc1 a0, $f12 + dmtc1 t0, $f14 + COP1_SYNC + cvt.d.l $f0, $f12 + cvt.d.l $f2, $f14 + add.d $f0, $f0, $f2 + dmfc1 v0, $f0 + jr ra +END(__floatundidf) + +LEAF_NOPROFILE(__floatunsidf) + sll a0, a0, 0 + dmtc1 a0, $f12 + COP1_SYNC + cvt.d.l $f0, $f12 + dmfc1 v0, $f0 + jr ra +END(__floatunsidf) + +STRONG_ALIAS(__eqdf2, __nedf2) +LEAF_NOPROFILE(__nedf2) + .set push + .set noreorder + dmtc1 a0, $f12 + dmtc1 a1, $f14 + COP1_SYNC + c.eq.d $f12, $f14 + bc1f 2f + li v0, 1 + move v0, zero +2: jr ra + nop + .set pop +END(__nedf2) + +STRONG_ALIAS(__gedf2, __ltdf2) +LEAF_NOPROFILE(__ltdf2) + .set push + .set noreorder + dmtc1 a0, $f12 + dmtc1 a1, $f14 + COP1_SYNC + c.olt.d $f12, $f14 + bc1t 2f + li v0, -1 + move v0, zero +2: jr ra + nop + .set pop +END(__ltdf2) + +STRONG_ALIAS(__gtdf2, __ledf2) +LEAF_NOPROFILE(__ledf2) + .set push + .set noreorder + dmtc1 a0, $f12 + dmtc1 a1, $f14 + COP1_SYNC + c.ole.d $f12, $f14 + bc1f 2f + li v0, 1 + move v0, zero +2: jr ra + nop + .set pop +END(__ledf2) + +LEAF_NOPROFILE(__unorddf2) + .set push + .set noreorder + dmtc1 a0, $f12 + dmtc1 a1, $f14 + COP1_SYNC + c.un.d $f12, $f14 + bc1t 2f + li v0, 1 + move v0, zero +2: jr ra + nop + .set pop +END(__unorddf2) diff --git a/lib/libc_fp/arch/mips/fpsf.S b/lib/libc_fp/arch/mips/fpsf.S new file mode 100644 index 000000000000..b9bf0a1c8597 --- /dev/null +++ b/lib/libc_fp/arch/mips/fpsf.S @@ -0,0 +1,243 @@ +/*- + * Copyright (c) 2016 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas of 3am Software Foundry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +RCSID("$NetBSD: fpsf.S,v 1.1 2016/07/14 01:59:18 matt Exp $") + +/* + * This file provides softfloat compatible routines which use FP instructions + * to do the actual work. This should give near hard-float performance while + * being compatible with soft-float code. + * + * This file implements the single precision floating point routines. + */ + +#ifdef MIPS3 +#define COP1_SYNC nop +#else +#define COP1_SYNC +#endif + +LEAF_NOPROFILE(__addsf3) + mtc1 a0, $f12 + mtc1 a1, $f14 + COP1_SYNC + add.s $f0, $f12, $f14 + mfc1 v0, $f0 + jr ra +END(__addsf3) + +LEAF_NOPROFILE(__subsf3) + mtc1 a0, $f12 + mtc1 a1, $f14 + COP1_SYNC + sub.s $f0, $f12, $f14 + mfc1 v0, $f0 + jr ra +END(__subsf3) + +LEAF_NOPROFILE(__mulsf3) + mtc1 a0, $f12 + mtc1 a1, $f14 + COP1_SYNC + mul.s $f0, $f12, $f14 + mfc1 v0, $f0 + jr ra +END(__mulsf3) + +LEAF_NOPROFILE(__divsf3) + mtc1 a0, $f12 + mtc1 a1, $f14 + COP1_SYNC + div.s $f0, $f12, $f14 + mfc1 v0, $f0 + jr ra +END(__divsf3) + +LEAF_NOPROFILE(__negsf2) + mtc1 a0, $f12 + COP1_SYNC + neg.s $f0, $f12 + mfc1 v0, $f0 + jr ra +END(__negsf2) + +LEAF_NOPROFILE(__truncdfsf2) + dmtc1 a0, $f12 + COP1_SYNC + cvt.s.d $f0, $f12 + mfc1 v0, $f0 + jr ra +END(__truncdfsf2) + +LEAF_NOPROFILE(__fixsfdi) + mtc1 a0, $f12 + COP1_SYNC + trunc.l.s $f0, $f12 + dmfc1 v0, $f0 + jr ra +END(__fixsfdi) + +LEAF_NOPROFILE(__fixsfsi) + mtc1 a0, $f12 + COP1_SYNC + trunc.w.s $f0, $f12 + mfc1 v0, $f0 + jr ra +END(__fixsfsi) + +LEAF_NOPROFILE(__fixunssfdi) + lui t0, 0x5f00 # 9223372036854775808.0 + mtc1 t0, $f0 + mtc1 a0, $f12 + COP1_SYNC + sub.s $f0, $f12, $f0 # convert to signed + trunc.l.s $f0, $f0 + dmfc1 v0, $f0 + li v1, 1 + dsll v1, v1, 63 + add v0, v0, v1 # convert to unsigned + jr ra +END(__fixunssfdi) + +LEAF_NOPROFILE(__fixunssfsi) + lui t0, 0x4f00 # 2147483648.0 + mtc1 t0, $f0 + mtc1 a0, $f12 + COP1_SYNC + sub.s $f0, $f12, $f0 # convert to signed + trunc.w.s $f0, $f0 + mfc1 v0, $f0 + lui v1, 0x8000 # 0xffffffff80000000 + add v0, v0, v1 # convert to unsigned + jr ra +END(__fixunssfsi) + +LEAF_NOPROFILE(__floatdisf) + dmtc1 a0, $f12 + COP1_SYNC + cvt.s.l $f0, $f12 + mfc1 v0, $f0 + jr ra +END(__floatdisf) + +LEAF_NOPROFILE(__floatsisf) + mtc1 a0, $f12 + COP1_SYNC + cvt.s.w $f0, $f12 + mfc1 v0, $f0 + jr ra +END(__floatsisf) + +LEAF_NOPROFILE(__floatundisf) + li t0, 1 + dsll t0, t0, 63 # 9223372036854775808.0 + dsub a0, a0, t0 # convert to signed + dmtc1 a0, $f12 + dmtc1 t0, $f14 + COP1_SYNC + cvt.s.l $f0, $f12 + cvt.s.l $f2, $f14 + add.s $f0, $f0, $f2 # convert back to unsigned + mfc1 v0, $f0 + jr ra +END(__floatundisf) + +LEAF_NOPROFILE(__floatunsisf) + sll a0, a0, 0 # sign extend to 64 bits + dmtc1 a0, $f12 + COP1_SYNC + cvt.s.l $f0, $f12 + mfc1 v0, $f0 + jr ra +END(__floatunsisf) + +STRONG_ALIAS(__eqsf2, __nedf2) +LEAF_NOPROFILE(__nesf2) + .set push + .set noreorder + mtc1 a0, $f12 + mtc1 a1, $f14 + COP1_SYNC + c.eq.s $f12, $f14 + bc1f 2f + li v0, 1 + move v0, zero +2: jr ra + nop + .set pop +END(__nesf2) + +STRONG_ALIAS(__gesf2, __ltdf2) +LEAF_NOPROFILE(__ltsf2) + .set push + .set noreorder + mtc1 a0, $f12 + mtc1 a1, $f14 + COP1_SYNC + c.olt.s $f12, $f14 + bc1t 2f + li v0, -1 + move v0, zero +2: jr ra + nop + .set pop +END(__ltsf2) + +STRONG_ALIAS(__gtsf2, __ledf2) +LEAF_NOPROFILE(__lesf2) + .set push + .set noreorder + mtc1 a0, $f12 + mtc1 a1, $f14 + COP1_SYNC + c.ole.s $f12, $f14 + bc1f 2f + li v0, 1 + move v0, zero +2: jr ra + nop + .set pop +END(__lesf2) + +LEAF_NOPROFILE(__unordsf2) + .set push + .set noreorder + mtc1 a0, $f12 + mtc1 a1, $f14 + COP1_SYNC + c.un.s $f12, $f14 + bc1t 2f + li v0, 1 + move v0, zero +2: jr ra + nop + .set pop +END(__unordsf2) diff --git a/lib/libc_fp/arch/mips/shlib_version b/lib/libc_fp/arch/mips/shlib_version new file mode 100644 index 000000000000..7acde61c5cfb --- /dev/null +++ b/lib/libc_fp/arch/mips/shlib_version @@ -0,0 +1,5 @@ +# $NetBSD: shlib_version,v 1.1 2016/07/14 01:59:18 matt Exp $ +# Remember to update distrib/sets/lists/base/shl.* when changing +# +major=0 +minor=0 diff --git a/lib/libc_fp/gcc-softfloat.c b/lib/libc_fp/gcc-softfloat.c new file mode 100644 index 000000000000..e2a5149b8f74 --- /dev/null +++ b/lib/libc_fp/gcc-softfloat.c @@ -0,0 +1,217 @@ +/* $NetBSD: gcc-softfloat.c,v 1.1 2016/07/14 01:59:18 matt Exp $ */ +/*- + * Copyright (c) 2016 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas of 3am Software Foundry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This contain the softfloat primitives used by GCC. + * It can be used to verify the functions invoked by tGCC to do softfloat. + * It can also be used to what FP instructions GCC generates to implement the + * various primitives. Your arch-dependent code should provide all of these + * that are easy to implement. + */ + +long long +xfixdfdi(double a) +{ + return (long long)a; +} + +int +xfixdfsi(double a) +{ + return (int)a; +} + +unsigned long long +xfixunsdfdi(double a) +{ + return (unsigned long long)a; +} + +unsigned int +xfixunsdfsi(double a) +{ + return (unsigned int)a; +} + +double +xfloatundidf(unsigned long long a) +{ + return (double) a; +} + +double +xfloatunsidf(unsigned int a) +{ + return (double) a; +} + +double +xfloatdidf(long long a) +{ + return (double) a; +} + +double +xfloatsidf(int a) +{ + return (double) a; +} + +double +xextendsfdf2(float a) +{ + return (double) a; +} + +int +xeqdf2(double a, double b) +{ + return a == b; +} + +int +xnedf2(double a, double b) +{ + return a != b; +} + +int +xledf2(double a, double b) +{ + return a <= b; +} + +int +xgtdf2(double a, double b) +{ + return a > b; +} + +int +xltdf2(double a, double b) +{ + return a < b; +} + +int +xgedf2(double a, double b) +{ + return a >= b; +} + +long long +xfixsfdi(float a) +{ + return (long long)a; +} + +int +xfixsfsi(float a) +{ + return (int)a; +} + +unsigned long long +xfixunssfdi(float a) +{ + return (unsigned long long)a; +} + +unsigned int +xfixunssfsi(float a) +{ + return (unsigned int)a; +} + +float +xfloatundisf(unsigned long long a) +{ + return (float) a; +} + +float +xfloatunsisf(unsigned int a) +{ + return (float) a; +} + +float +xfloatdisf(long long a) +{ + return (float) a; +} + +float +xfloatsisf(int a) +{ + return (float) a; +} + +float +xtruncdfsf2(double a) +{ + return (float) a; +} + +int +xeqsf2(float a, float b) +{ + return a == b; +} + +int +xnesf2(float a, float b) +{ + return a != b; +} + +int +xlesf2(float a, float b) +{ + return a <= b; +} + +int +xgtsf2(float a, float b) +{ + return a > b; +} + +int +xltsf2(float a, float b) +{ + return a < b; +} + +int +xgesf2(float a, float b) +{ + return a >= b; +}