diff --git a/execute.go b/execute.go index 890a5c2..470a8a8 100644 --- a/execute.go +++ b/execute.go @@ -213,15 +213,43 @@ func buildOpLogic(addressMode int, operation func(uint8, uint8) uint8) opFunc { } } +func buildOpAdd(addressMode int) opFunc { + return func(s *state, line []uint8, opcode opcode) { + value, _ := resolveWithAddressMode(s, line, addressMode) + if s.registers.getFlag(flagD) { + // TODO BCD + } else { + total := uint16(s.registers.getA()) + + uint16(value) + + uint16(s.registers.getFlagBit(flagC)) + truncated := uint8(total) + s.registers.setA(truncated) + s.registers.updateFlagZN(truncated) + s.registers.updateFlag(flagC, total > 0xFF) + } + } +} + +func buildOpSub(addressMode int) opFunc { + return func(s *state, line []uint8, opcode opcode) { + value, _ := resolveWithAddressMode(s, line, addressMode) + if s.registers.getFlag(flagD) { + // TODO BCD + } else { + total := 0x100 + uint16(s.registers.getA()) - + uint16(value) - + uint16(s.registers.getFlagBit(flagC)) + truncated := uint8(total) + s.registers.setA(truncated) + s.registers.updateFlagZN(truncated) + s.registers.updateFlag(flagC, total <= 0xFF) + } + } +} + /* TODO: - -ADC -SBC - -AND -ORA -EOR +http://www.6502.org/tutorials/decimal_mode.html BRK @@ -238,6 +266,15 @@ PLP */ var opcodes = [256]opcode{ + 0x09: opcode{"ORA", 2, 2, buildOpLogic(modeImmediate, operationOr)}, + 0x05: opcode{"ORA", 2, 3, buildOpLogic(modeZeroPage, operationOr)}, + 0x15: opcode{"ORA", 2, 4, buildOpLogic(modeZeroPageX, operationOr)}, + 0x0D: opcode{"ORA", 3, 4, buildOpLogic(modeAbsolute, operationOr)}, + 0x1D: opcode{"ORA", 3, 4, buildOpLogic(modeAbsoluteX, operationOr)}, // Extra cycles + 0x19: opcode{"ORA", 3, 4, buildOpLogic(modeAbsoluteY, operationOr)}, // Extra cycles + 0x01: opcode{"ORA", 2, 6, buildOpLogic(modeIndexedIndirectX, operationOr)}, + 0x11: opcode{"ORA", 2, 5, buildOpLogic(modeIndirectIndexedY, operationOr)}, // Extra cycles + 0x29: opcode{"AND", 2, 2, buildOpLogic(modeImmediate, operationAnd)}, 0x25: opcode{"AND", 2, 3, buildOpLogic(modeZeroPage, operationAnd)}, 0x35: opcode{"AND", 2, 4, buildOpLogic(modeZeroPageX, operationAnd)}, @@ -256,14 +293,23 @@ var opcodes = [256]opcode{ 0x41: opcode{"EOR", 2, 6, buildOpLogic(modeIndexedIndirectX, operationXor)}, 0x51: opcode{"EOR", 2, 5, buildOpLogic(modeIndirectIndexedY, operationXor)}, // Extra cycles - 0x09: opcode{"ORA", 2, 2, buildOpLogic(modeImmediate, operationOr)}, - 0x05: opcode{"ORA", 2, 3, buildOpLogic(modeZeroPage, operationOr)}, - 0x15: opcode{"ORA", 2, 4, buildOpLogic(modeZeroPageX, operationOr)}, - 0x0D: opcode{"ORA", 3, 4, buildOpLogic(modeAbsolute, operationOr)}, - 0x1D: opcode{"ORA", 3, 4, buildOpLogic(modeAbsoluteX, operationOr)}, // Extra cycles - 0x19: opcode{"ORA", 3, 4, buildOpLogic(modeAbsoluteY, operationOr)}, // Extra cycles - 0x01: opcode{"ORA", 2, 6, buildOpLogic(modeIndexedIndirectX, operationOr)}, - 0x11: opcode{"ORA", 2, 5, buildOpLogic(modeIndirectIndexedY, operationOr)}, // Extra cycles + 0x69: opcode{"ADC", 2, 2, buildOpAdd(modeImmediate)}, + 0x65: opcode{"ADC", 2, 3, buildOpAdd(modeZeroPage)}, + 0x75: opcode{"ADC", 2, 4, buildOpAdd(modeZeroPageX)}, + 0x6D: opcode{"ADC", 3, 4, buildOpAdd(modeAbsolute)}, + 0x7D: opcode{"ADC", 3, 4, buildOpAdd(modeAbsoluteX)}, // Extra cycles + 0x79: opcode{"ADC", 3, 4, buildOpAdd(modeAbsoluteY)}, // Extra cycles + 0x61: opcode{"ADC", 2, 6, buildOpAdd(modeIndexedIndirectX)}, + 0x71: opcode{"ADC", 2, 5, buildOpAdd(modeIndirectIndexedY)}, // Extra cycles + + 0xE9: opcode{"SBC", 2, 2, buildOpSub(modeImmediate)}, + 0xE5: opcode{"SBC", 2, 3, buildOpSub(modeZeroPage)}, + 0xF5: opcode{"SBC", 2, 4, buildOpSub(modeZeroPageX)}, + 0xED: opcode{"SBC", 3, 4, buildOpSub(modeAbsolute)}, + 0xFD: opcode{"SBC", 3, 4, buildOpSub(modeAbsoluteX)}, // Extra cycles + 0xF9: opcode{"SBC", 3, 4, buildOpSub(modeAbsoluteY)}, // Extra cycles + 0xE1: opcode{"SBC", 2, 6, buildOpSub(modeIndexedIndirectX)}, + 0xF1: opcode{"SBC", 2, 5, buildOpSub(modeIndirectIndexedY)}, // Extra cycles 0x24: opcode{"BIT", 2, 3, buildOpBit(modeZeroPage)}, 0x2C: opcode{"BIT", 2, 3, buildOpBit(modeAbsolute)}, diff --git a/execute_test.go b/execute_test.go index 25b3844..9e58b47 100644 --- a/execute_test.go +++ b/execute_test.go @@ -239,7 +239,7 @@ func TestClearSetFlag(t *testing.T) { } -func testLogic(t *testing.T) { +func TestLogic(t *testing.T) { var s state s.registers.setA(0xF0) @@ -261,6 +261,75 @@ func testLogic(t *testing.T) { } } +func TestAdd(t *testing.T) { + var s state + + s.registers.setA(0xA0) + s.registers.clearFlag(flagC) + executeLine(&s, []uint8{0x69, 0x0B}) + if s.registers.getA() != 0xAB { + t.Errorf("Error in ADC A0 + 0B. %v", s.registers) + } + if s.registers.getFlag(flagC) { + t.Errorf("Error in carry ADC A0 + 0B. %v", s.registers) + } + + s.registers.setA(0xFF) + s.registers.clearFlag(flagC) + executeLine(&s, []uint8{0x69, 0x02}) + if s.registers.getA() != 0x01 { + t.Errorf("Error in ADC A0 + 0B with carry. %v", s.registers) + } + if !s.registers.getFlag(flagC) { + t.Errorf("Error in carry ADC A0 + 0B with carry. %v", s.registers) + } + + s.registers.setA(0xA0) + s.registers.setFlag(flagC) + executeLine(&s, []uint8{0x69, 0x01}) + if s.registers.getA() != 0xA2 { + t.Errorf("Error in ADC C + A0 + 0B with carry. %v", s.registers) + } + if s.registers.getFlag(flagC) { + t.Errorf("Error in carry ADC C + A0 + 0B with carry. %v", s.registers) + } +} + +func TestSub(t *testing.T) { + var s state + + s.registers.setA(0x09) + s.registers.clearFlag(flagC) + executeLine(&s, []uint8{0xE9, 0x05}) + if s.registers.getA() != 0x04 { + t.Errorf("Error in SBC A0 + 0B. %v", s.registers) + } + if s.registers.getFlag(flagC) { + t.Errorf("Error in carry SBC A0 + 0B. %v", s.registers) + } + + s.registers.setA(0x01) + s.registers.clearFlag(flagC) + executeLine(&s, []uint8{0xE9, 0x02}) + if s.registers.getA() != 0xFF { + t.Errorf("Error in SBC A0 + 0B with carry. %v", s.registers) + } + if !s.registers.getFlag(flagC) { + t.Errorf("Error in carry SBC A0 + 0B with carry. %v", s.registers) + } + + s.registers.setA(0x08) + s.registers.setFlag(flagC) + executeLine(&s, []uint8{0xE9, 0x02}) + if s.registers.getA() != 0x05 { + t.Errorf("Error in SBC C + A0 + 0B with carry. %v", s.registers) + } + if s.registers.getFlag(flagC) { + t.Errorf("Error in carry SBC C + A0 + 0B with carry. %v", s.registers) + } + +} + func TestCompare(t *testing.T) { var s state