Do not use LD A,I to read interrupt enabled state

Страница 3/4
1 | 2 | | 4

By hit9918

Prophet (2891)

Аватар пользователя hit9918

27-12-2015, 21:41

yes, not wanting to have multiple versions of functions all day.
or using bios functions that one cant change.
things can continue with the DI : port 99... : EI style.

By RetroTechie

Paragon (1563)

Аватар пользователя RetroTechie

28-12-2015, 11:03

Prodatron wrote:

This wouldn't solve the problem, but even increase it. You lose, as soon as the IRQ occures in front of the DI command, and it doesn't matter if you put multiple JP PE before -> this would even increase the chance, that an IRQ occures at the wrong place.
The only chance I see here is to patch the #38 vector. This would set a flag, which overrides the P/V flag check in the routine.

I don't think so. You see, that code snippet wasn't designed to prevent an interrupt occurring in the wrong place, but to get actual EI/DI state into the P/V flag. That's what the JP's are for.
The problem is that "ld a,i" (or -r) doesn't reliable detect "DI" state. But otoh, if P/V flag reflects "EI" just once, you're done. Which is why that snippet tries "ld a,i" multiple times - but only if previous attempt signalled "DI" state.

For that sequence to fail, you'd need an interrupt to occur exactly during the first "ld a,i" instruction. And exactly during the 2nd "ld a,i". And perhaps 3rd, ..., etc. Not saying that couldn't happen (say, with a high rate of interrupts, or some interrupt-generating queue filled up). But if for example 1st interrupt occurred during the first "ld a,i" and a 2nd during the JP following it, no problem. Likewise if the first "ld a,i" is interrupted, the 2nd one as well, but not the 3rd. Like I said: theoretically not 100% impossible, but how likely? Especially considering how short / fast that snippet would execute.

Exact source of those interrupts isn't relevant. Just with a 50/60 Hz VDP interrupt only, it would be 100% foolproof. If you somehow persuaded the VDP to generate interrupts at an (extremely!) high rate, then problem may re-appear but likelyhood is greatly reduced. Same with external high-rate interrupt sources. But for example a relatively slow stream of RS232 / MIDI interrupts should be as safe as VDP-interrupt only.

Anyway, should be easy enough to test on real hardware what works & what doesn't. Might be that CPU type makes a difference: NMOS Z80 <-> CMOS Z80 <-> Z80 included in MSX engine like on some MSX2+ and Turbo-R.

Must say that kanima's solution is a clever one, Smile2 and potentially foolproof. May be possible to shave a few bytes/clocks off that, too.

By hit9918

Prophet (2891)

Аватар пользователя hit9918

28-12-2015, 19:00

Quote:

Exact source of those interrupts isn't relevant. Just with a 50/60 Hz VDP interrupt only, it would be 100% foolproof

But with diskROMs, the double interrupt is something that happens all day.
It goes EI in any random position in the display.
And there is interrupt request from previous frames because of long DI zones.
You get an interrupt, and any time soon later the border is hit and the VDP makes another one.

nop
interrupt
nop
interrupt

this could happen.

could this one too happen?

nop
interrupt
interrupt
nop

I badly start to wonder:

nop
interrupt
-- handler code
EI
no interrupt
RET
no interrupt	;the next instruction does not check for interrupt. that is the rule, isnt it?
-- back to main code
nop
interrupt

under interrupt overload, one instruction of the main app is run?

By hit9918

Prophet (2891)

Аватар пользователя hit9918

28-12-2015, 19:05

Reading about IFF1 and IFF2 it looks like it is about something else.
Not about "delay the situation to the next instruction" as I thought.
Now I guess the rule is simply "EI does not check for interrupts".
I'm not sure.

By Grauw

Ascended (9071)

Аватар пользователя Grauw

28-12-2015, 19:22

hit9918 wrote:

under interrupt overload, one instruction of the main app is run?

It can occur. The odds for it are low, but so are the odds for an interrupt to occur exactly during an ld a,i in the first place, but under the right circumstances it can be much more likely.

Then you get one user with a specific hardware setup reporting “about one in a hundred runs it crashes and I have to reset my MSX” or “while playing this 100-hour RPG, it crashed after loading this level, but only it only happened once”.

hit9918 wrote:

Reading about IFF1 and IFF2 it looks like it is about something else.

IFF2 exists for NMI interrupts, to restore the interrupt enabled state to IFF1 when it returns with RETN, it’s described by the Z80 user manual.

The 1-instruction delay for EI is done through some other mechanism, not related to IFF.

By RetroTechie

Paragon (1563)

Аватар пользователя RetroTechie

28-12-2015, 19:57

hit9918 wrote:

Now I guess the rule is simply "EI does not check for interrupts".

Even simpler: EI instruction -> 1-instruction delay before interrupts are accepted again (if they were disabled before that). This is officially documented.

The Z80 doesn't care what that instruction following EI is, but a properly written interrupt handler would make that the exiting "RET". That avoids nested interrupts and (possibly) running out of stack space in a heavily-interrupted system. Not necessarily that you have any CPU time left for the main program... Smile

Which btw. is probably the reason that EI -> 1-instruction delay was designed into the Z80. Its designers weren't stupid, you know. So the concept of high-rate, nested interrupts (and running out of stack space as a result) was probably known to them. That 1-instruction delay is a simple method to give programmers a way to avoid that.

By RetroTechie

Paragon (1563)

Аватар пользователя RetroTechie

28-12-2015, 20:24

hit9918 wrote:

But with diskROMs, the double interrupt is something that happens all day.
It goes EI in any random position in the display.
And there is interrupt request from previous frames because of long DI zones.

No, in the case of VDP it activates its interrupt line once, but doesn't 'remember' previously pending interrupts. Z80 handles it, reading VDP status register resets the VDP's interrupt line, and that's it.

If Z80 takes too long to accept that VDP interrupt (or read its status register), that interrupt will simply be lost when the next one comes along. Same thing may happen if a diskROM (or other software) disables interrupts for too long.

For other hardware like an RS232 receiver that may be different. But in any case you only have 1 interrupt routine running at most, not an interrupt handler interrupted again (nested interrupt). Unless interrupt handler re-enables interrupts halfway its own execution (which would be stupid).

By Grauw

Ascended (9071)

Аватар пользователя Grauw

28-12-2015, 20:29

RetroTechie, if something (e.g. the DiskROM) disables the interrupts to 0.2 ms before the next interrupt, an interrupt will occur and return, and depending on the time spent in the interrupt handler the next interrupt will either occur immediately or very soon after (possibly just 1 instruction after).

Also, something hooked into H.TIMI may be taking a lot of time to complete (disk motor timeout?), causing the same situation.

It’s usually not the case, but sketching worst case situations to break assumptions Smile.

By hit9918

Prophet (2891)

Аватар пользователя hit9918

28-12-2015, 20:28

it is funny. there are 4 extra flag bits.
two of them are "bit 5 of result" and "bit 3 of result".
it is funny that it was more compatible to 8080 to put the V flag over the parity flag when there were 2 more flag bits free.
some trick codes must have used bit 5 and bit 3?

that the DI state is not in the flags makes sense with all the POP AF and EX AF business.

By Grauw

Ascended (9071)

Аватар пользователя Grauw

28-12-2015, 20:36

@hit9918 A bit off-topic, but The Undocumented Z80 Documented by Sean Young has some details on unused flag register bits.

Страница 3/4
1 | 2 | | 4