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
Know issues:
- Test 6502/v1/20_55_13
- Not implemented undocumented opcodes for NMOS
- Errors on flags N and V for ADC in BCD mode
- Test 6502/v1/20_55_13 (Note 1)
- Not implemented undocumented opcodes for NMOS (Note 2)
- Errors on flag N for ADC in BCD mode (Note 3)
The tests are disabled by defaut because they take long to run
and require a huge download.
@ -51,7 +51,7 @@ func TestHarteNMOS6502(t *testing.T) {
path := ProcessorTestsPath + "6502/v1/"
for i := 0x00; i <= 0xff; i++ {
mnemonic := s.opcodes[i].name
if mnemonic != "" {
if mnemonic != "" { // Note 2
opcode := fmt.Sprintf("%02x", i)
t.Run(opcode+mnemonic, func(t *testing.T) {
t.Parallel()
@ -105,7 +105,7 @@ func testOpcode(t *testing.T, s *State, path string, opcode string, mnemonic str
}
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) {
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, "Y", s.reg.getY(), sc.Final.Y)
if s.reg.getFlag(flagD) && (mnemonic == "ADC") {
// TODO: fix N and V flags for ADC with BCD
assertFlags(t, sc, sc.Initial.P, s.reg.getP()&0x3f, sc.Final.P&0x3f)
// Note 3
assertFlags(t, sc, sc.Initial.P, s.reg.getP()&0x7f, sc.Final.P&0x7f)
} else {
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)
if s.reg.getFlag(flagD) {
totalBcdLo := int(aValue&0x0f) + int(value&0x0f) + int(carry)
totalBcdHi := int(aValue>>4) + int(value>>4)
totalBcdLo := uint(aValue&0x0f) + uint(value&0x0f) + uint(carry)
totalBcdHi := uint(aValue>>4) + uint(value>>4)
if totalBcdLo >= 10 {
totalBcdLo -= 10
totalBcdHi++
}
totalBcdHiPrenormalised := uint8(totalBcdHi & 0xf)
newCarry := false
if totalBcdHi >= 10 {
totalBcdHi -= 10
@ -181,14 +182,19 @@ func opADC(s *State, line []uint8, opcode opcode) {
totalBcd := uint8(totalBcdHi)<<4 + (uint8(totalBcdLo) & 0xf)
s.reg.setA(uint8(totalBcd))
s.reg.updateFlag(flagC, newCarry)
s.reg.updateFlag(flagV, (value>>7 == aValue>>7) &&
(value>>7 != totalBcdHiPrenormalised>>3))
} else {
s.reg.setA(truncated)
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.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
}
func opADCAlt(s *State, line []uint8, opcode opcode) {