cpu

package
v0.35.2 Latest Latest
Warning

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

Go to latest
Published: Nov 23, 2024 License: GPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

Package cpu emulates the 6507 microprocessor found in the Atari VCS. Like all 8-bit processors of the era, the 6507 executes instructions according to the single byte value read from an address pointed to by the program counter. This single byte is the opcode and is looked up in the instruction table. The instruction definition for that opcode is then used to move execution of the program forward.

The instance of the CPU type require an instance of a bus.CPUBus implementation as the sole argument. The CPUBus interface defines the memory operations required by the CPU. See the bus package for details.

The bread-and-butter of the CPU type is the ExecuteInstruction() function. Its sole argument is a callback function to be called at every cycle boundary of the instruction.

Let's assume mem is an instance of the CPUBus interface loaded 6507 instructions.

mc, _ := cpu.NewCPU(mem)

numCycles := 0
numInstructions := 0

for {
	mc.ExecuteInstruction(func() error {
		numCycles ++
	})
	numInstructions ++
}

The above program does nothing interesting except to show how ExecuteInstruction() can be used to pump information to an callback function. The VCS emulation uses this to run the TIA emulation three times for every CPU cycle - the CPU clock runs at 1.19MHz while the TIA clock runs at 3.57Mhz. TIA emulation is discussed more fully in the TIA package.

The CPU type contains some public fields that are worthy of mention. The LastResult field can be probed for information about the last instruction executed, or about the current instruction being executed if accessed from ExecuteInstruction()'s callback function. See the result package for more information. Very useful for debuggers.

The NoFlowControl flag is used by the disassembly package to prevent the CPU from honouring "flow control" functions (ie. JMP, BNE, BEQ, etc.). See instructions package for classifications.

Index

Constants

View Source
const (
	// NMI is the address where the non-maskable interrupt address is stored.
	NMI = uint16(0xfffa)

	// Reset is the address where the reset address is stored.
	Reset = uint16(0xfffc)

	// BRK is the address where the interrupt address is stored.
	BRK = uint16(0xfffe)
)

Variables

View Source
var ResetMidInstruction = errors.New("cpu: appears to have been reset mid-instruction")

sentinal errors returned by ExecuteInstruction.

Functions

func NilCycleCallback added in v0.19.0

func NilCycleCallback() error

NilCycleCallback can be provided as an argument to ExecuteInstruction(). It's a convenienct do-nothing function.

Types

type CPU

type CPU struct {
	PC     registers.ProgramCounter
	A      registers.Register
	X      registers.Register
	Y      registers.Register
	SP     registers.StackPointer
	Status registers.StatusRegister

	// controls whether cpu executes a cycle when it receives a clock tick (pin
	// 3 of the 6507)
	RdyFlg bool

	// last result. the address field is guaranteed to be always valid except
	// when the CPU has just been reset. we use this fact to help us decide
	// whether the CPU has just been reset (see HasReset() function)
	//
	// note a peculiarity in the current emulation means that LastResult is not
	// reset unless the RdyFlg is true at the start of the execution.
	LastResult execution.Result

	// NoFlowControl sets whether the cpu responds accurately to instructions
	// that affect the flow of the program (branches, JPS, subroutines and
	// interrupts).  we use this in the disassembly package to make sure we
	// reach every part of the program.
	//
	// note that the alteration of flow as a result of bank switching is still
	// possible even if NoFlowControl is true. this is because bank switching
	// is outside of the direct control of the CPU.
	NoFlowControl bool

	// Interrupted indicated that the CPU has been put into a state outside of
	// its normal operation. When true work may be done on the CPU that would
	// otherwise be considered an error. Resets to false on every call to
	// ExecuteInstruction()
	Interrupted bool

	// Whether the last memory access by the CPU was a phantom access
	PhantomMemAccess bool

	// the cpu has encounted a KIL instruction. requires a Reset()
	Killed bool
	// contains filtered or unexported fields
}

CPU implements the 6507 found as found in the Atari 2600. Register logic is implemented by the Register type in the registers sub-package.

func NewCPU

func NewCPU(mem Memory) *CPU

NewCPU is the preferred method of initialisation for the CPU structure. Note that the CPU will be initialised in a random state.

func (*CPU) ExecuteInstruction

func (mc *CPU) ExecuteInstruction(cycleCallback func() error) error

ExecuteInstruction steps CPU forward one instruction. The basic process when executing an instruction is this:

  1. read opcode and look up instruction definition
  2. read operands (if any) according to the addressing mode of the instruction
  3. using the operator as a guide, perform the instruction on the data

All instructions take at least 2 cycle. After each cycle, the cycleCallback() function is run, thereby allowing the rest of the VCS hardware to operate.

The cycleCallback arugment should *never* be nil. Use the NilCycleCallback() function in this package if you want a nil effect.

func (*CPU) HasReset

func (mc *CPU) HasReset() bool

HasReset checks whether the CPU has recently been reset.

func (*CPU) LoadPC

func (mc *CPU) LoadPC(directAddress uint16) error

LoadPC loads the contents of directAddress into the PC.

func (*CPU) LoadPCIndirect

func (mc *CPU) LoadPCIndirect(indirectAddress uint16) error

LoadPCIndirect loads the contents of indirectAddress into the PC.

func (*CPU) Plumb added in v0.7.1

func (mc *CPU) Plumb(mem Memory)

Plumb CPU into emulation

func (*CPU) PredictRTS added in v0.18.0

func (mc *CPU) PredictRTS() (uint16, bool)

PredictRTS returns the PC address that would result if RTS was run at the current moment.

func (*CPU) Reset

func (mc *CPU) Reset()

Reset reinitialises all registers. Does not load PC with RESET vector. Use cpu.LoadPCIndirect(cpubus.Reset) when appropriate.

func (*CPU) SetRDY added in v0.25.0

func (mc *CPU) SetRDY(rdy bool)

SetRDY sets the CPU RDY flag. equivalent to pin 3 of the 6507

func (*CPU) Snapshot added in v0.7.1

func (mc *CPU) Snapshot() *CPU

Snapshot creates a copy of the CPU in its current state.

func (*CPU) String

func (mc *CPU) String() string

type Memory added in v0.35.2

type Memory interface {
	Read(address uint16) (uint8, error)
	Write(address uint16, data uint8) error
}

Memory interface to underlying implmentation. See MemoryAddressError interface for optional functions

Directories

Path Synopsis
Package execution tracks the result of instruction execution on the CPU.
Package execution tracks the result of instruction execution on the CPU.
Package functional_test runs the 6502 functional test as defined by Klaus Dormann.
Package functional_test runs the 6502 functional test as defined by Klaus Dormann.
Package instructions defines the table of instruction for the 6507.
Package instructions defines the table of instruction for the 6507.
Package registers implements the three types of registers found in the 6507.
Package registers implements the three types of registers found in the 6507.
test
Package test contains functions useful for testing CPU registers.
Package test contains functions useful for testing CPU registers.

Jump to

Keyboard shortcuts

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