C64 Emulator Test Suite - Public Domain, no Copyright https://github.com/mattgodbolt/jsbeeb/blob/master/tests/suite/cbm-hackers-post.md The purpose of the C64 Emulator Test Suite is - to help C64 emulator authors improve the compatibility - ensure that updated emulators have no new bugs in old code parts The suite are a few hundred C64 programs which check the details of the C64 they are running on. The suite runs automated and stops only if it has detected an error. That the suite doesn't stop on my C64-I/PAL proves that the suite has no bugs. That the same suite doesn't stop on an emulator proves that this particular emulator is compatible to my C64 regarding every tested detail. Of course, the emulator may still have bugs in parts which are not tested by the suite. There may also be a difference between your C64 and my C64. While the Test Suite is running, the Datasette should be disconnected. Needs about 80 min to complete. The source code has been developed with MACRO(SS)ASS+ by Wolfram Roemhild. The file TEMPLATE.ASM provides a starting point for adding new tests to the suite. /////////////////////////////////////////////////////////////////////////////// Program _START - some 6510 basic commands, just as an insurance /////////////////////////////////////////////////////////////////////////////// Programs LDAb to SBCb(EB) - 6510 command function addressing modes ----------------------------------- n none (implied and accu) b byte (immediate) w word (absolute for JMP and JSR) z zero page zx zero page,x zy zero page,y a absolute ax absolute,x ay absolute,y i indirect (JMP) ix (indirect,x) iy (indirect),y r relative Display: before data accu xreg yreg flags sp after data accu xreg yreg flags sp right data accu xreg yreg flags sp Either press STOP or any other key to continue. All 256 opcodes are tested except HLTn (02 12 22 32 42 52 62 72 92 B2 D2 F2). Indexed addressing modes count the index registers from 00 to FF. JMPi (xxFF) is tested. Single operand commands: 256 data combinations from 00 to FF multiplied by 256 flag combinations. Two operand commands: 256 data combinations 00/00, 00/11, ... FF/EE, FF/FF multiplied by 256 flag combinations. ANEb, LASay, SHAay, SHAiy, SHXay, SHYax and SHSay are executed only in the y border. These commands cause unpredictable results when a DMA comes between the command byte and the operand. SHAay, SHAiy, SHXay, SHYax and SHSay are tested on a data address xxFF only. When the hibyte of the indexed address needs adjustment, these commands will write to different locations, depending on the data written. /////////////////////////////////////////////////////////////////////////////// Programs TRAP* - 6510 IO traps, page boundaries and wrap arounds # code data zd zptr aspect tested ----------------------------------------------------------------------------- 1 2800 29C0 F7 F7/F8 basic functionality 2 2FFE 29C0 F7 F7/F8 4k boundary within 3 byte commands 3 2FFF 29C0 F7 F7/F8 4k boundary within 2 and 3 byte commands 4 D000 29C0 F7 F7/F8 IO traps for code fetch 5 CFFE 29C0 F7 F7/F8 RAM/IO boundary within 3 byte commands 6 CFFF 29C0 F7 F7/F8 RAM/IO boundary within 2 and 3 byte commands 7 2800 D0C0 F7 F7/F8 IO traps for 16 bit data access 8 2800 D000 F7 F7/F8 IO trap adjustment in ax, ay and iy addressing 9 2800 29C0 02 F7/F8 wrap around in zx and zy addressing 10 2800 29C0 00 F7/F8 IO traps for 8 bit data access 11 2800 29C0 F7 02/03 wrap around in ix addressing 12 2800 29C0 F7 FF/00 wrap around and IO trap for pointer accesses 13 2800 0002 F7 F7/F8 64k wrap around in ax, ay and iy addressing 14 2800 0000 F7 F7/F8 64k wrap around plus IO trap 15 CFFF D0C6 00 FF/00 1-14 all together as a stress test 16 FFFE ---- -- --/-- 64k boundary within 3 byte commands 17 FFFF ---- -- --/-- 64k boundary within 2 and 3 byte commands In the programs TRAP16 and TRAP17, the locations of data, zerodata and zeroptr depend on the addressing mode. The CPU port at 00/01 is not able to hold all 256 bit combinations. The datasette may not be connected while TRAP16 and TRAP17 are running! Display: after data accu xreg yreg flags right data accu xreg yreg flags If all displayed values match, some other aspect is wrong, e.g. the stack pointer or data on stack. All 256 commands are tested except HLTn. Registers before: data 1B (00 01 10 11) accu C6 (11 00 01 10) xreg B1 (10 11 00 01) yreg 6C (01 10 11 00) flags 00 sptr not initialized, typically F8 The code length is 6 bytes maximum (SHSay). When the lowbyte of the data address is less than C0, SHAay, SHAiy, SHXay, SHYax and SHSay aren't tested. Those commands don't handle the address adjustment correctly. Relative jumps are tested in 4 combinations: offset 01 no jump, offset 01 jump, offset 80 no jump, offset 80 jump. For the offset 80, a RTS is written to the location at code - 7E. /////////////////////////////////////////////////////////////////////////////// Program BRANCHWRAP - Forward branches from FFxx to 00xx Backward branches from 00xx to FFxx were already tested in TRAP16 and TRAP17. /////////////////////////////////////////////////////////////////////////////// Program MMUFETCH - 6510 code fetching while memory configuration changes An example is the code sequence LDA #$37 : STA 1 : BRK in RAM at Axxx. Because STA 1 maps the Basic ROM, the BRK will never get executed. addr sequence --------------------- A4DF RAM-Basic-RAM B828 RAM-Basic-RAM EA77 RAM-Kernal-RAM FD25 RAM-Kernal-RAM D400 RAM-Charset-RAM D000 RAM-IO-RAM The sequence IO-Charset-IO is not tested because I didn't find some appropriate code bytes in the Charset ROM at D000-D3FF. The SID registers at D4xx are write-only. /////////////////////////////////////////////////////////////////////////////// Program MMU - 6510 port at 00/01 bits 0-2 Display: 0/1=0-7 repeated 6 times: values stored in 0 and 1 after 0 1 A000 E000 D000 IO right 0 1 A000 E000 D000 IO address value meaning ---------------------------------------- A000 94 read Basic, write RAM A000 01 read/write RAM E000 86 read Kernal, write RAM E000 01 read/write RAM D000/IO 3D/02 read Charset, write RAM D000/IO 01/02 read/write RAM D000/IO 00/03 read/write IO /////////////////////////////////////////////////////////////////////////////// Program CPUPORT - 6510 port at 00/01 bits 0-7 Display: 0/1=00/FF repeated 6 times: values stored in 0 and 1 after 00 01 right 00 01 The datasette may not be connected while CPUPORT is running! If both values match, the port behaves instable. On my C64, this will only happen when a datasette is connected. /////////////////////////////////////////////////////////////////////////////// Program CPUTIMING - 6510 timing whole commands Display: xx command byte clocks #measured right #2 #1 #2 command or addressing mode -------------------------------------- 2 2 n 2 2 b 3 3 Rz/Wz 5 5 Mz 4 8 Rzx/Rzy/Wzx/Wzy 6 10 Mzx/Mzy 4 4 Ra/Wa 6 6 Ma 4 8 Rax/Ray (same page) 5 9 Rax/Ray (different page) 5 9 Wax/Way 7 11 Max/May 6 8 Rix/Wix 8 10 Mix/Miy 5 7 Riy (same page) 6 8 Riy (different page) 6 8 Wiy 8 10 Miy 2 18 r+00 same page not taken 3 19 r+00 same page taken 3 19 r+7F same page taken 4 20 r+01 different page taken 4 20 r+7F different page taken 3 19 r-03 same page taken 3 19 r-80 same page taken 4 20 r-03 different page taken 4 20 r-80 different page taken 7 7 BRKn 3 3 PHAn/PHPn 4 4 PLAn/PLPn 3 3 JMPw 5 5 JMPi 6 6 JSRw 6 6 RTSn 6 6 RTIn #1 = command execution time without overhead #2 = displayed value including overhead for measurement R/W/M = Read/Write/Modify /////////////////////////////////////////////////////////////////////////////// Programs IRQ and NMI - CPU interrupts within commands Tested are all commands except HLTn. For a command of n cycles, a loop with the interrupt occurring before cycle 1..n is performed. Rax/Ray/Riy addressing is tested with both the same page and a different page. Branches are tested not taken, taken to the same page, and taken to a different page. Display: stack