Fix V flag on ADC for BCD
This commit is contained in:
parent
76f9ae514e
commit
71fd530e26
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue