Fix V flag on ADC for BCD

This commit is contained in:
Ivan Izaguirre 2021-09-26 23:29:11 +02:00
parent 76f9ae514e
commit 71fd530e26
2 changed files with 17 additions and 11 deletions

View File

@ -4,9 +4,9 @@ package core6502
Tests from https://github.com/TomHarte/ProcessorTests Tests from https://github.com/TomHarte/ProcessorTests
Know issues: Know issues:
- Test 6502/v1/20_55_13 - Test 6502/v1/20_55_13 (Note 1)
- Not implemented undocumented opcodes for NMOS - Not implemented undocumented opcodes for NMOS (Note 2)
- Errors on flags N and V for ADC in BCD mode - Errors on flag N for ADC in BCD mode (Note 3)
The tests are disabled by defaut because they take long to run The tests are disabled by defaut because they take long to run
and require a huge download. and require a huge download.
@ -51,7 +51,7 @@ func TestHarteNMOS6502(t *testing.T) {
path := ProcessorTestsPath + "6502/v1/" path := ProcessorTestsPath + "6502/v1/"
for i := 0x00; i <= 0xff; i++ { for i := 0x00; i <= 0xff; i++ {
mnemonic := s.opcodes[i].name mnemonic := s.opcodes[i].name
if mnemonic != "" { if mnemonic != "" { // Note 2
opcode := fmt.Sprintf("%02x", i) opcode := fmt.Sprintf("%02x", i)
t.Run(opcode+mnemonic, func(t *testing.T) { t.Run(opcode+mnemonic, func(t *testing.T) {
t.Parallel() t.Parallel()
@ -105,7 +105,7 @@ func testOpcode(t *testing.T, s *State, path string, opcode string, mnemonic str
} }
for _, scenario := range scenarios { for _, scenario := range scenarios {
if scenario.Name != "20 55 13" { // TODO: FIx JSR on the stack being modified if scenario.Name != "20 55 13" { // Note 1
t.Run(scenario.Name, func(t *testing.T) { t.Run(scenario.Name, func(t *testing.T) {
testScenario(t, s, &scenario, mnemonic) testScenario(t, s, &scenario, mnemonic)
}) })
@ -135,8 +135,8 @@ func testScenario(t *testing.T, s *State, sc *scenario, mnemonic string) {
assertReg8(t, sc, "X", s.reg.getX(), sc.Final.X) assertReg8(t, sc, "X", s.reg.getX(), sc.Final.X)
assertReg8(t, sc, "Y", s.reg.getY(), sc.Final.Y) assertReg8(t, sc, "Y", s.reg.getY(), sc.Final.Y)
if s.reg.getFlag(flagD) && (mnemonic == "ADC") { if s.reg.getFlag(flagD) && (mnemonic == "ADC") {
// TODO: fix N and V flags for ADC with BCD // Note 3
assertFlags(t, sc, sc.Initial.P, s.reg.getP()&0x3f, sc.Final.P&0x3f) assertFlags(t, sc, sc.Initial.P, s.reg.getP()&0x7f, sc.Final.P&0x7f)
} else { } else {
assertFlags(t, sc, sc.Initial.P, s.reg.getP(), sc.Final.P) assertFlags(t, sc, sc.Initial.P, s.reg.getP(), sc.Final.P)
} }

View File

@ -167,12 +167,13 @@ func opADC(s *State, line []uint8, opcode opcode) {
truncated := uint8(total) truncated := uint8(total)
if s.reg.getFlag(flagD) { if s.reg.getFlag(flagD) {
totalBcdLo := int(aValue&0x0f) + int(value&0x0f) + int(carry) totalBcdLo := uint(aValue&0x0f) + uint(value&0x0f) + uint(carry)
totalBcdHi := int(aValue>>4) + int(value>>4) totalBcdHi := uint(aValue>>4) + uint(value>>4)
if totalBcdLo >= 10 { if totalBcdLo >= 10 {
totalBcdLo -= 10 totalBcdLo -= 10
totalBcdHi++ totalBcdHi++
} }
totalBcdHiPrenormalised := uint8(totalBcdHi & 0xf)
newCarry := false newCarry := false
if totalBcdHi >= 10 { if totalBcdHi >= 10 {
totalBcdHi -= 10 totalBcdHi -= 10
@ -181,14 +182,19 @@ func opADC(s *State, line []uint8, opcode opcode) {
totalBcd := uint8(totalBcdHi)<<4 + (uint8(totalBcdLo) & 0xf) totalBcd := uint8(totalBcdHi)<<4 + (uint8(totalBcdLo) & 0xf)
s.reg.setA(uint8(totalBcd)) s.reg.setA(uint8(totalBcd))
s.reg.updateFlag(flagC, newCarry) s.reg.updateFlag(flagC, newCarry)
s.reg.updateFlag(flagV, (value>>7 == aValue>>7) &&
(value>>7 != totalBcdHiPrenormalised>>3))
} else { } else {
s.reg.setA(truncated) s.reg.setA(truncated)
s.reg.updateFlag(flagC, total > 0xFF) s.reg.updateFlag(flagC, total > 0xFF)
s.reg.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
// Effectively the same as the less clear:
// s.reg.updateFlag(flagV, (value>>7 == aValue>>7) && (value>>7 != truncated>>7))
// See http://www.6502.org/tutorials/vflag.html
} }
// ZNV flags behave for BCD as if the operation was binary? // ZN flags behave for BCD as if the operation was binary?
s.reg.updateFlagZN(truncated) s.reg.updateFlagZN(truncated)
s.reg.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
} }
func opADCAlt(s *State, line []uint8, opcode opcode) { func opADCAlt(s *State, line []uint8, opcode opcode) {