• We've made some quality of life improvements to the Trading Post. More info here.

PowerPC 601 Sail model - an executable ISA specification

Similar to my previous thread about the DSP3210, I just uploaded my PowerPC 601 Sail model in case anyone finds it useful:

https://github.com/pappadf/powerpc-sail

Sail is a language/format for describing an instruction set architecture (ISA). With the Sail specification you can for example:
  • Automatically generate a working emulator (this is actually what my small test system does)
  • Generate a disassembler
  • Generate an AST-to-binary assembler
  • Validate other emulators in lock-step (not recommended at this point, as the model hasn't been checked against real hardware)
Projects like pydrofoil (https://github.com/pydrofoil/pydrofoil) also open the door to much higher-performance JIT-based emulators, but that's very much outside my current scope.

I should make it very clear that this Sail model is immature:
  • It's written/transcribed from the PowerPC 601 manual
  • It's indirectly tested against GNU binutils - the test programs are assembled by a cross toolchain
  • It's tested against synthetic test programs found in the repo
  • It's NOT validated against real hardware (yet)
As always, if you find bugs in the Sail model (and I know there are plenty) - please let me know.

AI tools were used in developing the code, tests and documentation. I know that's a red flag for some, and I fully respect that.
 
In case it's of value for anyone (e.g. building or testing an emulator model - now or in the future); it now includes executable ISA models for 601, 603, 604, 604e and 750 (G3)

...and there's a dedicated project that based on this sail representation can generate an arbitrary amount of test vectors (https://github.com/pappadf/powerpc-test)


AI tools were used in developing the code, tests and documentation. I know that's a red flag for some, and I fully respect that.
 
I see in your github you also have a 68k model - is it usable yet? That's probably the most interesting for the 68kMLA audience :-)
 
I see in your github you also have a 68k model - is it usable yet? That's probably the most interesting for the 68kMLA audience :-)
Aren't you (we) also Sparc fans? What about a Sail model for Sparc? (though actually I'd start with V7).
 
Aren't you (we) also Sparc fans? What about a Sail model for Sparc? (though actually I'd start with V7).
Would be of interest as well, yes :-) , but for now I'm back on 68k - my FPGA-based Sun-2 is almost finished (a very subtle bug left in the core, my new very-old-SCSI implementation needs porting from VME to Multibus).
 
Would be of interest as well, yes :-) , but for now I'm back on 68k - my FPGA-based Sun-2 is almost finished (a very subtle bug left in the core, my new very-old-SCSI implementation needs porting from VME to Multibus).
Excellent! Hope you get that sorted soon. I keep forgetting that most of our conversation was about the Sun MMU (essentially a page cache rather than a modern Page table MMU design) which didn't change much between the Sun 2 and Sun 4.

Note to the uninitiated, working up from the bottom, the early Sun MMU had 4kB page tables (so virtual A<11:0> passed through as is), then the next level was 256 or 128x 64-entry blocks of page translations (this is the page cache). So, virtual A<17:12> indexed an entry in a block (called a PMeg). Next, virtual A<28:17> indexed an array of 4096 bytes each of which whose contents were a PMeg (an 8 or 7-bit value) which selected a block. This is called a context's Segment Map. Finally, there are 8 or 16 contexts, i.e. up to 32768 or 65536 bytes used to select PMegs, and the current context is a single 3 or 4 bit register in the MMU. Thus, a completely new set of mappings can be chosen by simply changing the context register.

One of the upshots of the MMU is that it works reasonably well up until the point where no more than 128 or 256 PMegs are used, because the segment map can't contain more than 128 (or 256) different PMeg values even though there are 32768 entries. So, once this is exceeded, the Segment map has to contain a software cache of PMegs and the Page Cache needs to swap blocks of 64 page translations. And these limits started to get hit once Sun workstations could have more than 16MB (or 32MB) of RAM.
 
Excellent! Hope you get that sorted soon
claude needed some firm hand-holding to figure out the core bug - which may or may not be an ambiguity in the manual (I think it is, claude doesn't ; my reading produces a fully working Sun-2...). Basically, a move byte memory-to-memory in a loop in loop mode (so MC68010 only) would crash if the first access faulted (normally - to allocate a page in the aforedescribed MMU) and enough weird stuff happened (page allocation, maybe recovery from disk in the swap, the clock(s) and/or serial port(s) interrupting, ...) before the RTE to continue the faulted instruction. That continuation would work, but then the next branch back in loop mode would end up executing the wrong opcode as the looped instruction because the opcode stored in the core had been changed somehow. Not restoring loop mode (which forces the core to reload the opcodes from memory) solves the problem.

Now the Z$0.01 question - is reloading the opcodes under those circumstances a deviation from the real MC68010 behavior? :) And now I wonder if that can be modelled in SAIL :devilish:

Edit: SCSI should be easy: same design, same driver in PROM/kernel, different busses already supported.
 
<snip> the opcode stored in the core had been changed somehow. <snip> Now the Z$0.01 question - is reloading the opcodes under those circumstances a deviation from the real MC68010 behavior? :) <snip>
The MC68010 loop-mode cache is only 3x 16-bit words isn't it? Just big enough to contain e.g. MOVE src,dst: DBRA rLoop,.-3 ?

I would be surprised if the MC68010's Loop-mode cache contained the same opcodes, because surely a page fault could result in a process switch which could do its own loop-mode, and then the cache would require reloading anyway. But I'd also expect the exception stack frame to contain enough information to back-track to the beginning of a loop-mode fault or some means of saving the loop-mode cache contents so they can be restored.
Edit: SCSI should be easy: same design, same driver in PROM/kernel, different busses already supported.
Great!
 
The MC68010 loop-mode cache is only 3x 16-bit words isn't it? Just big enough to contain e.g. MOVE src,dst: DBRA rLoop,.-3 ?
Yes. Very minimalist. I've actually had claude add a loop cache mode for bigger loops, which is invalidated for almost any reason, and does help a bit on some code without having any detrimental effect on SunOS. The core isn't cycle-accurate anyway, that wasn't a goal (that ever-relevant MMU is built out of BRAM in the FPGA and add 2 cycles of delay vs. Sun's clever 0-delay MMU, so the machine itself can't be cycle accurate anyway).
 
I see in your github you also have a 68k model - is it usable yet? That's probably the most interesting for the 68kMLA audience :-)

Yes, similar to the ppc model, I also have a project with m68k models (https://github.com/pappadf/m68k-sail)

Whether it is usable or not probably depends on the use case. In my case, I use/consume this model "indirectly" through the corresponding https://github.com/pappadf/m68k-test project, i.e. similar to the ppc variants above, the "test" project generates test vectors based on the sail model.

If the use case is to test an emulator or similar in general (what I do with the https://github.com/pappadf/granny-smith project), then it absolutely fulfils its purpose. I have caught multiple emulator bugs with it, even though I also encounter errors in the model as well.

However, for the specific problem that you bring up (68010 loop mode), these projects will unfortunately not really help you:

m68k-test will not really help, as it is based on single instruction vectors (the scenario you describe happend in a running loop, incuding how to continue after an exception in that loop.)

m68k-sail project will not really give you what you are looking for either, as it lacks some state that is not directly visible to programs, including the three-word instruction buffer, and the associated continuation mechanism (being able to stop half way, save working state in frame, resume on RTE).
 
Yes. Very minimalist.
Minimalism is good (this is where I contradict some of my earlier posts where I claimed the Amiga chipset was an asset).
<snip> (that ever-relevant MMU is built out of BRAM in the FPGA <snip>
As an aside, can a 68030's MMU be made to emulate the Sun MMU? Or did Sun rewrite the VM code for the 68030's actual MMU?
 
As an aside, can a 68030's MMU be made to emulate the Sun MMU? Or did Sun rewrite the VM code for the 68030's actual MMU?
No, they are completely different. The 3/80 and 3/4xx, the machines with the MC68030, use a different architecture and kernel - sun3x instead of sun3. The userland itself is compatible. The sun3x is unfortunately not very well documented, as it only had a short life - those machines only existed as a performance-update path for older m68k machines while everyone migrated to SPARC (the 3/80 shares a case with the original SPARCstation 1, a sun4c machine, and they were released after the initial batch of VME-based sun4).
 
No, they are completely different. The 3/80 and 3/4xx, the machines with the MC68030, use a different architecture and kernel - sun3x instead of sun3<snip>
OK, what I meant was whether it's possible for reads and writes to the Sun MMU peripheral space to be trapped and mimicked by a 68030 MMU. e.g. TC.IS=3 (so A<31:29>) aren't used, TC.PS=12 (4kB), TC.TIA=12 (A<28:18>), TC.TIB=6 (A<17:12>). TC.TIC=TC.TID=0. TIA page directories would only be able to point to the 128 (or 256) 64-entry TIB page tables. Changing a context would change the Root Pointer Descriptor. Thus at a minimum, using short descriptors, one needs 128kB for the TIA to emulate the segment map and 32kB to emulate the page map. Since I guess SunOS manages SegmentMap clashes in the kernel (which could be OK for shared libraries), Sun MMU emulation wouldn't even have to handle that. This is rather fanciful, obviously.

 
OK, what I meant was whether it's possible for reads and writes to the Sun MMU peripheral space to be trapped and mimicked by a 68030 MMU
Never though about it... I wouldn't have bothered with a hack like that myself - simply redoing the VM subsystem "the MC68030 way" would have probably been easier - in particular as the sun3x wasn't the only one with a non-Sun*style MMU, the sun4m with the SPARC Reference MMU would have a fairly similar software architecture, I think, and that was already there in the 600MP.
 
You'd need to make sure SunOS (or whatever you are running) doesn't try to use the 030 mmu, and have it set up with just the right tables to mimic the older memory map. Otherwise it'd just write over whatever you set up.

The old sun mmu was pretty primitive, from what little I've looked at it, so the 030's could very likely do what it did. You'd need to trap the io access for the old mmu (or however it changed states), and redo the 030 tables as they were needed on the fly. So, quite tricky mmu coding but it sounds like in theory it could be done.

I didn't know there were sparcs that used the old mmu!

I think a large amount of the source code for the old os's is out there, so there's more than one way you could do it. Either modifying the OS vm system, maybe, or something transparent to it that just emulates the old mmu.
 
<snip> make sure SunOS <snip> doesn't try to use the 030 mmu, and have it set up with just the right tables <snip>
Well, if it thought it was running on a 68020? Though that would involve fooling SunOS when it attempted to check the processor ID (assuming that's how SunOS does it). I was (not seriously) wondering if an '030 Mac could run SunOS.
sun mmu was pretty primitive <snip> need to trap the io access for the old mmu
That would be the idea. I think MMU access was via FC address spaces. A number of 80s CPUs had primitive MMUs. The ARM2 MEMC chip had a weird one where a 4MB physical space was split into 128 pages which contained their logical page translations. So, when a logical address was presented, it used a Content Addressable Memory to match the physical page it corresponded to. I'm more surprised personally that many 80s MMUs were so over-engineered, or overly complex. The 80286's MMU was virtually unusable and the 680x0 MMUs got simpler over time. I would have started with a simple user-side MMU with a single-level 4kB software-managed page table.
I didn't know there were sparcs that used the old mmu!
Yes, Sun-4m used Sparc V7, which didn't have an integral MMU. The SparcStation 1 used a SunOS MMU, with 8 contexts and a 7-bit PMeg.
I think a large amount of the source code for the old os's is out there, so there's more than one way you could do it. Either modifying the OS vm system, maybe, or something transparent to it that just emulates the old mmu.
Actually that's a good point, because I remember recompiling the kernel for SunOS 4.1.2 on a MAME emulated SS1. The VM code could be there.
 
Well, if it thought it was running on a 68020?
If you don't want to use the '030 MMU, then it's trivial. Just wire the '030 in '020 compatibility mode as documented by Motorola, which include disabling the MMU via /MDIS (plus all the synchronous bus stuff, ...).
In fact, the Sun 3/60 was a MC68020+MC68881 machine but did have an empty MC68030 socket, and could function with a MC68030+MC68881 machine. But with no benefits over a MC68020, as the MMU is still the external Sun MMU and the data cache is never enabled.
Yes, Sun-4m used Sparc V7, which didn't have an integral MMU. The SparcStation 1 used a SunOS MMU, with 8 contexts and a 7-bit PMeg.
sun4 and sun4c had Sun-style MMU. sun4m and later have the SRMMU from V8. The SS1 is sun4c. While most sun4m were SPARC v8, the original 600MP could ship with SM100 modules which are dual SPARC v7 - the MMU is decorelated from the actual SPARC version. You can actually run a pair of SM100 in a SPARCstation 20 and get a quad-SPARC v7 machine if you really want to - but you don't (a pair of good old SM61 to get dual 60 MHz SuperSPARC already feels faster). It's much more fun to run a pair of SM512 module (two 50 MHz SuperSPARC each, v8). Been there, tried both :-) (those SM512 are awesome, but are way too got for my taste).
 
If you don't want to use the '030 MMU
I meant use an '030 + its MMU, but report '020 to SunOS if that's how it determines which MMU to use. But it might just be explicitly compiled when the kernel is compiled and your next paragraph implies that that's how its done.
<snip> Sun 3/60 was a MC68020+MC68881 machine but did have an empty MC68030 socket, and could function with a MC68030+MC68881 machine. But with no benefits over a MC68020, as the MMU is still the external Sun MMU and the data cache is never enabled.
OK, how curious!
sun4 and sun4c had Sun-style MMU. sun4m and later have the SRMMU from V8.<snip>
My mistake, I meant sun4/sun4c and Sparc V7.
 
I meant use an '030 + its MMU, but report '020 to SunOS if that's how it determines which MMU to use
You'd still need kernel changes, as the sun3 uses virtually-addressed DMA - the DVMA requests have to go through the MMU, which isn't possible with an internal MMU.
And the MMU is unique to each architecture, not probed in the software - Sun-2 (whether type 1 Multibus or type 2 VME) all have the same Sun-style MMU; Sun-3 "sun3" all have the same Sun-style MMU (a bit different from the Sun-2 one), where Sun-3 "sun3x" have the MC68030 MMU; that's the choice that Sun made. Hacking support for the MC68030 MMU in software on a sun3 would effectively be recreating the sun3x architecture.
 
Back
Top