Fixed ADC and SBC in decimal mode. All tests pass.

This commit is contained in:
Ivan Izaguirre 2019-02-10 23:47:54 +01:00
parent f43150c93c
commit 8bd489522f
3 changed files with 108 additions and 55 deletions

View File

@ -221,43 +221,58 @@ func buildOpLogic(operation func(uint8, uint8) uint8) opFunc {
func opADC(s *state, line []uint8, opcode opcode) {
value, _, _ := resolve(s, line, opcode)
if s.registers.getFlag(flagD) {
// TODO BCD. See http://www.6502.org/tutorials/decimal_mode.html
panic("BCD not supported")
} else {
total := uint16(s.registers.getA()) +
uint16(value) +
uint16(s.registers.getFlagBit(flagC))
signedTotal := int16(int8(s.registers.getA())) +
int16(int8(value)) +
int16(s.registers.getFlagBit(flagC))
truncated := uint8(total)
aValue := s.registers.getA()
carry := s.registers.getFlagBit(flagC)
total := uint16(aValue) + uint16(value) + uint16(carry)
signedTotal := int16(int8(aValue)) + int16(int8(value)) + int16(carry)
truncated := uint8(total)
if s.registers.getFlag(flagD) {
totalBcdLo := int(aValue&0x0f) + int(value&0x0f) + int(carry)
totalBcdHi := int(aValue>>4) + int(value>>4)
if totalBcdLo >= 10 {
totalBcdHi++
}
totalBcd := (totalBcdHi%10)<<4 + (totalBcdLo % 10)
s.registers.setA(uint8(totalBcd))
s.registers.updateFlag(flagC, totalBcdHi > 9)
} else {
s.registers.setA(truncated)
s.registers.updateFlagZN(truncated)
s.registers.updateFlag(flagC, total > 0xFF)
s.registers.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
}
// ZNV flags behave for BCD as if the operation was binary?
s.registers.updateFlagZN(truncated)
s.registers.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
}
func opSBC(s *state, line []uint8, opcode opcode) {
value, _, _ := resolve(s, line, opcode)
aValue := s.registers.getA()
carry := s.registers.getFlagBit(flagC)
total := 0x100 + uint16(aValue) - uint16(value) + uint16(carry) - 1
signedTotal := int16(int8(aValue)) - int16(int8(value)) + int16(carry) - 1
truncated := uint8(total)
if s.registers.getFlag(flagD) {
// TODO BCD
panic("BCD not supported")
totalBcdLo := 10 + int(aValue&0x0f) - int(value&0x0f) + int(carry) - 1
totalBcdHi := 10 + int(aValue>>4) - int(value>>4)
if totalBcdLo < 10 {
totalBcdHi--
}
totalBcd := (totalBcdHi%10)<<4 + (totalBcdLo % 10)
s.registers.setA(uint8(totalBcd))
s.registers.updateFlag(flagC, totalBcdHi >= 10)
} else {
total := 0x100 + uint16(s.registers.getA()) -
uint16(value) +
uint16(s.registers.getFlagBit(flagC)) - 1
signedTotal := int16(int8(s.registers.getA())) -
int16(int8(value)) +
int16(s.registers.getFlagBit(flagC)) - 1
truncated := uint8(total)
s.registers.setA(truncated)
s.registers.updateFlagZN(truncated)
s.registers.updateFlag(flagC, total > 0xFF)
s.registers.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
}
// ZNV flags behave for SBC as if the operation was binary
s.registers.updateFlagZN(truncated)
s.registers.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
}
const stackAddress uint16 = 0x0100

View File

@ -268,30 +268,65 @@ func TestAdd(t *testing.T) {
s.registers.clearFlag(flagC)
executeLine(&s, []uint8{0x69, 0x0B})
if s.registers.getA() != 0xAB {
t.Errorf("Error in ADC A0 + 0B. %v", s.registers)
t.Errorf("Error in ADC. %v", s.registers)
}
if s.registers.getFlag(flagC) {
t.Errorf("Error in carry ADC A0 + 0B. %v", s.registers)
t.Errorf("Error in carry ADC. %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)
t.Errorf("Error in ADC with carry. %v", s.registers)
}
if !s.registers.getFlag(flagC) {
t.Errorf("Error in carry ADC A0 + 0B with carry. %v", s.registers)
t.Errorf("Error in carry ADC 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)
t.Errorf("Error in carried ADC with carry. %v", s.registers)
}
if s.registers.getFlag(flagC) {
t.Errorf("Error in carry ADC C + A0 + 0B with carry. %v", s.registers)
t.Errorf("Error in carry in carried ADC with carry. %v", s.registers)
}
}
func TestAddDecimal(t *testing.T) {
var s state
s.registers.setFlag(flagD)
s.registers.setA(0x12)
s.registers.clearFlag(flagC)
executeLine(&s, []uint8{0x69, 0x013})
if s.registers.getA() != 0x25 {
t.Errorf("Error in ADC decimal. %v", s.registers)
}
if s.registers.getFlag(flagC) {
t.Errorf("Error in carry ADC. %v", s.registers)
}
s.registers.setA(0x44)
s.registers.clearFlag(flagC)
executeLine(&s, []uint8{0x69, 0x68})
if s.registers.getA() != 0x12 {
t.Errorf("Error in ADC decimal with carry. %v", s.registers)
}
if !s.registers.getFlag(flagC) {
t.Errorf("Error in carry ADC decimal with carry. %v", s.registers)
}
s.registers.setA(0x44)
s.registers.setFlag(flagC)
executeLine(&s, []uint8{0x69, 0x23})
if s.registers.getA() != 0x68 {
t.Errorf("Error in carried ADC decimal with carry. %v", s.registers)
}
if s.registers.getFlag(flagC) {
t.Errorf("Error in carry in carried ADC decimal with carry. %v", s.registers)
}
}
@ -301,31 +336,31 @@ func TestSub(t *testing.T) {
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.getA() != 0x03 {
t.Errorf("Error in SBC. %v", s.registers)
}
if s.registers.getFlag(flagC) {
t.Errorf("Error in carry SBC A0 + 0B. %v", s.registers)
if !s.registers.getFlag(flagC) {
t.Errorf("Error in carry SBC. %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.getA() != 0xFE {
t.Errorf("Error in SBC with carry. %v", s.registers)
}
if !s.registers.getFlag(flagC) {
t.Errorf("Error in carry SBC A0 + 0B with carry. %v", s.registers)
if s.registers.getFlag(flagC) {
t.Errorf("Error in carry SBC 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.getA() != 0x06 {
t.Errorf("Error in carried SBC with carry. %v", s.registers)
}
if s.registers.getFlag(flagC) {
t.Errorf("Error in carry SBC C + A0 + 0B with carry. %v", s.registers)
if !s.registers.getFlag(flagC) {
t.Errorf("Error in carry in carried SBC with carry. %v", s.registers)
}
}

29
main.go
View File

@ -8,19 +8,22 @@ func main() {
s.registers.setPC(0x0400)
for true {
for i := 0; i < 20; i++ {
testCase := s.memory[0x0200]
log := testCase > 41
if log {
fmt.Printf("[ %d ] ", testCase)
}
pc := s.registers.getPC()
executeInstruction(&s, log)
if pc == s.registers.getPC() {
s.memory.printPage(0x00)
//s.memory.printPage(0x01)
panic("No change in PC")
}
testCase := s.memory[0x0200]
if testCase >= 240 {
break
}
log := testCase > 43
if log {
fmt.Printf("[ %d ] ", testCase)
}
pc := s.registers.getPC()
executeInstruction(&s, log)
if pc == s.registers.getPC() {
//s.memory.printPage(0x00)
//s.memory.printPage(0x01)
panic("No change in PC")
}
}
fmt.Printf("Test completed\n")
}