#include <ppc/context.h>
Go to the source code of this file.
Functions | |
int | _math_emulator (int sigcode, void **pdata, PPC_CPU_REGISTERS *regs) |
IEEE 754 compliance handler. |
int _math_emulator | ( | const int | sigcode, | |
void **const | pdata, | |||
PPC_CPU_REGISTERS *const | regs | |||
) |
IEEE 754 compliance handler.
This routine serves two major, somewhat independent purposes. It is primarily used as a user-mode handler for embedded floating point data and rounding exceptions raised by the hardware; it is also used as a means for the fp_status
and fenv
implementations in libm to make use of the SPEFSCR register in cooperation with the exception handling functionality.
Although the source code is quite lengthy, much of the bulk is made up of switch statements which sieve the opcode in various ways. The execution path through the routine for any given execution is intended to be as short as possible. Owing to the amount of state shared from step to step in what is essentially a sequential algorithm, it did not seem advisable to split the routine into pieces as it is conjectured that it might substantially degrade the compiler's ability to optimize the code.
FPE_NOFPU
for data, FPE_FLTRES
for rounding); the IAR pointing at the instruction causing the exception; and the remainder of the register context filled in appropriately. The high words of the GPRs and the accumulator are assumed to be in the state they were in at the time of the exception (since they can only be modified by embedded floating point instructions).kerext_debug
) to begin with a (true, non-embedded) floating point register save area, which is not otherwise used by the fpassist library and in which all registers are always set to zero. Following this is a softfloat environment, which is also unused by the fpassist library. (It is reserved for future extension and preserves an identical layout with the context used by the fpemu library. Although there is currently no functional need for compatibility, it may prove to be worthwhile if it is ever necessary to support both fpemu and fpassist simultaneously.) Next is the private context used by the fpassist library. This contains the current value of the application visible exception flags and mask.SIGFPE
should still be delivered; typically the result is not stored if a signal will be delivered (just as it would not had the fpassist library not been present.)fp_status
API and Protocolfp_setenv()
implementation in libm for SPE PPC uses a simple protocol to communicate with the fpassist library in order to cooperatively use the SPEFSCR register. It calls the _emulator_callout()
function directly, passing SIGFPE
; an IAR
of ~0U
; and a USPRG0 of either O_RDONLY
, for a read, or O_WRONLY
, for a write of the SPEFSCR. If the fpassist
library is missing, this will return non-zero (SIGFPE
) and fp_setenv()
will fall back to accessing the hardware directly. (In this case, unmasked exceptions will result in SIGFPE
delivery.) Otherwise, the value manipulated will in fact be the one from the application context allocated above.[in] | sigcode | The sigcode suggested by the caller. |
[in,out] | pdata | Pointer to pointer of TLS context save area. |
[in,out] | regs | Processor context. |
sigcode
to be delivered to the application thread (if any) ==0 | No signal required. | |
!=0 | sigcode to deliver. |
Definition at line 642 of file efp_assist.c.
References DPRINTF, float32_add(), float32_div(), float32_eq(), float32_eq_signaling(), float32_gt(), float32_gt_quiet(), float32_lt(), float32_lt_quiet(), float32_mul(), float32_sub(), float32_to_float64(), float32_to_int32(), float32_to_int32_round_to_zero(), float32_to_q31(), float32_to_uint32(), float32_to_uint32_round_to_zero(), float32_to_uq32(), float64_add(), float64_div(), float64_eq(), float64_eq_signaling(), float64_gt(), float64_gt_quiet(), float64_lt(), float64_lt_quiet(), float64_mul(), float64_sub(), float64_to_float32(), float64_to_int32(), float64_to_int32_round_to_zero(), float64_to_int64_round_to_zero(), float64_to_q31(), float64_to_uint32(), float64_to_uint32_round_to_zero(), float64_to_uint64_round_to_zero(), float64_to_uq32(), _run_options::float_exception_flags, float_flag_divbyzero, float_flag_inexact, float_flag_invalid, float_flag_overflow, float_flag_underflow, float_round_down, float_round_nearest_even, float_round_to_zero, float_round_up, _run_options::float_rounding_mode, getappenv(), getsfenv(), int32_to_float32(), int32_to_float64(), int64_to_float64(), load32(), load64(), loadh32(), NELEM, PPC_XO_efdabs, PPC_XO_efdadd, PPC_XO_efdcfs, PPC_XO_efdcfsf, PPC_XO_efdcfsi, PPC_XO_efdcfsid, PPC_XO_efdcfuf, PPC_XO_efdcfui, PPC_XO_efdcfuid, PPC_XO_efdcmpeq, PPC_XO_efdcmpgt, PPC_XO_efdcmplt, PPC_XO_efdctsf, PPC_XO_efdctsi, PPC_XO_efdctsidz, PPC_XO_efdctsiz, PPC_XO_efdctuf, PPC_XO_efdctui, PPC_XO_efdctuidz, PPC_XO_efdctuiz, PPC_XO_efddiv, PPC_XO_efdmul, PPC_XO_efdnabs, PPC_XO_efdneg, PPC_XO_efdsub, PPC_XO_efdtsteq, PPC_XO_efdtstgt, PPC_XO_efdtstlt, PPC_XO_efsabs, PPC_XO_efsadd, PPC_XO_efscfd, PPC_XO_efscfsf, PPC_XO_efscfsi, PPC_XO_efscfuf, PPC_XO_efscfui, PPC_XO_efscmpeq, PPC_XO_efscmpgt, PPC_XO_efscmplt, PPC_XO_efsctsf, PPC_XO_efsctsi, PPC_XO_efsctsiz, PPC_XO_efsctuf, PPC_XO_efsctui, PPC_XO_efsctuiz, PPC_XO_efsdiv, PPC_XO_efsmul, PPC_XO_efsnabs, PPC_XO_efsneg, PPC_XO_efssub, PPC_XO_efststeq, PPC_XO_efststgt, PPC_XO_efststlt, PPC_XO_evfsabs, PPC_XO_evfsadd, PPC_XO_evfscfsf, PPC_XO_evfscfsi, PPC_XO_evfscfuf, PPC_XO_evfscfui, PPC_XO_evfscmpeq, PPC_XO_evfscmpgt, PPC_XO_evfscmplt, PPC_XO_evfsctsf, PPC_XO_evfsctsi, PPC_XO_evfsctsiz, PPC_XO_evfsctuf, PPC_XO_evfsctui, PPC_XO_evfsctuiz, PPC_XO_evfsdiv, PPC_XO_evfsmul, PPC_XO_evfsnabs, PPC_XO_evfsneg, PPC_XO_evfssub, PPC_XO_evfststeq, PPC_XO_evfststgt, PPC_XO_evfststlt, q31_to_float32(), q31_to_float64(), softfloat_env_init(), appenv_type::spefscr, SPEFSCR_ENABLE_EXC_MASK, SPEFSCR_NEEDED_EXC_MASK, SPEFSCR_STICKY_EXC_MASK, SPEFSCR_STICKY_EXC_SHIFT, SPEFSCR_VECT_HI_EXC_MASK, SPEFSCR_VECT_LO_EXC_MASK, store32(), store64(), storeh32(), uint32_to_float32(), uint32_to_float64(), uint64_to_float64(), uq32_to_float32(), and uq32_to_float64().