Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Struggling with Fuse or trying to find an emulator with a specific feature. Ask your questions here.
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

Peter Helcmanovsky (aka Ped7g) has written a very professional test for the "recently" discovered behavior of the block instructions of the Z80. Currently, some emulator authors have added support for this to their Z80 cores.

The test checks the flags of the Z80 CPU after executing block instructions, which David Banks (aka Hoglet) found to behave differently to what was previously documented by Sean Young, when the condition is met and those instructions are repeated.

Click on the links to go to the original sources of the research and the resulting documentation.

This test has been run on real hardware confirming the results of David Banks' research:

Machine: ZX Spectrum 48K (Issue 4S)
CPU model: Zilog Z8400A PS (NMOS)
Test version: 2.0

Image

Machine: ZX Spectrum +
CPU model: SGS Z8400AB1 (NMOS)
Test version: 4.0

Image

In order to pass the test, the ZX Spectrum emulator must return 0 when the CPU reads the port of the Kempston joystick:

Code: Select all

if (0x001F == (port & 0x00FF)) return 0;
The source code can be downloaded here, and the assembled cassette image in TAP format here.

Many thanks to arjun and evolutional for for validating the results on real hardware.

Happy hacking!
Last edited by ZjoyKiLer on Sun Jan 02, 2022 8:01 pm, edited 2 times in total.
User avatar
Pegaz
Dynamite Dan
Posts: 1210
Joined: Mon Nov 13, 2017 1:44 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Pegaz »

Interesting discovery.
Obviously, theres no emulator, which passes this test, for now.
I've only tested a few, Es.pectrum looks the best so far, although inaccurate values prevail, with all of them...
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

Pegaz wrote: Sun Jan 02, 2022 7:31 pm Interesting discovery.
Obviously, theres no emulator, which passes this test, for now.
I've only tested a few, Es.pectrum looks the best so far, although inaccurate values prevail, with all of them...
There are some:

ZXSEC:
Image

Zero:
Image

evolutional's neccy:
Image

And mine, YUME:
Image

And some others like SpecEmu, Spud, Spin, etc, which will fully emulate this very soon.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Ast A. Moore »

ZjoyKiLer wrote: Sun Jan 02, 2022 7:57 pm
And mine, YUME:
Image
So rare to find a new Spectrum emulator for macOS these days. Is it publicly available? Could I have a copy? ;)
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Weiv
Microbot
Posts: 177
Joined: Fri Apr 06, 2018 5:28 pm
Location: Ukraine

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Weiv »

[mention]ZjoyKiLer[/mention], I suppose this behavior can be actual too for non-automatic block instructions when the interrupt executes after them (LDI,LDD,CPI,CPD,INI,IND,OUTI, OUTD). Did the crew try to verify their behavior too? (Also it's desirable to check what about non-mascable interrupts for full information, but it's much more hard to do, and not so useful).
Last edited by Weiv on Sun Jan 02, 2022 10:58 pm, edited 1 time in total.
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

Ast A. Moore wrote: Sun Jan 02, 2022 10:23 pm
ZjoyKiLer wrote: Sun Jan 02, 2022 7:57 pm
And mine, YUME:
Image
So rare to find a new Spectrum emulator for macOS these days. Is it publicly available? Could I have a copy? ;)
It's a modular multi-system emulator. Currently, it emulates ZX Spectrum, ZX80, ZX81, Master System, NES, Game Boy, Jupiter ACE and Nintendo 64. I will release a beta this year. Initially for macOS only, because macOS UI is more complete. But it works on Windows, Linux (Qt), Haiku, Nintendo 3DS and WebAssembly.
Last edited by ZjoyKiLer on Sun Jan 02, 2022 11:04 pm, edited 1 time in total.
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

Weiv wrote: Sun Jan 02, 2022 10:54 pm @ZjoyKiLer, I suppose this behavior can be actual too for non-automatic block instructions when the interrupt executes after them (LDI,LDD,CPI,CPD,INI,IND,OUTI, OUTD). Did the crew try to verify their behavior too? (Also it's desirable to check what about non-mascable interrupts for full information, but it's much more hard to do, and not so useful).
I think Hoglet checked this with NMI too, but I'm not sure, I have to re-read the thread at https://stardot.org.uk.

As for the non-automatic block instructions, I think you are right and it would be a good idea to test them. I will ask and see if that is possible.
Patrik Rak
Microbot
Posts: 117
Joined: Mon Apr 13, 2020 3:07 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Patrik Rak »

Thanks for sharing this. I heard about this some time ago but now with this test it was easy enough to update the ZXDS core to take this into account. Looks like I will have to prepare new versions for both the 3DS and original DS models. :lol:

BTW, the logic of the flags after interrupted I/O block instructions can be summarized a little bit more concisely like this:

Code: Select all

byte b = B ;
if ( CF ) {
    b += ( NF ? -1 : 1 ) ;
    HC = ( b ^ B ) ;
}
PV ^= ( b & 7 ) ;
where HF is bit 4 of HC and PF is parity of the value in PV.

Cheers,

Patrik

P.S. BTW, several months ago I have also learned in that Z80 Decoder thread that my Z80 tests accidentally missed the INDR instruction due to cut & paste mistake. I was busy preparing the RZX recording for Christmas ZXDS release, but now I plan update the tests accordingly as soon as I get around to it.
User avatar
Weiv
Microbot
Posts: 177
Joined: Fri Apr 06, 2018 5:28 pm
Location: Ukraine

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Weiv »

Patrik Rak wrote: Mon Jan 03, 2022 5:04 pm

Code: Select all

byte b = B ;
if ( CF ) {
    b += ( NF ? -1 : 1 ) ;
    HC = ( b ^ B ) ;
}
PV ^= ( b & 7 ) ;
where HF is bit 4 of HC and PF is parity of the value in PV.
It seems like you missed something because PV value is not defined before ^= .
Maybe like PV = (PF ^1)<<3;
Thanks.
Last edited by Weiv on Mon Jan 03, 2022 6:36 pm, edited 4 times in total.
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

Patrik Rak wrote: Mon Jan 03, 2022 5:04 pm Thanks for sharing this. I heard about this some time ago but now with this test it was easy enough to update the ZXDS core to take this into account. Looks like I will have to prepare new versions for both the 3DS and original DS models. :lol:

BTW, the logic of the flags after interrupted I/O block instructions can be summarized a little bit more concisely like this:

Code: Select all

byte b = B ;
if ( CF ) {
    b += ( NF ? -1 : 1 ) ;
    HC = ( b ^ B ) ;
}
PV ^= ( b & 7 ) ;
where HF is bit 4 of HC and PF is parity of the value in PV.

Cheers,

Patrik

P.S. BTW, several months ago I have also learned in that Z80 Decoder thread that my Z80 tests accidentally missed the INDR instruction due to cut & paste mistake. I was busy preparing the RZX recording for Christmas ZXDS release, but now I plan update the tests accordingly as soon as I get around to it.
Mmmmm... let me think about it.

We were using the following logic:

Code: Select all

IO is the value written to or read from the I/O port.
Lo is the "output" value of the L register after HL is incremented or decremented.
Bo is the "output" value of the B register after it is decremented.
PCi is the "input" value of the PC register, before it is incremented (address of the first byte of the instruction).

Code: Select all

if instruction == INIR
        T = IO + ((Ci + 1) & 0xFF)
else if instruction == INDR
        T = IO + ((Ci - 1) & 0xFF)
else if (instruction == OTIR) || (instruction == OTDR)
        T = IO + Lo

NF = IO.7
CF = T > 255

if B
        ZF = 0
        SF = Bo.7
        YF = PCi.13
        XF = PCi.11

        if CF
                if IO & 0x80
                        PF = ((T & 7) ^ Bo).parity == ((Bo - 1) & 7).parity
                        HF = !(Bo & 0xF)
                else
                        PF = ((T & 7) ^ Bo).parity == ((Bo + 1) & 7).parity
                        HF = (Bo & 0xF) == 0xF
        else
                PF = ((T & 7) ^ Bo).parity == (Bo & 7).parity

else
        SF = 0
        ZF = 1
        HF = CF
        PF = ((T & 7) ^ Bo).parity
This is my implementation in C:

Code: Select all

#define INXR_OTXR(io)							    \
	if (B)	{							    \
		FLAGS = (zuint8)(	    /* ZF = 0			*/  \
			(B & SF)	  | /* SF = Bo.7		*/  \
			((PC >> 8) & YXF) | /* YF = PCi.13; XF = PCi.11 */  \
			nf		  | /* NF = IO.7		*/  \
			(hcf	?					    \
				CF |					    \
				(io & 0x80				    \
					?				    \
					(!(B & 0xF) << 4) |		    \
					(pf ^ PF_PARITY((B - 1) & 7) ^ PF)  \
					:				    \
					(((B & 0xF) == 0xF) << 4) |	    \
					(pf ^ PF_PARITY((B + 1) & 7) ^ PF)) \
				: pf ^ PF_PARITY(B & 7) ^ PF));		    \
									    \
		return 21;						    \
		}							    \
									    \
	FLAGS = ZF  | /* ZF = 1; SF, YF, XF = 0     */			    \
		hcf | /* HF, CF = T > 255	    */			    \
		pf  | /* PF = ((T & 7) ^ Bo).parity */			    \
		nf;   /* NF = IO.7		    */			    \
									    \
	PC += 2;							    \
	return 16


#define INXR(hl_operator, memptr_operator)			\
	zuint8 in  = IN(BC);					\
	zuint8 nf  = (in >> 6) & NF;				\
	zuint  t   = (zuint)in + (zuint8)(C memptr_operator 1); \
	zuint8 hcf = t > 255 ? HCF : 0;				\
	zuint8 pf;						\
								\
	WRITE(HL hl_operator, in);				\
	MEMPTR = BC memptr_operator 1;				\
	B--;							\
	pf = PF_PARITY((t & 7) ^ B);				\
	INXR_OTXR(in)


#define OTXR(hl_operator, memptr_operator) \
	zuint8 out = READ(HL hl_operator); \
	zuint8 nf  = (out & 128) >> 6;	   \
	zuint  t   = (zuint)out + L;	   \
	zuint8 hcf = t > 255 ? HCF : 0;	   \
	zuint8 pf;			   \
					   \
	B--;				   \
	pf = PF_PARITY((t & 7) ^ B);	   \
	MEMPTR = BC memptr_operator 1;	   \
	OUT(BC, out);			   \
	INXR_OTXR(out)

Code: Select all

INSTRUCTION(inir) {INXR(++, +);}
INSTRUCTION(indr) {INXR(--, -);}
INSTRUCTION(otir) {OTXR(++, +);}
INSTRUCTION(otdr) {OTXR(--, -);}
Patrik Rak
Microbot
Posts: 117
Joined: Mon Apr 13, 2020 3:07 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Patrik Rak »

Weiv wrote: Mon Jan 03, 2022 6:09 pm Maybe like PV = (PF ^1)<<3;
PV contains the value which defined the PF prior that, during the IO instruction itself.

For example, here is my IND implementation:

Code: Select all

#define I_IND                           \
byte b;                                 \
TIIR(1);                                \
MP(BC-1);                               \
TIIN(BC);                               \
b=IN(BC);                               \
B--;                                    \
word bus=HL;                            \
TIW(bus,3);                             \
WB(bus,b);                              \
HL--;                                   \
Z=B;                                    \
UNDOC(S=Z);                             \
UNDOC(N=((b&0x80)>>(7-B_SUB))|F_QBIT);  \
UNDOC(CY=(((byte)(C-1))+b));            \
UNDOC(HC=(CY>>(8-B_HALF)));             \
UNDOC(PV=((CY&7)^B))
Patrik
User avatar
Lethargeek
Manic Miner
Posts: 743
Joined: Wed Dec 11, 2019 6:47 am

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Lethargeek »

what about the situation where LDxR is interrupted by overwriting itself?
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

Lethargeek wrote: Mon Jan 03, 2022 9:48 pm what about the situation where LDxR is interrupted by overwriting itself?
Good point!, We'll try to test it.
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

GitHub repo: https://github.com/MrKWatkins/ZXSpectru ... ctionFlags

Check there for new versions (I will also post them here).
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

We have tried the test in other machines.

Many thanks to [mention]Alone Coder[/mention] and Tolik_Trek.

Machine: ZX Evo
CPU model: Zilog Z84C0010PEC (CMOS)
Test version: 4.0

Image

Machine: Sprinter
CPU model: Z84C1516PSC (CMOS??)
Test version: 4.0

Image

I think we can assume that all Zilog models have the same flag behavior in those instructions.
Patrik Rak
Microbot
Posts: 117
Joined: Mon Apr 13, 2020 3:07 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Patrik Rak »

ZjoyKiLer wrote: Tue Jan 04, 2022 12:20 am GitHub repo: https://github.com/MrKWatkins/ZXSpectru ... ctionFlags
Hmm, looks like the test doesn't cover any of the cases where the half carry flag is set after I/O instructions. Could we have those, too? Both the 15->16 and 16->15 transitions would be appreciated.

Thanks,

Patrik
User avatar
Lethargeek
Manic Miner
Posts: 743
Joined: Wed Dec 11, 2019 6:47 am

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Lethargeek »

ZjoyKiLer wrote: Mon Jan 03, 2022 11:29 pm
Lethargeek wrote: Mon Jan 03, 2022 9:48 pm what about the situation where LDxR is interrupted by overwriting itself?
Good point!, We'll try to test it.
oh, and check INxR as well for the same thing
zx81
Microbot
Posts: 138
Joined: Sat Feb 17, 2018 9:33 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by zx81 »

I've updated JSpeccy to implement the new Z80 "features", HALT & LDxR et al.

I've put a test version on my DropBox: https://www.dropbox.com/s/l9imcrgejwahr ... y.jar?dl=0 (Java 11 as minimum)
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

Patrik Rak wrote: Tue Jan 04, 2022 10:02 am
ZjoyKiLer wrote: Tue Jan 04, 2022 12:20 am GitHub repo: https://github.com/MrKWatkins/ZXSpectru ... ctionFlags
Hmm, looks like the test doesn't cover any of the cases where the half carry flag is set after I/O instructions. Could we have those, too? Both the 15->16 and 16->15 transitions would be appreciated.

Thanks,

Patrik
Ped7g is working on that.
Magnus
Dizzy
Posts: 61
Joined: Sat Jan 06, 2018 6:47 am
Location: Sweden

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Magnus »

Hi!

Strangely, I get this result on my Spectrum+ issue 3B with the SGS Z8400AB1 Z80.

Image.

Maybe this is just a problem with my machine...

Edit: Sorry, my bad. Didn't realize that I needed a Kempston interface connected. Works now!
My ZX Spectrum emulator project: https://softspectrum48.weebly.com.
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

Magnus wrote: Thu Jan 06, 2022 9:05 am Hi!

Strangely, I get this result on my Spectrum+ issue 3B with the SGS Z8400AB1 Z80.

Image.

Maybe this is just a problem with my machine...

Edit: Sorry, my bad. Didn't realize that I needed a Kempston interface connected. Works now!
Thanks for validating the results on real hardware. Will you add support for this to your emulator?
Magnus
Dizzy
Posts: 61
Joined: Sat Jan 06, 2018 6:47 am
Location: Sweden

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Magnus »

ZjoyKiLer wrote: Thu Jan 06, 2022 1:49 pm Thanks for validating the results on real hardware. Will you add support for this to your emulator?
It is done :). Thanks for the information about this behaviour.
My ZX Spectrum emulator project: https://softspectrum48.weebly.com.
User avatar
Lethargeek
Manic Miner
Posts: 743
Joined: Wed Dec 11, 2019 6:47 am

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by Lethargeek »

[mention]ZjoyKiLer[/mention], i suggest also adding CPxR subtests where the match is found, just in case some emulator author checks BC only
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

Lethargeek wrote: Thu Jan 06, 2022 8:37 pm @ZjoyKiLer, i suggest also adding CPxR subtests where the match is found, just in case some emulator author checks BC only
When the match is found the instruction is not repeated, so the flag behavior is as usual. But don't worry, Ped7g is working on full coverage of all possibilities as far as the ZX Spectrum hardware allows. I've commented what you have suggested with him. It will be tested.
User avatar
ZjoyKiLer
Dizzy
Posts: 67
Joined: Thu Sep 09, 2021 3:20 pm

Re: Z80 Block Flags Test for the "recently" discovered behavior of the block instructions of the Z80 CPU

Post by ZjoyKiLer »

[mention]azesmbog[/mention] has replaced the CPU of his Profi with a 80A-CPU MME (a U880 model, NMOS).

This CPU passes the test:

Image
Post Reply