|
|
Message-ID: <alpine.LRH.2.02.2001261428440.4774@key0.esi.com.au>
Date: Sun, 26 Jan 2020 14:30:32 +1100 (AEDT)
From: Damian McGuckin <damianm@....com.au>
To: musl@...ts.openwall.com
Subject: Re: Considering x86-64 fenv.s to C
PowerPC 64:
/*
* powerpc64 ARCHITECTURE (tolterable reference is below)
*
* http://math-atlas.sourceforge.net/devel/assembly/ppc_isa.pdf
*
* PowerPC includes cause (or reason) bits which qualify why an INVALID
* exception get raised. The cause can be regarded as just an explanation
* in most cases. In fact, if only the ppropriate cause bit is set in the
* control register and this is fed to in a 'Move to FPSCR', the INVALID
* exception will be triggered automatically. The complete list is:
*
* VXSNAN caused by a floating point operation on a SNAN
* VXISI caused by the operation INFINITY - INFINITY
* VXIDI caused by the operation INFINITY / INFINITY
* VXZDZ caused by the operation 0.0 / 0.0
* VXIMZ caused by the operation INFINITY * 0
* VXCVI caused by an illegal integer conversion
* VXVC caused by an ordered comparison involving a NaN
* VXSOFT caused by an explicit sofware request
* VXSQRT caused by a sqrt/rsqrt on a negative & non-zero number
*
* The OR of all such causes is called FE_ALL_INVALID in the API.
*
* One above, VXSOFT, is that caused 'By (An Explicit Software) Request'. The
* documentation says that its purpose is to allow software to cause/raise an
* Invalid Operation Exception for a condition that is not necessarily
* associated with the execution of a floating-point instruction. It could
* even be used by a program to complain about some negative and non-zero
* operand long BEFORE it gets given to a SQRT or RSQRT imnstruction where
* it would otherwise invoke the VXSQRT cause and trigger that bit to be set.
*
* Note, when an FE_INVALID exception is cleared, all the causes including
* the ones that other instructions can generate, i.e all of the bits in the
* FE_ALL_INVALID bit mask, must be similarly also cleared. Otherwise, any
* CAUSE bit left in the mask will, when fed back into the 'MOVE to FPSCR'
* instruction (implicit in the 'fe_set_fpscr' routine) will retrigger the
* FE_INVALID exception. So MUSL must still cater for these non-standard
* causes, because to not do so will stab itself in the back.
*
* So MUSL makes the assumption that at least for a PowerPC, any raising of
* the INVALID exception must also raise a cause, that cause being by default,
* that called 'By Explicit Software Request'. That makes sense as this is
* beind done by the MUSL itself, not as a part, or side-effect, of some
* arithmetic operation. Note also that if a user has explicitly (violated
* the standard and) augmented an exception list to contain some other cause,
* that extra cause gets trashed on entry to the fenv(3) routines and only
* this default cause is added. The rejection of the benefits of the extra
* information provided by a PowerPC could be addressed in the future as
* the fix is trivial!
*
* The FE_INVALID_SOFTWARE flag is relabelled as FE_INVALID_BY_REQUEST to
* correctly explain its purpose and make any use remotely comprehensible.
* This is questionable in terms of style but without this, the ability of
* the comments to make sense is seriously compromised. For the same reason,
* FE_ALL_INVALID is relabelled FE_ALL_INVALID_CAUSES. At some stage, it is
* recommended that the IBM ISA documentation be enhanced to be more lucid.
*/
#include <fenv.h>
/*
* Remember that the floating point environment lives in a 'double' That
* is locked by the ABI defined in the architecture dependent <fenv.h>.
*
* The first routine pair gets and sets that environment for later use by
* the MUSL mandated pair of fe_get_csr_arch/fe_set_csr_arch routines
*/
static inline double fe_get_fpscr_f(void)
{
double fpscr;
__asm__ __volatile__ ("mffs %0" : "=d"(fpscr));
return fpscr;
}
static inline void fe_set_fpscr_f(double fpscr)
{
__asm__ __volatile__ ("mtfsf 255, %0" : : "d"(fpscr));
}
/*
* This routine pair move tos and from the double (of the environment) into
* MUSL's unsigned int object in which it stores control & status registers
*/
static inline unsigned int fe_get_csr_arch(void)
{
return (unsigned int) (union {double f; long i;}) {fe_get_fpscr_f()}.i;
}
static inline void fe_set_csr_arch(unsigned int fpscr)
{
fe_set_fpscr_f((union {long i; double f;}) {(long) fpscr}.f);
}
/*
* These two macros work with the environment directly
* Should they eventually move to being inline routines?
*/
#define fe_get_e(e) (*e = fe_get_fpscr_f())
#define fe_set_e(e) (fe_set_fpscr_f(*e))
/*
* the default value of a floating point environment of type fenv_t (double)
*/
#define FE_DFL_ENV_DATA 0.0
/*
* Eludicate the macros related to CAUSEs for improved readability.
* While this is tolerable at the architecture definition stage, it
* may need to change in the production code.
*/
#define FE_ALL_INVALID_CAUSES FE_ALL_INVALID
#define FE_INVALID_BY_REQUEST FE_INVALID_SOFTWARE
#include "../fenv-generic.c"
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
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.