1
0
mirror of https://github.com/ariejan/i6502.git synced 2024-06-08 18:29:33 +00:00
This commit is contained in:
Ariejan de Vroom 2014-08-12 20:46:41 +02:00
parent 9e3c9454e8
commit afa7d0d3f6
7 changed files with 109 additions and 21 deletions

View File

@ -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)

View File

@ -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.

View File

@ -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
View 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
}

BIN
intcore Normal file

Binary file not shown.

View File

@ -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

Binary file not shown.