mirror of
https://github.com/ariejan/i6502.git
synced 2025-02-22 07:28:56 +00:00
Add more documentation
This commit is contained in:
parent
22432de785
commit
e77a599b10
47
cpu.go
47
cpu.go
@ -2,15 +2,25 @@ package i6502
|
||||
|
||||
import "fmt"
|
||||
|
||||
/*
|
||||
The Cpu only contains the AddressBus, through which 8-bit values can be read and written
|
||||
at 16-bit addresses.
|
||||
|
||||
The Cpu has an 8-bit accumulator (A) and two 8-bit index registers (X,Y). There is a 16-bit
|
||||
Program Counter (PC) and an 8-bit Stack Pointer (SP), pointing to addresses in 0x0100-01FF.
|
||||
|
||||
The status register (P) contains flags for Zero, Negative, Break, Decimal, IrqDisable,
|
||||
Carry and Overflow flags.
|
||||
*/
|
||||
type Cpu struct {
|
||||
A byte // Accumulator
|
||||
X byte // Index register X
|
||||
Y byte // Index register Y
|
||||
|
||||
PC uint16 // 16-bit program counter
|
||||
P byte // Status Register
|
||||
SP byte // Stack Pointer
|
||||
|
||||
A byte // Accumulator
|
||||
X byte // X index register
|
||||
Y byte // Y index register
|
||||
|
||||
Bus *AddressBus // The address bus
|
||||
}
|
||||
|
||||
@ -23,21 +33,27 @@ const (
|
||||
|
||||
)
|
||||
|
||||
// Create an new Cpu instance with the specified AddressBus
|
||||
// Create an new Cpu, using the AddressBus for accessing memory.
|
||||
func NewCpu(bus *AddressBus) (*Cpu, error) {
|
||||
return &Cpu{Bus: bus}, nil
|
||||
}
|
||||
|
||||
// Returns a string containing the current state of the CPU.
|
||||
func (c *Cpu) String() string {
|
||||
str := ">>> CPU [ A ] [ X ] [ Y ] [ SP ] [ PC ] NVxBDIZC\n>>> 0x%02X 0x%02X 0x%02X 0x%02X 0x%04X %08b\n"
|
||||
return fmt.Sprintf(str, c.A, c.X, c.Y, c.SP, c.PC, c.P)
|
||||
}
|
||||
|
||||
func (c *Cpu) hasAddressBus() bool {
|
||||
return c.Bus != nil
|
||||
}
|
||||
/*
|
||||
Reset the CPU, emulating the RESB pin.
|
||||
|
||||
// Reset the CPU, emulating the RESB pin.
|
||||
The status register is reset to a know state (0x34, IrqDisabled set, Decimal unset, Break set).
|
||||
|
||||
Then the Program Counter is set to the value read from `ResetVector` (0xFFFC-FFFD).
|
||||
|
||||
Normally, no assumptions can be made about registers (A, X, Y) and the
|
||||
Stack Pointer. For convenience, these are reset to 0x00 (A,X,Y) and 0xFF (SP).
|
||||
*/
|
||||
func (c *Cpu) Reset() {
|
||||
c.PC = c.Bus.Read16(ResetVector)
|
||||
c.P = 0x34
|
||||
@ -49,11 +65,17 @@ func (c *Cpu) Reset() {
|
||||
c.SP = 0xFF
|
||||
}
|
||||
|
||||
// Simulate the IRQ pin
|
||||
/*
|
||||
Simulate the IRQ pin.
|
||||
|
||||
This will push the current Cpu state to the stack (P + PC) and set the PC
|
||||
to the address read from the `IrqVector` (0xFFFE-FFFF)
|
||||
*/
|
||||
func (c *Cpu) Interrupt() {
|
||||
c.handleIrq(c.PC)
|
||||
}
|
||||
|
||||
// Handles an interrupt or BRK.
|
||||
func (c *Cpu) handleIrq(PC uint16) {
|
||||
c.stackPush(byte(PC >> 8))
|
||||
c.stackPush(byte(PC))
|
||||
@ -65,7 +87,7 @@ func (c *Cpu) handleIrq(PC uint16) {
|
||||
}
|
||||
|
||||
// Load the specified program data at the given memory location
|
||||
// and point the Program Counter to the beginning of the program
|
||||
// and point the Program Counter to the beginning of the program.
|
||||
func (c *Cpu) LoadProgram(data []byte, location uint16) {
|
||||
for i, b := range data {
|
||||
c.Bus.Write(location+uint16(i), b)
|
||||
@ -74,13 +96,14 @@ func (c *Cpu) LoadProgram(data []byte, location uint16) {
|
||||
c.PC = location
|
||||
}
|
||||
|
||||
// Execute the instruction pointed to by the Program Counter (PC)
|
||||
// Read and execute the instruction pointed to by the Program Counter (PC)
|
||||
func (c *Cpu) Step() {
|
||||
instruction := c.readNextInstruction()
|
||||
c.PC += uint16(instruction.Size)
|
||||
c.execute(instruction)
|
||||
}
|
||||
|
||||
// Handle the execution of an instruction
|
||||
func (c *Cpu) execute(instruction Instruction) {
|
||||
switch instruction.opcodeId {
|
||||
case nop:
|
||||
|
@ -76,6 +76,9 @@ func TestCpuReset(t *testing.T) {
|
||||
// **1101** is specified, but we are satisfied with
|
||||
// 00110100 here.
|
||||
assert.Equal(0x34, cpu.P)
|
||||
assert.True(cpu.getIrqDisable())
|
||||
assert.False(cpu.getDecimal())
|
||||
assert.True(cpu.getBreak())
|
||||
|
||||
// Read PC from $FFFC-FFFD
|
||||
assert.Equal(0x1234, cpu.PC)
|
||||
|
@ -5,19 +5,15 @@ import (
|
||||
)
|
||||
|
||||
type Instruction struct {
|
||||
// Embed OpType
|
||||
OpType
|
||||
OpType // Embed OpType
|
||||
|
||||
// 8-bit operand for 2-byte instructions
|
||||
Op8 byte
|
||||
Op8 byte // 8-bit operand for 2-byte instructions
|
||||
Op16 uint16 // 16-bit operand for 3-byte instructions
|
||||
|
||||
// 16-bit operand for 3-byte instructions
|
||||
Op16 uint16
|
||||
|
||||
// Address location where this instruction got read
|
||||
Address uint16
|
||||
Address uint16 // Address location where this instruction got read, for debugging purposes
|
||||
}
|
||||
|
||||
// Return a string containing debug information about the instruction and operands.
|
||||
func (i Instruction) String() (output string) {
|
||||
switch i.Size {
|
||||
case 1:
|
||||
|
@ -1,5 +1,9 @@
|
||||
package i6502
|
||||
|
||||
/*
|
||||
Anything implementing the Memory interface can be attached to the AddressBus
|
||||
and become accessible by the Cpu.
|
||||
*/
|
||||
type Memory interface {
|
||||
Size() uint16
|
||||
Read(address uint16) byte
|
||||
|
18
opcodes.go
18
opcodes.go
@ -160,20 +160,12 @@ var instructionNames = [...]string{
|
||||
// addressing mode. It also includes some extra information for the
|
||||
// emulator, like number of cycles
|
||||
type OpType struct {
|
||||
// The actual Opcode byte read from memory
|
||||
Opcode byte
|
||||
Opcode byte // 65(C)02 Opcode, this includes an instruction and addressing mode
|
||||
Size uint8 // Size of the entire instruction in bytes
|
||||
Cycles uint8 // Number of clock cycles required to complete this instruction
|
||||
|
||||
// Opcode ID
|
||||
opcodeId uint8
|
||||
|
||||
// Addressing Mode ID
|
||||
addressingId uint8
|
||||
|
||||
// Size of this instruction, either 1, 2 or 3 bytes
|
||||
Size uint8
|
||||
|
||||
// Number of clock cycles this instruction needs
|
||||
Cycles uint8
|
||||
opcodeId uint8 // Decoded opcode Id,
|
||||
addressingId uint8 // Decoded address mode Id
|
||||
}
|
||||
|
||||
var opTypes = map[uint8]OpType{
|
||||
|
Loading…
x
Reference in New Issue
Block a user