Skip to content

Commit 830dc99

Browse files
committed
Support powerpc
This fixes #113, based on files from FreeBSD. Tested on machine hosted by [OSUOSL](http://osuosl.org/services/powerdev/).
1 parent 5cd80c4 commit 830dc99

11 files changed

Lines changed: 415 additions & 8 deletions

File tree

Make.inc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,12 @@ endif
4848
CFLAGS_add += -std=c99 -Wall -I$(OPENLIBM_HOME) -I$(OPENLIBM_HOME)/include -I$(OPENLIBM_HOME)/ld80 -I$(OPENLIBM_HOME)/$(ARCH) -I$(OPENLIBM_HOME)/src -DASSEMBLER -D__BSD_VISIBLE -Wno-implicit-function-declaration
4949

5050
# The optimization flag may be overriden with the environment variable CFLAGS.
51+
ifeq ($(ARCH),powerpc)
52+
# tests hang at higher optimization levels
53+
CFLAGS ?= -O0
54+
else
5155
CFLAGS ?= -O2
56+
endif
5257

5358
default: all
5459

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ include ./Make.inc
33

44
SUBDIRS = src $(ARCH) bsdsrc
55
ifneq ($(ARCH), arm)
6+
ifneq ($(ARCH), powerpc)
67
SUBDIRS += ld80
78
endif
9+
endif
810

911
define INC_template
1012
TEST=test
@@ -26,7 +28,7 @@ OBJS = $(patsubst %.f,%.f.o,\
2628

2729
.PHONY: all check test clean distclean install
2830

29-
all: libopenlibm.a libopenlibm.$(SHLIB_EXT)
31+
all: libopenlibm.a libopenlibm.$(SHLIB_EXT)
3032

3133
check test: test/test-double test/test-float
3234
test/test-double

include/openlibm_fenv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <openlibm_fenv_amd64.h>
99
#elif defined(__i386__)
1010
#include <openlibm_fenv_i387.h>
11+
#elif defined(__powerpc__)
12+
#include <openlibm_fenv_powerpc.h>
1113
#else
1214
#error "Unsupported platform"
1315
#endif

include/openlibm_fenv_powerpc.h

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
/*-
2+
* Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
* 1. Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* 2. Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in the
12+
* documentation and/or other materials provided with the distribution.
13+
*
14+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24+
* SUCH DAMAGE.
25+
*
26+
* $FreeBSD$
27+
*/
28+
29+
#ifndef _FENV_H_
30+
#define _FENV_H_
31+
32+
#include <sys/types.h>
33+
34+
#ifndef __fenv_static
35+
#define __fenv_static static
36+
#endif
37+
38+
typedef __uint32_t fenv_t;
39+
typedef __uint32_t fexcept_t;
40+
41+
/* Exception flags */
42+
#define FE_INEXACT 0x02000000
43+
#define FE_DIVBYZERO 0x04000000
44+
#define FE_UNDERFLOW 0x08000000
45+
#define FE_OVERFLOW 0x10000000
46+
#define FE_INVALID 0x20000000 /* all types of invalid FP ops */
47+
48+
/*
49+
* The PowerPC architecture has extra invalid flags that indicate the
50+
* specific type of invalid operation occurred. These flags may be
51+
* tested, set, and cleared---but not masked---separately. All of
52+
* these bits are cleared when FE_INVALID is cleared, but only
53+
* FE_VXSOFT is set when FE_INVALID is explicitly set in software.
54+
*/
55+
#define FE_VXCVI 0x00000100 /* invalid integer convert */
56+
#define FE_VXSQRT 0x00000200 /* square root of a negative */
57+
#define FE_VXSOFT 0x00000400 /* software-requested exception */
58+
#define FE_VXVC 0x00080000 /* ordered comparison involving NaN */
59+
#define FE_VXIMZ 0x00100000 /* inf * 0 */
60+
#define FE_VXZDZ 0x00200000 /* 0 / 0 */
61+
#define FE_VXIDI 0x00400000 /* inf / inf */
62+
#define FE_VXISI 0x00800000 /* inf - inf */
63+
#define FE_VXSNAN 0x01000000 /* operation on a signalling NaN */
64+
#define FE_ALL_INVALID (FE_VXCVI | FE_VXSQRT | FE_VXSOFT | FE_VXVC | \
65+
FE_VXIMZ | FE_VXZDZ | FE_VXIDI | FE_VXISI | \
66+
FE_VXSNAN | FE_INVALID)
67+
#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
68+
FE_ALL_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
69+
70+
/* Rounding modes */
71+
#define FE_TONEAREST 0x0000
72+
#define FE_TOWARDZERO 0x0001
73+
#define FE_UPWARD 0x0002
74+
#define FE_DOWNWARD 0x0003
75+
#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
76+
FE_UPWARD | FE_TOWARDZERO)
77+
78+
__BEGIN_DECLS
79+
80+
/* Default floating-point environment */
81+
extern const fenv_t __fe_dfl_env;
82+
#define FE_DFL_ENV (&__fe_dfl_env)
83+
84+
/* We need to be able to map status flag positions to mask flag positions */
85+
#define _FPUSW_SHIFT 22
86+
#define _ENABLE_MASK ((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
87+
FE_OVERFLOW | FE_UNDERFLOW) >> _FPUSW_SHIFT)
88+
89+
#ifndef _SOFT_FLOAT
90+
#define __mffs(__env) __asm __volatile("mffs %0" : "=f" (*(__env)))
91+
#define __mtfsf(__env) __asm __volatile("mtfsf 255,%0" : : "f" (__env))
92+
#else
93+
#define __mffs(__env)
94+
#define __mtfsf(__env)
95+
#endif
96+
97+
union __fpscr {
98+
double __d;
99+
struct {
100+
__uint32_t __junk;
101+
fenv_t __reg;
102+
} __bits;
103+
};
104+
105+
__fenv_static inline int
106+
feclearexcept(int __excepts)
107+
{
108+
union __fpscr __r;
109+
110+
if (__excepts & FE_INVALID)
111+
__excepts |= FE_ALL_INVALID;
112+
__mffs(&__r.__d);
113+
__r.__bits.__reg &= ~__excepts;
114+
__mtfsf(__r.__d);
115+
return (0);
116+
}
117+
118+
__fenv_static inline int
119+
fegetexceptflag(fexcept_t *__flagp, int __excepts)
120+
{
121+
union __fpscr __r;
122+
123+
__mffs(&__r.__d);
124+
*__flagp = __r.__bits.__reg & __excepts;
125+
return (0);
126+
}
127+
128+
__fenv_static inline int
129+
fesetexceptflag(const fexcept_t *__flagp, int __excepts)
130+
{
131+
union __fpscr __r;
132+
133+
if (__excepts & FE_INVALID)
134+
__excepts |= FE_ALL_EXCEPT;
135+
__mffs(&__r.__d);
136+
__r.__bits.__reg &= ~__excepts;
137+
__r.__bits.__reg |= *__flagp & __excepts;
138+
__mtfsf(__r.__d);
139+
return (0);
140+
}
141+
142+
__fenv_static inline int
143+
feraiseexcept(int __excepts)
144+
{
145+
union __fpscr __r;
146+
147+
if (__excepts & FE_INVALID)
148+
__excepts |= FE_VXSOFT;
149+
__mffs(&__r.__d);
150+
__r.__bits.__reg |= __excepts;
151+
__mtfsf(__r.__d);
152+
return (0);
153+
}
154+
155+
__fenv_static inline int
156+
fetestexcept(int __excepts)
157+
{
158+
union __fpscr __r;
159+
160+
__mffs(&__r.__d);
161+
return (__r.__bits.__reg & __excepts);
162+
}
163+
164+
__fenv_static inline int
165+
fegetround(void)
166+
{
167+
union __fpscr __r;
168+
169+
__mffs(&__r.__d);
170+
return (__r.__bits.__reg & _ROUND_MASK);
171+
}
172+
173+
__fenv_static inline int
174+
fesetround(int __round)
175+
{
176+
union __fpscr __r;
177+
178+
if (__round & ~_ROUND_MASK)
179+
return (-1);
180+
__mffs(&__r.__d);
181+
__r.__bits.__reg &= ~_ROUND_MASK;
182+
__r.__bits.__reg |= __round;
183+
__mtfsf(__r.__d);
184+
return (0);
185+
}
186+
187+
__fenv_static inline int
188+
fegetenv(fenv_t *__envp)
189+
{
190+
union __fpscr __r;
191+
192+
__mffs(&__r.__d);
193+
*__envp = __r.__bits.__reg;
194+
return (0);
195+
}
196+
197+
__fenv_static inline int
198+
feholdexcept(fenv_t *__envp)
199+
{
200+
union __fpscr __r;
201+
202+
__mffs(&__r.__d);
203+
*__envp = __r.__d;
204+
__r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
205+
__mtfsf(__r.__d);
206+
return (0);
207+
}
208+
209+
__fenv_static inline int
210+
fesetenv(const fenv_t *__envp)
211+
{
212+
union __fpscr __r;
213+
214+
__r.__bits.__reg = *__envp;
215+
__mtfsf(__r.__d);
216+
return (0);
217+
}
218+
219+
__fenv_static inline int
220+
feupdateenv(const fenv_t *__envp)
221+
{
222+
union __fpscr __r;
223+
224+
__mffs(&__r.__d);
225+
__r.__bits.__reg &= FE_ALL_EXCEPT;
226+
__r.__bits.__reg |= *__envp;
227+
__mtfsf(__r.__d);
228+
return (0);
229+
}
230+
231+
#if __BSD_VISIBLE
232+
233+
/* We currently provide no external definitions of the functions below. */
234+
235+
static inline int
236+
feenableexcept(int __mask)
237+
{
238+
union __fpscr __r;
239+
fenv_t __oldmask;
240+
241+
__mffs(&__r.__d);
242+
__oldmask = __r.__bits.__reg;
243+
__r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT;
244+
__mtfsf(__r.__d);
245+
return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
246+
}
247+
248+
static inline int
249+
fedisableexcept(int __mask)
250+
{
251+
union __fpscr __r;
252+
fenv_t __oldmask;
253+
254+
__mffs(&__r.__d);
255+
__oldmask = __r.__bits.__reg;
256+
__r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT);
257+
__mtfsf(__r.__d);
258+
return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
259+
}
260+
261+
static inline int
262+
fegetexcept(void)
263+
{
264+
union __fpscr __r;
265+
266+
__mffs(&__r.__d);
267+
return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT);
268+
}
269+
270+
#endif /* __BSD_VISIBLE */
271+
272+
__END_DECLS
273+
274+
#endif /* !_FENV_H_ */

powerpc/Make.files

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$(CUR_SRCS) = fenv.c

powerpc/fenv.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*-
2+
* Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
* 1. Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* 2. Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in the
12+
* documentation and/or other materials provided with the distribution.
13+
*
14+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24+
* SUCH DAMAGE.
25+
*
26+
* $FreeBSD$
27+
*/
28+
29+
#define __fenv_static
30+
#include <openlibm_fenv.h>
31+
32+
#ifdef __GNUC_GNU_INLINE__
33+
#error "This file must be compiled with C99 'inline' semantics"
34+
#endif
35+
36+
const fenv_t __fe_dfl_env = 0x00000000;
37+
38+
extern inline int feclearexcept(int __excepts);
39+
extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
40+
extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
41+
extern inline int feraiseexcept(int __excepts);
42+
extern inline int fetestexcept(int __excepts);
43+
extern inline int fegetround(void);
44+
extern inline int fesetround(int __round);
45+
extern inline int fegetenv(fenv_t *__envp);
46+
extern inline int feholdexcept(fenv_t *__envp);
47+
extern inline int fesetenv(const fenv_t *__envp);
48+
extern inline int feupdateenv(const fenv_t *__envp);

0 commit comments

Comments
 (0)