I've found a few 8080 CPU test suites available, but they all assume CP/M or a similar OS is already present and running - they call BDOS for I/O, etc. I'm working towards being able to run CP/M on my 8080 emulator, but for the moment, I'm looking for something that's just going to put the emulated CPU through its paces and output the results.
-
This queststion is way to be broad to be answered in a consitent fashion. You may want to specify what exactly you're looking for. Never the less, go ahead like with any other software project. So setup a test case for each function in detail and combined cases - here this may mean for each instruction, which seams like an acceptable effort. Also keep in mind, that test suites for real hardware may look for different issues here. – Raffzahn Mar 15 '19 at 20:50
-
1How will you output without calling an output routine? You could probably write a small "can output only" CP/M subset rather quickly. – Thorbjørn Ravn Andersen Mar 16 '19 at 0:49
-
@Raffzahn I don't think it is way to broad. As somebody who has written a Z80 emulator, I know exactly what he wants. – JeremyP Mar 16 '19 at 10:33
-
1Well, @JeremyP, I've writen more than just one emulator (4004, /360, 2650, 8085, Z80, 6502, 9900, 8086 pick your favourite:)), and to me this question is way to broad, as it fails to tell anything about the test setup the suite is needed, not what goals are to be reached, or at least what tests are required. Just testing isn't a value in itself. – Raffzahn Mar 16 '19 at 19:46
-
1@Raffzahn Well just because you can't grok the intent of the question doesn't mean it can't be grokked. It was obvious to me (and Tommy) that he wanted something like ZEXALL that would run on a bare machine. I mean, you've written enough emulators, isn't that what you always want. – JeremyP Mar 18 '19 at 9:42
I'm actually not aware of any major 8080 test suites; everything I've ever found has been for the Z80 rather than its parent.
That aside, I'd heavily suggest you don't discard the CP/M solutions you've found as they're usually pretty trivial to set up as test cases without any of the main substance of a CP/M environment.
For example, to run the CP/M version of Zexall all you need to do is this:
- give your z80 or 8080 64kb of RAM;
- load the raw bytes included in zexall.com to address
0x0100
; - put a RET (opcode
0xc9
) at address0x0005
; - whenever the CPU hits
0x0005
, check what's in theC
register, and:- if it's
9
then output a string starting from the address inDE
until you find a$
character; - if it's
2
then output the single character inE
;
- if it's
- set the PC to
0x0100
and let it run until the stack fully unwinds.
Then check your accumulated text output against that you accumulated during a passing run for a pass or fail; use your human judgment until you get to your first passing run.
So what you've effectively done is implement exactly two of the calls exposed via CP/M's CALL 5
interface, both of which just to append text to a buffer. And that's everything that zexall requires.
Otherwise: FUSE, the Spectrum emulator, provides tests for everything the Z80 does, in an ad hoc text format. I've transcribed those to JSON so that you don't have to write a parser. The full set of files including the original licence is here on Github.
Parse tests.in.json, and you'll get an array of initial CPU states plus bytes to put into memory. Parse tests.expected.json and you'll see both expected bus activity and the expected final state. Within the output there's a value, "tStates" that tells you how many cycles to run for to verify that the initial state turns into the final state.
The counts are in Z80 cycles so there may be some differences there, but most of the tests are very simple — they're just the one or two opcodes long. So you should be able to ignore the tests for opcodes the 8080 doesn't have, and the values for registers that the 8080 doesn't have, and just run until either the PC exits the data you loaded or you hit the expected final state.
-
1This is pretty much exactly what I did to make ZEXALL run on my Z80 emulator. – JeremyP Mar 16 '19 at 10:38
-
I did pretty much this solution: I replaced the call to 0005 (BDOS entry) with a simple OUT, so I could see the character output for the error code. I was able to fix one bug that way, and already passed all the tests in that test suite. – Charles Mangin Mar 17 '19 at 14:16
-
1@CharlesMangin: One could use a hybrid of the two approaches, using an 8080 machine-code routine to either output the value in E, or fetch bytes from (DE) and output them to e.g. I/O address zero until it finds a "$". – supercat Mar 20 '19 at 18:08
You can find some Intel 8080 CPU tests on this website. These can be run with no OS, just a minimal support framework described below:
These binaries should be loaded to memory starting at 0x0100, and at startup, your CPU should jump to 0x0100. You should also put two handlers at addresses 0x0000 and 0x0005:
The handler at 0x0000 signals the end of the test run.
The handler at 0x0005 is used to communicate the values of the registers
C
,D
andE
with the outside world. RegisterC
selects from multiple functions:C
= 0x02 signals printing the value of registerE
as an ASCII valueC
= 0x09 signals printing the value of memory pointed to byDE
until a'$'
character is encountered
The easiest is to put an OUT
instruction at 0x0000
onwards, and an IN
followed by a RET
at 0x0005
onwards, and then set your emulator to do the right thing on port writes / reads.
I have implemented this protocol in a testbench for an FPGA Intel 8080 implementation inspired by a software emulator test suite; both of these could be useful references for you in implementing the scaffolding necessary to run these CPU tests without any complicated OS, or even any computer, around your CPU.
-
1It probably can’t just be
IN
followed byRET
at address 5, as CP/M ABI requires the top of program memory to reside at address 6. MS-DOS took some pains to replicate this ABI: os2museum.com/wp/who-needs-the-address-wraparound-anyway – user3840170 Nov 6 '20 at 15:58 -
1@user3840170 - if the test programs never use this fact, then this won't be a problem. The idea isn't to support arbitrary CP/M programs, but rather to specifically allow one particular set of programs to run in as simple a fashion as possible. I'm not sure why specifically an
IN
instruction is most useful here (I'd personally prefer to useHLT
at address 0 andOUT
at address 5, assuming the tests don't use the former as that would require specific hardware support) but I see no reason it wouldn't work. – occipita Nov 7 '20 at 6:50 -
The only reason I initially used an
IN
instead of aHLT
was because that's what the code at github.com/superzazu/8080 used. I have since moved on toHLT
andOUT
. – Cactus Nov 7 '20 at 7:22