Understanding the X68000 interrupt controller registers

The Sharp X68000 is built around the Motorola 68000 family, so its interrupt system follows a very different model from a modern microcontroller. Devices do not usually jump directly to an arbitrary handler. They request an interrupt level, the controller resolves priority and masking, and the CPU performs an interrupt acknowledge cycle before entering the appropriate exception vector.

That sequence matters when diagnosing a machine that appears to hang during floppy access, MIDI activity, sound playback, serial communication or keyboard input. A register showing a pending request does not necessarily mean the handler has run, and clearing a request does not always mean the hardware source has stopped asserting it.

The names and physical addresses used for the X68000 interrupt hardware can vary between technical references, ROM versions and emulator documentation. The safest approach is to treat the registers as functional groups, confirm the exact address map for the target model, and test each bit with a known interrupt source.

Register function What it tells you Typical operation Common mistake
Interrupt mask Which sources are allowed through Set or clear enable bits Assuming a masked request has disappeared
Pending or request status Which sources are asking for service Read, then clear according to the hardware rule Clearing the status bit instead of the device
In-service or active state Which request is currently being handled Read during nested or priority-sensitive code Treating it as a permanent event log
Priority or level control Which request wins when several arrive Configure during initialisation Changing it while live traffic is present
Vector or acknowledge data Which exception entry the CPU receives Supplied during interrupt acknowledge Assuming every source has its own fixed vector
Edge/level configuration How a request is recognised Set once during device setup Using edge mode for a level-held signal

The 68000 interrupt path

The 68000 exposes interrupt priority through its IPL pins. Seven maskable levels are available, from level 1 through level 7, and the status register contains the interrupt mask that decides which levels the processor will accept. A request only reaches the handler when its level is higher than the current CPU mask, unless software deliberately changes that mask.

When the CPU accepts an interrupt, it saves an exception frame on the supervisor stack. It then performs an interrupt acknowledge cycle rather than reading an ordinary memory location. The interrupt controller or peripheral can provide a vector number during that cycle. If no device supplies one, an autovector entry is used, placing the handler in one of the level-specific slots in the exception vector table.

This is why an X68000 program can appear to ignore an interrupt even though a controller bit is set. The CPU may still be executing with a high interrupt mask, the source may be assigned to a lower level, or another device may be occupying the active priority path. A debugger should inspect both the saved status register and the controller state.

Level 7 deserves separate attention. It is non-maskable in normal 68000 operation and is generally associated with urgent hardware conditions. Code intended for ordinary peripherals should never casually raise the system to level 7 or leave the processor there.

The register groups you need to recognise

Documentation may use names such as interrupt request register, interrupt pending register, interrupt mask register, interrupt enable register, in-service register, priority register and vector register. Some X68000 references group these under the IOC or interrupt controller, while other descriptions discuss the MFP and individual peripheral interrupt flags separately.

The mask register is the first place to look when an interrupt does not arrive. A cleared enable bit blocks delivery to the CPU, but it normally does not remove the underlying event. A floppy controller can still finish a command, and a serial device can still receive a character, while its interrupt remains blocked. Enabling the source later may cause the old request to be serviced immediately.

A request or pending register records an asserted source. The correct clearing method depends on the device. Some requests are cleared by writing a bit to a controller register, some are cleared by reading a data register, and others remain asserted until the peripheral status condition is removed. Never assume that writing zero to a status register is harmless; several classic chips use write-one-to-clear behaviour or have partially writable status fields.

The in-service register, where present, represents arbitration state rather than a useful history of every interrupt. It helps explain priority nesting and end-of-interrupt handling. If the controller expects an explicit acknowledgement or end-of-interrupt write, omitting it can prevent lower-priority requests from being delivered.

MFP registers and peripheral status

The Motorola 68901 Multi-Function Peripheral, commonly called the MFP, combines timers, serial I/O, general-purpose pins and interrupt functions. Its own interrupt registers are often discussed separately from the X68000’s wider interrupt routing. The important MFP concepts include pending bits, in-service bits, enable or mask bits, a vector register and a general-purpose interrupt port.

MFP interrupt handling is commonly divided into two banks of source bits. A source can be pending without being enabled, enabled without currently being pending, or pending and enabled while the CPU is unable to accept its assigned level. Reading the register set as a progression—pending, in service, mask, then device status—usually gives a much clearer diagnosis than inspecting a single byte.

Timers are a classic source of confusion. A timer interrupt may continue to reappear because the timer is still running, even after software clears the controller-side flag. Serial input behaves similarly if the receive register is not emptied or if an error condition remains active. The handler should service the peripheral first, then apply the appropriate acknowledgement sequence.

The X68000 also contains custom logic around its video, DMA, floppy, sound and expansion hardware. An emulator may present these sources as neat logical bits, while a real machine routes them through discrete devices, gate arrays or board revisions. Code that depends on undocumented bit behaviour can therefore work under an emulator and fail on an XVI or Compact model.

Reading, writing and preserving register bits

Most X68000 peripheral interfaces are byte-oriented and are commonly accessed at odd addresses because of the 68000’s bus arrangement. That does not make every register an ordinary byte variable. Some locations are read-only, some have side effects, and some require a particular access width or timing relationship.

Use read-modify-write carefully. If a register contains live request flags, reading it and writing the modified value back can accidentally acknowledge events that arrived between the two operations. It can also rewrite reserved bits with values that are valid on one revision and unsafe on another. Prefer documented set, clear or mask operations when available.

Keep a software copy of configuration registers such as masks, trigger mode and priority. Update that copy, then write the complete intended value. For status registers, read once into a temporary variable and decode that snapshot. This avoids changing your interpretation halfway through a handler as another source becomes active.

Interrupt handlers should preserve the registers required by the calling convention and should do as little work as practical. Save the source state, service the peripheral, clear the request using the documented sequence and return through the proper 68000 exception instruction. A handler that prints text, waits on a busy flag or accesses a slow storage device can make unrelated interrupts look broken.

Vectors, acknowledgement and nested priorities

The vector number received during interrupt acknowledge determines the exception-table entry used by the CPU. It is not necessarily the same thing as the interrupt level. Multiple sources can share a level and use controller-provided vector information to reach different handlers, while some groups may use a common entry that performs software dispatch.

A reliable initialisation sequence normally disables the relevant sources, installs vectors, clears stale peripheral conditions, configures trigger and priority settings, and only then enables the mask bits. Enabling an interrupt before its vector is valid can send the machine into an unintended exception path as soon as a pending request is noticed.

Nested interrupts require particular discipline. If a handler raises or lowers the CPU mask, it changes which requests can pre-empt the current code. The controller’s in-service state and priority rules still matter, so simply lowering the mask is not a complete nesting strategy. Keep handlers re-entrant only when the shared data and peripheral access have been designed for it.

When a vector seems wrong, capture the interrupt level, the CPU status register, the pending bits and the peripheral’s own status at the same moment. A logic analyser on the interrupt line can show whether the source is pulsing or staying low. This distinction separates an edge-detection problem from a missing acknowledgement.

Practical debugging on a real X68000

Begin with a minimal test program that masks all unrelated sources and enables one known device. A periodic timer is usually easier to reason about than keyboard or floppy activity. Record the controller and MFP registers before enabling the source, on entry to the handler and immediately before returning. Comparing those snapshots reveals whether the request is never generated, blocked, repeatedly asserted or incorrectly cleared.

Physical maintenance can affect interrupt symptoms. A loose keyboard connector, oxidised contacts or a damaged membrane can make input appear intermittent even when the interrupt controller is operating normally. The keyboard membrane repair notes are useful background when keyboard events vanish during testing.

For video and synchronisation work, remember that a passive SCART connection does not magically fix timing or signal-level problems. The passive SCART cable guide is relevant when checking whether a display fault is being mistaken for a software interrupt fault. A stable monitor image and a stable interrupt trace should be established separately.

Australian owners often work with imported Japanese machines on a 240-volt supply, and replacement parts can take weeks to arrive from Japan. Use an appropriate step-down transformer where the machine requires it, and do not defeat earth or insulation protection. Mains repairs should follow Australian electrical-safety requirements and be performed by a licensed electrician when the work involves hazardous voltages.

Emulation, expansion and model differences

Emulators are valuable for learning the interrupt sequence because they can expose register accesses and interrupt assertions in a trace. They are less reliable as proof that an undocumented register behaves identically on every physical X68000. Compare emulator source code with hardware documentation, ROM disassembly and tests on the particular machine whenever possible.

Expansion boards add another layer. A Nereid-style network or storage board may use an interrupt line that shares controller resources with an existing peripheral. Its driver must reserve a source, install a compatible vector strategy and acknowledge the board before returning. A conflict can look like a faulty Ethernet or SCSI implementation when the actual problem is an occupied mask bit or an uncleared shared request.

The second-hand market in Australia is relatively small, with Sydney, Melbourne and Brisbane usually offering the greatest concentration of retrocomputing buyers and repair services. Gumtree and eBay listings may describe a machine as “untested”, which often means that interrupt behaviour, keyboard input and floppy completion have not been checked at all. Budget for shipping, Japanese-to-English documentation work and replacement capacitors rather than treating the purchase price as the whole project.

PAL displays, modern HDMI scalers and local replacement keyboards can also alter the test environment. A software interrupt test should use a known-good display path and controller setup before adding a scaler, MIDI interface or expansion card. Keep a written record of the model, ROM version, board modifications and register values; that information is far more useful than a vague report that interrupts “sometimes fail”.

A dependable register-reading method

Treat the interrupt controller as a chain of evidence. First identify the source at the peripheral. Next check whether its request reached the pending register. Then verify that the mask and CPU status permit delivery. Finally confirm the vector and in-service behaviour. Each stage eliminates a different class of fault.

A compact diagnostic routine can store a timestamp, CPU status word, interrupt level, pending bits, mask bits, in-service bits and relevant peripheral status in a RAM buffer. Avoid relying on console output inside the handler. Dump the buffer after interrupts are disabled, or transmit it through a separately verified channel.

Use symbolic names in source code and keep the register definitions in one header. Add comments explaining access width, side effects, reset values and clearing rules. If a bit is undocumented, mark it as model-dependent rather than giving it a confident name that future code will treat as fact.

Understanding the X68000 interrupt controller registers becomes much easier when hardware requests, controller arbitration and 68000 exception handling are examined as separate stages. Document your machine’s register map, test one source at a time and publish confirmed observations for the wider X68000 community. That practical record helps preserve both working hardware and the knowledge needed to repair it.

Nereid-X Expansion Board

A personally-produced LAN+USB+Memory expansion board for Sharp X68000 series computers. Multiple production runs were offered, including a final batch and a later revival reproduction run.

Power Supply Repair

X68 power supply repair and modification services were offered by the site owner, with documentation shared through diary entries spanning 2001–2006.

Server & Networking

Notes on FreeBSD administration, ISP changes, server migration, and networking topics. The site itself ran on FreeBSD with the hns diary system and Namazu search integration.

A two-ink risograph print in muted slate-blue and charcoal on off-white paper, showing a stylized desktop computer monitor beside a circuit board with soft geometric trace lines, conveying a calm retro-computing workshop atmosphere. A two-ink risograph print in deep purple and dark grey on cream stock, depicting a compact expansion card with connector ports and subtle Japanese technical annotations, evoking a hobbyist electronics bench. A two-ink risograph print in teal and charcoal on warm white paper, showing a server rack silhouette with soft network-line motifs and a small weather icon, suggesting a personal server room corner.

Get in touch

X68K.NET connects Sharp X68000 enthusiasts through community links and shared projects. Reach out with questions about the Nereid project or X68 resources.