Planning a test for BRK and IRQ concurrency glitch

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Bisqwit
Posts: 248
Joined: Fri Oct 14, 2011 1:09 am

Planning a test for BRK and IRQ concurrency glitch

Post by Bisqwit » Tue Mar 27, 2012 12:29 am

I am planning a test for the BRK and IRQ concurrency glitch.
My initial attempt, however, failed, because I was assuming that when the IRQ supersedes the BRK, the B flag will be cleared, which is not actually the case.
Apparently, when the IRQ supersedes the BRK, the actual interrupt will be indistinguishable from a BRK, if not for the fact that the device generating the IRQ (such as the APU) will give out a status flag indicating an IRQ is being signalled.
However, I cannot test this. If I check the status flag within the BRK/IRQ handler, it is possible that the IRQ was actually set after the BRK handler was already landed at. Any ideas how to perform this test reliably?
Would checking for the IRQ return address work?

There is another test I want to make here: I want to see whether, when an IRQ is signalled in the middle of a PHP instruction, the PHP pushes the B flag cleared. In my emulator, it currently does (because it shares code with the BRK/IRQ generating instruction), but I want to see if it happens also on the hardware and/or on any other emulator.

User avatar
koitsu
Posts: 4218
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Post by koitsu » Tue Mar 27, 2012 3:38 am

Will this video I made some time back help you at all? It doesn't test concurrency, but it might be helpful in other ways. Original thread which prompted me to make the video. Tepples' hardware IRQ ideas might be doable, but that'd take me some time to read about + rig up.

Bisqwit
Posts: 248
Joined: Fri Oct 14, 2011 1:09 am

Post by Bisqwit » Tue Mar 27, 2012 5:04 am

http://bisqwit.iki.fi/kala/test1.zip If someone has a real NES, I would be thankful of reports of this test ROM being run. Its purpose is to collect the reference data for the actual test. It works on both NTSC and PAL systems, but I am now focusing on NTSC.
EDIT: Test results collected (again).

Code: Select all

Nintendulator:
29823
	36 *	#INTs=1, f=$30, $4015=$00, B=1 <- Only BRK happened (IRQ was not asserted before test was over)
	12 *	#INTs=2, f=$20, $4015=$40, B=0 <- BRK occurring, followed by IRQ before SEI has caught effect 
	79 *	#INTs=2, f=$20, $4015=$40, B=1 <- BRK occurring, reads $4015 BEFORE the IRQ is asserted, immediately followed by IRQ before the next instruction in mainline 
	16 *	#INTs=1, f=$30, $4015=$40, B=1 <- BRK occurring, reads $4015 AFTER IRQ is asserted, IRQ never occurs
	107*	#INTs=2, f=$30, $4015=$00, B=1 <- IRQ occurs before BRK, followed by BRK occurring
	second flag value always $30
Nestopia:
29823
	Same as Nintedulator
	second flag value always $30
FCEUX:
29822
	Same as Nintendulator, except +1/-1 variances in some timings
	second flag value always $30
BSNES:
29822
	Same as FCEUX
	second flag value always $30
FAMICOM NTSC:
29823
	Same as Nintendulator, except $4015 always has bit 5 set (i.e. $20 and $60 instead of $00 and $40).
	second flag value always $30
USA NTSC:
29823
	RESULTS PENDING	
Still no sign of BRK being superseded by IRQ...

#INTs counts the number of times the IRQ handler was entered. B is 1, if the return address in the latest invoked interrupt pointed to the next instruction after the BRK (which was a double-byte NOP that did not occur anywhere else, for easy recognition).

If the BRK was superseded by an IRQ, there would be a line where #INTs=1 and B=0. Yet, such line never occurred :-/

Also no sign of the PHP bits being changed by an oncoming IRQ.

Curiously, bit 5 in $4015 always read back as 1. It always reads back as 0 in every emulator I tested. Looks like another previously unknown open bus case.
Last edited by Bisqwit on Tue Mar 27, 2012 7:42 am, edited 9 times in total.

crudelios
Posts: 24
Joined: Thu Feb 09, 2012 3:54 am

Post by crudelios » Tue Mar 27, 2012 5:39 am

That $4015 thing is strange.

What happens if you read $4015 right after a BRK? (without triggering an IRQ)

tepples
Posts: 22093
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Tue Mar 27, 2012 5:46 am

On my NES, with my PowerPak:

Code: Select all

Offset #INTs Flags   4015 B n
01     1     $30,$30 $20  1 2
13     2     $20,$30 $60  0 12
29     2     $20,$30 $60  1 16
- IRQ trigger timing: 29823
This result remained stable across multiple resets and even a couple power cycles.

User avatar
Zepper
Formerly Fx3
Posts: 3221
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper » Tue Mar 27, 2012 6:02 am

You make use of unofficial opcodes...?

Bisqwit
Posts: 248
Joined: Fri Oct 14, 2011 1:09 am

Post by Bisqwit » Tue Mar 27, 2012 6:12 am

Zepper wrote:You make use of unofficial opcodes...?
Where they are entirely consistent and a consequence of processor's logical design rather than subject to temperature-variant analog processes, yes. They are an unseparable part of the NES hardware.
In this test, I used the two-byte NOP opcode $F4 (which is really a "CPX zp,X" but which for some reason does nothing productive -- probably related to the fact that it refers to X twice).
EDIT: But I replaced it now with $59, "EOR abs,y". The point is just that the opcode must be sufficiently unique so that the return address is identified by looking at the opcode at that address alone.

User avatar
Zepper
Formerly Fx3
Posts: 3221
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper » Tue Mar 27, 2012 6:41 am

With RockNES:
Image

Bisqwit
Posts: 248
Joined: Fri Oct 14, 2011 1:09 am

Post by Bisqwit » Tue Mar 27, 2012 7:02 am

Zepper wrote:With RockNES:
Same results as on Nintendulator and Famicom (the HVC-001, not an emulator by that name), except that the it looks like in your emulator, an early read of $4015 cancels the upcoming IRQ even 5 cycles before the fact.

But why a 100 kilobyte JPG for something that compresses into less than 4 kilobytes as a lossless PNG? Know your file formats.
Last edited by Bisqwit on Tue Mar 27, 2012 7:39 am, edited 1 time in total.

FHorse
Posts: 231
Joined: Sat May 08, 2010 9:31 am

Post by FHorse » Tue Mar 27, 2012 7:08 am

And this with puNES:
Image

Bisqwit
Posts: 248
Joined: Fri Oct 14, 2011 1:09 am

Post by Bisqwit » Tue Mar 27, 2012 7:18 am

From my emulator:
TEST:test_cpu_flag_concurrency
Verifying that basic CPU flag operations work properly
DFL:30; 30 OK
NMI:20->30 OK
IRQ:20->30 OK
BRK:30->30 OK
Finding APU IRQ timings
OK, 29823<=29823<29823
Invoking a BRK-IRQ collision
Offs #INTs Flags 4015 B n
033 1 $30,$30 $00 1 34 <- Only BRK happened (IRQ was not asserted before test was over)
043 2 $20,$30 $40 0 10 <- BRK occurring, followed by IRQ before SEI has caught effect
124 2 $20,$30 $40 1 81 <- BRK occurring, reads $4015 BEFORE the IRQ is asserted, immediately followed by IRQ before the next instruction in mainline
136 1 $30,$30 $40 1 12 <- BRK occurring, reads $4015 AFTER IRQ is asserted, IRQ never occurs
138 1 $20,$30 $40 1 2 <- BRK superseded by IRQ (BRK-style return address, IRQ-style flags)
249 2 $30,$30 $00 1 111 <- IRQ occurs, followed by BRK occurring
This is obviously wrong in more than one aspect.
Also, I do not get $20 at $4015, even though I implemented the open bus feature in there. What could be causing it to happen on NES and Famicom?

FHorse wrote:And this with puNES:
You have a one-cycle difference between IRQ occurring and a read from $4015 preventing that happening compared to the real NES. Are you possibly fetching the contents of the register at wrong cycle relative to the instruction? Or do you have an extra buffer somewhere for IRQs?

User avatar
Zepper
Formerly Fx3
Posts: 3221
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper » Tue Mar 27, 2012 9:24 am

Do you know if the IRQ is acknowledged only in the last cycle of the current instruction? Do you write to $4017 before writing to $4015? How many cycles should be elapsed?

Bisqwit
Posts: 248
Joined: Fri Oct 14, 2011 1:09 am

Post by Bisqwit » Tue Mar 27, 2012 9:44 am

Zepper wrote:Do you know if the IRQ is acknowledged only in the last cycle of the current instruction? Do you write to $4017 before writing to $4015? How many cycles should be elapsed?
At no point do I write to $4015 in this test, not even in Blargg's library code (except in the end thereof).
I do write to $4017 whenever I want to toggle IRQ enable / disable, and/or to force IRQ to be happen at a certain time. I may read $4015 even when IRQ is not being triggered.
I can't answer the other questions.

tepples
Posts: 22093
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Tue Mar 27, 2012 12:17 pm

Results from updated test on NTSC NES + PowerPak:

Code: Select all

Offs #INTs Flags   4015 B n
035  1     $30,$30 $20  1 36
047  2     $20,$30 $60  0 12
126  2     $20,$30 $60  1 79
142  1     $30,$30 $60  1 16
249  2     $30,$30 $20  1 107
- IRQ trigger timing: 29823

FHorse
Posts: 231
Joined: Sat May 08, 2010 9:31 am

Post by FHorse » Tue Mar 27, 2012 1:49 pm

Code: Select all

Offs #INTs Flags   4015 B n
035  1     $30,$30 $20  1 36
047  2     $20,$30 $60  0 12
126  2     $20,$30 $60  1 79
142  1     $30,$30 $60  1 16
249  2     $30,$30 $20  1 107
- IRQ trigger timing: 29823
and after a debug session I've the same result with puNES. Thx Bisqwit for the test.

Post Reply