[← Home](../README.md) · [CPU & MMU](README.md)

# 68040.library and 68060.library — CPU Support Libraries

## Overview

The 68040 and 68060 processors **removed certain instructions** that the 68020/68030 and 68881/68882 FPU supported in hardware. These "unimplemented" instructions cause a Line-F exception (vector $2C) when executed. The `68040.library` and `68060.library` are **trap handler libraries** that catch these exceptions and **emulate the missing instructions in software**, providing transparent backward compatibility.

### Why Were Instructions Removed?

Motorola's 68040 design made a strategic tradeoff: **fit MMU, FPU, and dual caches onto a single die** while reaching competitive clock speeds — all within a ~1.2 million transistor budget. To achieve this, two painful decisions were made:

1. **Drop microcode-heavy FPU instructions.** Trigonometric (`FSIN`, `FCOS`), logarithmic (`FLOG2`, `FLOGN`), and exponential (`FETOX`, `FTWOTOX`) functions require ROM lookup tables and iterative algorithms in microcode, consuming thousands of transistors. Sacrificing them freed silicon for the on-chip 4 KB data + 4 KB instruction caches — a much larger performance win for typical integer-heavy Amiga software.

2. **Eliminate the barrel shifter.** The dedicated barrel shifter circuit was removed, simplifying the critical timing path and allowing higher clock speeds. This is why certain integer instructions (`MOVEP`) were also dropped.

The 68060 doubled down: additional integer instructions (`MOVEP`, `CMP2`, `CAS2`, `CHK2`) were removed to make the instruction decoder leaner, enabling **superscalar execution** (up to two instructions per clock in the best case).

### The Tradeoff: Pros and Cons

| Pro | Con |
|---|---|
| Smaller die → lower cost, higher yield | Programs crash without the trap library |
| Fewer transistors → less heat, lower power | Trap overhead: ~30–200 cycles per emulated instruction (vs ~15–80 if native) |
| Cleaner critical paths → higher MHz | 68040.library (~24 KB) + 68060.library (~40 KB) must ship separately |
| Freed silicon enabled on-chip MMU + larger caches | Some instructions (`FSINCOS`) have **no software workaround** |
| Fewer microcode bugs (68881/68882 errata avoided) | Timing unpredictability — trap latency varies by instruction |

**Bottom line:** Motorola bet that most applications lean on integer math (games, productivity, OS), where the larger caches and higher clocks delivered a clear win, while the small fraction of transcendental-heavy code could tolerate software emulation. For the Amiga ecosystem this was a good bet — every accelerator card shipped with SetPatch and the 68040.library on its install disk, making compatibility a one-time setup concern.

Without these libraries, any program using the affected instructions would crash with a Line-F exception on 040/060 hardware.

---

## What Instructions Are Emulated?

### 68040.library

The 68040 removed several FPU instructions that the 68881/68882 supported:

| Category | Missing Instructions | Description |
|---|---|---|
| Transcendental FPU | `FSIN`, `FCOS`, `FTAN`, `FASIN`, `FACOS`, `FATAN` | Trig functions |
| Transcendental FPU | `FSINH`, `FCOSH`, `FTANH`, `FATANH` | Hyperbolic functions |
| Transcendental FPU | `FLOG2`, `FLOG10`, `FLOGN`, `FLOGNP1` | Logarithms |
| Transcendental FPU | `FETOX`, `FETOXM1`, `FTWOTOX`, `FTENTOX` | Exponentials |
| Other FPU | `FMOD`, `FREM` | Modulo/remainder |
| Other FPU | `FGETEXP`, `FGETMAN` | Get exponent/mantissa |
| Other FPU | `FSGLDIV`, `FSGLMUL` | Single-precision ops |
| Integer | `MOVEP` | Move peripheral (not on all 040 revisions) |

### 68060.library

The 68060 removed **everything the 040 removed** plus additional instructions:

| Category | Additionally Missing | Description |
|---|---|---|
| Integer | `MOVEP` | Move peripheral (byte-strided) |
| Integer | `CAS2` | Compare-and-swap dual |
| Integer | `CHK2`, `CMP2` | Range check |
| Integer | `MULU.L (64-bit)` | 64-bit unsigned multiply |
| Integer | `MULS.L (64-bit)` | 64-bit signed multiply |
| Integer | `DIVU.L (64-bit)` | 64-bit unsigned divide |
| Integer | `DIVS.L (64-bit)` | 64-bit signed divide |
| FPU | All 68040-missing FPU ops | Same as above |
| FPU | `FMOVECR` | Move constant ROM |
| FPU | `FDABS`, `FDSQRT`, etc. | Some double-precision ops |

---

## How They Work

```
1. Program executes FSIN (opcode $F200 xxxx)
2. 68040/060 CPU has no microcode for this → Line-F exception (#11)
3. CPU vectors to the Line-F exception handler
4. 68040.library's handler decodes the opcode from the stack frame
5. Software emulates FSIN using basic FADD/FMUL/FDIV
6. Result is placed in the correct FPU register
7. Handler returns → program continues as if nothing happened
```

```mermaid
graph TB
    APP["Application code"] -->|executes FSIN| CPU["68040/060 CPU"]
    CPU -->|"opcode not in microcode"| EXC["Line-F Exception #11"]
    EXC --> VEC["Exception vector table"]
    VEC --> LIB["68040.library trap handler"]
    LIB --> DEC["Decode opcode from stack frame"]
    DEC --> EMU["Software emulation<br/>(FADD/FMUL/FDIV series)"]
    EMU --> RES["Place result in FPU register"]
    RES --> RET["RTE — return to application"]
    RET --> APP

    style CPU fill:#e8f4fd,stroke:#2196f3
    style LIB fill:#fff9c4,stroke:#f9a825
    style EMU fill:#ffe0b2,stroke:#ff9800
```

---

## Installation

These libraries are **loaded at boot time** as resident modules. They install themselves as the Line-F exception vector handler.

```
; In startup-sequence or user-startup:
LIBS:68040.library    ; for 68040 systems
; or:
LIBS:68060.library    ; for 68060 systems (replaces 68040.library)
```

The library is typically loaded by `SetPatch` or an explicit `C:LoadModule`:

```
C:LoadModule LIBS:68040.library
; or for 68060:
C:LoadModule LIBS:68060.library
```

---

## struct (ROM Tag)

Both libraries register as `RTF_COLDSTART` resident modules with high priority to ensure they are initialized before any user code runs:

```c
/* Typical RomTag for 68040.library: */
static struct Resident romtag = {
    RTC_MATCHWORD,         /* $4AFC */
    &romtag,
    &endskip,
    RTF_COLDSTART,         /* flags: cold start */
    40,                    /* version */
    NT_LIBRARY,
    105,                   /* priority: very high */
    "68040.library",
    "68040.library 40.1 (1.1.93)\r\n",
    initRoutine
};
```

---

## Detection

```c
/* Check which CPU is present: */
if (SysBase->AttnFlags & AFF_68040)  /* 68040 */
if (SysBase->AttnFlags & AFF_68060)  /* 68060 */

/* AttnFlags bits: */
#define AFB_68010   0
#define AFB_68020   1
#define AFB_68030   2
#define AFB_68040   3
#define AFB_68060   7   /* added by 68060.library */
#define AFB_68881   4   /* FPU present */
#define AFB_68882   5
#define AFB_FPU40   6   /* 040 internal FPU */
```

---

## Performance Impact

Software emulation of transcendental FPU instructions is **10–100x slower** than the 68881/68882 hardware implementation. Performance-critical code should:
- Use lookup tables for trig functions
- Use polynomial approximations (Chebyshev, CORDIC)
- Avoid `FSIN`/`FCOS` in tight loops

---

## Common Sources

| Library | Source |
|---|---|
| 68040.library 37.4 | Commodore (OS 3.0 distribution) |
| 68040.library 40.1 | Commodore (OS 3.1 distribution) |
| 68060.library 40.1 | Phase5 (original 68060 accelerators) |
| 68060.library 46.x | Motorola reference implementation |

---

## When to Use / When NOT to Use

| Scenario | Use Library? | Why |
|---|---|---|
| Running FPU-heavy code compiled for 68881/68882 on 040 | **Yes** | Missing transcendental instructions will crash |
| Running FPU-heavy code compiled for 68881/68882 on 060 | **Yes** | 68060.library replaces 68040.library; covers more missing ops |
| Your code only uses basic FPU (FADD/FMUL/FDIV) | **No** | These are native on 040/060 — no library needed |
| Your code uses MOVEP on 040 (some revisions) | **Yes** | Some 040 masks lack MOVEP microcode |
| Code uses CAS2 or CHK2 on 060 | **Yes** | 68060 removed these integer ops |
| Published application targeting 68000–060 | **Yes** | Ship both libraries as dependencies |
| Benchmarking FPU performance | **No** | Emulation skews results; use native ops only |

---

## Named Antipatterns

### 1. "The Missing Library" — No 68040.library on 040

**Symptom:** Program works on 68030, crashes with Line-F exception on 68040.

**Why it fails:** The software used `FSIN` (or another removed instruction) from a 68881 FPU library compiled for 68030. The 68040 has no microcode for it, and without the trap library, the exception is unhandled.

**Fix:** Always install `68040.library` on 040 systems and `68060.library` on 060 systems. `SetPatch` typically does this, but verify it loaded.

### 2. "The Trig Loop" — FSIN/FCOS in Inner Loops on 040

**Symptom:** Acceptable performance on 68030+68881, but drops to single-digit FPS on 68040.

```c
/* BROKEN — software-emulated FSIN on every frame */
for (int i = 0; i < count; i++) {
    float angle = i * step;
    points[i].x = sin(angle);  /* calls FSIN via library emulation */
}
```

**Fix:** Precompute a lookup table, or use a polynomial approximation that only needs FADD/FMUL:

```c
/* CORRECT — lookup table: no FSIN at runtime */
float sin_table[360];
for (int i = 0; i < 360; i++)
    sin_table[i] = sin(i * M_PI / 180.0);  /* done once at startup */
```

### 3. "The Wrong CPU Check" — Testing AFF_68040 on 68060

**Symptom:** Code detects CPU as 68040 when running on 68060, then loads wrong library.

```c
/* BROKEN — 68060 matches AFF_68040 check */
if (SysBase->AttnFlags & AFF_68040)
    LoadModule("LIBS:68040.library");  /* wrong library on 060! */
```

**Fix:** Check 68060 first — it's a superset:

```c
/* CORRECT — check most specific first */
if (SysBase->AttnFlags & AFF_68060)
    LoadModule("LIBS:68060.library");
else if (SysBase->AttnFlags & AFF_68040)
    LoadModule("LIBS:68040.library");
```

---

## Pitfalls

### 1. 68060.library Without First Installing 68040.library

Some setups load `68060.library` directly without also installing `68040.library`. The 68060 library is a **replacement** for the 68040 library (it includes all 040 emulation plus 060-specific additions), but boot scripts that check-for-library-before-loading can fail if both aren't present.

```
; WRONG — 68040.library may be needed by other components
C:LoadModule LIBS:68060.library

; CORRECT — install both or let 68060 supersede
C:LoadModule LIBS:68040.library LIBS:68060.library
; 68060.library patches over 68040.library's functions
```

### 2. Forgetting Library on Emulated 68040/060

On UAE or MiSTer with 68040/060 emulation enabled, the same Line-F exceptions occur. The emulated CPU has the same missing instructions as real silicon. Always include the libraries in your emulated Workbench setup.

---

## Impact on FPGA/Emulation — MiSTer & UAE

### TG68K Core

The Minimig-AGA core on MiSTer uses the TG68K CPU core, which implements **68020 only**. It does not implement the 68040 or 68060 instruction sets, so 68040.library and 68060.library are **not needed** on MiSTer's Minimig core.

### UAE Emulation

WinUAE and FS-UAE can emulate 68040 and 68060 CPUs. When these are enabled:
- The emulator's CPU **correctly triggers Line-F exceptions** for removed instructions
- The same trap libraries must be installed in the emulated Amiga's `LIBS:` directory
- Omitting them produces the same crashes as real hardware

### M68040 / M68060 FPGA Cores

If building a custom FPGA core with a 68040 or 68060 implementation (e.g., the `m68040` project in this workspace), the core must:
- Raise a Line-F exception for unimplemented opcodes
- Provide a valid exception stack frame so the library can decode the opcode
- Not silently execute removed instructions (producing wrong results with no error)

---

## Modern Analogies

| Amiga Concept | Modern Equivalent | Why It's the Same Pattern |
|---|---|---|
| 68040.library emulating FSIN | CPU microcode patches (Intel/AMD Spectre/Meltdown mitigations) | Hardware defect or missing feature patched by software at exception time |
| 68060.library superseding 68040.library | ARM exception levels with nested handlers | More-capable handler replaces less-capable one at same exception vector |
| Library auto-detection via `AttnFlags` | CPUID instruction + feature flag checking | Runtime query determines which code path to use |
| Trap-and-emulate for missing ops | Rosetta 2 (x86 → ARM translation) | Transparent instruction emulation invisible to application |

---

## FAQ

### Does 68060.library replace 68040.library entirely?

Yes. 68060.library contains all 68040.library emulation plus additional routines for instructions the 68060 removed beyond what the 040 removed (CAS2, CHK2, 64-bit MUL/DIV, etc.). It patches the same exception vector and supersedes the 040 library.

### Can I use FSIN in code shipped to 68040 customers?

Yes, but you must document that `68040.library` is required. The library will emulate FSIN transparently. However, be aware that emulated FSIN is 10–100x slower than native 68881 FSIN — avoid it in performance-critical paths.

### Does the library handle MOVE16 on 68040?

No. `MOVE16` is a **native** 68040 instruction — it is not emulated by the library. The confusion arises because `MOVEP` (a different instruction, byte-strided) IS emulated on 68040 revisions without microcode for it.

---

## References

- Motorola: *MC68040 User's Manual* — unimplemented instruction list
- Motorola: *MC68060 User's Manual* — unimplemented instruction list  
- NDK39: `exec/execbase.h` — `AttnFlags`
- Phase5: 68060.library source (public domain)
