From 76f9ae514e6d547efa5317477dfeb4994abfa1a1 Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Sun, 26 Sep 2021 18:25:11 +0200 Subject: [PATCH] Some undocumented NOPs for 6502 --- README.md | 1 + core6502/harteSuite_test.go | 33 ++++++++++++++++++------ core6502/nmos6502.go | 51 ++++++++++++++++++++++++++++++++++--- core6502/operations.go | 6 ++--- 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 75b0ec0..91e57ae 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ Portable emulator of an Apple II+ or //e. Written in Go. - Single file executable with embedded ROMs and DOS 3.3 - Pause (thanks a2geek) - Passes the [A2AUDIT 1.06](https://github.com/zellyn/a2audit) tests as II+, //e, and //e Enhanced. + - Partial pass ot the [ProcessorTests](https://github.com/TomHarte/ProcessorTests) for 6502 and 65c02. Failing test 6502/v1/20_55_13; flags N anv V issues with ADC; and missing some undocumented 6502 opcodes. By default the following configuration is launched: diff --git a/core6502/harteSuite_test.go b/core6502/harteSuite_test.go index 9ddc9e4..1a300eb 100644 --- a/core6502/harteSuite_test.go +++ b/core6502/harteSuite_test.go @@ -1,5 +1,19 @@ 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 + + The tests are disabled by defaut because they take long to run + and require a huge download. + To enable them, clone the repo https://github.com/TomHarte/ProcessorTests + and change the variables ProcessorTestsEnable and ProcessorTestsPath. +*/ + import ( "encoding/json" "fmt" @@ -7,6 +21,9 @@ import ( "testing" ) +var ProcessorTestsEnable = false +var ProcessorTestsPath = "/home/casa/code/ProcessorTests/" + type scenarioState struct { Pc uint16 S uint8 @@ -24,16 +41,14 @@ type scenario struct { Cycles [][]interface{} } -/* - Tests from https://github.com/TomHarte/ProcessorTests/tree/main/6502/v1 - more work needed. -*/ func TestHarteNMOS6502(t *testing.T) { - t.Skip("Not ready to be used in CI") + if !ProcessorTestsEnable { + t.Skip("TomHarte/ProcessorTests are not enabled") + } s := NewNMOS6502(nil) // Use to get the opcodes names - path := "/home/casa/code/ProcessorTests/6502/v1/" + path := ProcessorTestsPath + "6502/v1/" for i := 0x00; i <= 0xff; i++ { mnemonic := s.opcodes[i].name if mnemonic != "" { @@ -54,11 +69,13 @@ func TestHarteNMOS6502(t *testing.T) { } func TestHarteCMOS65c02(t *testing.T) { - t.Skip("Not ready to be used in CI") + if !ProcessorTestsEnable { + t.Skip("TomHarte/ProcessorTests are not enabled") + } s := NewCMOS65c02(nil) // Use to get the opcodes names - path := "/home/casa/code/ProcessorTests/wdc65c02/v1/" + path := ProcessorTestsPath + "wdc65c02/v1/" for i := 0x00; i <= 0xff; i++ { mnemonic := s.opcodes[i].name opcode := fmt.Sprintf("%02x", i) diff --git a/core6502/nmos6502.go b/core6502/nmos6502.go index 1b8858c..8060290 100644 --- a/core6502/nmos6502.go +++ b/core6502/nmos6502.go @@ -182,8 +182,51 @@ var opcodesNMOS6502 = [256]opcode{ 0xEA: {"NOP", 1, 2, modeImplicit, opNOP}, - // Undocumented opcodes, see http://bbc.nvg.org/doc/6502OpList.txt - 0x1A: {"NOP", 1, 2, modeImplicit, opNOP}, // INC A in the 65c02 - 0xC2: {"NOP", 2, 2, modeImplicit, opNOP}, - 0x02: {"NOP", 1, 3, modeImplicit, opHALT}, + /* + Undocumented opcodes, + see http://bbc.nvg.org/doc/6502OpList.txt + see https://www.nesdev.com/undocumented_opcodes.txt + */ + 0x1A: {"NOP", 1, 2, modeImplicit, opNOP}, + 0x3A: {"NOP", 1, 2, modeImplicit, opNOP}, + 0x5A: {"NOP", 1, 2, modeImplicit, opNOP}, + 0x7A: {"NOP", 1, 2, modeImplicit, opNOP}, + 0xDA: {"NOP", 1, 2, modeImplicit, opNOP}, + 0xFA: {"NOP", 1, 2, modeImplicit, opNOP}, + + 0x04: {"DOP", 2, 3, modeImplicit, opNOP}, + 0x14: {"DOP", 2, 4, modeImplicit, opNOP}, + 0x34: {"DOP", 2, 4, modeImplicit, opNOP}, + 0x44: {"DOP", 2, 3, modeImplicit, opNOP}, + 0x54: {"DOP", 2, 4, modeImplicit, opNOP}, + 0x64: {"DOP", 2, 3, modeImplicit, opNOP}, + 0x74: {"DOP", 2, 4, modeImplicit, opNOP}, + 0x80: {"DOP", 2, 2, modeImplicit, opNOP}, + 0x82: {"DOP", 2, 2, modeImplicit, opNOP}, + 0x89: {"DOP", 2, 2, modeImplicit, opNOP}, + 0xC2: {"DOP", 2, 2, modeImplicit, opNOP}, + 0xD4: {"DOP", 2, 4, modeImplicit, opNOP}, + 0xE2: {"DOP", 2, 2, modeImplicit, opNOP}, + 0xF4: {"DOP", 2, 4, modeImplicit, opNOP}, + + 0x0C: {"TOP", 3, 3, modeImplicit, opNOP}, + 0x1C: {"TOP", 3, 4, modeImplicit, opNOP}, + 0x3C: {"TOP", 3, 4, modeImplicit, opNOP}, + 0x5C: {"TOP", 3, 4, modeImplicit, opNOP}, + 0x7C: {"TOP", 3, 4, modeImplicit, opNOP}, + 0xDC: {"TOP", 3, 4, modeImplicit, opNOP}, + 0xFC: {"TOP", 3, 4, modeImplicit, opNOP}, + + 0x02: {"KIL", 1, 3, modeImplicit, opHALT}, + 0x12: {"KIL", 1, 3, modeImplicit, opHALT}, + 0x22: {"KIL", 1, 3, modeImplicit, opHALT}, + 0x32: {"KIL", 1, 3, modeImplicit, opHALT}, + 0x42: {"KIL", 1, 3, modeImplicit, opHALT}, + 0x52: {"KIL", 1, 3, modeImplicit, opHALT}, + 0x62: {"KIL", 1, 3, modeImplicit, opHALT}, + 0x72: {"KIL", 1, 3, modeImplicit, opHALT}, + 0x92: {"KIL", 1, 3, modeImplicit, opHALT}, + 0xB2: {"KIL", 1, 3, modeImplicit, opHALT}, + 0xD2: {"KIL", 1, 3, modeImplicit, opHALT}, + 0xF2: {"KIL", 1, 3, modeImplicit, opHALT}, } diff --git a/core6502/operations.go b/core6502/operations.go index f73b60d..e0d9076 100644 --- a/core6502/operations.go +++ b/core6502/operations.go @@ -181,16 +181,14 @@ 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.updateFlagZN(truncated) - s.reg.updateFlag(flagV, signedTotal < -128 || signedTotal > 127) } else { s.reg.setA(truncated) s.reg.updateFlag(flagC, total > 0xFF) - s.reg.updateFlagZN(truncated) - s.reg.updateFlag(flagV, signedTotal < -128 || signedTotal > 127) } // ZNV 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) {