mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-12 16:16:28 +00:00
327 lines
13 KiB
Markdown
327 lines
13 KiB
Markdown
[← 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)
|