Repository navigation
cpu: raise the FP exceptions IRIX's diagnostics check for - #406
Draft
jamesbraid wants to merge 2 commits into
Draft
jamesbraid wants to merge 2 commits into
jamesbraid wants to merge 2 commits into
Conversation
The R4400, R5000 and R10000 use the original MIPS NaN encoding: a NaN with the fraction MSB set is signalling, one with it clear is quiet. The default NaN is 0x7FBFFFFF for that reason. iris used the IEEE 754-2008 convention, the reverse, in the interpreter and in compiled code. An R4400 shows it. The cpu-tests case fpu/qnan_operand feeds 0x7FC00000 to ADD and gets Invalid and the default NaN, not Unimplemented, and the signalling-predicate compares agree. Swap the sense of the fraction-MSB test in is_snan and is_qnan and in their compiled twins, including the compare path. With the bit set the fraction is nonzero by construction, so the interpreter's signalling test shrinks to one mask and compare, and an ordinary operand skips the subnormal and quiet-NaN checks after one exponent test. Compiled code swaps a comparison and costs the same. The tests cover the default NaN as an operand (Unimplemented, no Invalid), a signalling NaN operand (Invalid, trapped and untrapped), and a compiled-versus-interpreter check over ADD, MUL, DIV, SQRT and the quiet and signalling compare predicates.
jamesbraid
force-pushed
the
ide-fpu-fix
branch
2 times, most recently
from
November 2, 2026 15:47
ad267e6 to
c968e9c
Compare
jamesbraid
marked this pull request as draft
November 2, 2026 16:29
jamesbraid
force-pushed
the
ide-fpu-fix
branch
2 times, most recently
from
November 2, 2026 18:54
4474a7f to
4bce574
Compare
The Octane PROM's ide FPU test checks results the host FPU gets wrong for MIPS: infinity minus infinity, zero times infinity, 0/0 and infinity/infinity are Invalid Operations that deliver the default NaN (0x7FBFFFFF), 0/0 is not a divide by zero, and MAX+MAX is Overflow with Inexact. iris returned the host's NaN with no flags. 12 of the 14 subtests passed. Classify those results on every CPU model, in both engines, at no cost to an ordinary result. ADD, SUB, MUL and DIV test the result's magnitude once. That test replaces the old denormal-result test, and the top of the range, which is where Invalid and Overflow live, goes to a cold classifier shared by both engines (a hook for compiled code). The operand flags those ops used to compute up front are gone: an ordinary result proves there were none, and the classifier finds a divide by zero itself. SQRT, RECIP, RSQRT, the multiply-add family and CVT.S.D swap the host's NaN, a signalling NaN under the MIPS encoding, for the default NaN and add V. They do it the same way round: one compare of the result's magnitude, and only an infinity or a NaN goes on to classify the operands. A finite result cannot come from a NaN operand, a zero divisor or a negative square root, so the signalling-NaN tests on up to three operands no longer run for ordinary arithmetic. CVT.S.D checks its source for a signalling NaN only after the conversion has already left the exact path, since a NaN is never equal to itself. Host instructions per FP op, perf stat instructions:u, ordinary operands, ship profile, against the commit before this series (slope over a 120-op region, three alternating rounds, counts do not move between rounds). R10000 numbers; R5000 and R4400 differ by a constant: compiled add.d, mul.d, div.d, sqrt.s, cvt.s.d no change compiled madd/msub/nmadd/nmsub .s and .d 56-63 -> 25-31 compiled recip.s, rsqrt.s 43 -> 25, 51 -> 27 interpreter add.d, mul.d, div.d 197-200 -> 171 interpreter madd/msub/nmadd/nmsub 168-181 -> 153-159 interpreter recip.s, rsqrt.s 145 -> 136, 153 -> 137 interpreter sqrt.s, cvt.s.d no change Every measured op, in both engines, on the R4400, R5000 and R10000, is within 0.1 instruction of the old count or cheaper. The tests that check results run on the ordinary passthrough models in both engines, and compiled code is checked against the interpreter for each rule. On an emulated Octane the ide fpu test passes 14 of 14 with the compiled engine and with the interpreter, and an IRIX 6.5.30 boot reaches login and powers off with halt -p.
jamesbraid
force-pushed
the
ide-fpu-fix
branch
2 times, most recently
from
November 2, 2026 20:51
710711f to
776e029
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
IRIX programs and SGI's diagnostics that check FCSR or NaNs got the wrong answer in iris, because it raised the wrong FP exceptions and used modern IEEE NaNs. The Octane PROM's
ideFPU test failed 2 of its 14 checks: 0/0 raised divide-by-zero instead of Invalid, and an overflowing add left FCSR empty. Now all 14 pass, under the interpreter and jitv2.cpu-testsalready showed this. Invalid results return the MIPS default NaN.The FPU code is shared, so the R4400 and R5000 change too.
Testing
ide fpu: 14/14 under jitv2 and the interpreter. It was 12/14.cargo test --release --lib --features jitv2: 2892 passed. Each fix has a test that fails without it.