go6502

package module
v0.0.0-...-07c6f37 Latest Latest
Warning

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

Go to latest
Published: Apr 22, 2015 License: MIT Imports: 5 Imported by: 0

README

go6502

THIS IS A FORK OF pda/go6502 which adds 65C02 support and re-factors the API for my own use. The original README is below.

 | | | | | | | | | | | | | | | | | | | |
.----------------------------------------.
|                   GO                   |
|                  6502                  |
|                  1213                  |
`----------------------------------------'
 | | | | | | | | | | | | | | | | | | | |

A go-based emulator and debugger for the 6502-based pda6502 homebrew computer.

GoDoc

Background

I've been designing and building a 6502-based homebrew computer.

It's powered by an 8-bit 6502 (WDC 65C02), varitions of which powered the venerable Commodore 64, Apple II, Vic 20, Nintendo and lots more.

74HC-series logic chips map the 64K address space to 32K RAM, 8K ROM, a VIA 6522 I/O controller, and room for expansion.

The first output device (beyond flashing LEDs) is a 128x32 pixel OLED, connected to one of the VIA 6522 parallel ports, with bit-banged serial comms.

go6502

go6502 emulates the 6502, address bus, RAM, ROM, 6522 and OLED display well enough to run the current pda6502 code and get the same display output.

It has a flexible address bus, which paves the way to emulating other 6502-based systems.

go6502 features a stepping debugger with breakpoints on instruction type, register values and memory location. This makes it far easier to get code working correctly before writing it to an actual EEPROM.

Running it

Set up Go:

  • brew install go / aptitude install golang / whatever.
  • Spend a few days making sense of, fighting against, and eventually tollerating the golang directory structure as described at http://golang.org/doc/code.html
  • Set your $GOPATH the way Go wants you to, e.g. $HOME/code/go.
  • Put Go's bin dir in your path, e.g. $HOME/code/go/bin

Get and run go6502:

  • Drop an 8 KB kernal.rom into $PWD/rom/, where ever that may be.
    • (pda6502 can help; see memory.conf and Makefile)
  • go get github.com/pda/go6502
  • go6502
  • go6502 --help
  • go6502 --debug

Example usage

Various invocations from my shell history; some run from this project, some from pda6502.

time go run go6502.go --debug --debug-commands='bi nop;run;q' --via-ssd1306 && open output.png
make && go6502 --debug --debug-symbol-file=build/debug --debug-commands="bi nop;c;q" --via-ssd1306 --sd-card=sd.bin
go build -o g6 go6502.go && gtimeout -s INT 0.2 ./g6 --via-ssd1306 --speedometer
time go run go6502.go --via-ssd1306 --debug
time go run go6502.go --debug --debug-commands='bi nop;r;q' --via-ssd1306 && open output.png
make && go6502 --debug --debug-symbol-file=build/debug --via-ssd1306 --sd-card=sd.bin
time go run go6502.go --via-ssd1306 --debug --debug-commands='bi nop;r;q' && open output.png
go run go6502.go --debug --debug-symbol-file=$HOME/code/pda6502/build/debug --via-ssd1306 --sd-card=$HOME/code/pda6502/sd.bin
make && go install github.com/pda/go6502 && gtimeout -s INT 0.1 go6502 --via-ssd1306 --sd-card="sd.bin" ; open ssd1306.png
go run go6502.go --via-ssd1306 --debug --debug-commands='bi nop;run'
go build go6502.go && gtimeout -s INT 1 ./go6502 --via-ssd1306 --speedometer
go build go6502.go && gtimeout -s INT 0.1 ./go6502 --via-ssd1306 --speedometer
make && go6502 -via-ssd1306 -sd-card=sd4gb.fat32 -debug -debug-symbol-file=build/debug -debug-commands="ba Halt; c; q" && hd -s 0x6000 -n 512 core
make && go6502 --debug --debug-symbol-file=build/debug --via-ssd1306 --sd-card=sd.bin --debug-commands="bi nop; c; q"
make && go6502 --debug --debug-symbol-file=build/debug --debug-commands="bi nop;c;q" --via-ssd1306 --sd-card=sd.bin && open ssd1306.png
go6502 -via-ssd1306 -sd-card=sd4gb.fat32
go6502 --debug --debug-symbol-file=build/debug --via-ssd1306 --sd-card=sd.bin
go run go6502.go --via-ssd1306 --debug
go run go6502.go --debug --debug-commands='bi nop;run;q' --via-ssd1306

Debugger / Monitor

Given there's almost no I/O, you'll probably want a debugger / monitor session.

$ go6502 --debug
CPU pc:0xE000 ac:0x00 x:0x00 y:0x00 sp:0xFF sr:--------
Instruction[SEI op:78 addr:6 bytes:1 cycles:2] op8:0x00 op16:0x0000
$E000> help

pda6502 debuger
---------------
break-address <addr> (alias: ba) e.g. ba 0x1000
break-instruction <mnemonic> (alias: bi) e.g. bi NOP
break-register <x|y|a> <value> (alias: br) e.g. br x 128
continue (alias: c) Run continuously until breakpoint.
exit (alias: quit, q) Shut down the emulator.
help (alias: h, ?) This help.
read <address> - Read and display 8-bit integer at address.
read16 <address> - Read and display 16-bit integer at address.
step (alias: s) Run only the current instruction.
(blank) Repeat the previous command.

Hex input formats: 0x1234 $1234
Commands expecting uint16 treat . as current address (PC).
$E000> step
CPU pc:0xE001 ac:0x00 x:0x00 y:0x00 sp:0xFF sr:--------
Instruction[LDX op:A2 addr:5 bytes:2 cycles:2] op8:0xFF op16:0x0000
$E001> break-instruction NOP
$E001> break-address $E003
$E001> continue
Breakpoint for PC address = $E003
CPU pc:0xE003 ac:0x00 x:0xFF y:0x00 sp:0xFF sr:n-------
Instruction[TXS op:9A addr:6 bytes:1 cycles:2] op8:0x00 op16:0x0000
$E003> continue
Breakpoint for instruction NOP
CPU pc:0xE0FC ac:0xFF x:0x00 y:0x00 sp:0xFF sr:-----izc
Instruction[NOP op:EA addr:6 bytes:1 cycles:2] op8:0x00 op16:0x0000
$E0FC> read $FFFC
$FFFC => $00 0b00000000 0 '\x00'
$E0FC> read16 $FFFC
$FFFC,FFFD => $E000 0b1110000000000000 57344
$E0FC> quit

License

Copyright 2013–2014 Paul Annesley, released under MIT license.

Documentation

Overview

Package bus provides a mappable 16-bit addressable 8-bit data bus for go6502. Different Memory backends can be attached at different base addresses.

Package cpu implements the MOS 6502 processor.

Cpu requires a Bus to read/write 8-bit data to 16-bit addresses.

Cpu also provides a monitor hook, allowing external code to observe and block on instructions before they're executed.

ROM & RAM for go6502; 16-bit address, 8-bit data.

Index

Constants

View Source
const StackBase = 0x0100

StackBase is the base address of the stack, which begins at StackBase+0xFF and grows downwards towards this address.

Variables

This section is empty.

Functions

This section is empty.

Types

type Bus

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

Bus is a 16-bit address, 8-bit data bus, which maps reads and writes at different locations to different backend Memory. For example the lower 32K could be RAM, the upper 8KB ROM, and some I/O in the middle.

func CreateBus

func CreateBus() (*Bus, error)

func (*Bus) Attach

func (b *Bus) Attach(mem memory.Memory, name string, offset uint16) error

Attach maps a bus address range to a backend Memory implementation, which could be RAM, ROM, I/O device etc.

func (*Bus) Read

func (b *Bus) Read(a uint16) byte

Read returns the byte from memory mapped to the given address. e.g. if ROM is mapped to 0xC000, then Read(0xC0FF) returns the byte at 0x00FF in that RAM device.

func (*Bus) Read16

func (b *Bus) Read16(a uint16) uint16

Read16 returns the 16-bit value stored in little-endian format with the low byte at address, and the high byte at address+1.

func (*Bus) Shutdown

func (b *Bus) Shutdown()

Shutdown tells the address bus a shutdown is occurring, and to pass the message on to subordinates.

func (*Bus) String

func (b *Bus) String() string

func (*Bus) Write

func (b *Bus) Write(a uint16, value byte)

Write the byte to the device mapped to the given address.

func (*Bus) Write16

func (b *Bus) Write16(a uint16, value uint16)

Write16 writes the given 16-bit value to the specifie address, storing it little-endian, with high byte at address+1.

type Cpu

type Cpu struct {

	// Program counter.
	PC uint16

	// Accumulator register.
	AC byte

	// X general purpose / index register.
	X byte

	// Y general purpose / index register.
	Y byte

	// Stack pointer (low byte of 0x0100..0x01FF).
	SP byte

	// Status register; carry, zero, interrupt, bcd, brk, _, overflow, sign.
	SR byte

	// Bus is the system address bus, mapping 64K of address space to
	// different back-end devices.
	Bus *Bus

	ExitChan chan int
	// contains filtered or unexported fields
}

Cpu represents the internal state of the CPU.

func (*Cpu) ADC

func (c *Cpu) ADC(in Instruction)

ADC: Add memory and carry to accumulator.

func (*Cpu) AND

func (c *Cpu) AND(in Instruction)

AND: And accumulator with memory.

func (*Cpu) ASL

func (c *Cpu) ASL(in Instruction)

ASL: Shift memory or accumulator left one bit.

func (*Cpu) AttachMonitor

func (c *Cpu) AttachMonitor(m Monitor)

AttachMonitor sets the given Monitor to observe instructions before they execute, in a blocking manner. This allows for logging, analysis, and interactive debugging.

func (*Cpu) BCC

func (c *Cpu) BCC(in Instruction)

BCC: Branch if carry clear.

func (*Cpu) BCS

func (c *Cpu) BCS(in Instruction)

BCS: Branch if carry set.

func (*Cpu) BEQ

func (c *Cpu) BEQ(in Instruction)

BEQ: Branch if equal (z=1).

func (*Cpu) BIT

func (c *Cpu) BIT(in Instruction)

BIT: Bit Test.

func (*Cpu) BMI

func (c *Cpu) BMI(in Instruction)

BMI: Branch if negative.

func (*Cpu) BNE

func (c *Cpu) BNE(in Instruction)

BNE: Branch if not equal.

func (*Cpu) BPL

func (c *Cpu) BPL(in Instruction)

BPL: Branch if positive.

func (*Cpu) BRA

func (c *Cpu) BRA(in Instruction)

BRA: Unconditional branch

func (*Cpu) BRK

func (c *Cpu) BRK(in Instruction)

BRK: software interrupt

func (*Cpu) BVC

func (c *Cpu) BVC(in Instruction)

BVC: Branch if overflow clear.

func (*Cpu) BVS

func (c *Cpu) BVS(in Instruction)

BVS: Branch if overflow set.

func (*Cpu) CLC

func (c *Cpu) CLC(in Instruction)

CLC: Clear carry flag.

func (*Cpu) CLD

func (c *Cpu) CLD(in Instruction)

CLD: Clear decimal mode flag.

func (*Cpu) CLI

func (c *Cpu) CLI(in Instruction)

CLI: Clear interrupt-disable flag.

func (*Cpu) CMP

func (c *Cpu) CMP(in Instruction)

CMP: Compare accumulator with memory.

func (*Cpu) CPX

func (c *Cpu) CPX(in Instruction)

CPX: Compare index register X with memory.

func (*Cpu) CPY

func (c *Cpu) CPY(in Instruction)

CPY: Compare index register Y with memory.

func (*Cpu) DEC

func (c *Cpu) DEC(in Instruction)

DEC: Decrement.

func (*Cpu) DEX

func (c *Cpu) DEX(in Instruction)

DEX: Decrement index register X.

func (*Cpu) DEY

func (c *Cpu) DEY(in Instruction)

DEY: Decrement index register Y.

func (*Cpu) EOR

func (c *Cpu) EOR(in Instruction)

EOR: Exclusive-OR accumulator with memory.

func (*Cpu) INC

func (c *Cpu) INC(in Instruction)

INC: Increment.

func (*Cpu) INX

func (c *Cpu) INX(in Instruction)

INX: Increment index register X.

func (*Cpu) INY

func (c *Cpu) INY(in Instruction)

INY: Increment index register Y.

func (*Cpu) JMP

func (c *Cpu) JMP(in Instruction)

JMP: Jump.

func (*Cpu) JSR

func (c *Cpu) JSR(in Instruction)

JSR: Jump to subroutine.

func (*Cpu) LDA

func (c *Cpu) LDA(in Instruction)

LDA: Load accumulator from memory.

func (*Cpu) LDX

func (c *Cpu) LDX(in Instruction)

LDX: Load index register X from memory.

func (*Cpu) LDY

func (c *Cpu) LDY(in Instruction)

LDY: Load index register Y from memory.

func (*Cpu) LSR

func (c *Cpu) LSR(in Instruction)

LSR: Logical shift memory or accumulator right.

func (*Cpu) NOP

func (c *Cpu) NOP(in Instruction)

NOP: No operation.

func (*Cpu) ORA

func (c *Cpu) ORA(in Instruction)

ORA: OR accumulator with memory.

func (*Cpu) PHA

func (c *Cpu) PHA(in Instruction)

PHA: Push accumulator onto stack.

func (*Cpu) PHP

func (c *Cpu) PHP(in Instruction)

PHP: Push status onto stack.

func (*Cpu) PHX

func (c *Cpu) PHX(in Instruction)

PHX: Push X onto stack.

func (*Cpu) PHY

func (c *Cpu) PHY(in Instruction)

PHY: Push Y onto stack.

func (*Cpu) PLA

func (c *Cpu) PLA(in Instruction)

PLA: Pull accumulator from stack.

func (*Cpu) PLP

func (c *Cpu) PLP(in Instruction)

PLP: Pull status from stack.

func (*Cpu) PLX

func (c *Cpu) PLX(in Instruction)

PLX: Pull X from stack.

func (*Cpu) PLY

func (c *Cpu) PLY(in Instruction)

PLY: Pull Y from stack.

func (*Cpu) ROL

func (c *Cpu) ROL(in Instruction)

ROL: Rotate memory or accumulator left one bit.

func (*Cpu) ROR

func (c *Cpu) ROR(in Instruction)

ROR: Rotate memory or accumulator left one bit.

func (*Cpu) RTS

func (c *Cpu) RTS(in Instruction)

RTS: Return from subroutine.

func (*Cpu) Reset

func (c *Cpu) Reset()

Reset the CPU, emulating triggering the RESB line. From 65C02 manual: All Registers are initialized by software except the Decimal and Interrupt disable mode select bits of the Processor Status Register (P) are initialized by hardware. ... The program counter is loaded with the reset vector from locations FFFC (low byte) and FFFD (high byte).

func (*Cpu) SBC

func (c *Cpu) SBC(in Instruction)

SBC: Subtract memory with borrow from accumulator.

func (*Cpu) SEC

func (c *Cpu) SEC(in Instruction)

SEC: Set carry flag.

func (*Cpu) SED

func (c *Cpu) SED(in Instruction)

SED: Set decimal mode flag.

func (*Cpu) SEI

func (c *Cpu) SEI(in Instruction)

SEI: Set interrupt-disable flag.

func (*Cpu) STA

func (c *Cpu) STA(in Instruction)

STA: Store accumulator to memory.

func (*Cpu) STX

func (c *Cpu) STX(in Instruction)

STX: Store index register X to memory.

func (*Cpu) STY

func (c *Cpu) STY(in Instruction)

STY: Store index register Y to memory.

func (*Cpu) STZ

func (c *Cpu) STZ(in Instruction)

STZ: Store zero to memory.

func (*Cpu) Shutdown

func (c *Cpu) Shutdown()

Shutdown tells the CPU to shut-down, and to pass the message on to subordinates such as the address bus.

func (*Cpu) Step

func (c *Cpu) Step() int

Step will single instruction step the CPU and return the number of machine cycles the instruction took.

func (*Cpu) StepCycles

func (c *Cpu) StepCycles(cc int) int

StepCycles will step the processor until *at least* cycles machine cycles have run. Since Cycle halts on an instruction boundary the actual number of cycles may be greater than requested. Returns the actual number of machine cycles executed.

func (*Cpu) String

func (c *Cpu) String() string

func (*Cpu) TAX

func (c *Cpu) TAX(in Instruction)

TAX: Transfer accumulator to index register X.

func (*Cpu) TAY

func (c *Cpu) TAY(in Instruction)

TAY: Transfer accumulator to index register Y.

func (*Cpu) TRB

func (c *Cpu) TRB(in Instruction)

TRB: Test and Reset bits

func (*Cpu) TSB

func (c *Cpu) TSB(in Instruction)

TSB: Test and Set bits

func (*Cpu) TSX

func (c *Cpu) TSX(in Instruction)

TSX: Transfer stack pointer to index register X.

func (*Cpu) TXA

func (c *Cpu) TXA(in Instruction)

TXA: Transfer index register X to accumulator.

func (*Cpu) TXS

func (c *Cpu) TXS(in Instruction)

TXS: Transfer index register X to stack pointer.

func (*Cpu) TYA

func (c *Cpu) TYA(in Instruction)

TYA: Transfer index register Y to accumulator.

type Instruction

type Instruction struct {
	OpType

	// The single-byte operand, for 2-byte instructions.
	Op8 uint8

	// The 16-bit operand, for 3-byte instructions.
	Op16 uint16
}

Instruction is an OpType plus its operand. One or both of the operand types will be zero. This is determined by (ot.Bytes - 1) / 8

func ReadInstruction

func ReadInstruction(pc uint16, bus *Bus) Instruction

ReadInstruction reads an instruction from the bus starting at the given address. An instruction may be 1, 2 or 3 bytes long, including its optional 8 or 16 bit operand.

func (Instruction) String

func (in Instruction) String() (s string)

type Memory

type Memory interface {
	Shutdown()
	Read(uint16) byte
	Write(uint16, byte)
	Size() int
}

Memory is a general interface for reading and writing bytes to and from 16-bit addresses.

type Monitor

type Monitor interface {
	BeforeExecute(Instruction)
	Shutdown()
}

A Monitor is a blocking observer of instruction execution.

type OffsetMemory

type OffsetMemory struct {
	Offset uint16
	Memory
}

OffsetMemory wraps a Memory object, rewriting read/write addresses by the given offset. This makes it possible to mount memory into a larger address space at a given base address.

func (OffsetMemory) Read

func (om OffsetMemory) Read(a uint16) byte

Read returns a byte from the underlying Memory after rewriting the address using the offset.

func (OffsetMemory) String

func (om OffsetMemory) String() string

func (OffsetMemory) Write

func (om OffsetMemory) Write(a uint16, value byte)

Write stores a byte in the underlying Memory after rewriting the address using the offset.

type OpType

type OpType struct {

	// Opcode is a byte representing an instruction and its addressing mode.
	Opcode byte

	// Bytes is the size of the instruction with its operand.
	// Opcodes with implicit/null operand are 1 byte.
	// Opcodes with immediate or zeropage operand are 2 bytes.
	// Opcodes with adddress operands are 3 bytes.
	Bytes uint8

	// Cycles is the number of times the system clock signal will rise and fall
	// before the instruction is complete.
	Cycles uint8
	// contains filtered or unexported fields
}

OpType represents a 6502 op-code instruction, including the addressing mode encoded into the op-code, but not the operand value following the opcode in memory.

func (OpType) IsAbsolute

func (ot OpType) IsAbsolute() bool

func (OpType) Name

func (ot OpType) Name() (s string)

Name returns the instruction mnemonic name, e.g. ADC or TYA.

func (OpType) String

func (ot OpType) String() string

type Ram

type Ram [0x8000]byte

Ram (32 KiB)

func (*Ram) Dump

func (mem *Ram) Dump(path string)

Dump writes the RAM contents to the specified file path.

func (*Ram) Read

func (mem *Ram) Read(a uint16) byte

Read a byte from a 16-bit address.

func (*Ram) Shutdown

func (r *Ram) Shutdown()

Shutdown is part of the Memory interface, but takes no action for Ram.

func (*Ram) Size

func (mem *Ram) Size() int

Size of the RAM in bytes.

func (*Ram) String

func (r *Ram) String() string

func (*Ram) Write

func (mem *Ram) Write(a uint16, value byte)

Write a byte to a 16-bit address.

type Rom

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

A Rom provides read-only memory, with data generally pre-loaded from a file.

func RomFromFile

func RomFromFile(path string) (*Rom, error)

Create a new ROM, loading the contents from a file. The size of the ROM is determined by the size of the file.

func (*Rom) Read

func (rom *Rom) Read(a uint16) byte

Read a byte from the given address.

func (*Rom) Shutdown

func (r *Rom) Shutdown()

Shutdown is part of the Memory interface, but takes no action for Rom.

func (*Rom) Size

func (r *Rom) Size() int

Size of the Rom in bytes.

func (*Rom) String

func (r *Rom) String() string

func (*Rom) Write

func (r *Rom) Write(_ uint16, _ byte)

Rom meets the go6502.Memory interface, but Write is not supported, and will cause an error.

Directories

Path Synopsis
Package cli provides command line support for go6502.
Package cli provides command line support for go6502.
Package debugger provides an interactive stepping debugger for go6502 with breakpoints on instruction type, register values and memory location.
Package debugger provides an interactive stepping debugger for go6502 with breakpoints on instruction type, register values and memory location.
Emulates 240x320 TFT color display with SPI interface.
Emulates 240x320 TFT color display with SPI interface.
Package SD emulates an SD/MMC card.
Package SD emulates an SD/MMC card.
Package spi implements parts of Serial Peripheral Interface Bus.
Package spi implements parts of Serial Peripheral Interface Bus.
Emulates a 128x32 pixel monochrome OLED display with SPI interface.
Emulates a 128x32 pixel monochrome OLED display with SPI interface.
Package via6522 emulates MOS Technology 6522, or the modern WDC 65C22.
Package via6522 emulates MOS Technology 6522, or the modern WDC 65C22.

Jump to

Keyboard shortcuts

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