mirror of
https://github.com/ariejan/i6502.git
synced 2024-06-08 18:29:33 +00:00
Wip
This commit is contained in:
parent
9e3c9454e8
commit
afa7d0d3f6
10
bus/bus.go
10
bus/bus.go
|
@ -58,7 +58,7 @@ func (bus *Bus) backendFor(address uint16) (memory.Memory, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("No module addressable at 0x%04X", address)
|
return nil, fmt.Errorf("No module addressable at 0x%04X\n", address)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read an 8-bit value from the module mapped on the bus at the
|
// Read an 8-bit value from the module mapped on the bus at the
|
||||||
|
@ -66,7 +66,9 @@ func (bus *Bus) backendFor(address uint16) (memory.Memory, error) {
|
||||||
func (bus *Bus) Read(address uint16) byte {
|
func (bus *Bus) Read(address uint16) byte {
|
||||||
memory, err := bus.backendFor(address)
|
memory, err := bus.backendFor(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
fmt.Printf("Reading from invalid address $%04X. Returning $00\n", address)
|
||||||
|
return 0x00
|
||||||
|
// panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
value := memory.Read(address)
|
value := memory.Read(address)
|
||||||
|
@ -78,7 +80,9 @@ func (bus *Bus) Read(address uint16) byte {
|
||||||
func (bus *Bus) Write(address uint16, value byte) {
|
func (bus *Bus) Write(address uint16, value byte) {
|
||||||
memory, err := bus.backendFor(address)
|
memory, err := bus.backendFor(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
fmt.Printf("Writing to invalid address $%04X. Faking write.\n", address)
|
||||||
|
return
|
||||||
|
// panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
memory.Write(address, value)
|
memory.Write(address, value)
|
||||||
|
|
62
cpu/cpu.go
62
cpu/cpu.go
|
@ -20,7 +20,12 @@ const (
|
||||||
|
|
||||||
// Beginning of the stack.
|
// Beginning of the stack.
|
||||||
// The stack grows downward, so it starts at 0x1FF
|
// The stack grows downward, so it starts at 0x1FF
|
||||||
const StackBase = 0x0100
|
const (
|
||||||
|
StackBase = 0x0100
|
||||||
|
NmiVector = 0xFFFA // + 0xFFFB
|
||||||
|
ResetVector = 0xFFFC // + 0xFFFD
|
||||||
|
IrqVector = 0xFFFE // + 0xFFFF
|
||||||
|
)
|
||||||
|
|
||||||
type Cpu struct {
|
type Cpu struct {
|
||||||
// Program counter
|
// Program counter
|
||||||
|
@ -42,7 +47,8 @@ type Cpu struct {
|
||||||
// Memory bus
|
// Memory bus
|
||||||
Bus *bus.Bus
|
Bus *bus.Bus
|
||||||
|
|
||||||
InterruptChan chan bool
|
IrqChan chan bool
|
||||||
|
NmiChan chan bool
|
||||||
|
|
||||||
// Handle exiting
|
// Handle exiting
|
||||||
ExitChan chan int
|
ExitChan chan int
|
||||||
|
@ -53,7 +59,7 @@ type Cpu struct {
|
||||||
// address 0xFFFC into the Program Counter. Note this is a 16 bit value, read from
|
// address 0xFFFC into the Program Counter. Note this is a 16 bit value, read from
|
||||||
// 0xFFFC-FFFD
|
// 0xFFFC-FFFD
|
||||||
func (c *Cpu) Reset() {
|
func (c *Cpu) Reset() {
|
||||||
c.PC = c.Bus.Read16(0xFFFC)
|
c.PC = c.Bus.Read16(ResetVector)
|
||||||
c.SR = 0x34
|
c.SR = 0x34
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +71,15 @@ func (c *Cpu) String() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cpu) handleInterrupt(returnPC uint16) {
|
func (c *Cpu) handleIrq(returnPC uint16) {
|
||||||
|
c.handleInterrupt(returnPC, IrqVector)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cpu) handleNmi() {
|
||||||
|
c.handleInterrupt(c.PC, NmiVector)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cpu) handleInterrupt(returnPC uint16, vector uint16) {
|
||||||
c.setStatus(sBreak, true)
|
c.setStatus(sBreak, true)
|
||||||
|
|
||||||
// Push PC + 1 onto stack
|
// Push PC + 1 onto stack
|
||||||
|
@ -77,7 +91,7 @@ func (c *Cpu) handleInterrupt(returnPC uint16) {
|
||||||
// Disable interrupts
|
// Disable interrupts
|
||||||
c.setStatus(sInterrupt, true)
|
c.setStatus(sInterrupt, true)
|
||||||
|
|
||||||
c.PC = c.Bus.Read16(0xFFFE)
|
c.PC = c.Bus.Read16(vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cpu) stackPush(data byte) {
|
func (c *Cpu) stackPush(data byte) {
|
||||||
|
@ -92,11 +106,13 @@ func (c *Cpu) stackPop() byte {
|
||||||
|
|
||||||
func (c *Cpu) Step() {
|
func (c *Cpu) Step() {
|
||||||
select {
|
select {
|
||||||
case <-c.InterruptChan:
|
case <-c.IrqChan:
|
||||||
if !c.getStatus(sInterrupt) {
|
if !c.getStatus(sInterrupt) {
|
||||||
// Handle interrupt
|
// Handle interrupt
|
||||||
c.handleInterrupt(c.PC)
|
c.handleIrq(c.PC)
|
||||||
}
|
}
|
||||||
|
case <-c.NmiChan:
|
||||||
|
c.handleNmi()
|
||||||
default:
|
default:
|
||||||
// Read the instruction (including operands)
|
// Read the instruction (including operands)
|
||||||
instruction := ReadInstruction(c.PC, c.Bus)
|
instruction := ReadInstruction(c.PC, c.Bus)
|
||||||
|
@ -105,13 +121,19 @@ func (c *Cpu) Step() {
|
||||||
// on the size of the optype we just read.
|
// on the size of the optype we just read.
|
||||||
c.PC += uint16(instruction.Bytes)
|
c.PC += uint16(instruction.Bytes)
|
||||||
|
|
||||||
|
fmt.Printf(instruction.String())
|
||||||
|
|
||||||
// Execute the instruction
|
// Execute the instruction
|
||||||
c.execute(instruction)
|
c.execute(instruction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cpu) stackHead(offset int8) uint16 {
|
func (c *Cpu) stackHead(offset int8) uint16 {
|
||||||
return uint16(StackBase) + uint16(c.SP) + uint16(offset)
|
address := uint16(StackBase) + uint16(c.SP) + uint16(offset)
|
||||||
|
val8 := c.Bus.Read(address)
|
||||||
|
val16 := c.Bus.Read16(address)
|
||||||
|
fmt.Printf("Addressing Stack at 0x%04X (8: 0x%02X; 16: 0x%04X from PC 0x%04X\n", address, val8, val16, c.PC)
|
||||||
|
return address
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cpu) resolveOperand(in Instruction) uint8 {
|
func (c *Cpu) resolveOperand(in Instruction) uint8 {
|
||||||
|
@ -285,6 +307,8 @@ func (c *Cpu) execute(in Instruction) {
|
||||||
c.ROL(in)
|
c.ROL(in)
|
||||||
case ror:
|
case ror:
|
||||||
c.ROR(in)
|
c.ROR(in)
|
||||||
|
case rti:
|
||||||
|
c.RTI(in)
|
||||||
case rts:
|
case rts:
|
||||||
c.RTS(in)
|
c.RTS(in)
|
||||||
case sbc:
|
case sbc:
|
||||||
|
@ -393,10 +417,13 @@ func (c *Cpu) BPL(in Instruction) {
|
||||||
|
|
||||||
// BRK: software interrupt
|
// BRK: software interrupt
|
||||||
func (c *Cpu) BRK(in Instruction) {
|
func (c *Cpu) BRK(in Instruction) {
|
||||||
|
fmt.Println("BRK:", c)
|
||||||
|
c.ExitChan <- 42
|
||||||
|
|
||||||
// Force interrupt
|
// Force interrupt
|
||||||
if !c.getStatus(sInterrupt) {
|
// if !c.getStatus(sInterrupt) {
|
||||||
c.handleInterrupt(c.PC + 1)
|
// c.handleIrq(c.PC + 1)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// CLC: Clear carry flag.
|
// CLC: Clear carry flag.
|
||||||
|
@ -595,11 +622,18 @@ func (c *Cpu) ROR(in Instruction) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RTS: Return from subroutine.
|
// RTI: Return from interrupt
|
||||||
func (c *Cpu) RTS(in Instruction) {
|
func (c *Cpu) RTI(in Instruction) {
|
||||||
|
c.SR = c.stackPop()
|
||||||
c.PC = c.Bus.Read16(c.stackHead(1))
|
c.PC = c.Bus.Read16(c.stackHead(1))
|
||||||
c.SP += 2
|
c.SP += 2
|
||||||
c.PC += 1
|
fmt.Printf("RTI: Returning to 0x%04X", c.PC)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RTS: Return from subroutine.
|
||||||
|
func (c *Cpu) RTS(in Instruction) {
|
||||||
|
c.PC = c.Bus.Read16(c.stackHead(1)) + 1
|
||||||
|
c.SP += 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// SBC: Subtract memory with borrow from accumulator.
|
// SBC: Subtract memory with borrow from accumulator.
|
||||||
|
|
|
@ -17,6 +17,21 @@ type Instruction struct {
|
||||||
Op16 uint16
|
Op16 uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Instruction) String() string {
|
||||||
|
var output string
|
||||||
|
|
||||||
|
switch i.Bytes {
|
||||||
|
case 1:
|
||||||
|
output = fmt.Sprintf("0x%02X - %s\n", i.Opcode, instructionNames[i.id])
|
||||||
|
case 2:
|
||||||
|
output = fmt.Sprintf("0x%02X - %s %02X\n", i.Opcode, instructionNames[i.id], i.Op8)
|
||||||
|
case 3:
|
||||||
|
output = fmt.Sprintf("0x%02X - %s %04X\n", i.Opcode, instructionNames[i.id], i.Op16)
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
func ReadInstruction(pc uint16, bus *bus.Bus) Instruction {
|
func ReadInstruction(pc uint16, bus *bus.Bus) Instruction {
|
||||||
// Read the opcode
|
// Read the opcode
|
||||||
opcode := bus.Read(pc)
|
opcode := bus.Read(pc)
|
||||||
|
@ -24,7 +39,7 @@ func ReadInstruction(pc uint16, bus *bus.Bus) Instruction {
|
||||||
// Do we know this opcode in our optypes table?
|
// Do we know this opcode in our optypes table?
|
||||||
optype, ok := optypes[opcode]
|
optype, ok := optypes[opcode]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Unknown opcode $%02X at $04X", opcode, pc))
|
panic(fmt.Sprintf("Unknown opcode $%02X at $%04X", opcode, pc))
|
||||||
}
|
}
|
||||||
|
|
||||||
instruction := Instruction{OpType: optype}
|
instruction := Instruction{OpType: optype}
|
||||||
|
|
21
devices/via6522.go
Normal file
21
devices/via6522.go
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package devices
|
||||||
|
|
||||||
|
type Via6522 struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Via6522) Size() int {
|
||||||
|
return 0x10
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Via6522) Read(address uint16) byte {
|
||||||
|
return 0x00
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Via6522) Write(address uint16, data byte) {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVia6522(interruptChan chan bool) *Via6522 {
|
||||||
|
via := &Via6522{}
|
||||||
|
return via
|
||||||
|
}
|
20
machine.go
20
machine.go
|
@ -5,6 +5,7 @@ import (
|
||||||
"github.com/ariejan/i6502/cpu"
|
"github.com/ariejan/i6502/cpu"
|
||||||
"github.com/ariejan/i6502/devices"
|
"github.com/ariejan/i6502/devices"
|
||||||
"github.com/ariejan/i6502/memory"
|
"github.com/ariejan/i6502/memory"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Machine struct {
|
type Machine struct {
|
||||||
|
@ -22,7 +23,8 @@ type Machine struct {
|
||||||
// Creates a new i6502 Machine instance
|
// Creates a new i6502 Machine instance
|
||||||
func CreateMachine() *Machine {
|
func CreateMachine() *Machine {
|
||||||
// Channel for handling interrupts
|
// Channel for handling interrupts
|
||||||
interruptChan := make(chan bool, 0)
|
irqChan := make(chan bool, 0)
|
||||||
|
nmiChan := make(chan bool, 0)
|
||||||
|
|
||||||
ram := memory.CreateRam()
|
ram := memory.CreateRam()
|
||||||
|
|
||||||
|
@ -31,14 +33,16 @@ func CreateMachine() *Machine {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
acia6551 := devices.NewAcia6551(interruptChan)
|
acia6551 := devices.NewAcia6551(irqChan)
|
||||||
|
via6522 := devices.NewVia6522(irqChan)
|
||||||
|
|
||||||
bus, _ := bus.CreateBus()
|
bus, _ := bus.CreateBus()
|
||||||
bus.Attach(ram, "32kB RAM", 0x0000)
|
bus.Attach(ram, "32kB RAM", 0x0000)
|
||||||
bus.Attach(rom, "16kB ROM", 0xC000)
|
bus.Attach(rom, "16kB ROM", 0xC000)
|
||||||
|
bus.Attach(via6522, "VIA 6522 Parallel", 0x8000)
|
||||||
bus.Attach(acia6551, "ACIA 6551 Serial", 0x8800)
|
bus.Attach(acia6551, "ACIA 6551 Serial", 0x8800)
|
||||||
|
|
||||||
cpu := &cpu.Cpu{Bus: bus, InterruptChan: interruptChan, ExitChan: make(chan int, 0)}
|
cpu := &cpu.Cpu{Bus: bus, IrqChan: irqChan, NmiChan: nmiChan, ExitChan: make(chan int, 0)}
|
||||||
|
|
||||||
machine := &Machine{SerialTx: make(chan byte, 256), SerialRx: make(chan byte, 256), cpu: cpu, bus: bus}
|
machine := &Machine{SerialTx: make(chan byte, 256), SerialRx: make(chan byte, 256), cpu: cpu, bus: bus}
|
||||||
|
|
||||||
|
@ -69,6 +73,16 @@ func CreateMachine() *Machine {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-machine.cpu.ExitChan:
|
||||||
|
ram.Dump("intcore")
|
||||||
|
os.Exit(42)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
cpu.Reset()
|
cpu.Reset()
|
||||||
|
|
||||||
return machine
|
return machine
|
||||||
|
|
BIN
rom/ehbasic.rom
BIN
rom/ehbasic.rom
Binary file not shown.
Loading…
Reference in New Issue
Block a user