diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/post/lib_powerpc/fpu | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/post/lib_powerpc/fpu')
-rw-r--r-- | roms/u-boot/post/lib_powerpc/fpu/20001122-1.c | 43 | ||||
-rw-r--r-- | roms/u-boot/post/lib_powerpc/fpu/20010114-2.c | 48 | ||||
-rw-r--r-- | roms/u-boot/post/lib_powerpc/fpu/20010226-1.c | 36 | ||||
-rw-r--r-- | roms/u-boot/post/lib_powerpc/fpu/980619-1.c | 42 | ||||
-rw-r--r-- | roms/u-boot/post/lib_powerpc/fpu/Makefile | 18 | ||||
-rw-r--r-- | roms/u-boot/post/lib_powerpc/fpu/acc1.c | 39 | ||||
-rw-r--r-- | roms/u-boot/post/lib_powerpc/fpu/compare-fp-1.c | 207 | ||||
-rw-r--r-- | roms/u-boot/post/lib_powerpc/fpu/darwin-ldouble.c | 119 | ||||
-rw-r--r-- | roms/u-boot/post/lib_powerpc/fpu/fpu.c | 74 | ||||
-rw-r--r-- | roms/u-boot/post/lib_powerpc/fpu/mul-subnormal-single-1.c | 85 |
10 files changed, 711 insertions, 0 deletions
diff --git a/roms/u-boot/post/lib_powerpc/fpu/20001122-1.c b/roms/u-boot/post/lib_powerpc/fpu/20001122-1.c new file mode 100644 index 000000000..4b452dc08 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/20001122-1.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +int fpu_post_test_math1 (void) +{ + volatile double a; + double c, d; + volatile double b; + + d = 1.0; + + do + { + c = d; + d = c * 0.5; + b = 1 + d; + } while (b != 1.0); + + a = 1.0 + c; + + if (a == 1.0) { + post_log ("Error in FPU math1 test\n"); + return -1; + } + + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/20010114-2.c b/roms/u-boot/post/lib_powerpc/fpu/20010114-2.c new file mode 100644 index 000000000..4aadd1e04 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/20010114-2.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +static float rintf (float x) +{ + volatile float TWO23 = 8388608.0; + + if (__builtin_fabs (x) < TWO23) + { + if (x > 0.0) + { + x += TWO23; + x -= TWO23; + } + else if (x < 0.0) + { + x = TWO23 - x; + x = -(x - TWO23); + } + } + + return x; +} + +int fpu_post_test_math2 (void) +{ + if (rintf (-1.5) != -2.0) { + post_log ("Error in FPU math2 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/20010226-1.c b/roms/u-boot/post/lib_powerpc/fpu/20010226-1.c new file mode 100644 index 000000000..b09a25c21 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/20010226-1.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +int fpu_post_test_math3 (void) +{ + volatile long double dfrom = 1.1; + volatile long double m1; + volatile long double m2; + volatile unsigned long mant_long; + + m1 = dfrom / 2.0; + m2 = m1 * 4294967296.0; + mant_long = ((unsigned long) m2) & 0xffffffff; + + if (mant_long != 0x8ccccccc) { + post_log ("Error in FPU math3 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/980619-1.c b/roms/u-boot/post/lib_powerpc/fpu/980619-1.c new file mode 100644 index 000000000..2fea70830 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/980619-1.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +int fpu_post_test_math4 (void) +{ + volatile float reale = 1.0f; + volatile float oneplus; + int i; + + if (sizeof (float) != 4) + return 0; + + for (i = 0; ; i++) + { + oneplus = 1.0f + reale; + if (oneplus == 1.0f) + break; + reale = reale / 2.0f; + } + /* Assumes ieee754 accurate arithmetic above. */ + if (i != 24) { + post_log ("Error in FPU math4 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/Makefile b/roms/u-boot/post/lib_powerpc/fpu/Makefile new file mode 100644 index 000000000..9b2c1fadb --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/Makefile @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +objs-before-objcopy := 20001122-1.o 20010114-2.o 20010226-1.o 980619-1.o \ + acc1.o compare-fp-1.o fpu.o mul-subnormal-single-1.o darwin-ldouble.o +targets += $(objs-before-objcopy) + +# remove -msoft-float flag +$(foreach m, $(objs-before-objcopy), $(eval CFLAGS_REMOVE_$m := -msoft-float)) +ccflags-y := -mhard-float -fkeep-inline-functions + +obj-y := $(objs-before-objcopy:.o=_.o) + +OBJCOPYFLAGS := -R .gnu.attributes +$(obj)/%_.o: $(obj)/%.o FORCE + $(call if_changed,objcopy) diff --git a/roms/u-boot/post/lib_powerpc/fpu/acc1.c b/roms/u-boot/post/lib_powerpc/fpu/acc1.c new file mode 100644 index 000000000..9e5783b25 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/acc1.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +static double func (const double *array) +{ + double d = *array; + + if (d == 0.0) + return d; + else + return d + func (array + 1); +} + +int fpu_post_test_math5 (void) +{ + double values[] = { 0.1e-100, 1.0, -1.0, 0.0 }; + + if (func (values) != 0.1e-100) { + post_log ("Error in FPU math5 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/compare-fp-1.c b/roms/u-boot/post/lib_powerpc/fpu/compare-fp-1.c new file mode 100644 index 000000000..d46a13adc --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/compare-fp-1.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ +/* + * Test for correctness of composite floating-point comparisons. + * Written by Paolo Bonzini, 26th May 2004. + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +static int failed; + +#define TEST(c) if ((c) != ok) failed++ +#define ORD(a, b) (!__builtin_isunordered ((a), (b))) +#define UNORD(a, b) (__builtin_isunordered ((a), (b))) +#define UNEQ(a, b) (__builtin_isunordered ((a), (b)) || ((a) == (b))) +#define UNLT(a, b) (__builtin_isunordered ((a), (b)) || ((a) < (b))) +#define UNLE(a, b) (__builtin_isunordered ((a), (b)) || ((a) <= (b))) +#define UNGT(a, b) (__builtin_isunordered ((a), (b)) || ((a) > (b))) +#define UNGE(a, b) (__builtin_isunordered ((a), (b)) || ((a) >= (b))) +#define LTGT(a, b) (__builtin_islessgreater ((a), (b))) + +static float pinf; +static float ninf; +static float NaN; + +static void iuneq (float x, float y, int ok) +{ + TEST (UNEQ (x, y)); + TEST (!LTGT (x, y)); + TEST (UNLE (x, y) && UNGE (x,y)); +} + +static void ieq (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNEQ (x, y)); +} + +static void iltgt (float x, float y, int ok) +{ + TEST (!UNEQ (x, y)); /* Not optimizable. */ + TEST (LTGT (x, y)); /* Same, __builtin_islessgreater does not trap. */ + TEST (ORD (x, y) && (UNLT (x, y) || UNGT (x,y))); +} + +static void ine (float x, float y, int ok) +{ + TEST (UNLT (x, y) || UNGT (x, y)); +} + +static void iunlt (float x, float y, int ok) +{ + TEST (UNLT (x, y)); + TEST (UNORD (x, y) || (x < y)); +} + +static void ilt (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNLT (x, y)); /* Not optimized */ + TEST ((x <= y) && (x != y)); + TEST ((x <= y) && (y != x)); + TEST ((x != y) && (x <= y)); /* Not optimized */ + TEST ((y != x) && (x <= y)); /* Not optimized */ +} + +static void iunle (float x, float y, int ok) +{ + TEST (UNLE (x, y)); + TEST (UNORD (x, y) || (x <= y)); +} + +static void ile (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNLE (x, y)); /* Not optimized */ + TEST ((x < y) || (x == y)); + TEST ((y > x) || (x == y)); + TEST ((x == y) || (x < y)); /* Not optimized */ + TEST ((y == x) || (x < y)); /* Not optimized */ +} + +static void iungt (float x, float y, int ok) +{ + TEST (UNGT (x, y)); + TEST (UNORD (x, y) || (x > y)); +} + +static void igt (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNGT (x, y)); /* Not optimized */ + TEST ((x >= y) && (x != y)); + TEST ((x >= y) && (y != x)); + TEST ((x != y) && (x >= y)); /* Not optimized */ + TEST ((y != x) && (x >= y)); /* Not optimized */ +} + +static void iunge (float x, float y, int ok) +{ + TEST (UNGE (x, y)); + TEST (UNORD (x, y) || (x >= y)); +} + +static void ige (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNGE (x, y)); /* Not optimized */ + TEST ((x > y) || (x == y)); + TEST ((y < x) || (x == y)); + TEST ((x == y) || (x > y)); /* Not optimized */ + TEST ((y == x) || (x > y)); /* Not optimized */ +} + +int fpu_post_test_math6 (void) +{ + pinf = __builtin_inf (); + ninf = -__builtin_inf (); + NaN = __builtin_nan (""); + + iuneq (ninf, pinf, 0); + iuneq (NaN, NaN, 1); + iuneq (pinf, ninf, 0); + iuneq (1, 4, 0); + iuneq (3, 3, 1); + iuneq (5, 2, 0); + + ieq (1, 4, 0); + ieq (3, 3, 1); + ieq (5, 2, 0); + + iltgt (ninf, pinf, 1); + iltgt (NaN, NaN, 0); + iltgt (pinf, ninf, 1); + iltgt (1, 4, 1); + iltgt (3, 3, 0); + iltgt (5, 2, 1); + + ine (1, 4, 1); + ine (3, 3, 0); + ine (5, 2, 1); + + iunlt (NaN, ninf, 1); + iunlt (pinf, NaN, 1); + iunlt (pinf, ninf, 0); + iunlt (pinf, pinf, 0); + iunlt (ninf, ninf, 0); + iunlt (1, 4, 1); + iunlt (3, 3, 0); + iunlt (5, 2, 0); + + ilt (1, 4, 1); + ilt (3, 3, 0); + ilt (5, 2, 0); + + iunle (NaN, ninf, 1); + iunle (pinf, NaN, 1); + iunle (pinf, ninf, 0); + iunle (pinf, pinf, 1); + iunle (ninf, ninf, 1); + iunle (1, 4, 1); + iunle (3, 3, 1); + iunle (5, 2, 0); + + ile (1, 4, 1); + ile (3, 3, 1); + ile (5, 2, 0); + + iungt (NaN, ninf, 1); + iungt (pinf, NaN, 1); + iungt (pinf, ninf, 1); + iungt (pinf, pinf, 0); + iungt (ninf, ninf, 0); + iungt (1, 4, 0); + iungt (3, 3, 0); + iungt (5, 2, 1); + + igt (1, 4, 0); + igt (3, 3, 0); + igt (5, 2, 1); + + iunge (NaN, ninf, 1); + iunge (pinf, NaN, 1); + iunge (ninf, pinf, 0); + iunge (pinf, pinf, 1); + iunge (ninf, ninf, 1); + iunge (1, 4, 0); + iunge (3, 3, 1); + iunge (5, 2, 1); + + ige (1, 4, 0); + ige (3, 3, 1); + ige (5, 2, 1); + + if (failed) { + post_log ("Error in FPU math6 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/darwin-ldouble.c b/roms/u-boot/post/lib_powerpc/fpu/darwin-ldouble.c new file mode 100644 index 000000000..16105c837 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/darwin-ldouble.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Borrowed from GCC 4.2.2 (which still was GPL v2+) + */ +/* 128-bit long double support routines for Darwin. + Copyright (C) 1993, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + +This file is part of GCC. + */ + +/* + * Implementations of floating-point long double basic arithmetic + * functions called by the IBM C compiler when generating code for + * PowerPC platforms. In particular, the following functions are + * implemented: __gcc_qadd, __gcc_qsub, __gcc_qmul, and __gcc_qdiv. + * Double-double algorithms are based on the paper "Doubled-Precision + * IEEE Standard 754 Floating-Point Arithmetic" by W. Kahan, February 26, + * 1987. An alternative published reference is "Software for + * Doubled-Precision Floating-Point Computations", by Seppo Linnainmaa, + * ACM TOMS vol 7 no 3, September 1981, pages 272-283. + */ + +/* + * Each long double is made up of two IEEE doubles. The value of the + * long double is the sum of the values of the two parts. The most + * significant part is required to be the value of the long double + * rounded to the nearest double, as specified by IEEE. For Inf + * values, the least significant part is required to be one of +0.0 or + * -0.0. No other requirements are made; so, for example, 1.0 may be + * represented as (1.0, +0.0) or (1.0, -0.0), and the low part of a + * NaN is don't-care. + * + * This code currently assumes big-endian. + */ + +#define fabs(x) __builtin_fabs(x) +#define isless(x, y) __builtin_isless(x, y) +#define inf() __builtin_inf() +#define unlikely(x) __builtin_expect((x), 0) +#define nonfinite(a) unlikely(!isless(fabs(a), inf())) + +typedef union { + long double ldval; + double dval[2]; +} longDblUnion; + +/* Add two 'long double' values and return the result. */ +long double __gcc_qadd(double a, double aa, double c, double cc) +{ + longDblUnion x; + double z, q, zz, xh; + + z = a + c; + + if (nonfinite(z)) { + z = cc + aa + c + a; + if (nonfinite(z)) + return z; + x.dval[0] = z; /* Will always be DBL_MAX. */ + zz = aa + cc; + if (fabs(a) > fabs(c)) + x.dval[1] = a - z + c + zz; + else + x.dval[1] = c - z + a + zz; + } else { + q = a - z; + zz = q + c + (a - (q + z)) + aa + cc; + + /* Keep -0 result. */ + if (zz == 0.0) + return z; + + xh = z + zz; + if (nonfinite(xh)) + return xh; + + x.dval[0] = xh; + x.dval[1] = z - xh + zz; + } + return x.ldval; +} + +long double __gcc_qsub(double a, double b, double c, double d) +{ + return __gcc_qadd(a, b, -c, -d); +} + +long double __gcc_qmul(double a, double b, double c, double d) +{ + longDblUnion z; + double t, tau, u, v, w; + + t = a * c; /* Highest order double term. */ + + if (unlikely(t == 0) /* Preserve -0. */ + || nonfinite(t)) + return t; + + /* Sum terms of two highest orders. */ + + /* Use fused multiply-add to get low part of a * c. */ +#ifndef __NO_FPRS__ + asm("fmsub %0,%1,%2,%3" : "=f"(tau) : "f"(a), "f"(c), "f"(t)); +#else + tau = fmsub(a, c, t); +#endif + v = a * d; + w = b * c; + tau += v + w; /* Add in other second-order terms. */ + u = t + tau; + + /* Construct long double result. */ + if (nonfinite(u)) + return u; + z.dval[0] = u; + z.dval[1] = (t - u) + tau; + return z.ldval; +} diff --git a/roms/u-boot/post/lib_powerpc/fpu/fpu.c b/roms/u-boot/post/lib_powerpc/fpu/fpu.c new file mode 100644 index 000000000..0de76ce05 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/fpu.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov <sposelenov@emcraft.com> + */ + +#include <common.h> + +/* + * FPU test + * + * This test checks the arithmetic logic unit (ALU) of CPU. + * It tests independently various groups of instructions using + * run-time modification of the code to reduce the memory footprint. + * For more details refer to post/cpu/ *.c files. + */ + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +#include <watchdog.h> + +extern int fpu_status (void); +extern void fpu_enable (void); +extern void fpu_disable (void); + +extern int fpu_post_test_math1 (void); +extern int fpu_post_test_math2 (void); +extern int fpu_post_test_math3 (void); +extern int fpu_post_test_math4 (void); +extern int fpu_post_test_math5 (void); +extern int fpu_post_test_math6 (void); +extern int fpu_post_test_math7 (void); + +int fpu_post_test (int flags) +{ + int fpu = fpu_status (); + + int ret = 0; + + WATCHDOG_RESET (); + + if (!fpu) + fpu_enable (); + + if (ret == 0) + ret = fpu_post_test_math1 (); + if (ret == 0) + ret = fpu_post_test_math2 (); + if (ret == 0) + ret = fpu_post_test_math3 (); + if (ret == 0) + ret = fpu_post_test_math4 (); + if (ret == 0) + ret = fpu_post_test_math5 (); + if (ret == 0) + ret = fpu_post_test_math6 (); + if (ret == 0) + ret = fpu_post_test_math7 (); + + if (!fpu) + fpu_disable (); + + WATCHDOG_RESET (); + + return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/mul-subnormal-single-1.c b/roms/u-boot/post/lib_powerpc/fpu/mul-subnormal-single-1.c new file mode 100644 index 000000000..cb61c9114 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/mul-subnormal-single-1.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ +/* + * This file is originally a part of the GCC testsuite. + * Check that certain subnormal numbers (formerly known as denormalized + * numbers) are rounded to within 0.5 ulp. PR other/14354. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +union uf +{ + unsigned int u; + float f; +}; + +static float +u2f (unsigned int v) +{ + union uf u; + u.u = v; + return u.f; +} + +static unsigned int +f2u (float v) +{ + union uf u; + u.f = v; + return u.u; +} + +static int ok = 1; + +static void +tstmul (unsigned int ux, unsigned int uy, unsigned int ur) +{ + float x = u2f (ux); + float y = u2f (uy); + + if (f2u (x * y) != ur) + /* Set a variable rather than aborting here, to simplify tracing when + several computations are wrong. */ + ok = 0; +} + +/* We don't want to make this const and static, or else we risk inlining + causing the test to fold as constants at compile-time. */ +struct +{ + unsigned int p1, p2, res; +} static volatile expected[] = +{ + {0xfff, 0x3f800400, 0xfff}, + {0xf, 0x3fc88888, 0x17}, + {0xf, 0x3f844444, 0xf} +}; + +int fpu_post_test_math7 (void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(expected); i++) + { + tstmul (expected[i].p1, expected[i].p2, expected[i].res); + tstmul (expected[i].p2, expected[i].p1, expected[i].res); + } + + if (!ok) { + post_log ("Error in FPU math7 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ |