Skip to content

feat(cpu): decode COP1 compares and conversions, fix NaN convention - #28

Merged
doublegate merged 6 commits into
mainfrom
feat/cop1-compares-and-conversions
Jul 20, 2026
Merged

feat(cpu): decode COP1 compares and conversions, fix NaN convention#28
doublegate merged 6 commits into
mainfrom
feat/cop1-compares-and-conversions

Conversation

@doublegate

@doublegate doublegate commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Motivation

After #27, the dominant remaining n64-systemtest block was the undecoded COP1 funct space
roughly 1,700 of 2,682 failures. Everything needed was already implemented in fpu.rs; none of it
was reachable.

Result

Stage Failing assertions
After #27 2,682
Compares + conversions decoded 1,468
NaN convention corrected 1,098

All sixteen C.cond.fmt tests now pass outright — from 42 failures apiece to zero.

1. The compares and conversions (2,682 → 1,468)

Decode admitted only funct 0..=3 and 5..=7 in the .S/.D formats, and never admitted the
integer source formats .W/.L at all
— so every integer-to-float conversion was a silent no-op
too. Same shape of gap as MOV.fmt in #27, found this time by asking which neighbouring encodings
shared the range rather than waiting for it to cost another investigation.

ROUND/TRUNC/CEIL/FLOOR take their rounding mode from the opcode and ignore FCSR.RM;
CVT.W/CVT.L consult it. That is the entire difference between the two families, and it is
invisible whenever RM happens to agree — so the test sets RM to nearest and converts -1.5,
where truncate gives -1 and nearest gives -2.

fp_arith is restructured around a single commit-or-trap point: each family returns an FpCommit
plus flags, and the trap check, the Cause-only write and the non-retirement happen once rather
than being duplicated per family.

2. The NaN convention (1,468 → 1,098)

The VR4300 classifies a NaN as signalling when the significand's MSB is SET — the legacy MIPS
convention, inverted from IEEE-754:2008. 0x7FC0_0000, which Rust produces as f32::NAN and
everything else calls quiet, raises Invalid on this processor.

Established from the oracle's own expectations, which name their constants the IEEE way and then
assert the opposite. For a non-signalling compare:

Operand IEEE name Expected Implies
0x7FC0_0000 (MSB set) "quiet" Invalid signalling here
0x7FBF_FFFF (MSB clear) "signalling" no flags quiet here

The signalling compare forms raise for both and so do not distinguish the conventions —
checking only those would have left the question open.

The corroboration that makes it more than a curve fit: the VR4300's own default NaN result is
0x7FBF_FFFF, MSB clear. Read as IEEE, that is a processor whose invalid-operation result is a
signalling NaN, which would re-trap the instant anything touched it. Read under this convention it
is an ordinary quiet one. Two independent facts, from different tests, agreeing on the same
inversion. Accuracy ledger C-12.

Five existing tests asserted the IEEE convention and were updated. One now asserts
is_snan_f32(f32::NAN) deliberately, because that is the case most likely to be "fixed" back by
someone who has not read the ledger entry.

Testing

347 passing. Every guard mutation-checked — revert the fix, confirm red, restore.

Worth flagging: the decode arm initially had no test at all. Reverting it broke nothing, which
is exactly the decoded-but-no-op blind spot AGENTS.md now warns about. The enumerated decode test
and two execution tests were added until the revert goes red. The decode test enumerates the whole
range rather than spot-checking, because the failure mode here is a gap, and a gap is what a
single representative encoding does not find.

Also

.coderabbit.yaml, tuned to this project's decided rules rather than generic Rust style — clippy
(pedantic + nursery, -D warnings) already gates the generic advice, so the useful thing a review
bot can add is catching contradictions with an ADR or invented facts. It also lists the deliberate
deviations (reverse pipeline cascade, reproduced errata, the inverted NaN convention, soft-float
over native operators) so they are not reported as defects.

Not in scope

Phase 1 is not complete; v0.2.0 is not cut. The dominant remaining block is now the
unmaskable unimplemented-operation cause (bit 17), which the VR4300 raises for subnormal
operands and results and for a quiet-NaN operand to an arithmetic operation. SQRT (funct 4)
also stays undecoded — there is no square-root implementation, so it remains
Cop1Unimplemented rather than becoming a wrong result.

…NaN convention

n64-systemtest: 2,682 -> 1,098. All sixteen `C.cond.fmt` tests now pass outright.

Two changes, measured separately.

**The compares and conversions (2,682 -> 1,468).** `C.cond.fmt`, the `CVT`
family and `ROUND`/`TRUNC`/`CEIL`/`FLOOR` to `.W`/`.L` were implemented in
`fpu.rs` all along but unreachable: decode admitted only `funct 0..=3` and
`5..=7`, and never admitted the INTEGER source formats `.W`/`.L` at all, so
every integer-to-float conversion was a silent no-op too. The same shape of gap
as `MOV.fmt`, found by asking which neighbouring encodings shared the range.

`ROUND`/`TRUNC`/`CEIL`/`FLOOR` take their rounding mode from the OPCODE and
ignore `FCSR.RM`; `CVT.W`/`CVT.L` consult it. That is the entire difference
between the two families, and it is invisible whenever `RM` happens to agree --
so the test sets `RM` to nearest and converts `-1.5`, where the two disagree.

`fp_arith` is restructured around one commit-or-trap point: each family returns
an `FpCommit` plus flags, and the trap check, the `Cause`-only write and the
non-retirement all happen once rather than per family.

**The NaN convention (1,468 -> 1,098).** The VR4300 classifies a NaN as
signalling when the significand's MSB is SET -- the legacy MIPS convention,
inverted from IEEE-754:2008. `0x7FC0_0000`, which Rust produces as `f32::NAN`
and everything else calls quiet, raises Invalid here.

Established from the oracle's own expectations, which name their constants the
IEEE way and then assert the opposite: for a non-signalling compare it expects
MSB-set to raise Invalid and MSB-clear to raise nothing. The signalling compare
forms raise for both and so do not distinguish the conventions -- checking only
those would have left it open.

The corroboration that makes it more than a curve fit: the VR4300's own default
NaN result is `0x7FBF_FFFF`, MSB clear. Read as IEEE that is a processor whose
invalid-operation result is a signalling NaN, which would re-trap on first use.
Read under this convention it is an ordinary quiet one. Two independent facts
agreeing on the same inversion. Accuracy ledger C-12.

Five existing tests asserted the IEEE convention and were updated; one now
asserts `is_snan_f32(f32::NAN)` on purpose, because that is the case most likely
to be "fixed" back by someone who has not read the ledger entry.

All three guards mutation-checked. The decode arm initially had NO test --
reverting it broke nothing -- which is exactly the decoded-but-no-op blind spot
AGENTS.md now warns about; the enumerated decode test and two execution tests
were added until the revert goes red.

Also adds `.coderabbit.yaml`, tuned to this project's decided rules rather than
generic Rust style, so a second review bot does not spend its comments on things
clippy already gates or flag deliberate deviations as defects.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 20, 2026 21:54
@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added support for COP1 comparison, conversion, and fixed-rounding operations, including C.cond.fmt, CVT, ROUND, TRUNC, CEIL, and FLOOR.
    • Corrected integer-to-floating-point conversions and rounding-mode handling.
  • Bug Fixes

    • Corrected VR4300-specific signalling and quiet NaN classification.
    • Fixed floating-point condition updates, exception handling, and stale unimplemented-operation status.
    • Reduced reported system-test failures from 2,682 to 1,098.
  • Documentation

    • Updated status reports, accuracy records, and development guidance to reflect the corrected COP1 behaviour.

Walkthrough

COP1 compare and conversion instructions now decode and execute through a refactored floating-point commit and trap flow. VR4300 NaN classification is updated across arithmetic and soft-float paths, with tests and project records revised. CodeRabbit review settings are added.

Changes

COP1 execution updates

Layer / File(s) Summary
COP1 decode and commit flow
crates/rustyn64-cpu/src/decode.rs, crates/rustyn64-cpu/src/pipeline.rs
Compare and conversion encodings decode to Op::FpArith; execution handles operation-specific rounding, FCSR condition commits, traps, integer conversions, and regression tests.
VR4300 NaN classification
crates/rustyn64-cpu/src/fpu.rs, crates/rustyn64-cpu/src/softfloat.rs
Signalling NaN detection uses the significand-MSB convention for f32 and f64, with updated propagation and classification tests.
Status and accuracy records
AGENTS.md, CHANGELOG.md, docs/STATUS.md, docs/accuracy-ledger.md
Guidance, changelog entries, COP1 status, failure counts, remaining gaps, and ledger entry C-12 reflect the execution and NaN changes.

Review configuration

Layer / File(s) Summary
CodeRabbit review configuration
.coderabbit.yaml
Adds review behaviour settings, path exclusions, Rust and documentation instructions, tooling gates, pre-merge checks, automatic chat replies, and knowledge-base settings.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant COP1Instruction
  participant Decoder
  participant fp_arith
  participant FCSRAndFPR
  COP1Instruction->>Decoder: decode funct and format
  Decoder->>fp_arith: dispatch Op::FpArith
  fp_arith->>FCSRAndFPR: commit FPR result or FCSR.C
  fp_arith->>FCSRAndFPR: write Cause on floating-point trap
Loading
🚥 Pre-merge checks | ✅ 8 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docs-As-Spec Sync ⚠️ Warning FAIL: AGENTS.md says docs/ is the spec and must update in the same PR as code; rustyn64-cpu behaviour changed, but docs/cpu.md was not updated and the PR body gives no justification. Add the matching docs/cpu.md spec update, or state in the PR body why the chip-behaviour change needs no subsystem-doc change.
Measured, Never Tuned ⚠️ Warning Measured, never tuned: FCSR.C bit 23 in pipeline.rs is only test-confirmed; docs/accuracy-ledger.md C-12 covers NaN convention, not this constant. Add a UM/wiki citation for the compare-condition bit position, or record its derivation in docs/accuracy-ledger.md with how it was established.
✅ Passed checks (8 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the PR and satisfies Conventional Commits: feat(cpu): subject, under 72 characters, with no trailing period.
Description check ✅ Passed The description is directly related to COP1 decode, NaN handling, and review config, so it is on-topic for this changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Oracle Number Is Stated ✅ Passed PASS: behaviour changes state n64-systemtest effects in CHANGELOG/STATUS/ledger (2,682→1,468; 1,468→1,098); tooling/docs-only edits are exempt.
Changelog Entry For User-Visible Changes ✅ Passed PASS: CHANGELOG.md has an [Unreleased] section with Added/Fixed entries covering the user-visible COP1 decode and NaN behaviour changes.
Unsafe Stays Out Of The Chip Crates ✅ Passed PASS: PR only touches docs and rustyn64-cpu; no actual unsafe syntax was found, and all chip crates/core still have #![forbid(unsafe_code)].

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR wires up previously-implemented COP1 compare (C.cond.fmt) and conversion/rounding operations in the decoder/execute path, and corrects NaN signalling classification to match the VR4300’s legacy MIPS convention (significand MSB set ⇒ signalling). It reduces n64-systemtest failures from 2,682 → 1,098 and updates project docs/changelog to reflect the new accuracy milestone.

Changes:

  • Expanded COP1 decode/execute to cover compares, conversions, and fixed-mode integer conversions (keeping SQRT intentionally undecoded).
  • Updated NaN signalling detection (and related tests/docs) to the VR4300-inverted convention (ledger C-12).
  • Updated status/ledger/changelog/agent guidance and added CodeRabbit configuration to align review automation with repo decisions.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
docs/STATUS.md Updates COP1 “partial” status and the current n64-systemtest failing count/next blocker.
docs/accuracy-ledger.md Adds ledger entry C-12 documenting the inverted VR4300 NaN convention and its impact.
crates/rustyn64-cpu/src/softfloat.rs Updates NaN signalling classification in unpacking logic and adjusts tests/comments accordingly.
crates/rustyn64-cpu/src/pipeline.rs Refactors COP1 execution around an FpCommit to unify commit-or-trap handling and adds compare/conversion support.
crates/rustyn64-cpu/src/fpu.rs Implements VR4300 NaN signalling classification and adds/updates corroborating tests.
crates/rustyn64-cpu/src/decode.rs Broadens COP1 decode coverage (incl. integer source formats) and adds enumerated decode tests to prevent gaps.
CHANGELOG.md Records the new COP1 decode coverage and NaN convention fix with updated n64-systemtest deltas.
AGENTS.md Updates project guidance to include the inverted NaN convention and the new failure count/state.
.coderabbit.yaml Adds repo-specific CodeRabbit review instructions emphasizing ADR/ledger consistency and known deliberate deviations.
Comments suppressed due to low confidence (1)

docs/STATUS.md:131

  • This paragraph still says the conversions and C.cond.fmt compares are “not yet decoded” and “unreachable”, which contradicts the updated COP1 status just above (and the PR’s stated result). It should be updated/removed so docs/STATUS.md remains the single source of truth.
`SQRT` (funct 4), the conversions and the `C.cond.fmt` compares are implemented
in `fpu.rs` but **not yet decoded**, so they remain unreachable. `ABS`, `MOV`
and `NEG` were in that list until they were found to be the cause of ~100
failures — a *decoded-but-no-op* instruction is invisible to `cargo test`, and
`MOV` in particular is emitted by the compiler for every FP call boundary.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/rustyn64-cpu/src/pipeline.rs Outdated
Comment thread docs/accuracy-ledger.md Outdated
…leared

`CAUSE_MASK` covered only bits 16:12. Bit 17, `Unimplemented Operation`, is part
of the `Cause` field even though it is not an IEEE exception and so has no
`Enable` bit and no sticky `Flags` twin -- which means that mask is the ONLY
thing that can ever clear it. Once raised it stayed set forever, and software
reading `FCSR` after a perfectly successful conversion would still see the
previous failure.

Found by Copilot on PR #28. The suite could not have caught it: no test raised
bit 17 and then ran another COP1 instruction. There is one now, mutation-checked
against reverting the mask.

Also adopts Copilot's second comment: the C-11 paragraph naming the undecoded
funct space as "the dominant remaining block" is now false, and is rewritten in
explicit past tense rather than back-edited. A ledger read top to bottom should
show what was believed when each entry was written.

Rewrites `.coderabbit.yaml` against the published schema (schema.v2.json) rather
than from memory. All the original keys were valid but the file was thin:

- `tools`: clippy and markdownlint OFF, because this repo already gates both
  harder than a bot will (pedantic + nursery at `-D warnings`, and a pinned
  markdownlint pre-commit hook). Leaving them on spends review comments on
  findings CI has already blocked. actionlint, yamllint, shellcheck and gitleaks
  stay on -- they cover ground no local gate does.
- `finishing_touches`: generated docstrings and unit tests OFF. rustdoc is a
  blocking gate and every test here carries a rationale comment saying what it
  would catch, so generated stand-ins would have to be rewritten.
- `pre_merge_checks`: Conventional Commits title, plus two custom checks -- that
  a behaviour change states its measured n64-systemtest delta, and that a chip
  change touches that chip's doc.
- New path instructions for tests (flagging convergent success/failure paths)
  and for workflows (flagging a gate piped into tail/grep, which has hidden
  three real failures here).
- `knowledge_base.code_guidelines` pointed at AGENTS.md, the accuracy ledger and
  engineering-lessons, with learnings scoped local.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.coderabbit.yaml:
- Around line 66-71: Expand the Markdown lint configuration in the
`.coderabbit.yaml` review instructions so the mandatory check applies to every
Markdown file, not only `docs/**/*.md`. Update the existing Markdown path rule
or add the appropriate repository-wide Markdown pattern, while preserving the
current documentation-specific guidance for files under `docs/`.
- Line 31: Update the ROM ignore pattern in the CodeRabbit configuration to
exclude only tests/roms/external/**, allowing the committed
tests/roms/n64-systemtest/ corpus to remain visible during review.

In `@docs/accuracy-ledger.md`:
- Around line 689-693: Correct the NaN classification in the “Still open, and
adjacent” entry: describe an MSB-clear NaN as IEEE-signalling and VR4300-quiet
under the documented inverted convention, while preserving the stated
unimplemented-operation behavior and its connection to the arithmetic tests.

In `@docs/STATUS.md`:
- Around line 105-125: Remove or update the stale COP1 status paragraph near the
referenced section that claims compares and conversions are not decoded or
reachable. Ensure docs/STATUS.md consistently states that compares and
conversions decode and execute, while preserving the current blocker
descriptions for unimplemented-operation causes and SQRT.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fb82f1cc-054b-4a7c-9509-c22e9687861c

📥 Commits

Reviewing files that changed from the base of the PR and between 7c5fc75 and fbecc9e.

📒 Files selected for processing (9)
  • .coderabbit.yaml
  • AGENTS.md
  • CHANGELOG.md
  • crates/rustyn64-cpu/src/decode.rs
  • crates/rustyn64-cpu/src/fpu.rs
  • crates/rustyn64-cpu/src/pipeline.rs
  • crates/rustyn64-cpu/src/softfloat.rs
  • docs/STATUS.md
  • docs/accuracy-ledger.md

Comment thread .coderabbit.yaml Outdated
Comment thread .coderabbit.yaml Outdated
Comment thread docs/accuracy-ledger.md Outdated
Comment thread docs/STATUS.md
@doublegate

Copy link
Copy Markdown
Owner Author

@coderabbitai review

Re-requesting after 3be3c85, which rewrote .coderabbit.yaml against schema.v2.json — this run should pick up the new tools, finishing_touches, pre_merge_checks (including the two custom checks) and the extra path instructions.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

@doublegate Reviewing #28 again with the updated .coderabbit.yaml configuration and its current path instructions and checks.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…ertive

All four were correct.

- `.coderabbit.yaml` hid `tests/roms/**` from review, which over-reached: the
  `n64-systemtest/` corpus is committed (MIT, with its upstream LICENSE beside
  it) and `tests/roms/README.md` carries the licence-tiering rules. Narrowed to
  `!tests/roms/external/**`, the gitignored tier that was actually meant.
- The markdownlint instruction covered only `docs/**/*.md`, leaving AGENTS.md
  and CHANGELOG.md -- edited on nearly every PR -- outside the one rule that
  mentions it. It is now a `**/*.md` entry, and says why it matters: markdownlint
  has no CI job here, so it is the single gate that can silently not run.
- Ledger C-12 described the still-open case as an "IEEE-quiet NaN operand (MSB
  clear)", which is self-contradictory: under IEEE-754:2008 MSB *set* is quiet.
  The oracle settles it -- the ADD.S case expecting unimplemented-operation uses
  `SIGNALLING_NAN_START_64` (MSB clear) -- so it is IEEE-signalling and
  VR4300-quiet. Both readings are now named at every mention, here and in
  docs/STATUS.md, since C-12 exists precisely because they disagree.
- docs/STATUS.md contradicted itself: a trailing paragraph still claimed the
  compares and conversions were undecoded. Rewritten to name only `SQRT`, and to
  keep the rule that paragraph produced -- when adding a decode arm, enumerate
  the neighbouring funct space rather than only the encoding that prompted it.

Profile raised from `chill` to `assertive`, the most feedback CodeRabbit offers.
Its docs warn that may feel nitpicky; that is the right trade here, because a
missed defect on this project is measured in weeks of misdirected investigation
(ledger C-10), every comment is adjudicated individually rather than skimmed,
and the path instructions already list the deliberate deviations not to report
-- which is what makes assertive affordable rather than noisy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/rustyn64-cpu/src/pipeline.rs (1)

1698-1764: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Thread FCSR.RM into the inexact CVT helpers.

CVT.S.D, CVT.S.W, CVT.S.L, and CVT.D.L still go through mode-blind casts, so directed rounding is lost for non-exact conversions. That violates docs/accuracy-ledger.md U-8 and the FPU rounding contract in crates/rustyn64-cpu/src/fpu.rs. CVT.D.S and CVT.D.W are exact and fine; add a regression under a non-default RM.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rustyn64-cpu/src/pipeline.rs` around lines 1698 - 1764, Update
fp_convert so the inexact conversions CVT.S.D, CVT.S.W, CVT.S.L, and CVT.D.L
receive and honor the FCSR.RM mode through the corresponding FPU conversion
helpers, rather than using mode-blind casts. Leave the exact CVT.D.S and CVT.D.W
paths unchanged, preserve existing flag and trap handling, and add a regression
covering non-default rounding.

Source: Coding guidelines

🧹 Nitpick comments (1)
.coderabbit.yaml (1)

172-185: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Include docs/STATUS.md in local review guidance.

The configured checks rely on status/count accuracy but omit the declared source of truth from filePatterns.

Proposed fix
     filePatterns:
       - "AGENTS.md"
       - "docs/accuracy-ledger.md"
       - "docs/engineering-lessons.md"
+      - "docs/STATUS.md"
       - "CONTRIBUTING.md"

As per coding guidelines, docs/STATUS.md must be read before work and is the single source of truth for counts and state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.coderabbit.yaml around lines 172 - 185, Update the
code_guidelines.filePatterns configuration to include docs/STATUS.md alongside
the existing guidance files, ensuring local reviews read the documented source
of truth for counts and state.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/rustyn64-cpu/src/pipeline.rs`:
- Around line 1505-1518: Update the earlier fp_arith documentation describing
the FCSR Cause field to include bits 17:12 instead of 16:12, explicitly
identifying Cause.E (Unimplemented Operation) at bit 17. Keep the documentation
consistent with the CAUSE_MASK definition and its stale-bit-clearing behavior.

---

Outside diff comments:
In `@crates/rustyn64-cpu/src/pipeline.rs`:
- Around line 1698-1764: Update fp_convert so the inexact conversions CVT.S.D,
CVT.S.W, CVT.S.L, and CVT.D.L receive and honor the FCSR.RM mode through the
corresponding FPU conversion helpers, rather than using mode-blind casts. Leave
the exact CVT.D.S and CVT.D.W paths unchanged, preserve existing flag and trap
handling, and add a regression covering non-default rounding.

---

Nitpick comments:
In @.coderabbit.yaml:
- Around line 172-185: Update the code_guidelines.filePatterns configuration to
include docs/STATUS.md alongside the existing guidance files, ensuring local
reviews read the documented source of truth for counts and state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e0a38df4-08ac-4aec-9eb3-944b9d0748dd

📥 Commits

Reviewing files that changed from the base of the PR and between fbecc9e and 3be3c85.

📒 Files selected for processing (3)
  • .coderabbit.yaml
  • crates/rustyn64-cpu/src/pipeline.rs
  • docs/accuracy-ledger.md

Comment thread crates/rustyn64-cpu/src/pipeline.rs
… copied

RustyNES's `.coderabbit.yaml` is far more complete than this one was, and
comparing them surfaced a dozen valid keys this file never set. All were
re-verified against schema.v2.json rather than trusted from the sibling repo.

Added: sequence_diagrams, estimate_code_review_effort, changed_files_summary,
related_issues/related_prs, suggested_labels/reviewers (with the auto-apply
counterparts explicitly OFF -- single-maintainer repo), slop_detection,
auto_review.ignore_title_keywords, the full finishing_touches block, three more
pre_merge_checks, `!Cargo.lock` in path_filters, knowledge_base.web_search, and
an explicit 49-entry tools list.

Where this DELIBERATELY differs from RustyNES, and why:

- `markdownlint` ON here, OFF there in spirit. This repo has no markdownlint CI
  job at all -- it is pre-commit only, so it silently does not run for anyone
  without the hook. That makes it the one linter CodeRabbit ADDS rather than
  duplicates.
- `clippy` OFF. CI runs it at pedantic + nursery with `-D warnings`, a strict
  superset of default clippy, so the tool could only repeat findings that
  already block the merge or contradict a lint the workspace allows.
- `opengrep` OFF as a semgrep fork, on the same duplicate-findings reasoning
  RustyNES applies to pylint/flake8.
- Tool list rebuilt from THIS repo's footprint (Rust, Markdown, TOML, YAML,
  shell, one Python file). RustyNES needs detekt/swiftlint/luacheck/clang for
  its Kotlin, Swift, Lua and C; this project has none of those.
- `finishing_touches` fully off, including autofix and fix_ci. Every change here
  goes through one conditional gate and every guard is mutation-checked before
  it is kept; a bot-authored commit bypasses both.
- `drafts: true` (RustyNES has false). Branches here run long -- PR #27 reached
  49 commits -- and the expensive mistakes are the ones caught before the branch
  is finished. `ignore_title_keywords` is the escape hatch.
- `learnings.scope: local` rather than auto. This is a public repo and the
  conventions learned here -- notably the inverted NaN classification -- are
  correct for the VR4300 and wrong almost everywhere else.

Path instructions gained per-crate entries for the CPU (reverse-cascade latch
reads), core (the one permitted chip-to-chip edge), the test harness (an oracle
that runs nothing looks exactly like one that passes) and scripts (two of them
are commit gates that block committing a commercial ROM).

Note for the sibling repo: RustyNES's config still states the markdownlint hook
is pinned to v0.39.0. Both repos pin v0.49.1; the same stale claim was corrected
here earlier in this branch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@doublegate doublegate changed the title feat(cpu): COP1 compares and conversions, and the inverted NaN convention (2,682 → 1,098) feat(cpu): decode COP1 compares and conversions, fix NaN convention Jul 20, 2026
…7:12

The comment and the code disagreed in exactly the way this project's own
convention warns about -- and this pair had already produced the stale-bit
defect fixed in 3be3c85, where CAUSE_MASK matched the wrong comment rather than
the architecture.

Now states that Cause is 17:12, that bit 17 is Cause.E with no Enable bit and no
sticky Flags twin, and that the narrower 16:12 range used by the enable
comparison is a different statement about the five *maskable* conditions.

Found by CodeRabbit under the assertive profile, citing the path instruction
that comments disagreeing with the implementation must be flagged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.coderabbit.yaml:
- Around line 424-431: Update the CodeRabbit configuration for the “unsafe stays
out of the chip crates” check so its enforcement matches the intended policy:
enable reviews.request_changes_workflow for blocking error checks, or change
this check’s mode from error to warning if it should remain non-blocking.

In `@docs/STATUS.md`:
- Around line 128-134: Update the SQRT status statement in the documentation to
say that SQRT (funct 4) is both undecoded and unimplemented, aligning it with
the implementation status described in Lines 115–117. Leave the surrounding
history and neighboring instruction details unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a2e228a3-8364-461a-9e3b-7aca4e750316

📥 Commits

Reviewing files that changed from the base of the PR and between 3be3c85 and 6db210e.

📒 Files selected for processing (3)
  • .coderabbit.yaml
  • docs/STATUS.md
  • docs/accuracy-ledger.md

Comment thread .coderabbit.yaml
Comment thread docs/STATUS.md Outdated
Two CodeRabbit findings, both correct.

STATUS.md called SQRT "implemented-but-undecoded" eleven lines after saying it
has no implementation. It is neither, so it is not an instance of the
decoded-but-no-op pattern at all -- the conversions and compares were, until
this sprint.

The `unsafe` pre-merge check was set to `error` mode, which only blocks when
`request_changes_workflow` is enabled; it is not, so the mode claimed a gate
that could never fire. Downgraded to `warning`, which is also the honest level:
`#![forbid(unsafe_code)]` makes this a COMPILE error in every chip crate, and
this config's stated principle is not to duplicate a gate the repo already runs
harder.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@doublegate
doublegate merged commit bf54699 into main Jul 20, 2026
8 of 9 checks passed
@doublegate
doublegate deleted the feat/cop1-compares-and-conversions branch July 20, 2026 22:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/rustyn64-cpu/src/pipeline.rs (1)

1717-1758: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Pass FCSR.RM into the CVT.S.* / CVT.D.L paths. pipeline.rs still calls mode-blind helpers here, so directed rounding is ignored whenever the conversion is inexact, contrary to UM §7.2.4 and accuracy-ledger C-11. Add mode-aware helpers and regression cases for CVT.S.D, CVT.S.W, CVT.S.L, and CVT.D.L under all four rounding modes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rustyn64-cpu/src/pipeline.rs` around lines 1717 - 1758, Update the
conversion handling in the `0o40` and `0o41` branches to pass the current
`FCSR.RM` into mode-aware FPU helpers for `CVT.S.D`, `CVT.S.W`, `CVT.S.L`, and
`CVT.D.L`, preserving the existing unimplemented-trap behavior for restricted
long inputs. Add regression coverage for each conversion under all four rounding
modes, including inexact results.

Source: MCP tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/rustyn64-cpu/src/pipeline.rs`:
- Around line 1477-1480: In the documentation comment near Cop1Control::ctc1 and
CAUSE_MASK, narrow the bit 17 clearing claim to state that the mask is the only
automatic clear in this arithmetic path. Preserve the existing explanation of
bit 17 and its lack of Enable and sticky Flags counterparts.

---

Outside diff comments:
In `@crates/rustyn64-cpu/src/pipeline.rs`:
- Around line 1717-1758: Update the conversion handling in the `0o40` and `0o41`
branches to pass the current `FCSR.RM` into mode-aware FPU helpers for
`CVT.S.D`, `CVT.S.W`, `CVT.S.L`, and `CVT.D.L`, preserving the existing
unimplemented-trap behavior for restricted long inputs. Add regression coverage
for each conversion under all four rounding modes, including inexact results.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cccb6091-7413-468f-93b5-760250d10e2a

📥 Commits

Reviewing files that changed from the base of the PR and between 6db210e and 4e3cd88.

📒 Files selected for processing (3)
  • .coderabbit.yaml
  • crates/rustyn64-cpu/src/pipeline.rs
  • docs/STATUS.md

Comment on lines +1477 to +1480
/// **The field is 17:12, not 16:12.** Bit 17 is `Cause.E`, Unimplemented
/// Operation — part of `Cause` despite having no `Enable` bit and no sticky
/// `Flags` twin, which means the mask is the *only* thing that ever clears
/// it. This comment said 16:12 while `CAUSE_MASK` covered 16:12 too, and

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Narrow the “only clears it” claim.

Cop1Control::ctc1 also lets software clear writable Cause bits, so CAUSE_MASK is not the only mechanism that can clear bit 17. Change “the mask is the only thing that ever clears it” to “the only automatic clear in this arithmetic path”. This follows the FCSR contract in crates/rustyn64-cpu/src/cop1.rs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rustyn64-cpu/src/pipeline.rs` around lines 1477 - 1480, In the
documentation comment near Cop1Control::ctc1 and CAUSE_MASK, narrow the bit 17
clearing claim to state that the mask is the only automatic clear in this
arithmetic path. Preserve the existing explanation of bit 17 and its lack of
Enable and sticky Flags counterparts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants