Skip to content

Vibe-coded ARM2 emulator, an architecture released in 1986. Cross-platform in Go

License

Notifications You must be signed in to change notification settings

lookbusy1344/arm_emulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,163 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ARM Emulator - a vibe coding project

CI

This is an example of using vibe coding to re-create my first commercial project, from 1992, which implemented an ARM2 emulator. The original code was written in Turbo Pascal for 16-bit MS-DOS and is completely lost.

Here I am attempting to use Claude Code to broadly recreate the emulator as a cross-platform Go project, with a simple TUI debugger. Claude was given a one-paragraph prompt and essentially left to its own devices, with only gentle high level steering.

After the TUI interface, I added a REST API backend to support GUI frontends. The project now includes two native GUI applications: a Swift app for macOS and an Avalonia app for Windows/Linux/macOS, both calling into the Go VM using the REST API.

The project therefore consists of:

  • A Go backend implementing the ARM2 emulator, CLI and TUI debugger, and REST API for GUI integration
  • A native Swift macOS app providing a GUI frontend using SwiftUI and MVVM architecture
  • An Avalonia cross-platform GUI using .NET and ReactiveUI (Windows/Linux/macOS)

Security

This project was vibe-coded. See docs/SECURITY.md for a comprehensive security audit generated by Copilot.

Background

ARM2 is the earliest commercial precursor to the AARCH64 architecture we all use in our smartphones, Macs and low-power Windows laptops. It started life in the mid-1980’s at the UK’s Acorn Computers.

The ARM1 (Acorn RISC Machine 1) was Acorn Computers' first microprocessor design. The ARM1 was the initial result of the Advanced Research and Development division Acorn Computers formed in order to advance the development of their own RISC processor. Design started in 1983, and when it was finished in 1985 the ARM1 was the simplest RISC processor produced worldwide.

Introduced in 1986, the ARM2 was capable of exceeding 10 MIPS when not bottlenecked by memory with an average of around 6 MIPS. Unlike the ARM1 which was predominantly a research project, the ARM2 became the first commercially successful ARM microprocessor.

The Acorn Archimedes family of personal computers was built using the ARM2 along with a number of fully custom support chips that were also designed by Acorn Computers.

https://en.wikichip.org/wiki/acorn/microarchitectures/arm1

Vibe Coded

This is a vibe-coded project. Details of the initial prompt and development process followed in the first few weeks are documented in Vibe_coding.md.

As a rough guide to the size of the project, the Go code on 13 Jan 2026 is around 61,000 lines. The Swift GUI code is around 6,100 lines.

Documentation

Project Documentation

User Documentation

Developer Documentation

Features

Core Emulation:

  • Complete ARM2 instruction set (16 data processing, all memory ops, branch, multiply)
  • All ARM2 addressing modes (immediate, register, shifted, pre/post-indexed)
  • 35+ syscalls (console I/O, file operations, memory management, system info, debugging)
  • ARMv3M extensions: long multiply (UMULL/UMLAL/SMULL/SMLAL), PSR transfer (MRS/MSR)

Development Tools:

  • Interactive TUI debugger with visual panels, breakpoints, watchpoints
  • Assembly parser with macros and preprocessor
  • Dynamic literal pool sizing (20+ literals per pool, tested up to 33)
  • Machine code encoder/decoder
  • Diagnostic modes: code coverage, stack trace, flag trace, register access analysis
  • Performance statistics (JSON/CSV/HTML export)
  • Execution and memory tracing with filtering
  • Development tools: linter, formatter, cross-reference generator

Prerequisites

  • Go 1.25 or higher (only required if building from source)
  • Supported platforms: macOS, Linux, Windows

Installation

Option 1: Download Pre-built Binaries (Recommended)

Pre-built binaries are available for download from the Releases page.

Available platforms:

  • Linux (64-bit): arm-emulator-linux-amd64
  • macOS (Apple Silicon): arm-emulator-macos-arm64
  • Windows: arm-emulator-win-amd64.exe (AMD64/x64) and arm-emulator-win-arm64.exe (ARM64)

To install:

  1. Visit the Releases page
  2. Download the binary for your platform
  3. On Linux/macOS, make it executable: chmod +x arm-emulator-*
  4. Optionally verify the download using the provided SHA256 checksums

Security Note for Windows Users: Some anti-virus software may flag the Windows binary due to heuristic detection of emulator behavior patterns (memory management, file I/O). This is a false positive - the software is safe. See docs/SECURITY.md for a complete security audit. You may need to whitelist the application or build from source.

Option 2: Build from Source

Clone the repository and build the project:

git clone <repository-url>
cd arm_emulator
go build -o arm-emulator

Usage

Running Assembly Programs

Run an ARM assembly program directly:

./arm-emulator program.s

The emulator will execute the program starting from _start (or main if _start is not found). The program runs until it encounters a SWI #0x00 (exit) instruction or an error occurs.

Using the Debugger

The emulator includes a powerful debugger with both command-line and TUI (Text User Interface) modes:

# Command-line debugger mode
./arm-emulator --debug program.s

# TUI mode with visual panels for source, registers, memory, etc.
./arm-emulator --tui program.s

Quick debugger commands:

  • run (r) - Start/restart program execution
  • step (s) - Execute one instruction (step into)
  • next (n) - Execute one instruction (step over)
  • continue (c) - Continue until breakpoint or exit
  • break <location> (b) - Set breakpoint at label or address
  • print <expr> (p) - Evaluate expression (registers, memory, etc.)
  • info registers (i r) - Show all registers
  • help - Show all available commands

TUI keyboard shortcuts:

  • F5 - Continue execution
  • F9 - Toggle breakpoint at current line
  • F10 - Step over
  • F11 - Step into
  • Ctrl+L - Refresh display
  • Tab - Switch between panels

TUI visual features:

  • Register highlighting - Changed registers shown in green
  • Memory write highlighting - Written memory bytes shown in green (auto-scrolls to written address)
  • Stack highlighting - PUSH/POP operations highlighted in green
  • Symbol-aware display - Function/label names shown instead of raw addresses
  • Source view - Shows current line with > indicator, handles labels and comments properly
  • Multi-panel layout - Source, Registers, Memory, Stack, Breakpoints, Watchpoints, Console

For complete debugger documentation including conditional breakpoints, watchpoints, memory examination, and expression syntax, see docs/debugger_reference.md.

GUI Mode (Graphical Interface)

Swift Native macOS App (Primary)

Native SwiftUI app that automatically manages the Go backend lifecycle:

Quick start:

# Install prerequisites
brew install xcodegen swiftlint swiftformat xcbeautify

# Generate and open project
cd swift-gui
xcodegen generate
open ARMEmulator.xcodeproj
# Press Cmd+R to build and run

Features:

  • Native SwiftUI interface with MVVM architecture
  • Real-time register updates via WebSocket
  • Code editor (editable when stopped, read-only during execution)
  • 6 execution states: idle, running, breakpoint, halted, error, waiting_for_input
  • Console output view with state-driven UI

Requirements: macOS 26.2, Swift 6.2, Xcode 26.2. Enforces 0 SwiftLint violations.

Documentation:

Avalonia Cross-Platform GUI

.NET-based GUI for Windows, Linux, and macOS. Built with Avalonia UI and ReactiveUI using MVVM architecture.

Requirements: .NET SDK 10.0+

Documentation:

Symbol Table Dump

Inspect the parsed symbols from your assembly program:

# Dump symbol table to stdout
./arm-emulator --dump-symbols program.s

# Save symbol table to a file
./arm-emulator --dump-symbols --symbols-file symbols.txt program.s

The symbol dump displays all labels, constants, and variables with their addresses, types, and definition status. This is useful for understanding program layout and debugging symbol resolution issues.

Performance Analysis

The emulator includes built-in tracing and statistics capabilities:

# Enable execution tracing
./arm-emulator --trace --trace-file trace.txt program.s

# Enable memory access tracing
./arm-emulator --mem-trace --mem-trace-file mem_trace.txt program.s

# Generate performance statistics
./arm-emulator --stats --stats-file stats.html --stats-format html program.s

Performance features:

  • Execution trace with register changes and timing
  • Memory access tracking (reads/writes)
  • Instruction frequency analysis
  • Branch statistics and prediction
  • Function call profiling
  • Hot path analysis
  • Export to JSON, CSV, or HTML formats

Diagnostic Modes

Advanced debugging tools with symbol-aware output:

# Code coverage - track executed/unexecuted instructions, show dead code
./arm-emulator --coverage program.s

# Stack trace - monitor stack operations, detect overflow/underflow
./arm-emulator --stack-trace program.s

# Flag trace - track CPSR flag changes (N, Z, C, V)
./arm-emulator --flag-trace program.s

# Register trace - analyze access patterns, detect unused registers, flag read-before-write issues
./arm-emulator --register-trace program.s

# Combine multiple modes
./arm-emulator --coverage --stack-trace --flag-trace --register-trace --verbose program.s

All modes support text and JSON formats (--coverage-format json). Output includes function/label names instead of raw addresses.

Example Programs

49 fully functional ARM assembly programs demonstrating various features:

  • Basic: hello.s, arithmetic.s, loops.s, conditionals.s, functions.s
  • Algorithms: fibonacci.s, factorial.s, bubble_sort.s, binary_search.s, quicksort.s, gcd.s
  • Data Structures: arrays.s, linked_list.s, hash_table.s, stack.s, strings.s
  • Advanced: addressing_modes.s, add_128bit.s (128-bit arithmetic), literal pools, syscall tests
  • Interactive: bubble_sort.s, calculator.s, fibonacci.s (require stdin input)

See examples/README.md for complete descriptions and usage instructions.

Development

Building

go build -o arm-emulator

Formatting

go fmt ./...

Testing

go clean -testcache
go test ./...

Update dependencies

go get -u ./...
go mod tidy
go mod verify

Release Builds

Quick build with version info:

make build  # Embeds git tag, commit hash, and build timestamp

Optimized local build:

go build -ldflags="-s -w" -o arm-emulator  # ~30-40% smaller

Automated releases: Push a git tag to trigger GitHub Actions building binaries for linux-amd64, macos-arm64, windows-amd64, windows-arm64:

git tag v1.0.0
git push origin v1.0.0

Download pre-built binaries with SHA256 checksums from Releases.

Project Structure

.
├── main.go              # Entry point and CLI
├── vm/                  # Virtual machine implementation
├── parser/              # Assembly parser with preprocessor
├── instructions/        # Instruction implementations
├── encoder/             # Machine code encoder/decoder
├── debugger/            # Debugging utilities with TUI
├── config/              # Cross-platform configuration
├── tools/               # Development tools (lint, format, xref)
├── api/                 # HTTP REST API backend for GUIs
├── service/             # Service layer for API/GUI integration
├── swift-gui/           # Swift native macOS app (SwiftUI + MVVM)
├── avalonia-gui/        # Avalonia cross-platform GUI (.NET + ReactiveUI)
├── tests/               # Test files (1,024 tests, 100% passing, 75% coverage)
├── examples/            # Example ARM assembly programs (49 programs)
└── docs/                # User and developer documentation

Instruction Set Completeness

Complete ARM2 instruction set (1986) plus ARMv3M/ARMv3 extensions:

Implemented:

  • All core ARM2 instructions and addressing modes
  • Long multiply (UMULL/UMLAL/SMULL/SMLAL) from ARMv3M
  • PSR transfer (MRS/MSR) from ARMv3

Not implemented:

  • Atomic swap (SWP/SWPB) - ARMv2a/ARM3 only
  • Coprocessor instructions - rarely used

Security

Security audit summary:

  • ✅ No network connectivity or download capability
  • ✅ Only operates on user-specified files
  • ✅ Legitimate, well-known dependencies
  • ✅ Full source code available for inspection

Anti-Virus False Positives: Windows binaries may be flagged as Program:Win32/Wacapew.C!ml due to heuristic detection of emulator behaviors. This is a false positive. See docs/SECURITY.md.

Filesystem Sandboxing

Guest programs are restricted to a specified directory (current directory by default):

./arm-emulator program.s                    # Restrict to current directory
./arm-emulator -fsroot /tmp/sandbox program.s  # Custom sandbox

Security guarantees:

  • Path traversal (..) and symlink escapes are blocked
  • Absolute paths treated as relative to sandbox root
  • No unrestricted access mode

Note: Programs can still read/write/delete files within the sandbox and consume resources. Use a dedicated sandbox directory for maximum isolation.

See docs/SECURITY.md for detailed analysis.

License

MIT License. See LICENSE file for details.