m68kemu

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 26, 2026 License: MIT Imports: 5 Imported by: 0

README

m68kemu

A Motorola 68000 emulator written in Go.

This project provides a cycle-accurate Motorola 68000 CPU emulator, suitable for use in retro-computing projects, emulators for classic computers and consoles, or for educational purposes.

Features

  • Motorola 68000 instruction set emulation.
  • Cycle-accurate execution.
  • Supervisor and user modes.
  • Exception and interrupt handling.
  • Address bus with support for multiple devices (e.g., RAM).
  • Tracing and breakpoint support for debugging.

Getting Started

This package is designed to be used as a library in your own projects.

Installation
go get github.com/jens/m68kemu
Example Usage

Here's a simple example of how to set up the CPU, load a program, and run it:

package main

import (
	"fmt"
	"log"

	"github.com/jens/m68kemu"
)

func main() {
	// Create a 64KB RAM device at address 0.
	ram := m68kemu.NewRAM(0, 64*1024)

	// Create a bus and attach the RAM.
	bus := m68kemu.NewBus(ram)

	// Set up the initial stack pointer and program counter.
	// SSP at 0x1000, PC at 0x2000.
	ram.Write(m68kemu.Long, 0, 0x1000)
	ram.Write(m68kemu.Long, 4, 0x2000)

	// Create the CPU.
	cpu, err := m68kemu.NewCPU(bus)
	if err != nil {
		log.Fatalf("Failed to create CPU: %v", err)
	}

	// Assemble a simple program: MOVEQ #5, D0 (opcode 0x7005)
	program := []byte{0x70, 0x05}
	startPC, _ := ram.Read(m68kemu.Long, 4)

	for i, b := range program {
		if err := ram.Write(m68kemu.Byte, startPC+uint32(i), uint32(b)); err != nil {
			log.Fatalf("Failed to write program: %v", err)
		}
	}

	// Step one instruction.
	if err := cpu.Step(); err != nil {
		log.Fatalf("CPU step failed: %v", err)
	}

	// Print registers to see the result.
	regs := cpu.Registers()
	fmt.Printf("D0 = %d\n", regs.D) // Should be 5
	fmt.Printf("PC = 0x%04x\n", regs.PC) // Should be 0x2002
}

Testing

The emulator has an extensive test suite, including instruction-level tests and small programs.

To run the tests:

go test ./...

To run the benchmarks:

go test -bench=. ./...

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

View Source
const (
	Version           = "1.1.0"
	XBusError         = 2
	XAddressError     = 3
	XIllegal          = 4
	XDivByZero        = 5
	XPrivViolation    = 8
	XUninitializedInt = 15
	XTrap             = 32
)

Variables

This section is empty.

Functions

This section is empty.

Types

type AddressBus

type AddressBus interface {
	Read(s Size, address uint32) (uint32, error)
	Write(s Size, address uint32, value uint32) error
	Reset()
}

AddressBus for accessing address areas

type AddressError

type AddressError uint32

func (AddressError) Error

func (ae AddressError) Error() string

type AddressRangeDevice added in v1.1.0

type AddressRangeDevice interface {
	AddressRange() (start uint32, end uint32)
}

AddressRangeDevice exposes a fixed address range that can be indexed by the bus.

type Breakpoint

type Breakpoint struct {
	Address   uint32
	OnExecute bool
	OnRead    bool
	OnWrite   bool
	Halt      bool
	Callback  func(BreakpointEvent) error
}

type BreakpointEvent

type BreakpointEvent struct {
	Type      BreakpointType
	Address   uint32
	Registers Registers
}

type BreakpointHit

type BreakpointHit struct {
	Address uint32
	Type    BreakpointType
}

func (BreakpointHit) Error

func (bh BreakpointHit) Error() string

type BreakpointType

type BreakpointType int
const (
	BreakpointExecute BreakpointType = iota
	BreakpointRead
	BreakpointWrite
)

func (BreakpointType) String

func (bt BreakpointType) String() string

type Bus

type Bus struct {
	// contains filtered or unexported fields
}

Bus multiplexes memory access between attached devices and performs common checks such as alignment and bus error handling.

func NewBus

func NewBus(devices ...Device) *Bus

NewBus constructs a bus optionally seeded with devices.

func (*Bus) AddDevice

func (b *Bus) AddDevice(device Device)

AddDevice attaches an additional device to the bus.

func (*Bus) Peek added in v1.1.0

func (b *Bus) Peek(s Size, address uint32) (uint32, error)

Peek reads from the mapped device without charging wait states. Devices may use this for debugger-friendly, side-effect-free inspection.

func (*Bus) Read

func (b *Bus) Read(s Size, address uint32) (uint32, error)

Read forwards a read to the mapped device after performing alignment and mapping checks.

func (*Bus) Reset

func (b *Bus) Reset()

Reset propagates a reset to all attached devices.

func (*Bus) SetWaitHook

func (b *Bus) SetWaitHook(hook WaitHook)

SetWaitHook installs a callback that receives the configured wait states for every transaction. Callers can use this to count cycles or block for a desired duration.

func (*Bus) SetWaitStates

func (b *Bus) SetWaitStates(states uint32)

SetWaitStates defines how many states the bus should report for each transaction when a WaitHook is configured.

func (*Bus) Write

func (b *Bus) Write(s Size, address uint32, value uint32) error

Write forwards a write to the mapped device after performing alignment and mapping checks.

type BusError

type BusError uint32

func (BusError) Error

func (be BusError) Error() string

type CPU

type CPU interface {
	Registers() Registers
	Step() error
	RunCycles(budget uint64) error
	Reset() error
	SetTracer(TraceCallback)
	SetScheduler(*CycleScheduler)
	Scheduler() *CycleScheduler
	AddBreakpoint(Breakpoint)
	RequestInterrupt(level uint8, vector *uint8) error
	Cycles() uint64
}

CPU exposes the minimal interface for interacting with the emulator core.

func NewCPU

func NewCPU(bus AddressBus) (CPU, error)

type CycleListener added in v1.1.0

type CycleListener interface {
	AdvanceCycles(delta uint64, now uint64)
}

type CycleScheduler added in v1.1.0

type CycleScheduler struct {
	// contains filtered or unexported fields
}

type Device

type Device interface {
	Contains(address uint32) bool
	Read(Size, uint32) (uint32, error)
	Write(Size, uint32, uint32) error
	Reset()
}

Device represents a memory-mapped peripheral on the address bus. Implementations are expected to be safe for repeated Reset calls and must internally validate the address ranges they cover.

func MapDevice added in v1.1.0

func MapDevice(start, end uint32, device Device) Device

type InterruptController

type InterruptController struct {
	// contains filtered or unexported fields
}

func NewInterruptController

func NewInterruptController() *InterruptController

func (*InterruptController) Pending

func (ic *InterruptController) Pending(mask uint16) (uint8, uint32, bool)

func (*InterruptController) Request

func (ic *InterruptController) Request(level uint8, vector *uint8) error

type MappedDevice added in v1.1.0

type MappedDevice struct {
	// contains filtered or unexported fields
}

MappedDevice wraps another device with an explicit 24-bit address range.

func (*MappedDevice) AddressRange added in v1.1.0

func (d *MappedDevice) AddressRange() (uint32, uint32)

func (*MappedDevice) Contains added in v1.1.0

func (d *MappedDevice) Contains(address uint32) bool

func (*MappedDevice) Peek added in v1.1.0

func (d *MappedDevice) Peek(size Size, address uint32) (uint32, error)

func (*MappedDevice) Read added in v1.1.0

func (d *MappedDevice) Read(size Size, address uint32) (uint32, error)

func (*MappedDevice) Reset added in v1.1.0

func (d *MappedDevice) Reset()

func (*MappedDevice) Write added in v1.1.0

func (d *MappedDevice) Write(size Size, address uint32, value uint32) error

type PeekDevice added in v1.1.0

type PeekDevice interface {
	Peek(Size, uint32) (uint32, error)
}

PeekDevice exposes a side-effect-free read path for debugging and disassembly.

type RAM

type RAM struct {
	// contains filtered or unexported fields
}

simple flat memory structure

func NewRAM

func NewRAM(offset, size uint32) *RAM

func (*RAM) Contains

func (ram *RAM) Contains(address uint32) bool

func (*RAM) Read

func (ram *RAM) Read(s Size, address uint32) (uint32, error)

func (*RAM) Reset

func (ram *RAM) Reset()

func (*RAM) WaitStates

func (ram *RAM) WaitStates(Size, uint32) uint32

WaitStates allows RAM to satisfy WaitStateDevice while imposing no additional delay.

func (*RAM) Write

func (ram *RAM) Write(s Size, address uint32, value uint32) error

type Registers

type Registers struct {
	D   [8]int32
	A   [8]uint32
	PC  uint32
	SR  uint16
	SSP uint32
	USP uint32
	IR  uint16 // instruction register
}

Registers represents the programmer visible registers of the 68000 CPU.

func (*Registers) String

func (regs *Registers) String() string

type ScheduledEvent added in v1.1.0

type ScheduledEvent struct {
	At uint64
	Fn func(now uint64)
}

type Size

type Size uint32
const (
	Byte Size = 1
	Word Size = 2
	Long Size = 4
)

type TraceCallback

type TraceCallback func(TraceInfo)

type TraceInfo

type TraceInfo struct {
	PC        uint32
	SR        uint16
	Registers Registers
}

type WaitHook

type WaitHook func(states uint32)

WaitHook can be used to simulate wait states or count cycles for bus access.

type WaitStateDevice

type WaitStateDevice interface {
	WaitStates(Size, uint32) uint32
}

WaitStateDevice optionally advertises additional wait states a device imposes per transaction. Implementations may vary their contribution based on access size and address.

Directories

Path Synopsis
cmd
qsortdemo command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL