Implement more opcodes, minor improvements

This commit is contained in:
Ariejan de Vroom 2014-08-14 11:07:10 +02:00
parent 9c8f47abbc
commit f3f95dda39
5 changed files with 2123 additions and 12 deletions

67
cpu.go
View File

@ -7,6 +7,7 @@ type Cpu struct {
PC uint16 // 16-bit program counter
P byte // Status Register
SP byte // Stack Pointer
A byte // Accumulator
X byte // X index register
@ -52,8 +53,74 @@ func (c *Cpu) Step() {
func (c *Cpu) execute(instruction Instruction) {
switch instruction.opcodeId {
case nop:
break
case adc:
c.ADC(instruction)
case sbc:
c.SBC(instruction)
case sec:
c.setCarry(true)
case sed:
c.setDecimal(true)
case sei:
c.setInterrupt(true)
case clc:
c.setCarry(false)
case cld:
c.setDecimal(false)
case cli:
c.setInterrupt(false)
case clv:
c.setOverflow(false)
case inx:
c.setX(c.X + 1)
case iny:
c.setY(c.Y + 1)
case inc:
c.INC(instruction)
case dex:
c.setX(c.X - 1)
case dey:
c.setY(c.Y - 1)
case dec:
c.DEC(instruction)
case lda:
c.LDA(instruction)
case ldx:
c.LDX(instruction)
case ldy:
c.LDY(instruction)
case ora:
c.ORA(instruction)
case and:
c.AND(instruction)
case eor:
c.EOR(instruction)
case sta:
c.STA(instruction)
case stx:
c.STX(instruction)
case sty:
c.STY(instruction)
case tax:
c.setX(c.A)
case tay:
c.setY(c.A)
case txa:
c.setA(c.X)
case tya:
c.setA(c.Y)
case tsx:
c.setX(c.SP)
case txs:
c.setSP(c.X)
case asl:
c.ASL(instruction)
case lsr:
c.LSR(instruction)
default:
panic(fmt.Errorf("Unimplemented instruction: %s", instruction))
}
}

View File

@ -3,15 +3,120 @@ package i6502
// Add Memory to Accumulator with Carry
func (c *Cpu) ADC(in Instruction) {
operand := c.resolveOperand(in)
carryIn := c.getStatusInt(sCarry)
carryIn := c.getCarryInt()
if c.getStatus(sDecimal) {
if c.getDecimal() {
c.adcDecimal(c.A, operand, carryIn)
} else {
c.adcNormal(c.A, operand, carryIn)
}
}
// Substract memory from Accummulator with carry
func (c *Cpu) SBC(in Instruction) {
operand := c.resolveOperand(in)
carryIn := c.getCarryInt()
if c.getDecimal() {
c.sbcDecimal(c.A, operand, carryIn)
} else {
c.adcNormal(c.A, ^operand, carryIn)
}
}
func (c *Cpu) INC(in Instruction) {
address := c.memoryAddress(in)
value := c.bus.Read(address) + 1
c.bus.Write(address, value)
c.setArithmeticFlags(value)
}
func (c *Cpu) DEC(in Instruction) {
address := c.memoryAddress(in)
value := c.bus.Read(address) - 1
c.bus.Write(address, value)
c.setArithmeticFlags(value)
}
func (c *Cpu) LDA(in Instruction) {
value := c.resolveOperand(in)
c.setA(value)
}
func (c *Cpu) LDX(in Instruction) {
value := c.resolveOperand(in)
c.setX(value)
}
func (c *Cpu) LDY(in Instruction) {
value := c.resolveOperand(in)
c.setY(value)
}
func (c *Cpu) ORA(in Instruction) {
value := c.resolveOperand(in)
c.setA(c.A | value)
}
func (c *Cpu) AND(in Instruction) {
value := c.resolveOperand(in)
c.setA(c.A & value)
}
func (c *Cpu) EOR(in Instruction) {
value := c.resolveOperand(in)
c.setA(c.A ^ value)
}
func (c *Cpu) STA(in Instruction) {
address := c.memoryAddress(in)
c.bus.Write(address, c.A)
}
func (c *Cpu) STX(in Instruction) {
address := c.memoryAddress(in)
c.bus.Write(address, c.X)
}
func (c *Cpu) STY(in Instruction) {
address := c.memoryAddress(in)
c.bus.Write(address, c.Y)
}
func (c *Cpu) ASL(in Instruction) {
switch in.addressingId {
case accumulator:
c.setCarry((c.A >> 7) == 1)
c.A <<= 1
c.setArithmeticFlags(c.A)
default:
address := c.memoryAddress(in)
value := c.bus.Read(address)
c.setCarry((value >> 7) == 1)
value <<= 1
c.bus.Write(address, value)
c.setArithmeticFlags(value)
}
}
func (c *Cpu) LSR(in Instruction) {
switch in.addressingId {
case accumulator:
c.setCarry((c.A & 0x01) == 1)
c.A >>= 1
c.setArithmeticFlags(c.A)
default:
address := c.memoryAddress(in)
value := c.bus.Read(address)
c.setCarry((value & 0x01) == 1)
value >>= 1
c.bus.Write(address, value)
c.setArithmeticFlags(value)
}
}
// Performs regular, 8-bit addition
func (c *Cpu) adcNormal(a uint8, b uint8, carryIn uint8) {
result16 := uint16(a) + uint16(b) + uint16(carryIn)
@ -24,9 +129,7 @@ func (c *Cpu) adcNormal(a uint8, b uint8, carryIn uint8) {
// Set the overflow bit
c.setOverflow(overflow)
// Store the resulting value (8-bits)
c.A = result
// Update sZero and sNegative
c.setArithmeticFlags(c.A)
c.setA(result)
}
// Performs addition in decimal mode
@ -50,7 +153,35 @@ func (c *Cpu) adcDecimal(a uint8, b uint8, carryIn uint8) {
c.setCarry(high > 15)
c.setZero(result == 0)
c.setNegative(false) // BCD is never negative
c.setNegative(false) // BCD never sets negative
c.setOverflow(false) // BCD never sets overflow
c.A = result
}
func (c *Cpu) sbcDecimal(a uint8, b uint8, carryIn uint8) {
var carryB uint8 = 0
carryIn = (carryIn + 1) % 1
low := (a & 0x0F) - (b & 0x0F) - carryIn
if (low & 0x10) != 0 {
low -= 6
}
if (low & 0x10) != 0 {
carryB = 1
}
high := (a >> 4) - (b >> 4) - carryB
if (high & 0x10) != 0 {
high -= 6
}
result := (low & 0x0F) | (high << 4)
c.setCarry((high & 0xFF) < 15)
c.setZero(result == 0)
c.setNegative(false) // BCD never sets negative
c.setOverflow(false) // BCD never sets overflow
c.A = result

View File

@ -32,18 +32,62 @@ func (c *Cpu) setCarry(state bool) {
c.setStatus(sCarry, state)
}
func (c *Cpu) setOverflow(state bool) {
c.setStatus(sOverflow, state)
}
func (c *Cpu) setZero(state bool) {
c.setStatus(sZero, state)
}
func (c *Cpu) setInterrupt(state bool) {
c.setStatus(sInterrupt, state)
}
func (c *Cpu) setDecimal(state bool) {
c.setStatus(sDecimal, state)
}
func (c *Cpu) setBreak(state bool) {
c.setStatus(sBreak, state)
}
func (c *Cpu) setOverflow(state bool) {
c.setStatus(sOverflow, state)
}
func (c *Cpu) setNegative(state bool) {
c.setStatus(sNegative, state)
}
func (c *Cpu) getCarry() bool {
return c.getStatus(sCarry)
}
func (c *Cpu) getCarryInt() uint8 {
return c.getStatusInt(sCarry)
}
func (c *Cpu) getZero() bool {
return c.getStatus(sZero)
}
func (c *Cpu) getInterrupt() bool {
return c.getStatus(sInterrupt)
}
func (c *Cpu) getDecimal() bool {
return c.getStatus(sDecimal)
}
func (c *Cpu) getBreak() bool {
return c.getStatus(sBreak)
}
func (c *Cpu) getOverflow() bool {
return c.getStatus(sOverflow)
}
func (c *Cpu) getNegative() bool {
return c.getStatus(sNegative)
}
func (c *Cpu) setArithmeticFlags(value uint8) {
// Set sZero if value is 0
c.setStatus(sZero, value == 0)
@ -53,3 +97,23 @@ func (c *Cpu) setArithmeticFlags(value uint8) {
// negatives
c.setStatus(sNegative, (value>>7) == 1)
}
func (c *Cpu) setA(value byte) {
c.A = value
c.setArithmeticFlags(c.A)
}
func (c *Cpu) setX(value byte) {
c.X = value
c.setArithmeticFlags(c.X)
}
func (c *Cpu) setY(value byte) {
c.Y = value
c.setArithmeticFlags(c.Y)
}
func (c *Cpu) setSP(value byte) {
c.SP = value
c.setArithmeticFlags(c.SP)
}

File diff suppressed because it is too large Load Diff

View File

@ -144,12 +144,157 @@ type OpType struct {
var opTypes = map[uint8]OpType{
0xEA: OpType{0xEA, nop, implied, 1, 2},
// Set instruction
0x38: OpType{0x38, sec, implied, 1, 2},
0xF8: OpType{0xF8, sed, implied, 1, 2},
0x78: OpType{0x78, sei, implied, 1, 2},
// Clear instructions
0x18: OpType{0x18, clc, implied, 1, 2},
0xD8: OpType{0xD8, cld, implied, 1, 2},
0x58: OpType{0x58, cli, implied, 1, 2},
0xB8: OpType{0xB8, clv, implied, 1, 2},
// ADC
0x69: OpType{0x69, adc, immediate, 2, 2},
0x65: OpType{0x65, adc, zeropage, 2, 2},
0x65: OpType{0x65, adc, zeropage, 2, 3},
0x75: OpType{0x75, adc, zeropageX, 2, 4},
0x6D: OpType{0x6D, adc, absolute, 3, 4},
0x7D: OpType{0x7D, adc, absoluteX, 3, 4},
0x79: OpType{0x79, adc, absoluteY, 3, 4},
0x61: OpType{0x61, adc, indirectX, 2, 6},
0x71: OpType{0x71, adc, indirectY, 2, 5},
// SBC
0xE9: OpType{0xE9, sbc, immediate, 2, 2},
0xE5: OpType{0xE5, sbc, zeropage, 2, 3},
0xF5: OpType{0xF5, sbc, zeropageX, 2, 4},
0xED: OpType{0xED, sbc, absolute, 3, 4},
0xFD: OpType{0xFD, sbc, absoluteX, 3, 4},
0xF9: OpType{0xF9, sbc, absoluteY, 3, 4},
0xE1: OpType{0xE1, sbc, indirectX, 2, 6},
0xF1: OpType{0xF1, sbc, indirectY, 2, 5},
// Increments
0xE8: OpType{0xE8, inx, implied, 1, 2},
0xC8: OpType{0xC8, iny, implied, 1, 2},
0xE6: OpType{0xE6, inc, zeropage, 2, 5},
0xF6: OpType{0xF6, inc, zeropageX, 2, 6},
0xEE: OpType{0xEE, inc, absolute, 3, 6},
0xFE: OpType{0xFE, inc, absoluteX, 3, 7},
// Decrements
0xCA: OpType{0xCA, dex, implied, 1, 2},
0x88: OpType{0x88, dey, implied, 1, 2},
0xC6: OpType{0xC6, dec, zeropage, 2, 5},
0xD6: OpType{0xD6, dec, zeropageX, 2, 6},
0xCE: OpType{0xCE, dec, absolute, 3, 6},
0xDE: OpType{0xDE, dec, absoluteX, 3, 7},
// LDA
0xA9: OpType{0xA9, lda, immediate, 2, 2},
0xA5: OpType{0xA5, lda, zeropage, 2, 3},
0xB5: OpType{0xB5, lda, zeropageX, 2, 4},
0xAD: OpType{0xAD, lda, absolute, 3, 4},
0xBD: OpType{0xBD, lda, absoluteX, 3, 4},
0xB9: OpType{0xB9, lda, absoluteY, 3, 4},
0xA1: OpType{0xA1, lda, indirectX, 2, 6},
0xB1: OpType{0xB1, lda, indirectY, 2, 5},
// LDX
0xA2: OpType{0xA2, ldx, immediate, 2, 2},
0xA6: OpType{0xA6, ldx, zeropage, 2, 3},
0xB6: OpType{0xB6, ldx, zeropageY, 2, 4},
0xAE: OpType{0xAE, ldx, absolute, 3, 4},
0xBE: OpType{0xBE, ldx, absoluteY, 3, 4},
// LDY
0xA0: OpType{0xA0, ldy, immediate, 2, 2},
0xA4: OpType{0xA4, ldy, zeropage, 2, 3},
0xB4: OpType{0xB4, ldy, zeropageY, 2, 4},
0xAC: OpType{0xAC, ldy, absolute, 3, 4},
0xBC: OpType{0xBC, ldy, absoluteY, 3, 4},
// ORA
0x09: OpType{0x09, ora, immediate, 2, 2},
0x05: OpType{0x05, ora, zeropage, 2, 3},
0x15: OpType{0x15, ora, zeropageX, 2, 4},
0x0D: OpType{0x0D, ora, absolute, 3, 4},
0x1D: OpType{0x1D, ora, absoluteX, 3, 4},
0x19: OpType{0x19, ora, absoluteY, 3, 4},
0x01: OpType{0x01, ora, indirectX, 2, 6},
0x11: OpType{0x11, ora, indirectY, 2, 5},
// AND
0x29: OpType{0x29, and, immediate, 2, 2},
0x25: OpType{0x25, and, zeropage, 2, 3},
0x35: OpType{0x35, and, zeropageX, 2, 4},
0x2D: OpType{0x2D, and, absolute, 3, 4},
0x3D: OpType{0x3D, and, absoluteX, 3, 4},
0x39: OpType{0x39, and, absoluteY, 3, 4},
0x21: OpType{0x21, and, indirectX, 2, 6},
0x31: OpType{0x31, and, indirectY, 2, 5},
// EOR
0x49: OpType{0x49, eor, immediate, 2, 2},
0x45: OpType{0x45, eor, zeropage, 2, 3},
0x55: OpType{0x55, eor, zeropageX, 2, 4},
0x4D: OpType{0x4D, eor, absolute, 3, 4},
0x5D: OpType{0x5D, eor, absoluteX, 3, 4},
0x59: OpType{0x59, eor, absoluteY, 3, 4},
0x41: OpType{0x41, eor, indirectX, 2, 6},
0x51: OpType{0x51, eor, indirectY, 2, 5},
// STA
0x85: OpType{0x85, sta, zeropage, 2, 3},
0x95: OpType{0x95, sta, zeropageX, 2, 4},
0x8D: OpType{0x8D, sta, absolute, 3, 4},
0x9D: OpType{0x9D, sta, absoluteX, 3, 5},
0x99: OpType{0x99, sta, absoluteY, 3, 5},
0x81: OpType{0x81, sta, indirectX, 2, 6},
0x91: OpType{0x91, sta, indirectY, 2, 6},
// STX
0x86: OpType{0x86, stx, zeropage, 2, 3},
0x96: OpType{0x96, stx, zeropageY, 2, 4},
0x8E: OpType{0x8E, stx, absolute, 3, 4},
// STY
0x84: OpType{0x84, sty, zeropage, 2, 3},
0x94: OpType{0x94, sty, zeropageX, 2, 4},
0x8C: OpType{0x8C, sty, absolute, 3, 4},
// TAX
0xAA: OpType{0xAA, tax, implied, 1, 2},
// TAY
0xA8: OpType{0xA8, tay, implied, 1, 2},
// TXA
0x8A: OpType{0x8A, txa, implied, 1, 2},
// TXA
0x98: OpType{0x98, tya, implied, 1, 2},
// TSX
0xBA: OpType{0xBA, tsx, implied, 1, 2},
// TXS
0x9A: OpType{0x9A, txs, implied, 1, 2},
// ASL
0x0A: OpType{0x0A, asl, accumulator, 1, 2},
0x06: OpType{0x06, asl, zeropage, 2, 5},
0x16: OpType{0x16, asl, zeropageX, 2, 6},
0x0E: OpType{0x0E, asl, absolute, 3, 6},
0x1E: OpType{0x1E, asl, absoluteX, 3, 7},
// LSR
0x4A: OpType{0x4A, lsr, accumulator, 1, 2},
0x46: OpType{0x46, lsr, zeropage, 2, 5},
0x56: OpType{0x56, lsr, zeropageX, 2, 6},
0x4E: OpType{0x4E, lsr, absolute, 3, 6},
0x5E: OpType{0x5E, lsr, absoluteX, 3, 7},
}