mailing list of musl libc
 help / color / mirror / code / Atom feed
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;
}

  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).