Skip to content

SAGE: fix thirteen 68000 bugs that kept the UCSD p-System from booting - #579

Open
ajfa wants to merge 1 commit into
open-simh:masterfrom
ajfa:sage-68k-instruction-fixes
Open

SAGE: fix thirteen 68000 bugs that kept the UCSD p-System from booting#579
ajfa wants to merge 1 commit into
open-simh:masterfrom
ajfa:sage-68k-instruction-fixes

Conversation

@ajfa

@ajfa ajfa commented Aug 21, 2026

Copy link
Copy Markdown

The Sage II simulator only ever gets exercised by CP/M-68K, and readme-sage.txt still lists UCSD Pascal as "does not run yet". It turns out the p-System is blocked by thirteen separate bugs in the 68000 core rather than by anything specific to the Sage hardware.

With this patch:

  • the four Sage p-System IV.13 diskettes boot to Command: E(dit, R(un, F(ile, ... and the Filer lists both drives
  • the four Stride p-System IV.21 diskettes boot to their startup utility
  • CP/M-68K 1.2 boots exactly as before

The commit message lists all thirteen. The three with the widest reach are probably these:

  • MOVE never cleared V and C, which accounts for most of the difference on its own
  • the (d8,An,Xn) modes sign extended the 8 bit displacement as if it were 16 bits, in all eleven places that build such an address, so every negative displacement reached the wrong memory
  • the bit mask table had four wrong entries, so BTST, BSET, BCLR and BCHG worked on the wrong bit whenever the bit number was 15, 19, 23 or 27

How this was tested

A differential tester runs one random instruction at a time on this core and on Musashi from the same starting state, then compares the sixteen registers, the PC, the condition codes and a 64 byte window of memory. The SIMH side is driven through the simulator's own command interface, with deposit, step 1 and examine, so what gets tested is the simulator as built rather than a relinked copy of the core.

Out of 425 comparable cases in a run of 800 random instructions, 98 disagreed before these fixes and 8 after. Five of those eight are cases where the two models take a different view of addresses outside the simulated 512 KB. The other three are real and still open: the carry flag of ROR.B and ROR.L, and the flags of CHK.W.

The p-System images used for the boot tests are David Erhart's ImageDisk dumps of original Sage and Stride diskettes. They contain compressed sectors, so they need uncompressing before the simulator will mount them read/write.

🤖 Generated with Claude Code

The Sage II simulator has only ever been exercised by CP/M-68K, and the readme
lists the UCSD p-System as not working yet. Trying to boot it turns up thirteen
defects in the 68000 core. With these fixes the four Sage p-System IV.13
diskettes and the four Stride IV.21 diskettes reach their command prompts, the
Filer lists both drives, and CP/M-68K 1.2 still boots exactly as before.

What was wrong:

* MOVE.B/.W/.L did not clear V and C.
* CMP, CMPA and CMPI wrote the X flag, which they must leave untouched.
* CMPA.W compared a truncated address register against an unextended source.
* CMPM.B/.W/.L were not implemented.
* SUBX had its operands the wrong way round in all six forms.
* MOVE to SR, the immediate forms of ANDI/ORI/EORI to SR, and STOP did not
  swap A7 with USP when the S bit changed, so a program that dropped to user
  mode carried on pushing onto the supervisor stack.
* The 8 bit displacement of the (d8,An,Xn) modes was sign extended as if it
  were 16 bits, in all eleven places that build such an address. Every
  negative displacement therefore reached the wrong memory.
* OR.L <ea>,Dn computed an AND.
* OR.W <ea>,Dn stored its result as a byte.
* DIVS.W never fetched its source operand and used whatever the previous
  instruction had left in the temporary.
* DIVS.W divided by the raw unsigned divisor instead of the sign extended one.
* The bit mask table had four wrong entries, so BTST, BSET, BCLR and BCHG
  worked on the wrong bit whenever the bit number was 15, 19, 23 or 27.
* ROXR.L and ROXL.L loaded a signed int32 into their 64 bit temporary, which
  carried the sign into the rotated result.

How they were found: a differential tester runs one random instruction at a
time on this core and on Musashi from the same starting state, then compares
the sixteen registers, the PC, the condition codes and a 64 byte window of
memory. Out of 425 comparable cases, 98 disagreed before these fixes and 8
after. Five of those eight are cases where the two models take a different
view of addresses outside the simulated 512 KB. The remaining three are the
carry flag of ROR.B and ROR.L and the flags of CHK.W, which are still open.

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

Copy link
Copy Markdown
Contributor

Similar comment about identifying who you are mentioned in simh/simh#1256.

Otherwise, since you're making a good jump at fixing things here in a simulator which, seems to have had a very quiet life in the 12 years it has been in the codebase, why stop before addressing the remaining 8 cases you found to be unexpected?

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