cpu-tests: grow the fpu group from 26 tests to 88 - #87
Merged
Conversation
The FPU was the thinnest group in the suite relative to its surface. 26 tests
covered arithmetic and FCSR bookkeeping; the entire *trapped* exception path,
denormals, half the compare predicates and most of double precision had no
coverage at all. Seven new files under tests/fpu/, one under tests/mips4/, and
a generator for the expectations:
fpu_trap.c (14) enabled exceptions — the Cause/Enable/Flag interaction,
what a trap must not write, EPC and Cause.BD
fpu_denorm.c (9) denormal operands and results, underflow, FCSR.FS, and
the Unimplemented Operation path they all lead to
fpu_compare.c (7) all sixteen C.cond predicates in both formats, quiet vs
signalling NaNs, the condition bit's ownership
fpu_vectors.c (10) arithmetic, all four rounding modes and every integer
conversion, against generated tables
fpu_double.c (8) the double paths with no vector: NaN results, the bit
operations, and conversion between the two formats
fpu_fr0.c (8) the FR=0 paired register file — the mode every o32 IRIX
binary runs the FPU in
fpu_breadth.c (6) all 32 registers, signalling-NaN operands, out-of-range
conversions, unaligned FP access
mips4_fp.c (6) RECIP.D/RSQRT.D, LDXC1/SWXC1/SDXC1/PREFX, MSUB/NMADD/
NMSUB in both formats, and the FP conditional moves —
each computing on R5000 and required to raise Reserved
Instruction on R4400
gen/fpvectors.py computes every expectation with exact rational arithmetic and
cross-checks it against the host FPU before writing anything (`make vectors`;
CI fails if the checked-in tables are stale). That is what makes it practical
to assert the FCSR flags *exactly*, for every vector, rather than hand-writing
a hundred Inexact bits — and its own first bug is written up in gotchas.md,
because computing an expectation from a value the register cannot hold fails in
the most misleading way available.
Five findings, all in docs/findings.md §6-§10, each traced to the line
responsible: a trapped exception still writes its result and its Flag bit;
FCSR.Cause accumulates instead of being rewritten per operation; denormals
never raise Unimplemented Operation and FCSR.FS is inert; a signalling NaN
raises Invalid only where a quiet one would; ABS.fmt and NEG.fmt never touch
FCSR at all. rules/testing/ gets the short version.
Everything the FPU is asked to *compute* passes on both CPUs: every generated
vector, all 128 predicate results, both formats, all four rounding modes,
every conversion.
Three fixes in the runner, none in the tests:
- run/run-local.sh never passed --config run/bare.toml, so `make run` died
before the guest ran an instruction (the default config attaches a scsi1.raw
that does not exist). Its --serial-log was also always empty: under
--load-elf the SCC is never programmed, so nothing reaches the backend to be
teed. It now tees stdout, like matrix.sh and CI already did.
- the suite halted the machine before the SCC drained, and run-prom.sh read
the log the instant the DONE token appeared. Either one truncates
"IRIS-CPUTEST-DONE rc=100" to "rc=" — the line run-prom.sh matches on to
decide pass or fail.
- run-prom.sh defaulted to a per-cell binary name matrix.sh stopped using.
R4400 interpreter: 2041 checks passed, 121 failed (240 tests, 29 failing).
R5000 interpreter: 2095 passed, 37 failed (13 failing). Booted through the
PROM from a mkvh image: 2041/121, the same answer down the path the bootable
disc will use.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
The FPU was the thinnest group in the suite relative to its surface. 26 tests covered arithmetic and FCSR bookkeeping; the entire trapped exception path, denormals, half the compare predicates and most of double precision had no coverage at all. Seven new files under tests/fpu/, one under tests/mips4/, and a generator for the expectations:
fpu_trap.c (14) enabled exceptions — the Cause/Enable/Flag interaction,
what a trap must not write, EPC and Cause.BD
fpu_denorm.c (9) denormal operands and results, underflow, FCSR.FS, and
the Unimplemented Operation path they all lead to
fpu_compare.c (7) all sixteen C.cond predicates in both formats, quiet vs
signalling NaNs, the condition bit's ownership
fpu_vectors.c (10) arithmetic, all four rounding modes and every integer
conversion, against generated tables
fpu_double.c (8) the double paths with no vector: NaN results, the bit
operations, and conversion between the two formats
fpu_fr0.c (8) the FR=0 paired register file — the mode every o32 IRIX
binary runs the FPU in
fpu_breadth.c (6) all 32 registers, signalling-NaN operands, out-of-range
conversions, unaligned FP access
mips4_fp.c (6) RECIP.D/RSQRT.D, LDXC1/SWXC1/SDXC1/PREFX, MSUB/NMADD/
NMSUB in both formats, and the FP conditional moves —
each computing on R5000 and required to raise Reserved
Instruction on R4400
gen/fpvectors.py computes every expectation with exact rational arithmetic and cross-checks it against the host FPU before writing anything (
make vectors; CI fails if the checked-in tables are stale). That is what makes it practical to assert the FCSR flags exactly, for every vector, rather than hand-writing a hundred Inexact bits — and its own first bug is written up in gotchas.md, because computing an expectation from a value the register cannot hold fails in the most misleading way available.Five findings, all in docs/findings.md §6-§10, each traced to the line responsible: a trapped exception still writes its result and its Flag bit; FCSR.Cause accumulates instead of being rewritten per operation; denormals never raise Unimplemented Operation and FCSR.FS is inert; a signalling NaN raises Invalid only where a quiet one would; ABS.fmt and NEG.fmt never touch FCSR at all. rules/testing/ gets the short version.
Everything the FPU is asked to compute passes on both CPUs: every generated vector, all 128 predicate results, both formats, all four rounding modes, every conversion.
Three fixes in the runner, none in the tests:
make rundied before the guest ran an instruction (the default config attaches a scsi1.raw that does not exist). Its --serial-log was also always empty: under --load-elf the SCC is never programmed, so nothing reaches the backend to be teed. It now tees stdout, like matrix.sh and CI already did.R4400 interpreter: 2041 checks passed, 121 failed (240 tests, 29 failing). R5000 interpreter: 2095 passed, 37 failed (13 failing). Booted through the PROM from a mkvh image: 2041/121, the same answer down the path the bootable disc will use.