m68kemu

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Jan 26, 2026 License: MIT Imports: 3 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.0.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 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) 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)
	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 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.

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 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 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