diff --git a/debug.test b/debug.test new file mode 100755 index 0000000..1732a0f Binary files /dev/null and b/debug.test differ diff --git a/execute.go b/execute.go index 182baa9..f87f075 100644 --- a/execute.go +++ b/execute.go @@ -181,6 +181,25 @@ func buildOpBranch(flag uint8, value bool) opFunc { } } +func buildOpBit(addressMode int) opFunc { + return func(s *state, line []uint8, opcode opcode) { + value, _ := resolveWithAddressMode(s, line, addressMode) + acc := s.registers.getA() + s.registers.updateFlag(flagZ, value&acc == 0) + s.registers.updateFlag(flagN, value&(1<<7) != 0) + s.registers.updateFlag(flagV, value&(1<<6) != 0) + } +} + +func buildOpCompare(addressMode int, reg int) opFunc { + return func(s *state, line []uint8, opcode opcode) { + value, _ := resolveWithAddressMode(s, line, addressMode) + reference := s.registers.getRegister(reg) + s.registers.updateFlagZN(reference - value) + s.registers.updateFlag(flagC, reference >= value) + } +} + /* TODO: @@ -191,11 +210,6 @@ AND ORA EOR -BIT -CMP -CPX -CPY - BRK JMP @@ -211,6 +225,26 @@ PLP */ var opcodes = [256]opcode{ + 0x24: opcode{"BIT", 2, 3, buildOpBit(modeZeroPage)}, + 0x2C: opcode{"BIT", 2, 3, buildOpBit(modeAbsolute)}, + + 0xC9: opcode{"CMP", 2, 2, buildOpCompare(modeImmediate, regA)}, + 0xC5: opcode{"CMP", 2, 3, buildOpCompare(modeZeroPage, regA)}, + 0xD5: opcode{"CMP", 2, 4, buildOpCompare(modeZeroPageX, regA)}, + 0xCD: opcode{"CMP", 3, 4, buildOpCompare(modeAbsolute, regA)}, + 0xDD: opcode{"CMP", 3, 4, buildOpCompare(modeAbsoluteX, regA)}, // Extra cycles + 0xD9: opcode{"CMP", 3, 4, buildOpCompare(modeAbsoluteY, regA)}, // Extra cycles + 0xC1: opcode{"CMP", 2, 6, buildOpCompare(modeIndexedIndirectX, regA)}, + 0xD1: opcode{"CMP", 2, 5, buildOpCompare(modeIndirectIndexedY, regA)}, // Extra cycles + + 0xE0: opcode{"CPX", 2, 2, buildOpCompare(modeImmediate, regX)}, + 0xE4: opcode{"CPX", 2, 3, buildOpCompare(modeZeroPage, regX)}, + 0xEC: opcode{"CPX", 3, 4, buildOpCompare(modeAbsolute, regX)}, + + 0xC0: opcode{"CPY", 2, 2, buildOpCompare(modeImmediate, regY)}, + 0xC4: opcode{"CPY", 2, 3, buildOpCompare(modeZeroPage, regY)}, + 0xCC: opcode{"CPY", 3, 4, buildOpCompare(modeAbsolute, regY)}, + 0x2A: opcode{"ROL", 1, 2, buildShift(modeAccumulator, true, true)}, 0x26: opcode{"ROL", 2, 5, buildShift(modeZeroPage, true, true)}, 0x36: opcode{"ROL", 2, 6, buildShift(modeZeroPageX, true, true)}, @@ -272,14 +306,14 @@ var opcodes = [256]opcode{ 0xAD: opcode{"LDA", 3, 4, buildOpLoad(modeAbsolute, regA)}, 0xBD: opcode{"LDA", 3, 4, buildOpLoad(modeAbsoluteX, regA)}, // Extra cycles 0xB9: opcode{"LDA", 3, 4, buildOpLoad(modeAbsoluteY, regA)}, // Extra cycles + 0xA1: opcode{"LDA", 2, 6, buildOpLoad(modeIndexedIndirectX, regA)}, + 0xB1: opcode{"LDA", 2, 5, buildOpLoad(modeIndirectIndexedY, regA)}, // Extra cycles 0xA2: opcode{"LDX", 2, 2, buildOpLoad(modeImmediate, regX)}, 0xA6: opcode{"LDX", 2, 3, buildOpLoad(modeZeroPage, regX)}, 0xB6: opcode{"LDX", 2, 4, buildOpLoad(modeZeroPageY, regX)}, 0xAE: opcode{"LDX", 3, 4, buildOpLoad(modeAbsolute, regX)}, 0xBE: opcode{"LDX", 3, 4, buildOpLoad(modeAbsoluteY, regX)}, // Extra cycles - 0xA1: opcode{"LDX", 2, 6, buildOpLoad(modeIndexedIndirectX, regA)}, - 0xB1: opcode{"LDX", 2, 5, buildOpLoad(modeIndirectIndexedY, regA)}, // Extra cycles 0xA0: opcode{"LDY", 2, 2, buildOpLoad(modeImmediate, regY)}, 0xA4: opcode{"LDY", 2, 3, buildOpLoad(modeZeroPage, regY)}, diff --git a/execute_test.go b/execute_test.go index 5c609ca..d24afed 100644 --- a/execute_test.go +++ b/execute_test.go @@ -153,6 +153,7 @@ func TestTransfer(t *testing.T) { if s.registers.getSP() != 0xB4 { t.Error("Error in TXS") } + s.registers.setY(0xB5) executeLine(&s, []uint8{0x98}) if s.registers.getA() != 0xB5 { @@ -238,6 +239,63 @@ func TestClearSetFlag(t *testing.T) { } +func TestCompare(t *testing.T) { + var s state + + s.registers.setA(0x02) + executeLine(&s, []uint8{0xC9, 0x01}) + if s.registers.getP() != 0x01 { + t.Errorf("Error in CMP <. %v", s.registers) + } + + executeLine(&s, []uint8{0xC9, 0x02}) + if s.registers.getP() != 0x03 { + t.Errorf("Error in CMP =. %v", s.registers) + } + + executeLine(&s, []uint8{0xC9, 0x03}) + if s.registers.getP() != 0x80 { + t.Errorf("Error in CMP >. %v", s.registers) + } + + s.registers.setX(0x04) + executeLine(&s, []uint8{0xE0, 0x05}) + if s.registers.getP() != 0x80 { + t.Errorf("Error in CPX >. %v", s.registers) + } + + s.registers.setY(0x08) + executeLine(&s, []uint8{0xC0, 0x09}) + if s.registers.getP() != 0x80 { + t.Errorf("Error in CPY >. %v", s.registers) + } + +} +func TestBit(t *testing.T) { + var s state + + s.registers.setA(0x0F) + s.memory[0x0040] = 0xF0 + executeLine(&s, []uint8{0x24, 0x40}) + if s.registers.getP() != 0xC2 { + t.Errorf("Error in BIT. %v", s.registers) + } + + s.registers.setA(0xF0) + s.memory[0x0040] = 0xF0 + executeLine(&s, []uint8{0x24, 0x40}) + if s.registers.getP() != 0xC0 { + t.Errorf("Error in BIT, 2. %v", s.registers) + } + + s.registers.setA(0xF0) + s.memory[0x01240] = 0x80 + executeLine(&s, []uint8{0x2C, 0x40, 0x12}) + if s.registers.getP() != 0x80 { + t.Errorf("Error in BIT, 2. %v", s.registers) + } +} + func TestBranch(t *testing.T) { var s state s.registers.setPC(0xC600)