• Please review our updated Terms and Rules here

Intel 8080 CPU emulator: need help finding bug(s)

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
Hi all, VERY long time since I've posted here. I see a lot of both old and new names on the VCF! This isnt about programming FOR a vintage computer, but I didn't know where else to post this.

As the title says, I think I need some help tracking down a bug in an 8080 emulator that I've been writing in C over the last couple of days. I wrote it from scratch based on Intel documentation. I've never used this CPU and wasn't really familiar with it other than it being thr 8086's predecessor.

This emulator mostly seems to work, but there is clearly some issue with it. If I run the "8080 instruction exerciser" in the emulator, here are my results:

Code:
8080 instruction exerciser (KR580VM80A CPU)
dad <b,d,h,sp>................  ERROR **** crc expected:14474ba6 found:33b6a681
aluop nn......................  ERROR **** crc expected:9e922f9e found:284aecbe
aluop <b,c,d,e,h,l,m,a>.......  ERROR **** crc expected:cf762c86 found:0c2144eb
<daa,cma,stc,cmc>.............  ERROR **** crc expected:bb3f030c found:797efb2b
<inr,dcr> a...................  ERROR **** crc expected:adb6460e found:0e5332db
<inr,dcr> b...................  ERROR **** crc expected:83ed1345 found:9fc94769
<inx,dcx> b...................  ERROR **** crc expected:f79287cd found:eb7d1a2b
<inr,dcr> c...................  ERROR **** crc expected:e5f6721b found:1695262e
<inr,dcr> d...................  ERROR **** crc expected:15b5579a found:d594aa97
<inx,dcx> d...................  ERROR **** crc expected:7f4e2501 found:63a1b8e7
<inr,dcr> e...................  ERROR **** crc expected:cf2ab396 found:2b639ce1
<inr,dcr> h...................  ERROR **** crc expected:12b2952c found:9bee5682
<inx,dcx> h...................  ERROR **** crc expected:9f2b23c0 found:83c4be26
<inr,dcr> l...................  ERROR **** crc expected:ff57d356 found:1d476ec3
<inr,dcr> m...................  ERROR **** crc expected:92e963bd found:28f7092b
<inx,dcx> sp..................  ERROR **** crc expected:d5702fab found:c99fb24d
lhld nnnn.....................  ERROR **** crc expected:a9c3d5cb found:6d1eeb35
shld nnnn.....................  ERROR **** crc expected:e8864f26 found:2c5b71d8
lxi <b,d,h,sp>,nnnn...........  OK
ldax <b,d>....................  ERROR **** crc expected:2b821d5f found:06cfc034
mvi <b,c,d,e,h,l,m,a>,nn......  OK
mov <bcdehla>,<bcdehla>.......  ERROR **** crc expected:10b58cee found:dfe39de0
sta nnnn / lda nnnn...........  ERROR **** crc expected:ed57af72 found:c01a7219
<rlc,rrc,ral,rar>.............  ERROR **** crc expected:e0d89235 found:4bae6af9
stax <b,d>....................  ERROR **** crc expected:2b0471e9 found:b726a433
Tests complete

The fact that there are apparently errors in SO MANY opcodes leads me to believe that the bug has something to do with a common piece of code used by some or many of them. Perhaps something like decoding register fields or the like. Although, I've already tried to find issues there, and I'm not able to see one. Either that, or it's a problem in an opcode that the test software uses to calculate the CRC of the results. Unfortunately, I can't find the source code to this test software. Or maybe it's an issue with flag calculation(s)?? Could be so many things, that's the hard part about writing CPU emulators, the debugging!

Here is the source code: https://pastebin.com/mweNgfae (Note: I need to clean it up a bit, and it doesn't have cycle timing implemented yet)

It DOES run Space Invaders, but there is a bug there where rows of enemies don't get cleared from the screen at the top as they move down the play field as you can see below. Maybe this will help someone. Thanks for any help you guys can provide. I think I need a fresh set of eyes on this.

k74TFt6.png
 
The most common issue is with flags. Pay particular attention to the parity and carry flags.

There have been tons of 8080 emulators written (I've written a couple), so it shouldn't be difficult to compare your code with other folks.

What's useful is a "stimulator" for your emulator. Basically, you run a sample instruction mix paying attention to end cases and look at the register file and flags after each instruction. Something will certainly stick out like a sore thumb.

For example (INX/DCX don't affect any flags; INR, DCR don't affect carry...etc.)
 
Why not write some code your self. It shouldn't take much to cause the error. After each instruction print the result and the flags. Like Chuck says, it seems to fail everything so it shouldn't take much to find the issue. Try to write code that uses each of the flags, both changing and remaining the same. Try all the corner cases. You know, just 1 short of carry or 1 over.
Dwight
 
Unfortunately, I can't find the source code to this test software.

Is this what you were trying to find? Don't know if this source would help at all in trying to understand the issue.

github.com/begoon/i8080-core/blob/master/8080EX1.MAC

Looks like the test case table and expected CRC values match your output.

Code:
; add hl,<bc,de,hl,sp> (19,456 cycles)
add16:	db	0ffh		; flag mask
	tstr	9,0c4a5h,0c4c7h,0d226h,0a050h,058eah,08566h,0c6h,0deh,09bc9h
	tstr	030h,0,0,0,0f821h,0,0,0,0,0		; (512 cycles)
	tstr	0,0,0,0,-1,-1,-1,0d7h,0,-1		; (38 cycles)
	db	014h, 047h, 04bh, 0a6h			; expected crc
	tmsg	'dad <b,d,h,sp>'

; aluop a,nn (28,672 cycles)
alu8i:	db	0ffh		; flag mask
	tstr	0c6h,09140h,07e3ch,07a67h,0df6dh,05b61h,00b29h,010h,066h,085b2h
	tstr	038h,0,0,0,0,0,0,0,-1,0			; (2048 cycles)
	tstr	<0,-1>,0,0,0,0,0,0,0d7h,0,0		; (14 cycles)
	db	09eh, 092h, 02fh, 09eh			; expected crc
	tmsg	'aluop nn'

; aluop a,<b,c,d,e,h,l,(hl),a> (753,664 cycles)
alu8r:	db	0ffh		; flag mask
	tstr	080h,0c53eh,0573ah,04c4dh,msbt,0e309h,0a666h,0d0h,03bh,0adbbh
	tstr	03fh,0,0,0,0,0,0,0,-1,0			; (16,384 cycles)
	tstr	0,0ffh,0,0,0,-1,-1,0d7h,0,0		; (46 cycles)
	db	0cfh, 076h, 02ch, 086h			; expected crc
	tmsg	'aluop <b,c,d,e,h,l,m,a>'

; <daa,cpl,scf,ccf>
daa:	db	0ffh		; flag mask
	tstr	027h,02141h,009fah,01d60h,0a559h,08d5bh,09079h,004h,08eh,0299dh
	tstr	018h,0,0,0,0,0,0,0d7h,-1,0		; (65,536 cycles)
	tstr	0,0,0,0,0,0,0,0,0,0			; (1 cycle)
	db	0bbh,03fh,003h,00ch			; expected crc
	tmsg	'<daa,cma,stc,cmc>'

; <inc,dec> a (3072 cycles)
inca:	db	0ffh		; flag mask
	tstr	03ch,04adfh,0d5d8h,0e598h,08a2bh,0a7b0h,0431bh,044h,05ah,0d030h
	tstr	001h,0,0,0,0,0,0,0,-1,0			; (512 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	0adh,0b6h,046h,00eh			; expected crc
	tmsg	'<inr,dcr> a'

; <inc,dec> b (3072 cycles)
incb:	db	0ffh		; flag mask
	tstr	004h,0d623h,0432dh,07a61h,08180h,05a86h,01e85h,086h,058h,09bbbh
	tstr	001h,0,0,0,0,0,0ff00h,0,0,0		; (512 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	083h,0edh,013h,045h			; expected crc
	tmsg	'<inr,dcr> b'

; <inc,dec> bc (1536 cycles)
incbc:	db	0ffh		; flag mask
	tstr	003h,0cd97h,044abh,08dc9h,0e3e3h,011cch,0e8a4h,002h,049h,02a4dh
	tstr	008h,0,0,0,0,0,0f821h,0,0,0		; (256 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	0f7h,092h,087h,0cdh			; expected crc
	tmsg	'<inx,dcx> b'

; <inc,dec> c (3072 cycles)
incc:	db	0ffh		; flag mask
	tstr	00ch,0d789h,00935h,0055bh,09f85h,08b27h,0d208h,095h,005h,00660h
	tstr	001h,0,0,0,0,0,0ffh,0,0,0		; (512 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	0e5h,0f6h,072h,01bh			; expected crc
	tmsg	'<inr,dcr> c'

; <inc,dec> d (3072 cycles)
incd:	db	0ffh		; flag mask
	tstr	014h,0a0eah,05fbah,065fbh,0981ch,038cch,0debch,043h,05ch,003bdh
	tstr	001h,0,0,0,0,0ff00h,0,0,0,0		; (512 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	015h,0b5h,057h,09ah			; expected crc
	tmsg	'<inr,dcr> d'

; <inc,dec> de (1536 cycles)
incde:	db	0ffh		; flag mask
	tstr	013h,0342eh,0131dh,028c9h,00acah,09967h,03a2eh,092h,0f6h,09d54h
	tstr	008h,0,0,0,0,0f821h,0,0,0,0		; (256 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	07fh,04eh,025h,001h			; expected crc
	tmsg	'<inx,dcx> d'

; <inc,dec> e (3072 cycles)
ince:	db	0ffh		; flag mask
	tstr	01ch,0602fh,04c0dh,02402h,0e2f5h,0a0f4h,0a10ah,013h,032h,05925h
	tstr	001h,0,0,0,0,0ffh,0,0,0,0		; (512 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	0cfh,02ah,0b3h,096h			; expected crc
	tmsg	'<inr,dcr> e'

; <inc,dec> h (3072 cycles)
inch:	db	0ffh		; flag mask
	tstr	024h,01506h,0f2ebh,0e8ddh,0262bh,011a6h,0bc1ah,017h,006h,02818h
	tstr	001h,0,0,0,0ff00h,0,0,0,0,0		; (512 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	012h,0b2h,095h,02ch			; expected crc
	tmsg	'<inr,dcr> h'

; <inc,dec> hl (1536 cycles)
inchl:	db	0ffh		; flag mask
	tstr	023h,0c3f4h,007a5h,01b6dh,04f04h,0e2c2h,0822ah,057h,0e0h,0c3e1h
	tstr	008h,0,0,0,0f821h,0,0,0,0,0		; (256 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	09fh,02bh,023h,0c0h			; expected crc
	tmsg	'<inx,dcx> h'

; <inc,dec> l (3072 cycles)
incl:	db	0ffh		; flag mask
	tstr	02ch,08031h,0a520h,04356h,0b409h,0f4c1h,0dfa2h,0d1h,03ch,03ea2h
	tstr	001h,0,0,0,0ffh,0,0,0,0,0		; (512 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	0ffh,057h,0d3h,056h			; expected crc
	tmsg	'<inr,dcr> l'

; <inc,dec> (hl) (3072 cycles)
incm:	db	0ffh		; flag mask
	tstr	034h,0b856h,00c7ch,0e53eh,msbt,0877eh,0da58h,015h,05ch,01f37h
	tstr	001h,0ffh,0,0,0,0,0,0,0,0		; (512 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	092h,0e9h,063h,0bdh			; expected crc
	tmsg	'<inr,dcr> m'

; <inc,dec> sp (1536 cycles)
incsp:	db	0ffh		; flag mask
	tstr	033h,0346fh,0d482h,0d169h,0deb6h,0a494h,0f476h,053h,002h,0855bh
	tstr	008h,0,0,0,0,0,0,0,0,0f821h		; (256 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	0d5h,070h,02fh,0abh			; expected crc
	tmsg	'<inx,dcx> sp'

; ld hl,(nnnn) (16 cycles)
ld162:	db	0ffh		; flag mask
	tstr	<02ah,low msbt,high msbt>,09863h,07830h,02077h,0b1feh,0b9fah,0abb8h,004h,006h,06015h
	tstr	0,0,0,0,0,0,0,0,0,0			; (1 cycle)
	tstr	0,-1,0,0,0,0,0,0,0,0			; (16 cycles)
	db	0a9h,0c3h,0d5h,0cbh			; expected crc
	tmsg	'lhld nnnn'
	
; ld (nnnn),hl (16 cycles)
ld166:	db	0ffh		; flag mask
	tstr	<022h,low msbt,high msbt>,0d003h,07772h,07f53h,03f72h,064eah,0e180h,010h,02dh,035e9h
	tstr	0,0,0,0,0,0,0,0,0,0			; (1 cycle)
	tstr	0,0,0,0,-1,0,0,0,0,0			; (16 cycles)
	db	0e8h,086h,04fh,026h			; expected crc
	tmsg	'shld nnnn'

; ld <bc,de,hl,sp>,nnnn (64 cycles)
ld16im:	db	0ffh		; flag mask
	tstr	1,05c1ch,02d46h,08eb9h,06078h,074b1h,0b30eh,046h,0d1h,030cch
	tstr	030h,0,0,0,0,0,0,0,0,0			; (4 cycles)
	tstr	<0,0ffh,0ffh>,0,0,0,0,0,0,0,0,0		; (16 cycles)
	db	0fch,0f4h,06eh,012h			; expected crc
	tmsg	'lxi <b,d,h,sp>,nnnn'

; ld a,<(bc),(de)> (44 cycles)
ld8bd:	db	0ffh		; flag mask
	tstr	00ah,0b3a8h,01d2ah,07f8eh,042ach,msbt,msbt,0c6h,0b1h,0ef8eh
	tstr	010h,0,0,0,0,0,0,0,0,0			; (2 cycles)
	tstr	0,0ffh,0,0,0,0,0,0d7h,-1,0		; (22 cycles)
	db	02bh,082h,01dh,05fh			; expected crc
	tmsg	'ldax <b,d>'

; ld <b,c,d,e,h,l,(hl),a>,nn (64 cycles)
ld8im:	db	0ffh		; flag mask
	tstr	6,0c407h,0f49dh,0d13dh,00339h,0de89h,07455h,053h,0c0h,05509h
	tstr	038h,0,0,0,0,0,0,0,0,0			; (8 cycles)
	tstr	0,0,0,0,0,0,0,0,-1,0			; (8 cycles)
	db	0eah,0a7h,020h,044h			; expected crc
	tmsg	'mvi <b,c,d,e,h,l,m,a>,nn'

; ld <b,c,d,e,h,l,a>,<b,c,d,e,h,l,a> (3456 cycles)
ld8rr:	db	0ffh		; flag mask
	tstr	040h,072a4h,0a024h,061ach,msbt,082c7h,0718fh,097h,08fh,0ef8eh
	tstr	03fh,0,0,0,0,0,0,0,0,0			; (64 cycles)
	tstr	0,0ffh,0,0,0,-1,-1,0d7h,-1,0		; (54 cycles)
	db	010h,0b5h,08ch,0eeh			; expected crc
	tmsg	'mov <bcdehla>,<bcdehla>'

; ld a,(nnnn) / ld (nnnn),a (44 cycles)
lda:	db	0ffh		; flag mask
	tstr	<032h,low msbt,high msbt>,0fd68h,0f4ech,044a0h,0b543h,00653h,0cdbah,0d2h,04fh,01fd8h
	tstr	008h,0,0,0,0,0,0,0,0,0			; (2 cycle)
	tstr	0,0ffh,0,0,0,0,0,0d7h,-1,0		; (22 cycles)
	db	0edh,057h,0afh,072h			; expected crc
	tmsg	'sta nnnn / lda nnnn'

; <rlca,rrca,rla,rra> (6144 cycles)
rot8080: db	0ffh		; flag mask
	tstr	7,0cb92h,06d43h,00a90h,0c284h,00c53h,0f50eh,091h,0ebh,040fch
	tstr	018h,0,0,0,0,0,0,0,-1,0			; (1024 cycles)
	tstr	0,0,0,0,0,0,0,0d7h,0,0			; (6 cycles)
	db	0e0h,0d8h,092h,035h			; expected crc
	tmsg	'<rlc,rrc,ral,rar>'

; ld (<bc,de>),a (96 cycles)
stabd:	db	0ffh		; flag mask
	tstr	2,00c3bh,0b592h,06cffh,0959eh,msbt,msbt+1,0c1h,021h,0bde7h
	tstr	018h,0,0,0,0,0,0,0,0,0			; (4 cycles)
	tstr	0,-1,0,0,0,0,0,0,-1,0			; (24 cycles)
	db	02bh,004h,071h,0e9h			; expected crc
	tmsg	'stax <b,d>'
 
+1 for Chuck's post regarding the flag setting code. I have written a number of emulators also (some of which are in commercial products) - and this is generally where the 'fun' occurs.

It also doesn't help matters that the manufacturer's data sheets are not necessarily correct either...

I generally start off with 2 or 3 copies of the instruction set and do a 'paperwork' excercise to see what is similar and what is different.

Beware, however, that one document (e.g. a book) may already have used one of your sources as its reference...

If you have written this emulator (and qdos to you for doing so) I would check your source with the source for MAME and SIMH to see if there are differences...

I am currently working on an 8008 emulator in javascript - but have found some of the few emulators out there already do not fully implement the instruction set correctly. For eample, the 8008 has 3 HLT instructions - only one is emulated - and the code I am trying to run uses one of the 'other' implementations. It also doesn't support the RST instruction (which is used heavily in the application I am writing the emulator for). As a result, I can't trust the emulator I have downloaded - so I am starting again myself. Using various C/C++ examples as a cross-reference for my work.

Good luck.

Dave
 
+1 for Chuck's post regarding the flag setting code. I have written a number of emulators also (some of which are in commercial products) - and this is generally where the 'fun' occurs.

It also doesn't help matters that the manufacturer's data sheets are not necessarily correct either...

I generally start off with 2 or 3 copies of the instruction set and do a 'paperwork' excercise to see what is similar and what is different.

Beware, however, that one document (e.g. a book) may already have used one of your sources as its reference...

If you have written this emulator (and qdos to you for doing so) I would check your source with the source for MAME and SIMH to see if there are differences...

I am currently working on an 8008 emulator in javascript - but have found some of the few emulators out there already do not fully implement the instruction set correctly. For eample, the 8008 has 3 HLT instructions - only one is emulated - and the code I am trying to run uses one of the 'other' implementations. It also doesn't support the RST instruction (which is used heavily in the application I am writing the emulator for). As a result, I can't trust the emulator I have downloaded - so I am starting again myself. Using various C/C++ examples as a cross-reference for my work.

Good luck.

Dave

Are we changing tracks or is it the 8080 and the 8008 is a typo?
Dwight
 
I recall running this test while developing the CPU emulation for the Altair 8800 Clone. This program evaluates all 8 bits of the status register, not just the 5 bits that are used, so you'll want to ensure the unused bits in the status register are as follows:


7 6 5 4 3 2 1 0
S Z 0 AC 0 P 1 C


This may cure a lot of your problems. There is also an unusual flag behavior with the ANA instructions (not ANI). AC is set equal to the OR of bit 3 of the two operands. I forget where I found that documented.

Mike
 
There is also an unusual flag behavior with the ANA instructions (not ANI). AC is set equal to the OR of bit 3 of the two operands. I forget where I found that documented.

Found it - here's the quote from the "Intel 8080/8085 Assembly Language Programming Manual"

"There is some difference in the handling of the auxiliary carry flag by the logical AND instructions in the 8080 processor and the 8085 processor. The 8085 logical AND instructions always set the auxiliary flag ON. The 8080 logical AND instructions set the flag to reflect the logical OR of bit 3 of the values involved in the AND operation."

This quote is at the top of page 1-12. Here's a link to the manual: http://bitsavers.trailing-edge.com/...ssembly_Language_Programming_Manual_Nov78.pdf

Mike
 
That's the problem with the diagnostic--it simply takes a CRC of the register file and says "it doesn't match; it's wrong". Try another diagnostic that says "I got this; it should be this". Worst case, you could run the test on real hardware, record the results and then re-run it on your emulator.

Flags error doesn't explain why, for instance, LHLD and SHLD are failing the test--both instructions are flag-neutral.
 
Thanks for the tips everyone! And to gslick for the tester source code link.

deramp5113 - You helped a lot! I was already making sure bit 1 of the flags register was always set, but I wasn't bothering to mask out bits 3 and 5. This helped a LOT! There are still some errors, but they appear to be now just limited to 8-bit ALU operations so this narrows down my scope of debugging a ton.

Now getting this:

Code:
8080 instruction exerciser (KR580VM80A CPU)
dad <b,d,h,sp>................  OK
aluop nn......................  ERROR **** crc expected:9e922f9e found:fd2bdf95
aluop <b,c,d,e,h,l,m,a>.......  ERROR **** crc expected:cf762c86 found:63dcfef6
<daa,cma,stc,cmc>.............  ERROR **** crc expected:bb3f030c found:02e11466
<inr,dcr> a...................  ERROR **** crc expected:adb6460e found:0f15bffe
<inr,dcr> b...................  ERROR **** crc expected:83ed1345 found:adcd6374
<inx,dcx> b...................  OK
<inr,dcr> c...................  ERROR **** crc expected:e5f6721b found:17d3ab0b
<inr,dcr> d...................  ERROR **** crc expected:15b5579a found:e7908e8a
<inx,dcx> d...................  OK
<inr,dcr> e...................  ERROR **** crc expected:cf2ab396 found:1967b8fc
<inr,dcr> h...................  ERROR **** crc expected:12b2952c found:a9ea729f
<inx,dcx> h...................  OK
<inr,dcr> l...................  ERROR **** crc expected:ff57d356 found:1c01e3e6
<inr,dcr> m...................  ERROR **** crc expected:92e963bd found:29b1840e
<inx,dcx> sp..................  OK
lhld nnnn.....................  OK
shld nnnn.....................  OK
lxi <b,d,h,sp>,nnnn...........  OK
ldax <b,d>....................  OK
mvi <b,c,d,e,h,l,m,a>,nn......  OK
mov <bcdehla>,<bcdehla>.......  OK
sta nnnn / lda nnnn...........  OK
<rlc,rrc,ral,rar>.............  OK
stax <b,d>....................  OK
Tests complete

I'll see what I can track down. :)

Chuck(G) - You are absolutely right about the CRC testing. I'll try to get some alternative testing going. And as you can see, masking out the always-zero bits in the flags register made LHLD and SHLD pass along with many others. I also implemented the unusual AC flag behavior for AND, but that didn't make any more tests pass, it just changed some of the failing CRCs. Flags were probably the most painful part of when I wrote an 8086 emulator, I'm remembering that vividly now.

I feel like I'm getting pretty close here. Once I've got this nailed down, I'll probably expand this into a Z80 emulator, which gives me a lot more options for interesting systems it can be used to emulate. It's mainly just old arcade machines that are 8080 that I can see. That and the Altair, of course.
 
No typo. Dwight, I am doing an 8008 emulator.

I just wanted to explain to the OP the fun and games I am having and what to look out for with their 8080 work.

It sounds like you are pretty close now...

Dave
 
That's the problem with the diagnostic--it simply takes a CRC of the register file and says "it doesn't match; it's wrong". Try another diagnostic that says "I got this; it should be this". Worst case, you could run the test on real hardware, record the results and then re-run it on your emulator.

Actually, this test is designed to compare against real silicon. The program was written to 1) generate a set of signatures for a given die version (e.g., manufacturer and die rev), and 2) allow comparison against any given manufacturer and die rev.

The baseline version of 8080EXER has zeros for the "crc expected" values (e.g., see http://altairclone.com/downloads/cpu_tests/8080EXER.PNG). The author had a table of chip/manufacturer versus resulting CRC values at http://www.idb.me.uk/sunhillow/8080.html. The table included CRC signatures of real silicon from Intel, NEC, NS, OKI, TI, etc., and included several Russian versions as well. Unfortunately, it looks like this page is now gone. I should have scraped the page five years ago...

The version of 8080EXER that Mike Chambers found and ran has the "crc expected" values filled in to compare against a KR580VM80A version of the 8080 CPU (Russian 8080 clone). The CRC values shown are the same signatures as the Intel version of the 8080.

Bottom line, if Mike's emulation duplicates the CRC values in the version of 8080EXER he is running, then his emulation is duplicating the CRC values generated by (among others) all Intel versions of the 8080.

Mike
 
More 8080 oddities that will probably wipe out a few more errors:

1) The carry flag is carry for additions, but is "borrow" for subtract and compare operations. This is different than most processors in which carry is carry no matter what.

2) INR, DCR do NOT affect carry

3) ANA, ANI always clears carry

4) ORA, ORI, XRA, XRI always clear carry and AC

5) CMA affects no flags.

6) The "P"arity flag is an odd one. Make sure it is computed for all instructions that set/clear it.

etc., etc. - lots of status flag "special cases" with the 8080

Mike
 
1) The carry flag is carry for additions, but is "borrow" for subtract and compare operations. This is different than most processors in which carry is carry no matter what.


Mike

I think this was because of the troubles they made with the 4004. Subtraction was a pain as you always had to complement the carry between each subtraction.
Dwight
 
Bottom line, if Mike's emulation duplicates the CRC values in the version of 8080EXER he is running, then his emulation is duplicating the CRC values generated by (among others) all Intel versions of the 8080.

I believe that you're missing my point. The problem with the test, as wonderful as it may be, is that it gives a sort of "Your program doesn't work" message--there is no detail, as in "This test expected x, but got y, and the differences are the following"

Without any sort of detail as to the nature of the error, it's going to keep Mke guessing a lot.
 
Without any sort of detail as to the nature of the error, it's going to keep Mke guessing a lot.

Gotcha - makes sense.

There are a couple of other tests here http://altairclone.com/downloads/cpu_tests/ in addition the 8080EXER program that work in a manner more like you're talking about. However, neither "CPUTEST" or "TST8080" gives great error messages either. TST8080 does give an address of where a failure occurred so you can then look at the TST8080 listing file and see what type of instruction failed.

Of these three CPU tests, the 8080EXER caught subtle problems that the others missed. And 8080EXER does break the test down into 25 different instruction categories, so at least you have an idea where to look. As Mike is finding already, just a few changes can rapidly eat away at the bug list :)

Mike
 
Last edited:
I believe that you're missing my point. The problem with the test, as wonderful as it may be, is that it gives a sort of "Your program doesn't work" message--there is no detail, as in "This test expected x, but got y, and the differences are the following"

Without any sort of detail as to the nature of the error, it's going to keep Mke guessing a lot.

The source code for the 8080EX1 test admits that it isn't designed to pinpoint the exact error, only to point out that errors exist, and the pinpointing is left as an exercise for the user:

Code:
; This program is designed to detect differences between
; implementations and is not ideal for diagnosing the causes of any
; discrepancies.  However, provided a reference implementation (or
; real system) is available, a failing test case can be isolated by
; hand using a binary search of the test space.

In reality through as the comment points out, if you do have access to a reference system which passes the test along with the system which has errors, and access to the source code for the test and can rebuild it, it seems like it shouldn't be too hard to run instrumented versions of the test side by side on the two platforms and find out where they first diverge. If someone is capable of writing an emulator in the first place, how much more difficult can that be? Time consuming probably, difficult no.

From a very quick look at the test source code, maybe I would start by instrumenting the test to log the single byte new value input to the updcrc routine, run the test side by side on the two platforms, and inspect the logs to find where the input values first differ. I suppose a counter would also be need to added which corresponds to the instance of the updcrc call and a mechanism to break on that count when the test is run again to examine the last test instruction sequence that was executed.
 
I've got it to the point where the Microcosm Associates diag v1.0 passes, but all other tests are still failing. It also appears to run Tiny Basic correctly when I added a simple UART. Still a lot of debugging to do though. Space Invaders still has issues. You guys have been a ton of help so far.

Code:
O:\dev\i8080\Release>i8080.exe tinybasic2dms.bin
TINY BASIC

OK
>10 PRINT "Hi there!"
>20 FOR N = 1 TO 25
>30 PRINT N
>40 NEXT N
>LIST
  10 PRINT "Hi there!"
  20 FOR N = 1 TO 25
  30 PRINT N
  40 NEXT N

OK
>RUN
Hi there!
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

OK
>
 
Bonus fun after I got tired of debugging for the night. :eek:

The XT runs it more than fast enough for Tiny Basic. Probably would be acceptable for running most old CP/M-80 programs actually. After I squash the bugs, I'd like to write a streamlined asm version and see how fast I can get it. Jump table for ops, map 8080 ops as directly to 8086 ops as I can, use 8086's existing flag calcs when possible, keep 8080 registers in the 8086 registers as much as possible, etc.

Excuse the mess.

ItqxuZv.jpg
 
Last edited:
No typo. Dwight, I am doing an 8008 emulator.

I just wanted to explain to the OP the fun and games I am having and what to look out for with their 8080 work.

It sounds like you are pretty close now...

Dave

What are you planning on doing with the 8008 emulator? Just curious.
 
Back
Top