Some undocumented NOPs for 6502
This commit is contained in:
parent
2a7cf020ae
commit
76f9ae514e
|
@ -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
|
- Single file executable with embedded ROMs and DOS 3.3
|
||||||
- Pause (thanks a2geek)
|
- Pause (thanks a2geek)
|
||||||
- Passes the [A2AUDIT 1.06](https://github.com/zellyn/a2audit) tests as II+, //e, and //e Enhanced.
|
- 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:
|
By default the following configuration is launched:
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,19 @@
|
||||||
package core6502
|
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 (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -7,6 +21,9 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ProcessorTestsEnable = false
|
||||||
|
var ProcessorTestsPath = "/home/casa/code/ProcessorTests/"
|
||||||
|
|
||||||
type scenarioState struct {
|
type scenarioState struct {
|
||||||
Pc uint16
|
Pc uint16
|
||||||
S uint8
|
S uint8
|
||||||
|
@ -24,16 +41,14 @@ type scenario struct {
|
||||||
Cycles [][]interface{}
|
Cycles [][]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Tests from https://github.com/TomHarte/ProcessorTests/tree/main/6502/v1
|
|
||||||
more work needed.
|
|
||||||
*/
|
|
||||||
func TestHarteNMOS6502(t *testing.T) {
|
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
|
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++ {
|
for i := 0x00; i <= 0xff; i++ {
|
||||||
mnemonic := s.opcodes[i].name
|
mnemonic := s.opcodes[i].name
|
||||||
if mnemonic != "" {
|
if mnemonic != "" {
|
||||||
|
@ -54,11 +69,13 @@ func TestHarteNMOS6502(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHarteCMOS65c02(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
|
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++ {
|
for i := 0x00; i <= 0xff; i++ {
|
||||||
mnemonic := s.opcodes[i].name
|
mnemonic := s.opcodes[i].name
|
||||||
opcode := fmt.Sprintf("%02x", i)
|
opcode := fmt.Sprintf("%02x", i)
|
||||||
|
|
|
@ -182,8 +182,51 @@ var opcodesNMOS6502 = [256]opcode{
|
||||||
|
|
||||||
0xEA: {"NOP", 1, 2, modeImplicit, opNOP},
|
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
|
Undocumented opcodes,
|
||||||
0xC2: {"NOP", 2, 2, modeImplicit, opNOP},
|
see http://bbc.nvg.org/doc/6502OpList.txt
|
||||||
0x02: {"NOP", 1, 3, modeImplicit, opHALT},
|
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},
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,16 +181,14 @@ 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.updateFlagZN(truncated)
|
|
||||||
s.reg.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
|
|
||||||
} else {
|
} else {
|
||||||
s.reg.setA(truncated)
|
s.reg.setA(truncated)
|
||||||
s.reg.updateFlag(flagC, total > 0xFF)
|
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?
|
// 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) {
|
func opADCAlt(s *State, line []uint8, opcode opcode) {
|
||||||
|
|
Loading…
Reference in New Issue