diff --git a/core6502/harteSuite_test.go b/core6502/harteSuite_test.go index 1a300eb..4cff966 100644 --- a/core6502/harteSuite_test.go +++ b/core6502/harteSuite_test.go @@ -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) } diff --git a/core6502/operations.go b/core6502/operations.go index e0d9076..ecc2fe8 100644 --- a/core6502/operations.go +++ b/core6502/operations.go @@ -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) {