106 lines
1.7 KiB
Go
106 lines
1.7 KiB
Go
package neon
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"time"
|
|
)
|
|
|
|
type CPU struct {
|
|
// Accumulators:
|
|
A, B uint8
|
|
|
|
// Addresses:
|
|
PC uint16 // program counter
|
|
SP uint16 // stack pointer
|
|
|
|
// Flags:
|
|
T bool // test
|
|
C bool // carry
|
|
I bool // interrupt disable
|
|
J bool // jump disable
|
|
|
|
// Data:
|
|
RAM [0xFFFF + 1]byte
|
|
|
|
// Debugger hooks:
|
|
OnStep func(addr uint16, cd Condition, op Operator)
|
|
OnError func(error) Interrupt
|
|
|
|
// Subsystems:
|
|
Rand *rand.Rand
|
|
}
|
|
|
|
type Interrupt uint8
|
|
|
|
const NoInterrupt Interrupt = 0
|
|
|
|
func New() *CPU {
|
|
ns := time.Now().UnixNano()
|
|
src := rand.NewSource(ns)
|
|
return &CPU{
|
|
Rand: rand.New(src),
|
|
}
|
|
}
|
|
|
|
func (c *CPU) Load(data []byte) {
|
|
copy(c.RAM[:], data)
|
|
}
|
|
|
|
func (c *CPU) Step() Interrupt {
|
|
start := c.PC
|
|
next := c.RAM[start]
|
|
c.PC++
|
|
cd := Condition(next >> 6)
|
|
op := Operator(next & 0b00111111)
|
|
if c.OnStep != nil {
|
|
c.OnStep(start, cd, op)
|
|
}
|
|
data := operatorTable[op]
|
|
if data.step == nil {
|
|
return c.errorf("illegal operator 0x%02X", op)
|
|
}
|
|
addr := data.mode(c)
|
|
if !c.condition(cd) {
|
|
return NoInterrupt
|
|
}
|
|
return data.step(c, addr)
|
|
}
|
|
|
|
func (c *CPU) Run() Interrupt {
|
|
for {
|
|
interrupt := c.Step()
|
|
if interrupt != NoInterrupt {
|
|
return interrupt
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *CPU) get16(addr uint16) uint16 {
|
|
a := c.RAM[addr]
|
|
b := c.RAM[addr+1]
|
|
return uint16(b)<<8 | uint16(a)
|
|
}
|
|
|
|
func (c *CPU) condition(cd Condition) bool {
|
|
switch cd {
|
|
case Always:
|
|
return true
|
|
case IfTrue:
|
|
return c.T
|
|
case IfFalse:
|
|
return !c.T
|
|
case Randomly:
|
|
return c.Rand.Intn(2) == 1
|
|
default:
|
|
panic("unreachable")
|
|
}
|
|
}
|
|
|
|
func (c *CPU) errorf(format string, args ...any) Interrupt {
|
|
if c.OnError != nil {
|
|
return c.OnError(fmt.Errorf(format, args...))
|
|
}
|
|
return NoInterrupt
|
|
}
|