1
0
mirror of https://github.com/zellyn/go6502.git synced 2024-06-24 15:29:40 +00:00

Doc fixes.

This commit is contained in:
Zellyn Hunter 2013-02-23 14:25:46 -08:00
parent 769924cd72
commit 5102e1af3f
6 changed files with 67 additions and 53 deletions

View File

@ -1,5 +1,5 @@
/*
Package asm provides routines for decomiling 6502 assembly language.
Package asm provides routines for decompiling 6502 assembly language.
*/
package asm

View File

@ -1,23 +1,22 @@
/*
6502 implementation.
TODO(zellyn): Provide configurable options
TODO(zellyn): Implement IRQ, NMI
TODO(zellyn): Does BRK on 65C02 CLD?
*/
package cpu
// BUG(zellyn): Implement IRQ, NMI.
// BUG(zellyn): implement interrupts, and 6502/65C02
// decimal-mode-clearing and BRK-skipping quirks. See
// http://en.wikipedia.org/wiki/MOS_Technology_6502#Bugs_and_quirks.
import (
"fmt"
)
// See http://en.wikipedia.org/wiki/MOS_Technology_6502#Bugs_and_quirks
// Chip versions.
const (
VERSION_6502 = iota
VERSION_65C02
)
// Interface for the Cpu type.
type Cpu interface {
Reset()
Step() error
@ -28,18 +27,21 @@ type Cpu interface {
PC() uint16
P() byte // [NV-BDIZC]
SP() byte
// TODO(zellyn): Add signaling of interrupts
// BUG(zellyn): Add signaling of interrupts.
}
// Memory interface, for all memory access.
type Memory interface {
Read(uint16) byte
Write(uint16, byte)
}
// Ticker interface, for keeping track of cycles.
type Ticker interface {
Tick()
}
// Interrupt vectors.
const (
STACK_BASE = 0x100
IRQ_VECTOR = 0xFFFE
@ -47,6 +49,7 @@ const (
RESET_VECTOR = 0xFFFC
)
// Flag masks.
const (
FLAG_C = 1 << iota
FLAG_Z
@ -76,6 +79,7 @@ type cpu struct {
version int
}
// Create and return a new Cpu object with the given memory, ticker, and of the given version.
func NewCPU(memory Memory, ticker Ticker, version int) Cpu {
c := cpu{m: memory, t: ticker, version: version}
c.r.P |= FLAG_UNUSED // Set unused flag to 1
@ -101,10 +105,12 @@ func (c *cpu) SP() byte {
return c.r.SP
}
// Helper for reading a word of memory.
func (c *cpu) readWord(address uint16) uint16 {
return uint16(c.m.Read(address)) + (uint16(c.m.Read(address+1)) << 8)
}
// Reset performs a reset.
func (c *cpu) Reset() {
c.r.SP = 0
c.r.PC = c.readWord(RESET_VECTOR)
@ -119,6 +125,7 @@ func (c *cpu) Reset() {
}
}
// Step takes a single step (which will last several cycles, calling Tick() on the Ticker for each).
func (c *cpu) Step() error {
c.oldPC = c.r.PC
i := c.m.Read(c.r.PC)
@ -133,15 +140,7 @@ func (c *cpu) Step() error {
return fmt.Errorf("Unknown opcode at location $%04X: $%02X", c.r.PC, i)
}
// Set the program counter.
func (c *cpu) SetPC(address uint16) {
c.r.PC = address
}
func (c *cpu) SetNZ(value byte) {
c.r.P = (c.r.P &^ FLAG_N) | (value & FLAG_N)
if value == 0 {
c.r.P |= FLAG_Z
} else {
c.r.P &^= FLAG_Z
}
}

View File

@ -1,11 +1,6 @@
/*
Package cpu provides routines for emulating a 6502 or 65C02. It also
provides data about opcodes that is used by the asm package to
(dis)assemble 6502 assembly language.
BUG(zellyn): 6502 should do invalid reads when doing indexed addressing across page boundaries. See http://en.wikipedia.org/wiki/MOS_Technology_6502#Bugs_and_quirks.
BUG(zellyn): rmw instructions should write old data back on 6502, read twice on 65C02. See http://en.wikipedia.org/wiki/MOS_Technology_6502#Bugs_and_quirks.
BUG(zellyn): implement interrupts, and 6502/65C02 decimal-mode-clearing and BRK-skipping quirks.
*/
package cpu

View File

@ -2,6 +2,16 @@ package cpu
// Helpers and instruction-builders
// setNZ uses the given value to set the N and Z flags.
func (c *cpu) setNZ(value byte) {
c.r.P = (c.r.P &^ FLAG_N) | (value & FLAG_N)
if value == 0 {
c.r.P |= FLAG_Z
} else {
c.r.P &^= FLAG_Z
}
}
// samePage is a helper that returns true if two memory addresses
// refer to the same page.
func samePage(a1 uint16, a2 uint16) bool {
@ -62,7 +72,7 @@ func adc(c *cpu, value byte) {
c.r.P |= FLAG_V
}
c.r.A = result
c.SetNZ(result)
c.setNZ(result)
}
// adc_d performs decimal-mode add-with-carry.
@ -105,7 +115,7 @@ func adc_d(c *cpu, value byte) {
}
case VERSION_65C02:
c.t.Tick()
c.SetNZ(byte(a & 0xFF))
c.setNZ(byte(a & 0xFF))
default:
panic("Unknown chip version")
}
@ -113,13 +123,13 @@ func adc_d(c *cpu, value byte) {
func and(c *cpu, value byte) {
c.r.A &= value
c.SetNZ(c.r.A)
c.setNZ(c.r.A)
}
func asl(c *cpu, value byte) byte {
result := value << 1
c.r.P = (c.r.P &^ FLAG_C) | (value >> 7)
c.SetNZ(result)
c.setNZ(result)
return result
}
@ -166,7 +176,7 @@ func cmp(c *cpu, value byte) {
if c.r.A >= value {
c.r.P |= FLAG_C
}
c.SetNZ(v)
c.setNZ(v)
}
func cpx(c *cpu, value byte) {
@ -175,7 +185,7 @@ func cpx(c *cpu, value byte) {
if c.r.X >= value {
c.r.P |= FLAG_C
}
c.SetNZ(v)
c.setNZ(v)
}
func cpy(c *cpu, value byte) {
@ -184,47 +194,47 @@ func cpy(c *cpu, value byte) {
if c.r.Y >= value {
c.r.P |= FLAG_C
}
c.SetNZ(v)
c.setNZ(v)
}
func dec(c *cpu, value byte) byte {
result := value - 1
c.SetNZ(result)
c.setNZ(result)
return result
}
func dex(c *cpu) {
c.r.X--
c.SetNZ(c.r.X)
c.setNZ(c.r.X)
c.t.Tick()
}
func dey(c *cpu) {
c.r.Y--
c.SetNZ(c.r.Y)
c.setNZ(c.r.Y)
c.t.Tick()
}
func eor(c *cpu, value byte) {
c.r.A ^= value
c.SetNZ(c.r.A)
c.setNZ(c.r.A)
}
func inc(c *cpu, value byte) byte {
result := value + 1
c.SetNZ(result)
c.setNZ(result)
return result
}
func inx(c *cpu) {
c.r.X++
c.SetNZ(c.r.X)
c.setNZ(c.r.X)
c.t.Tick()
}
func iny(c *cpu) {
c.r.Y++
c.SetNZ(c.r.Y)
c.setNZ(c.r.Y)
c.t.Tick()
}
@ -294,29 +304,29 @@ func jsr(c *cpu) {
func lda(c *cpu, value byte) {
c.r.A = value
c.SetNZ(value)
c.setNZ(value)
}
func ldx(c *cpu, value byte) {
c.r.X = value
c.SetNZ(value)
c.setNZ(value)
}
func ldy(c *cpu, value byte) {
c.r.Y = value
c.SetNZ(value)
c.setNZ(value)
}
func lsr(c *cpu, value byte) byte {
result := (value >> 1)
c.r.P = (c.r.P &^ FLAG_C) | (value & FLAG_C)
c.SetNZ(result)
c.setNZ(result)
return result
}
func ora(c *cpu, value byte) {
c.r.A |= value
c.SetNZ(c.r.A)
c.setNZ(c.r.A)
}
func nop(c *cpu) {
@ -355,14 +365,14 @@ func plp(c *cpu) {
func rol(c *cpu, value byte) byte {
result := value<<1 | (c.r.P & FLAG_C)
c.r.P = (c.r.P &^ FLAG_C) | (value >> 7)
c.SetNZ(result)
c.setNZ(result)
return result
}
func ror(c *cpu, value byte) byte {
result := (value >> 1) | (c.r.P << 7)
c.r.P = (c.r.P &^ FLAG_C) | (value & FLAG_C)
c.SetNZ(result)
c.setNZ(result)
return result
}
@ -424,7 +434,7 @@ func sbc_bin(c *cpu, value byte) byte {
if (c.r.A^result)&(value^result)&0x80 > 0 {
c.r.P |= FLAG_V
}
c.SetNZ(result)
c.setNZ(result)
return result
}
@ -466,7 +476,7 @@ func sbc_d(c *cpu, value byte) {
// fmt.Printf(" a=$%04X ($%02X)\n", a, byte(a))
c.r.A = byte(a)
c.t.Tick()
c.SetNZ(c.r.A)
c.setNZ(c.r.A)
default:
panic("Unknown chip version")
}
@ -486,25 +496,25 @@ func sty(c *cpu) byte {
func tax(c *cpu) {
c.r.X = c.r.A
c.SetNZ(c.r.X)
c.setNZ(c.r.X)
c.t.Tick()
}
func tay(c *cpu) {
c.r.Y = c.r.A
c.SetNZ(c.r.Y)
c.setNZ(c.r.Y)
c.t.Tick()
}
func tsx(c *cpu) {
c.r.X = c.r.SP
c.SetNZ(c.r.X)
c.setNZ(c.r.X)
c.t.Tick()
}
func txa(c *cpu) {
c.r.A = c.r.X
c.SetNZ(c.r.A)
c.setNZ(c.r.A)
c.t.Tick()
}
@ -515,6 +525,6 @@ func txs(c *cpu) {
func tya(c *cpu) {
c.r.A = c.r.Y
c.SetNZ(c.r.A)
c.setNZ(c.r.A)
c.t.Tick()
}

View File

@ -1,5 +1,13 @@
package cpu
// BUG(zellyn): 6502 should do invalid reads when doing indexed
// addressing across page boundaries. See
// http://en.wikipedia.org/wiki/MOS_Technology_6502#Bugs_and_quirks.
// BUG(zellyn): rmw instructions should write old data back on 6502,
// read twice on 65C02. See
// http://en.wikipedia.org/wiki/MOS_Technology_6502#Bugs_and_quirks.
// immediate2 performs 2-opcode, 2-cycle immediate mode instructions.
func immediate2(f func(*cpu, byte)) func(*cpu) {
return func(c *cpu) {

View File

@ -50,6 +50,8 @@ var NoOp = Opcode{"???", MODE_IMPLIED, nil}
// The list of Opcodes.
var Opcodes = map[byte]Opcode{
// BUG(zellyn): Add 65C02 instructions.
// Flag set and clear
0x18: {"CLC", MODE_IMPLIED, clearFlag(FLAG_C)}, // CLC
0xD8: {"CLD", MODE_IMPLIED, clearFlag(FLAG_D)}, // CLD