z80test: LDIR->NOP'

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
SkoolKid
Manic Miner
Posts: 407
Joined: Wed Nov 15, 2017 3:07 pm

z80test: LDIR->NOP'

Post by SkoolKid »

Test 089 in Patrik Rak's z80test suite (v1.2) is named LDIR->NOP', and tests the LDIR instruction (EDB0) overwriting itself so that it becomes ED00 (effectively NOP).

Does anyone know how LDIR overwriting itself affects the flags (specifically, bits 5 and 3 of F) differently from when LDIR does not overwrite itself? I haven't been able to find any documentation on this phenomenon anywhere. I would normally go to Fuse to figure something like this out, but the version of Fuse I have fails the LDIR->NOP' test, so it's not much use.

Same question goes for tests 090, 102 and 103 too (LDDR->NOP', INIR->NOP', INDR->NOP'), but I'm guessing the solution to the LDIR->NOP' mystery will shed light on those.
SkoolKit - disassemble a game today
Pyskool - a remake of Skool Daze and Back to Skool
User avatar
Einar Saukas
Bugaboo
Posts: 3160
Joined: Wed Nov 15, 2017 2:48 pm

Re: z80test: LDIR->NOP'

Post by Einar Saukas »

SkoolKid wrote: Mon Nov 14, 2022 1:08 am I would normally go to Fuse to figure something like this out, but the version of Fuse I have fails the LDIR->NOP' test, so it's not much use.
Did you try SpecEmu? It's the most accurate emulator.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: z80test: LDIR->NOP'

Post by Ast A. Moore »

SkoolKid wrote: Mon Nov 14, 2022 1:08 am Does anyone know how LDIR overwriting itself affects the flags (specifically, bits 5 and 3 of F) differently from when LDIR does not overwrite itself? I haven't been able to find any documentation on this phenomenon anywhere.
According to Patrik himself:

Code: Select all

flags   s,1,z,1,f5,0,hc,1,f3,0,pv,1,n,1,c,1
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
SkoolKid
Manic Miner
Posts: 407
Joined: Wed Nov 15, 2017 3:07 pm

Re: z80test: LDIR->NOP'

Post by SkoolKid »

Einar Saukas wrote: Mon Nov 14, 2022 12:26 pm Did you try SpecEmu? It's the most accurate emulator.
I don't have any Windows machines to try that on. But if someone can confirm that it passes the LDIR->NOP' test, I'll see if I can get it running via Wine.
SkoolKit - disassemble a game today
Pyskool - a remake of Skool Daze and Back to Skool
User avatar
SkoolKid
Manic Miner
Posts: 407
Joined: Wed Nov 15, 2017 3:07 pm

Re: z80test: LDIR->NOP'

Post by SkoolKid »

Ast A. Moore wrote: Mon Nov 14, 2022 1:23 pm According to Patrik himself:

Code: Select all

flags   s,1,z,1,f5,0,hc,1,f3,0,pv,1,n,1,c,1
I think that tells us that all the officially documented flags (i.e. s, z, hc, pv, n and c) are affected by the test, but it doesn't tell us how.
SkoolKit - disassemble a game today
Pyskool - a remake of Skool Daze and Back to Skool
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: z80test: LDIR->NOP'

Post by Ast A. Moore »

SkoolKid wrote: Mon Nov 14, 2022 1:33 pm I don't have any Windows machines to try that on. But if someone can confirm that it passes the LDIR->NOP' test, I'll see if I can get it running via Wine.
It runs very well in Wine (or CrossOver, for that matter).
SkoolKid wrote: Mon Nov 14, 2022 1:35 pm I think that tells us that all the officially documented flags (i.e. s, z, hc, pv, n and c) are affected by the test, but it doesn't tell us how.
Hmm. I thought those are the actual expected flag values (i.e. set/reset).

I don’t have the time to go over the source code, so if you tell me the address for the break point(s) you’re interested in, I can run in SpecEmu and post the state of the F register for you.
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
Bedazzle
Manic Miner
Posts: 305
Joined: Sun Mar 24, 2019 9:03 am

Re: z80test: LDIR->NOP'

Post by Bedazzle »

SkoolKid wrote: Mon Nov 14, 2022 1:33 pm I don't have any Windows machines to try that on. But if someone can confirm that it passes the LDIR->NOP' test, I'll see if I can get it running via Wine.
Image

Image
User avatar
SkoolKid
Manic Miner
Posts: 407
Joined: Wed Nov 15, 2017 3:07 pm

Re: z80test: LDIR->NOP'

Post by SkoolKid »

Thanks for doing this test!

Just to be sure, that is the z80full test, right?
SkoolKit - disassemble a game today
Pyskool - a remake of Skool Daze and Back to Skool
User avatar
Bedazzle
Manic Miner
Posts: 305
Joined: Sun Mar 24, 2019 9:03 am

Re: z80test: LDIR->NOP'

Post by Bedazzle »

SkoolKid wrote: Mon Nov 14, 2022 4:42 pm Just to be sure, that is the z80full test, right?
Exactly.
User avatar
SkoolKid
Manic Miner
Posts: 407
Joined: Wed Nov 15, 2017 3:07 pm

Re: z80test: LDIR->NOP'

Post by SkoolKid »

I got SpecEmu working via Wine, and I've looked into how it handles the flags register when the second byte of LDIR (EDB0) and INIR (EDB2) is overwritten by itself (with something other than B0/B2 that effectively turns the instruction into a NOP).

LDIR is pretty straightforward: If the new (decremented) value of BC is not 0, bits 5 and 3 of F are always reset.

INIR is not straightforward, though. Bits 5 and 3 of F are always reset, but H (bit 4) and P (bit 2) are affected in a way whose logic escapes me (so far).
SkoolKit - disassemble a game today
Pyskool - a remake of Skool Daze and Back to Skool
AndyC
Dynamite Dan
Posts: 1414
Joined: Mon Nov 13, 2017 5:12 am

Re: z80test: LDIR->NOP'

Post by AndyC »

In theory it should match the logic for when the instruction repeats, since that's effectively what happens (except the "repeated" version is now a NOP instruction)
edjones
Drutt
Posts: 33
Joined: Fri Feb 28, 2020 1:42 pm

Re: z80test: LDIR->NOP'

Post by edjones »

SkoolKid wrote: Tue Nov 15, 2022 9:49 pm INIR is not straightforward, though. Bits 5 and 3 of F are always reset, but H (bit 4) and P (bit 2) are affected in a way whose logic escapes me (so far).
Those bits are bonkers anyway, see http://www.z80.info/zip/z80-documented.pdf !
User avatar
SkoolKid
Manic Miner
Posts: 407
Joined: Wed Nov 15, 2017 3:07 pm

Re: z80test: LDIR->NOP'

Post by SkoolKid »

Ast A. Moore wrote: Mon Nov 14, 2022 3:52 pm It runs very well in Wine (or CrossOver, for that matter).

Hmm. I thought those are the actual expected flag values (i.e. set/reset).

I don’t have the time to go over the source code, so if you tell me the address for the break point(s) you’re interested in, I can run in SpecEmu and post the state of the F register for you.
Do you mean the source code of z80test, or the source code of SpecEmu? If I had the source code of SpecEmu, I'd just go looking for the relevant logic there.

btw, the breakpoint address in z80test would be 33579/$832B (the address of the LDIR/INIR instruction being tested). The relevant inputs in the LDIR->NOP' test are A, (HL) and BC, and for INIR they are F and B. So far I've gone through enough iterations of the LDIR->NOP' test to understand what's going on there, and enough iterations of the INIR->NOP' test to be completely mystified.
SkoolKit - disassemble a game today
Pyskool - a remake of Skool Daze and Back to Skool
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: z80test: LDIR->NOP'

Post by Ast A. Moore »

Yes, I meant the source code of the test. But I see you got SpecEmu up and running already.
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.
beginner
Drutt
Posts: 37
Joined: Sat May 21, 2022 10:23 pm

Re: z80test: LDIR->NOP'

Post by beginner »

Hello @SkoolKid,

I'm not sure if this is what you are looking for but here are a couple of links that might shed some more light on how flags are affected in block instructions:
https://github.com/hoglet67/Z80Decoder/ ... nted-Flags
https://github.com/MrKWatkins/ZXSpectru ... ctionFlags

More detailed comments can also be found in the source code of the flags test:
https://github.com/MrKWatkins/ZXSpectru ... t.asm#L701

If I understand correctly, for all intents and purposes, the LDIR instruction is practically a repeated LDI, until BC reaches 0.
However, LDIR does some extra flag changes when it repeats (BC != 0). These are in addition to the flag changes that are done in a normal LDI, as shown below:

Code: Select all

LDI() {
	...
	HF = reset; 
	PF = set if (BC - 1) != 0; otherwise, it is reset (as described in the official manual).
	NF = reset;
	3F = bit 3 of (copied value+A);  // as described here: https://rk.nvg.ntnu.no/sinclair/faq/tech_z80.html#UNDOC
	5F = bit 5 of (copied value+A);  // as described here: https://rk.nvg.ntnu.no/sinclair/faq/tech_z80.html#UNDOC
}


LDIR {
	LDI();
	if (BC != 0) { 		// perform additional flag changes when the instruction is repeated
		PC -= 2;	// repeat the instruction
		3F = PC.11 	// bit 11 of PC, as described in the links above		
		5F = PC.13	// bit 13 of PC, as described in the links above
	}
}
As far as I know, ED00 will translate to a NONI + NOP (8 T-states, as described here: http://www.z80.info/decoding.htm ) and it will not trigger any flag changes. However, if I understood correctly Patrik's comment from a previous post, it will allow to "break out" of LDIR before it finishes, thus allowing to reveal the values of the intermediate flags (the ones set when BC != 0) instead of the final flags (the ones set by the "normal" LDI() part of LDIR).

LDIR/LDDR/CPIR/CPDR pretty much modify the same flags when they repeat (BC != 0).

The same principle applies to the I/O block instructions. However, when repeating, in addition to the 3F and 5F flags they also modify HF and PF. Description of how HF and PF are computed in these cases can be found in the links above.

More info is also available in the following thread: viewtopic.php?t=6102 .

Hope this helps :)

Cheers!
User avatar
SkoolKid
Manic Miner
Posts: 407
Joined: Wed Nov 15, 2017 3:07 pm

Re: z80test: LDIR->NOP'

Post by SkoolKid »

the.beginner wrote: Wed Nov 16, 2022 4:00 pm Hope this helps :)
Yes, it does - it's exactly the information I was looking for. Thank you!

Now to get SkoolKit's Z80 instruction set simulator passing the LDIR/LDDR->NOP' and INIR/INDR->NOP' tests...
SkoolKit - disassemble a game today
Pyskool - a remake of Skool Daze and Back to Skool
beginner
Drutt
Posts: 37
Joined: Sat May 21, 2022 10:23 pm

Re: z80test: LDIR->NOP'

Post by beginner »

I just noticed I made a small mistake in my previous post. Here it is, just in case somebody stumbles on this in the future:

LDI()

Code: Select all

		5F = bit 5 of (copied value+A);
should be

Code: Select all

		5F = bit 1 of (copied value+A);
Post Reply