This hardware behavior makes sense, as the FI bit is used to signify an
inexact result. An inexact result is a form of value that results during
the rounding phase of denormalization. If any bits of the significand
are lost during said rounding, then the result is considered to be
inexact.
However NaN and infinity are not classed as subnormals and therefore
don't undergo the denormalization step, making loss of precision not
possible (in NaN's case, numerically rounding something that is
literally Not a Number doesn't even make sense).
FR is set to indicate whether or not the last arithmetic or rounding and
conversion instruction that rounded the intermediate result incremented
the fractional portion of the result. Given neither input types would be
affected by this, this should also be unset.
This corrects more of the exceptional case handling for these values to
match hardware.
As suggested here: https://dolp.in/pr7059#pullrequestreview-125401778
More descriptive than having a std::tuple of FS::Mode, and lets us
give names to known triplets of modes (like in ES). Functions that
only forward mode arguments are slightly less verbose now too.
Prevents implicit conversions to types and requires explicitly
specifying them in order to construct instances of them. Given these are
used within emulation code directly, being explicit is always better
than implicit.
As explained within 179d73ac0d2873ebf2dedd7a4069ea5ded4a66f1, the table
within the Programming Environments Manual for PowerPC lists the FI and
FR bits as cleared for invalid operation cases. So, we amend the
relevant cases here in order to be accurate to hardware.
As explained within commit a08ad82ace064f961b13369c96a0f3b48ca7ca5c, if
an invalid exception occurs and VE is set, then the destination register
should remain unchanged. Ditto for when ZE is set and a zero divide
exception occurs.
This is only used internally, so we don't need to expose it in the
header. This also allows getting rid of inclusion of the byte swapping
utilities in the header as well.
Given they were only made public so that the callback could access class
state, we can simply make the callback a private static function of
CEXIMic, which allows access to members from the callback function
without making all of said members public.
In the PEM manual, within Table 3-12, which lists what should occur for
invalid operation exceptions, the FPSCR.FI and FPSCR.FR bits are listed
as "Cleared" for when FPSCR.VE is unset and set. So we clear these bits
as well to match hardware behavior.