From: Damian McGuckin <damianm@esi.com.au>
To: musl@lists.openwall.com
Subject: Re: [musl] Considering x86-64 fenv.s to C
Date: Mon, 3 Feb 2020 11:54:52 +1100 (AEDT) [thread overview]
Message-ID: <alpine.LRH.2.02.2002031144370.25330@key0.esi.com.au> (raw)
In-Reply-To: <20200125001100.GY30412@brightrain.aerifal.cx>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 595 bytes --]
Latest Implementation Document is attached.
Comments need reviewing and clarification.
Style issues will need to be addressed.
This is meant for for ARM with hardware floating point, any MIPS, RISC-V,
M68K, Hitachi SuperH, IBM S390x, Powerpc64, and (in theory) Sparc.
The version to handle Intel i386, x32 and x86-64 will be very different.
Regards - Damian
Pacific Engineering Systems International, 277-279 Broadway, Glebe NSW 2037
Ph:+61-2-8571-0847 .. Fx:+61-2-9692-9623 | unsolicited email not wanted here
Views & opinions here are mine and not those of any past or present employer
[-- Attachment #2: Type: TEXT/plain, Size: 9158 bytes --]
/*
* these lines are here to allow the compilation of this file
* in isolation and the lint'ing of the same with 'splint'!!
*/
#include <assert.h>
#define TEST
#ifdef TEST
#include "../../../arch/powerpc64/bits/fenv.h"
typedef unsigned int fe_csr_t;
extern unsigned int fe_get_sr();
extern void fe_set_sr(unsigned int);
extern unsigned int fe_get_cr();
extern void fe_set_cr(unsigned int);
extern double fe_get_csr_f();
extern void fe_set_csr_f(double);
extern void fe_get_env(fenv_t *e);
extern void fe_set_env(fenv_t *e);
extern void fe_set_env_but_keep_raised_excepts(fenv_t *e);
extern void fe_get_env_and_clear_all_excepts(fenv_t *e);
extern void fescrubexcept(void);
extern fenv_t fe_dfl_env;
extern int FE_ROUNDING_TYPE(int);
#endif
\f
/*
* fenv-generic.c (use 'fenv-trivial.v' for soft-float environments):
*
* All architectures which fit the generic mould are assumed to have a status
* register (sr) which contains the exception flags are stored and a control
* register (cr) which contains the rounding mode. These registers may be one
* and the same or they may be distinct. All architecture-dependent features
* live in an individual 'fenv.c' file which contains function definitions,
* mainly of one-line embedded assembler, declarations, macros and typedef's:
*
* a) the type 'fe_csr_t' which can store both 'sr' and 'cr',
* - this is an unsigned int on all known architectures
* b) routines to copy 'sr' and 'cr' into memory, respectively
* - fe_csr_ fe_get_sr() and fe_csr_t fe_get_cr()
* c) routines to load 'sr' and 'cr' from memory, respectively
* - void fe_set_sr(fe_csr_t) and void fe_set_cr(fe_csr_t)
* d) routines to copy and load an architecture's floating point environment,
* - fe_get_env(fenv_t *) and fe_set_env(fenv_t *) respectively
* - 'fenv_t' is defined in an architectures own 'fenv.h' file
* e) a routine to reset an architecture's floating point environment
* - like fe_set_env(fenv_t *) but currently raised exceptions stay raised
* f) a routine to clone an architecture's floating point environment
* - like fe_get_env(fenv_t *) but currently raised exceptions get cleared
* g) a macro yielding a ratified exception list during a CLEAR operation
* - FE_RATIFY_CLEAR_EXCEPTS
* h) a macro yielding a ratified exception list during a RAISE operation
* - FE_RATIFY_RAISE_EXCEPTS
* i) macros which maps from the rounding mode to a rounding style
* - FE_ROUNDING_STYLE
* j) a (macro) bit-mask of all legal rounding modes
* - FE_ROUNDING_MASK
* - it returns the value to be returned by the FLT_ROUNDS macro
* k) an initialization for the default fenv_t
* - i.e. static const fenv_t fe_dfl_env = .....
*
* (k) is an implicitly hidden, IEEE 754 default floating point environment in
* which all exceptions are clear, non-stop (or continue on exception) mode is
* active, and rounding to nearest will be used for all arithmetic.
*
* For most architectures, the macros (g) and (h) can be allowed to default
* to the handling done by the routine 'fe_ratified_excepts'. This routine
* reviews all the exceptions implicit in the mask 'excepts' fed to all the
* 'fe*' routines, discarding any inappropriate bits. In this case, these
* macros are defined automatically as seen below. Only one architecture,
* the PowerPC, does not fit this mould, and its definitions are explained
* in detail in that architecture's own 'fenv.c'.
*
* If the architecture-specific 'fenv.c' file does not define the mask (j),
* all four IEEE 754 rounding modes are assumed to exist, a mask which is
* the OR'd combinations of those modes will be automatically created, as
* well as the macro (i) which maps the machine-dependent rounding mode of
* the control register to the machine-independent rounding style which is
* provided by FLT_ROUNDS. If all four modes are not available, this mask
* and macro must be provided in the architecture-specific 'fenv.c' file.
* Apart from architectures with soft floating point, only the Hitachi
* SuperH RISC chip (sh) needs such definitions.
*
* After all these definitions and declarations, the architectures-specific
* file must then also include this file, i.e. 'fenv-generic,c' following
* current practice as
*
* #include "../fenv-generic.c"
*/
\f
#ifndef FE_RATIFIED_RAISE_EXCEPTS
#define FE_RATIFIED_RAISE_EXCEPTS(e) fe_ratified_excepts(e)
#endif
#ifndef FE_RATIFIED_CLEAR_EXCEPTS
#define FE_RATIFIED_CLEAR_EXCEPTS(e) fe_ratified_excepts(e)
#endif
/*
* take a bit mask which should be just an OR'd combination of IEEE 754
* exceptions and discard any bit which is not one of those exceptions.
*/
static inline int
fe_ratified_excepts(int excepts)
{
return excepts & FE_ALL_EXCEPT;
}
#ifndef FE_ROUNDING_MASK
#define FE_ROUNDING_MASK (FE_TOWARDZERO|FE_DOWNWARD|FE_UPWARD)
/*
* Map an architecture-dependent rounding mode to that needed by FLT_ROUNDS.
* There are better ways to do this but none of those reads as well as this.
*/
static inline int
fe_rounding_style(int rounding)
{
return
(
rounding == FE_DOWNWARD
?
3
:
rounding == FE_UPWARD
?
2
:
(int) (rounding == FE_TONEAREST)
);
}
#define FE_ROUNDING_STYLE(m) fe_rounding_style(m)
#endif
\f
/*
* mask out the bits with 'bits' from 'mask' ensuring type compatability
*/
static inline fe_csr_t
fe_clear_bits(fe_csr_t mask, int bits)
{
return mask & ~((fe_csr_t) bits);
}
/*
* get the rounding mask
*/
int
fegetround(void)
{
return (int) (fe_get_cr() & FE_ROUNDING_MASK);
}
/*
* internals for FLT_ROUNDS
*/
int __flt_rounds()
{
return FE_ROUNDING_STYLE(fegetround());
}
/*
* set the rounding mode - returning (-1) if input is not a valid mode
*/
int
fesetround(int rounding_mode)
{
if ((rounding_mode & FE_ROUNDING_MASK) != rounding_mode)
return -1;
fe_set_cr(fe_clear_bits(fe_get_cr(), FE_ROUNDING_MASK) | rounding_mode);
return 0;
}
\f
/*
* returns a word in which the bits (which represent IEEE 754 exceptions)
* are set that were also set in the argument 'excepts' and for which the
* corresponding exception is currently set. The only legal bits that can
* be given in the argment are those which correspond to an exception.
*/
int
fetestexcept(int excepts)
{
return (int) (fe_get_sr() & fe_ratified_excepts(excepts));
}
/*
* clears the supported exceptions represented by the bits in its argument.
*/
int
feclearexcept(int excepts)
{
excepts = FE_RATIFIED_CLEAR_EXCEPTS(excepts);
fe_set_sr(fe_clear_bits(fe_get_sr(), excepts));
return 0;
}
/*
* raises the supported exceptions represented by the bits in its argument.
*/
int
feraiseexcept(int excepts)
{
/*
* assume single OP is faster than double OP
*/
const float zero = (float) 0;
const float one = (float) 1;
const float large = 2.076919e+34; // 2^(+108)
const float small = 4.814826e-35; // 2^(-108)
volatile float x;
/*
* if it is just a simple exception, arithmetic expressions are optimal
*/
switch(excepts)
{
case FE_INVALID:
x = zero, x /= x;
break;
case FE_DIVBYZERO:
x = zero, x = one / x;
break;
case FE_INEXACT:
x = small, x += one;
break;
case FE_OVERFLOW | FE_INEXACT:
x = large, x *= x;
break;
case FE_UNDERFLOW | FE_INEXACT:
x = small, x *= x;
break;
default:
/*
* if multiple exceptions exist, a sledgehammer is viable
*/
excepts = FE_RATIFIED_RAISE_EXCEPTS(excepts);
fe_set_sr(fe_get_sr() | excepts);
break;
}
return 0;
}
\f
/*
* copy the complete current exception state into *fp
*/
int
fegetexceptflag(fexcept_t *fp, int excepts)
{
*fp = (fexcept_t) fetestexcept(excepts);
return 0;
}
/*
* load the exception state from *fp, but intelligently avoiding
* clearing (raising) exceptions which are already cleared (raised).
*/
int
fesetexceptflag(const fexcept_t *fp, int excepts)
{
const fe_csr_t sr = fe_get_sr();
const fe_csr_t fx = (fe_csr_t) *fp;
const int requested = excepts & FE_ALL_EXCEPT;
const int excepts_old = (int) (sr & requested);
const int excepts_new = (int) (fx & requested);
const int essential = excepts_old ^ excepts_new;
const int clear = FE_RATIFIED_CLEAR_EXCEPTS(excepts_old & essential);
const int raise = FE_RATIFIED_RAISE_EXCEPTS(excepts_new & essential);
if ((clear | raise) != 0)
fe_set_sr(fe_clear_bits(sr, clear) | raise);
return 0;
}
/*
* copy the floating point environment into memory
*/
int
fegetenv(fenv_t *e)
{
fe_get_env(e);
return 0;
}
/*
* load the floating point environment from memory
*/
int
fesetenv(fenv_t *e)
{
fe_set_env(e != FE_DFL_ENV ? e : &fe_dfl_env);
return 0;
}
/*
* as for fesetenv but retain the exception data
*/
int
feupdateenv(fenv_t *e)
{
fe_set_env_but_keep_raised_excepts(e != FE_DFL_ENV ? e : &fe_dfl_env);
return 0;
}
/*
* as for fegetenv but clear the exception states
*/
int
feholdexcept(fenv_t *e)
{
fe_get_env_and_clear_all_excepts(e);
return 0;
}
next prev parent reply other threads:[~2020-02-03 0:55 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-16 4:30 Damian McGuckin
2020-01-16 15:11 ` Markus Wichmann
2020-01-16 16:14 ` Rich Felker
2020-01-16 18:56 ` Damian McGuckin
2020-01-16 19:33 ` Rich Felker
2020-01-16 21:31 ` Damian McGuckin
2020-01-17 3:36 ` Damian McGuckin
2020-01-17 3:48 ` Damian McGuckin
2020-01-17 3:53 ` David Edelsohn
2020-01-17 14:13 ` Rich Felker
2020-01-17 14:19 ` David Edelsohn
2020-01-17 14:53 ` Rich Felker
2020-01-18 4:45 ` Damian McGuckin
2020-01-18 5:29 ` Rich Felker
2020-01-19 8:50 ` Damian McGuckin
2020-01-19 9:07 ` Damian McGuckin
2020-01-19 10:42 ` Szabolcs Nagy
2020-01-19 12:25 ` Damian McGuckin
2020-01-20 5:32 ` Damian McGuckin
2020-01-20 17:38 ` Rich Felker
2020-01-20 21:11 ` [musl] Triggering Overflow (or Underflow) without triggering Inexact on i386 Damian McGuckin
2020-01-20 22:32 ` Szabolcs Nagy
2020-01-21 3:53 ` [musl] Considering x86-64 fenv.s to C Damian McGuckin
2020-01-21 4:22 ` Rich Felker
2020-01-21 4:46 ` Damian McGuckin
2020-01-21 7:26 ` Damian McGuckin
2020-01-17 16:41 ` Markus Wichmann
2020-01-18 1:15 ` Szabolcs Nagy
2020-01-18 5:03 ` Damian McGuckin
2020-01-18 5:37 ` Rich Felker
2020-01-18 9:40 ` Szabolcs Nagy
2020-01-24 0:42 ` Damian McGuckin
2020-01-24 1:11 ` Rich Felker
2020-01-24 4:13 ` Damian McGuckin
2020-01-24 4:55 ` Rich Felker
2020-01-24 6:08 ` Damian McGuckin
2020-01-24 13:44 ` Rich Felker
2020-01-24 14:45 ` Damian McGuckin
2020-01-24 23:59 ` Damian McGuckin
2020-01-25 0:11 ` Rich Felker
2020-01-26 3:28 ` Damian McGuckin
2020-01-26 3:28 ` Damian McGuckin
2020-01-26 3:30 ` Damian McGuckin
2020-01-26 3:32 ` Damian McGuckin
2020-01-26 5:25 ` Damian McGuckin
2020-01-27 3:32 ` Damian McGuckin
2020-01-27 5:39 ` Damian McGuckin
2020-02-02 0:47 ` Damian McGuckin
2020-02-03 0:54 ` Damian McGuckin [this message]
2020-02-03 2:09 ` Rich Felker
2020-02-03 2:12 ` Damian McGuckin
2020-02-22 20:17 ` Rich Felker
2020-02-22 20:53 ` Damian McGuckin
2020-02-23 5:41 ` Damian McGuckin
2020-02-23 6:25 ` Rich Felker
2020-02-23 8:35 ` Damian McGuckin
2020-02-07 21:25 ` Damian McGuckin
2020-02-07 21:38 ` Rich Felker
2020-02-07 23:53 ` Damian McGuckin
2020-02-09 5:04 ` Damian McGuckin
2020-01-24 7:10 ` Damian McGuckin
2020-01-18 5:04 ` Markus Wichmann
2020-02-03 14:16 [musl] PPC64(LE) support in musl requires ALTIVEC Romain Naour
2020-02-03 14:50 ` Rich Felker
2020-02-05 1:32 ` [musl] Considering x86-64 fenv.s to C Damian McGuckin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.LRH.2.02.2002031144370.25330@key0.esi.com.au \
--to=damianm@esi.com.au \
--cc=musl@lists.openwall.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).