z80test: LDIR->NOP'
z80test: LDIR->NOP'
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.
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.
- Einar Saukas
- Bugaboo
- Posts: 3160
- Joined: Wed Nov 15, 2017 2:48 pm
Re: z80test: LDIR->NOP'
Did you try SpecEmu? It's the most accurate emulator.
- Ast A. Moore
- Rick Dangerous
- Posts: 2641
- Joined: Mon Nov 13, 2017 3:16 pm
Re: z80test: LDIR->NOP'
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.
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.
Re: z80test: LDIR->NOP'
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.Einar Saukas wrote: ↑Mon Nov 14, 2022 12:26 pm Did you try SpecEmu? It's the most accurate emulator.
Re: z80test: LDIR->NOP'
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.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
- Ast A. Moore
- Rick Dangerous
- Posts: 2641
- Joined: Mon Nov 13, 2017 3:16 pm
Re: z80test: LDIR->NOP'
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.
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.
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.
Re: z80test: LDIR->NOP'
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).
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).
Re: z80test: LDIR->NOP'
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)
Re: z80test: LDIR->NOP'
Those bits are bonkers anyway, see http://www.z80.info/zip/z80-documented.pdf !
Re: z80test: LDIR->NOP'
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.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.
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.
- Ast A. Moore
- Rick Dangerous
- Posts: 2641
- Joined: Mon Nov 13, 2017 3:16 pm
Re: z80test: LDIR->NOP'
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.
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.
Re: z80test: LDIR->NOP'
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:
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!
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
}
}
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!
Re: z80test: LDIR->NOP'
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...
Re: z80test: LDIR->NOP'
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()
should be
LDI()
Code: Select all
5F = bit 5 of (copied value+A);
Code: Select all
5F = bit 1 of (copied value+A);