internal/{cpu,vm}: add memory to the vm, and refactor cpu/vm/memory code

This commit is contained in:
Bradford Lamson-Scribner 2020-05-27 21:19:43 -06:00
parent 17df9a44f0
commit f77b94f885
5 changed files with 66 additions and 38 deletions

View File

@ -4,4 +4,5 @@ Current references:
- [6502 instruction set](https://www.masswerk.at/6502/6502_instruction_set.html) - [6502 instruction set](https://www.masswerk.at/6502/6502_instruction_set.html)
- [6502 memory test](http://www.willegal.net/appleii/6502mem.htm) - [6502 memory test](http://www.willegal.net/appleii/6502mem.htm)
- [6502 instructions description with undocumented commands](http://www.zimmers.net/anonftp/pub/cbm/documents/chipdata/64doc) - [6502 instructions description with undocumented commands](http://www.zimmers.net/anonftp/pub/cbm/documents/chipdata/64doc)
- [a rust implementation](https://github.com/alexander-akhmetov/mos6502) - [a rust implementation](https://github.com/alexander-akhmetov/mos6502)
- [MOS hardware manual](http://bytecollector.com/archive/misc/6500-10A_MCS6500hwMan_Jan76.pdf)

View File

@ -1,5 +1,5 @@
package cpu // Package cpu emulates a Mos6502 cpu
//
// A .... Accumulator OPC A operand is AC (implied single byte instruction) // A .... Accumulator OPC A operand is AC (implied single byte instruction)
// abs .... absolute OPC $LLHH operand is address $HHLL * // abs .... absolute OPC $LLHH operand is address $HHLL *
// abs,X .... absolute, X-indexed OPC $LLHH,X operand is address; effective address is address incremented by X with carry ** // abs,X .... absolute, X-indexed OPC $LLHH,X operand is address; effective address is address incremented by X with carry **
@ -13,9 +13,9 @@ package cpu
// zpg .... zeropage OPC $LL operand is zeropage address (hi-byte is zero, address = $00LL) // zpg .... zeropage OPC $LL operand is zeropage address (hi-byte is zero, address = $00LL)
// zpg,X .... zeropage, X-indexed OPC $LL,X operand is zeropage address; effective address is address incremented by X without carry ** // zpg,X .... zeropage, X-indexed OPC $LL,X operand is zeropage address; effective address is address incremented by X without carry **
// zpg,Y .... zeropage, Y-indexed OPC $LL,Y operand is zeropage address; effective address is address incremented by Y without carry ** // zpg,Y .... zeropage, Y-indexed OPC $LL,Y operand is zeropage address; effective address is address incremented by Y without carry **
//
// 16-bit address words are little endian, lo(w)-byte first, followed by the hi(gh)-byte. // 16-bit address words are little endian, lo(w)-byte first, followed by the hi(gh)-byte.
//
// SR Flags (bit 7 to bit 0): // SR Flags (bit 7 to bit 0):
// N .... Negative // N .... Negative
// V .... Overflow // V .... Overflow
@ -25,15 +25,16 @@ package cpu
// I .... Interrupt (IRQ disable) // I .... Interrupt (IRQ disable)
// Z .... Zero // Z .... Zero
// C .... Carry // C .... Carry
//
// Processor Stack: // Processor Stack:
// LIFO, top down, 8 bit range, 0x0100 - 0x01FF // LIFO, top down, 8 bit range, 0x0100 - 0x01FF
package cpu
// addressingMode is a type alias for a string, used below for defining addressing mode types // addrMode is a type alias for a string, used below for defining addressing modes
type addressingMode int type addrMode int
const ( const (
accumulator addressingMode = iota accumulator addrMode = iota
absolute absolute
absoluteXIndexed absoluteXIndexed
absoluteYIndexed absoluteYIndexed
@ -48,17 +49,39 @@ const (
zeroPageYIndexed zeroPageYIndexed
) )
// Available cpu flags written as binary integer literals
const (
flagDefault uint8 = 0B_00110000
flagNegative uint8 = 0B_10000000
flagOverflow uint8 = 0B_01000000
flagB uint8 = 0B_00010000
flagDecimal uint8 = 0B_00001000
flagInterrupt uint8 = 0B_00000100
flagZero uint8 = 0B_00000010
flagCarry uint8 = 0B_00000001
)
// StackBottom represents the bottom address
const StackBottom uint16 = 0x0100 // 256
// Mos6502 TODO: docs // Mos6502 TODO: docs
type Mos6502 struct { type Mos6502 struct {
pc uint16 // program counter (16 bit) sp uint8 // stack pointer
ac uint8 // accumulator (8 bit) pc uint16 // program counter
x uint8 // X register (8 bit) a uint8 // accumulator register
y uint8 // Y register (8 bit) x uint8 // X index register
sr uint8 // status register [NV-BDIZC] (8 bit) y uint8 // Y index register
sp uint8 // stack pointer (8 bit) p uint8 // processor flags
} }
// New TODO: docs // New TODO: docs
func New() *Mos6502 { func New() *Mos6502 {
return &Mos6502{} return &Mos6502{
sp: 0xFF,
pc: 0,
a: 0,
x: 0,
y: 0,
p: flagDefault,
}
} }

View File

@ -3,18 +3,18 @@ package cpu
// op represents an operation. It includes the name of the op, it's 8 bit hexidecimal // op represents an operation. It includes the name of the op, it's 8 bit hexidecimal
// opcode, how many bytes it occupies (it's size), as well as it's addressing mode. // opcode, how many bytes it occupies (it's size), as well as it's addressing mode.
type op struct { type op struct {
name string name string
opcode uint8 opcode uint8
size uint8 size uint8
addressingMode addressingMode addrMode addrMode
} }
func newOp(name string, opcode, size uint8, addressingMode addressingMode) op { func newOp(name string, opcode, size uint8, addrMode addrMode) op {
return op{ return op{
name: name, name: name,
opcode: opcode, opcode: opcode,
size: size, size: size,
addressingMode: addressingMode, addrMode: addrMode,
} }
} }

17
internal/vm/vm.go Normal file
View File

@ -0,0 +1,17 @@
package vm
import "github.com/bradford-hamilton/apple-1/internal/cpu"
// Appleone represents the virtual Apple 1 computer
type Appleone struct {
cpu *cpu.Mos6502 // virtual Mos6502 cpu
mem [64 * 1024]byte // available memory (64kiB)
}
// New returns a pointer to an initialized Appleone with a brand spankin new CPU
func New() *Appleone {
return &Appleone{
cpu: cpu.New(),
mem: [64 * 1024]byte{},
}
}

View File

@ -1,13 +0,0 @@
package appleone
import "github.com/bradford-hamilton/apple-1/internal/cpu"
// Appleone represents our virtual Apple 1 computer
type Appleone struct {
cpu *cpu.Mos6502
}
// New returns a pointer to an initialized Appleone with a brand spankin new CPU
func New() *Appleone {
return &Appleone{cpu: cpu.New()}
}