Support for ADC and SBC without BCD

This commit is contained in:
Ivan Izaguirre 2019-02-02 18:16:29 +01:00
parent d56bea182f
commit 1c1bd79f13
2 changed files with 131 additions and 16 deletions

View File

@ -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: TODO:
http://www.6502.org/tutorials/decimal_mode.html
ADC
SBC
AND
ORA
EOR
BRK BRK
@ -238,6 +266,15 @@ PLP
*/ */
var opcodes = [256]opcode{ 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)}, 0x29: opcode{"AND", 2, 2, buildOpLogic(modeImmediate, operationAnd)},
0x25: opcode{"AND", 2, 3, buildOpLogic(modeZeroPage, operationAnd)}, 0x25: opcode{"AND", 2, 3, buildOpLogic(modeZeroPage, operationAnd)},
0x35: opcode{"AND", 2, 4, buildOpLogic(modeZeroPageX, 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)}, 0x41: opcode{"EOR", 2, 6, buildOpLogic(modeIndexedIndirectX, operationXor)},
0x51: opcode{"EOR", 2, 5, buildOpLogic(modeIndirectIndexedY, operationXor)}, // Extra cycles 0x51: opcode{"EOR", 2, 5, buildOpLogic(modeIndirectIndexedY, operationXor)}, // Extra cycles
0x09: opcode{"ORA", 2, 2, buildOpLogic(modeImmediate, operationOr)}, 0x69: opcode{"ADC", 2, 2, buildOpAdd(modeImmediate)},
0x05: opcode{"ORA", 2, 3, buildOpLogic(modeZeroPage, operationOr)}, 0x65: opcode{"ADC", 2, 3, buildOpAdd(modeZeroPage)},
0x15: opcode{"ORA", 2, 4, buildOpLogic(modeZeroPageX, operationOr)}, 0x75: opcode{"ADC", 2, 4, buildOpAdd(modeZeroPageX)},
0x0D: opcode{"ORA", 3, 4, buildOpLogic(modeAbsolute, operationOr)}, 0x6D: opcode{"ADC", 3, 4, buildOpAdd(modeAbsolute)},
0x1D: opcode{"ORA", 3, 4, buildOpLogic(modeAbsoluteX, operationOr)}, // Extra cycles 0x7D: opcode{"ADC", 3, 4, buildOpAdd(modeAbsoluteX)}, // Extra cycles
0x19: opcode{"ORA", 3, 4, buildOpLogic(modeAbsoluteY, operationOr)}, // Extra cycles 0x79: opcode{"ADC", 3, 4, buildOpAdd(modeAbsoluteY)}, // Extra cycles
0x01: opcode{"ORA", 2, 6, buildOpLogic(modeIndexedIndirectX, operationOr)}, 0x61: opcode{"ADC", 2, 6, buildOpAdd(modeIndexedIndirectX)},
0x11: opcode{"ORA", 2, 5, buildOpLogic(modeIndirectIndexedY, operationOr)}, // Extra cycles 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)}, 0x24: opcode{"BIT", 2, 3, buildOpBit(modeZeroPage)},
0x2C: opcode{"BIT", 2, 3, buildOpBit(modeAbsolute)}, 0x2C: opcode{"BIT", 2, 3, buildOpBit(modeAbsolute)},

View File

@ -239,7 +239,7 @@ func TestClearSetFlag(t *testing.T) {
} }
func testLogic(t *testing.T) { func TestLogic(t *testing.T) {
var s state var s state
s.registers.setA(0xF0) 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) { func TestCompare(t *testing.T) {
var s state var s state