mmu.resource and the CPU Support Libraries¶
Besides mmu.library and memory.library, Thomas Richter's MMULib documents a small stack of processor support components in the NDK 3.2 MuManual/ tree:
- 680x0.library — the generic CPU dispatcher: identifies CPU, FPU and MMU and loads the processor-specific library.
- 68040.library / 68060.library — the processor-specific support libraries (MMULib editions): FPU/integer emulation, cache workarounds, exec replacements and MMU setup through
mmu.library. - fpsp.resource — direct entry points into the Motorola FPSP emulation code, built by the 68040/68060 library.
- mmu.resource — an optional low-level driver underneath
mmu.library, for emulators or unusual MMUs.
All of these are third-party MMULib components, not parts of AmigaOS 3.2. This article covers what their MuManual autodocs, headers and example sources document. The NDK's own SetPatch and CPU release notes describe how AmigaOS 3.2 interacts with them.
How the pieces load¶
SetPatch
└─ 680x0.library (generic dispatcher, stays resident)
├─ 68000/68010/68020/68030/68040/68060.library (CPU specific)
│ └─ fpsp.resource (built by the 68040/68060.library)
└─ mmu.library (sets up the MMU; uses mmu.resource if present)
From 680x0.doc: "The 680x0.library is usually loaded by 'SetPatch' on startup and remains in the system. It then checks the available hardware and loads the CPU and MMU specific drivers." The 68040 and 68060 autodocs say that MMU setup "is not done by the 68040.library directly but by the mmu.library which is loaded by the 68040.library on startup" (likewise for the 68060).
The AmigaOS SetPatch release notes (ReleaseNotes/SetPatch-RelNotes) record the OS side:
| SetPatch | Change |
|---|---|
| 45.2 | "the code attempts to load a library named 680x0.library upfront. This library is supposed to be the generic CPU dispatcher." Also looks for 68020.library on the 68020 |
| 45.3 | If 680x0.library is already loaded, SetPatch does not start the CPU-specific libraries |
| 45.10 | 68060 without 68060.library: SetPatch at least fixes UMult64/SMult64 of utility V40 "such that one can run at least the workbench correctly" |
| 45.11 | On a 68040/68060, math libraries older than V45 are removed so they re-probe the FPU when reopened |
| 45.12 | If a core math library was removed, the matching trans library is removed too |
| 47.2 | AFF_FPGA is honored; "there is currently no CPU support library for this flag" |
exec/execbase.h defines AFB_FPGA as bit 10 (AFF_FPGA = 1L<<10) of AttnFlags. The exec.library Reference notes that exec's coldstart only detects a 68060 FPU, so the 68060.library is responsible for FPU handling.
680x0.library¶
| Name | MC680X0_NAME = "680x0.library" |
| Base | struct MC680X0Base (only struct Library dllib_Library is public) |
| Headers | libraries/680x0.h, clib/680x0_protos.h, proto/680x0.h, lvo/680x0_lvo.i, BMAPs/680x0_lib.bmap |
| LVO | Function | Registers | Returns |
|---|---|---|---|
| -30 | char CPUType(void) |
— | CPUTYPE_* |
| -36 | char FPUType(void) |
— | FPUTYPE_* |
| -42 | char MMUType(void) |
— | MUTYPE_* (from mmu/mmubase.h) |
| -48 | ULONG SetFPUExceptions(ULONG flags, ULONG mask) |
d0, d1 | previous disable mask |
Type codes are characters, not bit masks:
| CPU | Value | FPU | Value | MMU | Value |
|---|---|---|---|---|---|
CPUTYPE_68000 |
'0' |
FPUTYPE_NONE |
0 |
MUTYPE_NONE |
0 |
CPUTYPE_68010 |
'1' |
FPUTYPE_68881 |
'1' |
MUTYPE_68851 |
'2' |
CPUTYPE_68020 |
'2' |
FPUTYPE_68882 |
'2' |
MUTYPE_68030 |
'3' |
CPUTYPE_68030 |
'3' |
FPUTYPE_68040 |
'4' |
MUTYPE_68040 |
'4' |
CPUTYPE_68040 |
'4' |
FPUTYPE_68060 |
'6' |
MUTYPE_68060 |
'6' |
CPUTYPE_68060 |
'6' |
Notes from the autodoc:
CPUType()results "are more precise than those that can be found in SysBase->AttnFlags", and "will be correct even for the 68060".FPUType()returnsFPUTYPE_68040/FPUTYPE_68060whenever such an FPU exists, "regardless whether the processor support code has been loaded and the 68881/68882 instructions can be emulated". CheckSysBase->AttnFlagsif you need to know that emulation is active.MMUType()is routed straight tommu.libraryGetMMUType()and returnsMUTYPE_NONEifmmu.libraryis not available. (The autodoc synopsis prints it asGetMMUType(); the prototype and LVO name itMMUType.)SetFPUExceptions()is routed to the CPU-specific library (68020, 68030, 68040 or 68060). It does not touch the FPU. If the driver is missing or cannot change the mask, it does nothing and returns 0.
FPU exception control bits¶
A set bit in flags disables the exception; mask selects which bits are valid. SetFPUExceptions(0, 0) reads the current setting.
| Bit | FPUCtrlB_* |
FPUCtrlF_* |
Disables |
|---|---|---|---|
| 0 | FPUCtrlB_BSUN |
1L<<0 |
branch or set on unordered |
| 1 | FPUCtrlB_INEX |
1L<<1 |
inexact result |
| 2 | FPUCtrlB_DIVZ |
1L<<2 |
divide by zero |
| 3 | FPUCtrlB_UNFL |
1L<<3 |
underflow |
| 4 | FPUCtrlB_OVFL |
1L<<4 |
overflow |
| 5 | FPUCtrlB_SNAN |
1L<<5 |
signalling NaN |
| 6 | FPUCtrlB_OPERR |
1L<<6 |
operand error |
The same definitions appear in libraries/68040.h and libraries/68060.h.
Example: query CPU/FPU and disable an exception¶
Adapted from C_Sources/FPU.c, the Shell tool that sets these flags:
#include <exec/types.h>
#include <libraries/680x0.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/680x0.h>
struct MC680X0Base *MC680x0Base;
int main(void)
{
ULONG flags;
if (MC680x0Base = (struct MC680X0Base *)OpenLibrary(MC680X0_NAME, 40L)) {
Printf("CPU 680%lc0, FPU type '%lc'\n",
(LONG)CPUType(), (LONG)(FPUType() ? FPUType() : '-'));
/* disable the inexact-result exception, leave the others alone */
SetFPUExceptions(FPUCtrlF_INEX, FPUCtrlF_INEX);
flags = SetFPUExceptions(0L, 0L); /* read back */
if (flags & FPUCtrlF_INEX)
Printf("INEX disabled\n");
CloseLibrary((struct Library *)MC680x0Base);
} else {
Printf("680x0.library required.\n");
}
return 0;
}
The base variable name must match what proto/680x0.h expects (FPU.c declares MC680x0Base).
68040.library and 68060.library¶
Each exports one documented function, at an unusual offset: "lots and lots of offsets reserved here.... sigh" says fd/68060_lib.fd, which uses ##bias 222.
| Library | Name constant | Function | LVO | Registers |
|---|---|---|---|---|
68040.library |
MC68040_NAME |
ULONG FPUControl(ULONG flags, ULONG mask) |
-222 | d0, d1 |
68060.library |
MC68060_NAME |
ULONG FPUControl(ULONG flags, ULONG mask) |
-222 | d0, d1 |
FPUControl() takes the FPUCtrl* bits above. It "does not alter the FPU status at all"; it sets control bits in the library base that the library's own FPU exception vectors read, so "this library vector does nothing if someone altered the FPU exception vectors manually". Both autodocs say not to call it directly: "call the same vector of the 680x0.library", i.e. SetFPUExceptions().
What the libraries do, per their --Background-- sections:
| Task | 68040.library | 68060.library |
|---|---|---|
| Cache-related fixes and workarounds for programs | yes | yes |
| Replacement exec CPU functions | yes | yes |
| Load the Motorola FPSP (unimplemented FPU instructions) | FPSP68040 | FPSP68060 |
| Replace the exec scheduler for FPU support | yes | |
| Emulate unimplemented integer instructions | yes | |
MMU setup (delegated to mmu.library) |
yes | yes |
| Workarounds for 68060 bugs | yes |
Selected changes from the MMULib ReadMe history:
- 43.8: the 68040 and 68060.library patch utility.library's division (and on the 68040 also multiplication) routines, "since some kickstart versions apparently do not patch in the optimized versions".
- 43.11: CPU libraries patch the private exec
ExitIntr()to avoid spurious interrupts on fast boards where Paula has not yet cleared the interrupt bits; MMU detection can identify a 68060 that some P5 boards report as a 68010 during bootstrap. - 43.11.1: the 68060.library also clears the branch cache in
CacheClearU()andCacheClearE(). - 43.13.2: all CPU libraries install trampolines to
p5emu.libraryif present, for P5 programs that call undocumented LVOs. - 43.14: the 68060.library uses an explicit test, rather than the CPU revision, to decide whether to disable the load/store bypass on faulty CPUs.
- 46.5: CPU libraries bumped to V46.
fpsp.resource¶
The fpsp.resource is not disk based; the 68040 or 68060.library builds it at startup. Normally every unimplemented FPU instruction goes through exception processing, which "will therefore stop multitasking". Calling the FPSP routines through the resource avoids that overhead. The MMULib FastIEEE tool patches the system IEEE math libraries to use it.
| Function | Inputs | Result |
|---|---|---|
BYTE FPSPMonadic(UWORD opword, IEEEExtended operand) |
d0 = opword, fp0 = operand | d0 = store flag, result in fp0 (and fp1 for FSINCOS) |
BYTE FPSPDyadic(UWORD opword, IEEEExtended op1, IEEEExtended op2) |
d0 = opword, fp0 = source, fp1 = destination | d0 = store flag, result in fp0 |
Rules from fpsp.doc:
- These are assembly-language stubs, "not designed to be callable from C"; applications should reach them through a link library or the math libraries.
- They are re-entrant and interrupt-callable, and do not need a6 loaded with the resource base.
opwordis the second word of the 68881/68882 instruction. Bits 15 and 13 must be 0 (no control instructions), R/M (bit 14) 0, destination (bits 9–7) 0. The source field (bits 12–10) is 0 for monadic and 1 for dyadic. Bits 5–0 hold the opcode; forFSINCOSthe FPC field (bits 2–0) must be001.- FPCR and FPSR supply rounding and exception settings. FPSR comes back as a real 68881/68882 would set it.
- The code never raises an FPU exception itself. A store flag of 0 means a result was produced — possibly NaN or Inf. A non-zero flag means an enabled exception condition was found and fp0 is undefined; the caller must raise the exception if desired.
- BUGS (dyadic): the encoding implies the source is in fp1, but the function takes it in fp0 and returns the destination in fp0.
C_Sources/FPSPSnoop.c (with FPSPSnoopHandler.asm) shows the other side: it takes over the line-F, FPU exception and unimplemented-instruction vectors in the VBR and prints instructions that would reach the FPSP. It uses mmu.library and disassembler.library V40.
mmu.resource¶
mmu.resource is "the low-level driver of the mmu.library … just one level above hardware". Application programs never use it: "There is absolutely no need to make use of this resource whatsoever; the calling syntax is wierd and requires assembly language". It exists so mmu.library can run on MMUs it does not natively support — "more advanced processors, external MMUs or even 'software emulated' MMUs for emulators". mmu.library gained support for it in 43.2, so the MC68K MMU could be emulated "on non-native CPUs (i.e. x86) without the need to re-write the entire library".
Contract for implementers¶
- Make the resource available with
AddResource()at boot, beforemmu.libraryloads. If it is absent, the library uses built-in routines; it never creates one itself. - Provide the usual library entries
LibOpen(),LibClose(),LibExpunge()andLibExtFunc()(currently unused). - Most calls expect a6 =
mmu.librarybase, not the resource base, and some return values in several registers or in the condition codes, mainly for speed. CheckMMUInterface(version, mmubase, mmuresbase)(d0, a0, a6) is the handshake. The lowest API level is 43: "you should currently check for this value and fail if you get anything different". Keep themmubaseit passes;Exception()does not receive it.MMUResType(mmuresbase)(a6) returns the one-byte MMU ID thatmmu.librarypasses on throughGetMMUType().- Flush and push calls run in supervisor mode and must cover both the user and the supervisor tree.
Function groups¶
| Group | Functions (registers) |
|---|---|
| Handshake / identity | CheckMMUInterface (d0, a0, a6), MMUResType (a6) |
| MMU registers | ReadMMUConfig(config) (a0), WriteMMUConfig(config) (a0), BuildMMUConfig(uctx, sctx, defconfig, destconfig) (a0–a3), ParseTT(ctxt, config) (a0, a1), LoadRoot(uroot, sroot) (a0, a1), RootStarter(config, atd, type) (a1, a0, d0) |
| Context setup | DefineMMUContext(config, ctxt) (a0, a5), AdjustMMUContext(depth, destctxt, parent) (d0, a0, a1), AdjustCtxtSettings(ctxt) (a5) |
| Descriptors | ReadDescriptor / ReadFastDescriptor(deptr, atd, type, level, ctxt) (a1, a0, d0, d1, a5), WriteDescriptor(atd, level, ctxt) (a0, d1, a5), FindDescriptor(addr, ctxt) (a0, a5), CmpDescriptor(descr1, descr2, type, delta) (a0, a1, d0, d1; result in CCR), IncrementDescriptor(atd, index) (a0, d0), ReadUMFlags(descr, level, ctxt) (a0, d0, a5) |
| Page install | InstallNewPage / InstallPage(level, tablesize, dest, descr, data, addr, ctxt) (d2, d1, a2, d0, d4, a0, a5), SetIndirect(where, logical, descr) (a0, a1, d0), SetIndirectArray(where, descr, num) (a0, a1, d0) |
| ATC flush | PFlush(addr) (a0), PFlushA(), PFlushTwo(addr1, addr2) (a2, a3) |
| Cache push | PushAll(), PushLine(addr) (a0), PushPage(addr) (a0), PushTwo(addr1, addr2) (a2, a3) |
| DMA | ForbidDMACache(addr, ctxt) (a0, a5), PermitDMACache(addr, ctxt) (a0, a5) |
| Misc | WithoutMMU(userproc) (a5), Exception() (installed directly in the CPU vector table) |
a6 = mmu.library base in every call except CheckMMUInterface and MMUResType. The structures involved are struct MMUConfig (mmu/config.h: mcf_UserRootPointer[2], mcf_SupervisorRootPointer[2], mcf_TranslationControl, mcf_DTT0, mcf_DTT1, mcf_ITT0, mcf_ITT1) and struct AbstractDescriptor (mmu/descriptor.h). IMMUContext and struct MMUResBase are internal and not in the MuManual headers. The MuManual provides no LVO or FD file for the resource.
Gotchas from the autodoc:
PFlush()flushes the descriptor of one page. Early-termination descriptors cover several pages, so other pages they describe may stay in the ATC.PushPage()pushes the data cache and flushes the instruction cache. 68060 bug: unless the address is page aligned, the instruction cache may not be flushed, and the resource does not work around this — align the address first.Exception()is "the complete access error handler" and "maybe the most trickiest one". Its required steps include: flushing the 68060 branch cache on a branch-prediction error; emulatingAbsExecBasereads from a cached copy ("Do NOT attempt to read it from the zero page"); passing physical bus errors and read-modify-write cycles tomulib_OldException; handlingMOVE16, predecrementMOVEM,FMOVE.XandFMOVE.Dwhen computing fault addresses; and supportingMAPP_ROMwrites andMAPP_REPAIRABLEread-back through trace-mode emulation when there is no pipeline access.
External MMU-Configuration commands¶
mmuexternals.doc documents the plug-in interface used by tools such as P5Init. mmu.library executes the MMU-Configuration text file at startup. A command that is not built in is looked up in LIBS:mmu, loaded with LoadSeg(), and scanned for a Resident structure with the same name: type NT_UNKNOWN, version at least 40, rt_AutoInit cleared. Its rt_Init is called with:
| Register | Contents |
|---|---|
| a0 | struct RDArgs *, to pass as the third argument of ReadArgs() |
| a1 | the MMUContext to modify |
| a2 | DOSBase |
| a6 | MMUBase — do not OpenLibrary("mmu.library"); the code runs inside the library's startup in the ramlib process |
The command is called twice, once with the default user context and once with the supervisor context, and is unloaded in between. Allocate shared resources only once. Return 0 for success; 5 or more aborts the mmu.library setup. The MMU is not loaded yet when you run. Start the file with moveq #-1,d0 / rts so that running it from the Shell fails harmlessly.
The CPU command (AmigaOS 3.2)¶
The OS CPU command identifies the same hardware and works alongside these libraries (ReleaseNotes/CPU-RelNotes):
- 45.1:
FASTROM/NOFASTROM/TRAP/NOTRAPbecame dummies ("did not go through the mmu.library"); 68060 support and CPU errata tests added. - 45.5:
CHECKINSTALLtests whether a CPU library is present on CPU models that need one. - 45.7:
CPUTYPEandFPUTYPEswitches print minimal output for scripts, alongside an MMU type switch;TOredirects output. - 46.1 / 46.2: 68060 F6 bug test; the I4 test no longer changes the installed cache settings.
See Also¶
- mmu.library — Hardware-Independent MMU Programming
- memory.library — Virtual Memory
- exec.library Reference
- MC68040 and MC68060 Architecture
- MC68030 MMU and Caches
- Amiga Debugging Tools
Sources: NDK 3.2 R4 MuManual/Autodocs/{680x0,68040,68060,fpsp,mmures,mmuexternals}.doc, MuManual/Include/libraries/{680x0,68040,68060}.h, MuManual/Include/clib/{680x0,68040,68060}_protos.h, MuManual/Include/lvo/{680x0,68040,68060}_lvo.i, MuManual/Include/mmu/{config,descriptor,mmubase}.h, MuManual/fd/68060_lib.fd, MuManual/C_Sources/{FPU,FPSPSnoop}.c, MuManual/ReadMe, ReleaseNotes/SetPatch-RelNotes, ReleaseNotes/CPU-RelNotes, Include_H/exec/execbase.h Updated: 2026-11-13