diff --git a/execute.go b/execute.go index 60b5742..8843f14 100644 --- a/execute.go +++ b/execute.go @@ -21,7 +21,7 @@ const modeIndexedIndirectX = 7 const modeIndirectIndexedY = 8 // https://www.masswerk.at/6502/6502_instruction_set.html - +// http://www.emulator101.com/reference/6502-reference.html func getWordInLine(line []uint8) uint16 { return uint16(line[1]) + 0x100*uint16(line[2]) } @@ -41,20 +41,22 @@ func buildOPTransfer(regSrc int, regDst int) opFunc { return func(s *state, line []uint8, opcode opcode) { value := s.registers.getRegister(regSrc) s.registers.setRegister(regDst, value) - // TODO: Update flags (N, Z) + if regDst != regSP { + s.registers.updateFlagZN(value) + } } } func buildOpIncDecRegister(reg int, inc bool) opFunc { return func(s *state, line []uint8, opcode opcode) { - value := s.registers.getRegister(reg) + 1 + value := s.registers.getRegister(reg) if inc { value++ } else { value-- } s.registers.setRegister(reg, value) - // TODO: Update flags (N, Z) for all but TXS + s.registers.updateFlagZN(value) } } @@ -93,8 +95,7 @@ func buildOpLoad(addressMode int, regDst int) opFunc { } s.registers.setRegister(regDst, value) - - // TODO: Update flags (N, Z) + s.registers.updateFlagZN(value) } } diff --git a/execute_test.go b/execute_test.go index dde28e0..70ce222 100644 --- a/execute_test.go +++ b/execute_test.go @@ -12,6 +12,16 @@ func TestLoad(t *testing.T) { t.Error("Error in LDA #") } + executeLine(&s, []uint8{0xA9, 0x00}) + if s.registers.getP() != flagZ { + t.Error("Error in flags for LDA $0") + } + + executeLine(&s, []uint8{0xA9, 0xF0}) + if s.registers.getP() != flagN { + t.Error("Error in flags for LDA $F0") + } + executeLine(&s, []uint8{0xA0, 0xFE}) if s.registers.getY() != 0xFE { t.Error("Error in LDY #") @@ -84,6 +94,9 @@ func TestTransfer(t *testing.T) { if s.registers.getX() != 0xB0 { t.Error("Error in TAX") } + if s.registers.getP() != flagN { + t.Error("Error in TAX flags") + } s.registers.setA(0xB1) executeLine(&s, []uint8{0xA8}) @@ -114,3 +127,23 @@ func TestTransfer(t *testing.T) { t.Error("Error in TYA") } } + +func TestIncDec(t * testing.T) { + var s state + + s.registers.setX(0x7E) + executeLine(&s, []uint8{0xE8}) + if s.registers.getX() != 0x7F { + t.Errorf("Error in INX %v", s.registers.getX()) + } + + s.registers.setY(0xFC) + executeLine(&s, []uint8{0x88}) + if s.registers.getY() != 0xFB { + t.Error("Error in DEY") + } + if s.registers.getP() != flagN { + t.Error("Error in DEY flags") + } + +} diff --git a/registers.go b/registers.go index 3780303..31aba75 100644 --- a/registers.go +++ b/registers.go @@ -9,6 +9,16 @@ const ( regPC = 6 // 2 bytes ) +const ( + flagN uint8 = 1 << 7 + flagV uint8 = 1 << 6 + flagB uint8 = 1 << 4 + flagD uint8 = 1 << 3 + flagI uint8 = 1 << 2 + flagZ uint8 = 1 << 1 + flagC uint8 = 1 << 0 +) + type registers struct { data [8]uint8 } @@ -38,3 +48,28 @@ func (r *registers) setPC(v uint16) { r.data[regPC] = uint8(v >> 8) r.data[regPC+1] = uint8(v) } + +func (r *registers) getFlag(i uint8) bool { + return (r.data[regP] & i ) != 0 +} + +func (r *registers) setFlag(i uint8) { + r.data[regP] |= i +} + +func (r *registers) clearFlag(i uint8) { + r.data[regP] &^= i +} + +func (r *registers) updateFlag(i uint8, v bool) { + if v { + r.setFlag(i) + } else { + r.clearFlag(i) + } +} + +func (r *registers) updateFlagZN(t uint8) { + r.updateFlag(flagZ, t == 0) + r.updateFlag(flagN, t >= (1<<7)) +} diff --git a/registers_test.go b/registers_test.go index 44d902d..45862cf 100644 --- a/registers_test.go +++ b/registers_test.go @@ -20,3 +20,50 @@ func TestRegPC(t *testing.T) { t.Error("Error storing and loading PC") } } + +func TestFlags(t *testing.T) { + var r registers + r.setP(0x23) + if r.getP() != 0x23 { + t.Error("Error storing and loading P") + } + + r.setP(0) + r.setFlag(flagD) + if !r.getFlag(flagD) { + t.Error("Error setting and getting flag") + } + + r.clearFlag(flagD) + if r.getFlag(flagD) { + t.Error("Error clearing flag") + } + + r.updateFlag(flagD, true) + if !r.getFlag(flagD) { + t.Error("Error update flag to true") + } + + r.updateFlag(flagD, false) + if r.getFlag(flagD) { + t.Error("Error updating flag to false") + } +} + +func TestUpdateFlagZN(t *testing.T) { + var r registers + r.updateFlagZN(0) + if r.getP() != flagZ { + t.Error("Error update flags ZN with 0") + } + + r.updateFlagZN(0x10) + if r.getP() != 0 { + t.Error("Error update flags ZN with 0x10") + } + + r.updateFlagZN(0xF2) + if r.getP() != flagN { + t.Error("Error update flags ZN with 0xF2") + } +} \ No newline at end of file