ANESE/roms/tests/cpu/cpu_interrupts_v2/readme.txt
Daniel Prilik 2238090a05 *initial commit
Setting up the project. Also, iNES parsing
2017-10-13 20:18:31 -07:00

251 lines
6.9 KiB
Text
Vendored

NES CPU Interrupt Tests
-----------------------
Tests behavior and timing of CPU in the presence of interrupts, both IRQ
and NMI.
CLI Latency Summary
-------------------
The RTI instruction affects IRQ inhibition immediately. If an IRQ is
pending and an RTI is executed that clears the I flag, the CPU will
invoke the IRQ handler immediately after RTI finishes executing.
The CLI, SEI, and PLP instructions effectively delay changes to the I
flag until after the next instruction. For example, if an interrupt is
pending and the I flag is currently set, executing CLI will execute the
next instruction before the CPU invokes the IRQ handler. This delay only
affects inhibition, not the value of the I flag itself; CLI followed by
PHP will leave the I flag cleared in the saved status byte on the stack
(bit 2), as expected.
1-cli_latency
-------------
Tests the delay in CLI taking effect, and some basic aspects of IRQ
handling and the APU frame IRQ (needed by the tests). It uses the APU's
frame IRQ and first verifies that it works well enough for the tests.
The later tests execute CLI followed by SEI and equivalent pairs of
instructions (CLI, PLP, where the PLP sets the I flag). These should
only allow at most one invocation of the IRQ handler, even if it doesn't
acknowledge the source of the IRQ. RTI is also tested, which behaves
differently. These tests also *don't* disable interrupts after the first
IRQ, in order to test whether a pair of instructions allows only one
interrupt or causes continuous interrupts that block the main code from
continuing.
2) RTI should not adjust return address (as RTS does)
3) APU should generate IRQ when $4017 = $00
4) Exactly one instruction after CLI should execute before IRQ is taken
5) CLI SEI should allow only one IRQ just after SEI
6) In IRQ allowed by CLI SEI, I flag should be set in saved status flags
7) CLI PLP should allow only one IRQ just after PLP
8) PLP SEI should allow only one IRQ just after SEI
9) PLP PLP should allow only one IRQ just after PLP
10) CLI RTI should not allow any IRQs
11) Unacknowledged IRQ shouldn't let any mainline code run
12) RTI RTI shouldn't let any mainline code run
2-nmi_and_brk
-------------
NMI behavior when it interrupts BRK. Occasionally fails on
NES due to PPU-CPU synchronization.
Result when run:
NMI BRK --
27 36 00 NMI before CLC
26 36 00 NMI after CLC
26 36 00
36 00 00 NMI interrupting BRK, with B bit set on stack
36 00 00
36 00 00
36 00 00
36 00 00
27 36 00 NMI after SEC at beginning of IRQ handler
27 36 00
3-nmi_and_irq
-------------
NMI behavior when it interrupts IRQ vectoring.
Result when run:
NMI IRQ
23 00 NMI occurs before LDA #1
21 00 NMI occurs after LDA #1 (Z flag clear)
21 00
20 00 NMI occurs after CLC, interrupting IRQ
20 00
20 00
20 00
20 00
20 00
20 00 Same result for 7 clocks before IRQ is vectored
25 20 IRQ occurs, then NMI occurs after SEC in IRQ handler
25 20
4-irq_and_dma
-------------
Has IRQ occur at various times around sprite DMA.
First column refers to what instruction IRQ occurred
after. Second column is time of IRQ, in CPU clocks relative
to some arbitrary starting point.
0 +0
1 +1
1 +2
2 +3
2 +4
4 +5
4 +6
7 +7
7 +8
7 +9
7 +10
8 +11
8 +12
8 +13
...
8 +524
8 +525
8 +526
9 +527
5-branch_delays_irq
-------------------
A taken non-page-crossing branch ignores IRQ during
its last clock, so that next instruction executes
before the IRQ. Other instructions would execute the
NMI before the next instruction.
The same occurs for NMI, though that's not tested here.
test_jmp
T+ CK PC
00 02 04 NOP
01 01 04
02 03 07 JMP
03 02 07
04 01 07
05 02 08 NOP
06 01 08
07 03 08 JMP
08 02 08
09 01 08
test_branch_not_taken
T+ CK PC
00 02 04 CLC
01 01 04
02 02 06 BCS
03 01 06
04 02 07 NOP
05 01 07
06 04 0A JMP
07 03 0A
08 02 0A
09 01 0A JMP
test_branch_taken_pagecross
T+ CK PC
00 02 0D CLC
01 01 0D
02 04 00 BCC
03 03 00
04 02 00
05 01 00
06 04 03 LDA $100
07 03 03
08 02 03
09 01 03
test_branch_taken
T+ CK PC
00 02 04 CLC
01 01 04
02 03 07 BCC
03 02 07
04 05 0A LDA $100 *** This is the special case
05 04 0A
06 03 0A
07 02 0A
08 01 0A
09 03 0A JMP
Multi-tests
-----------
The NES/NSF builds in the main directory consist of multiple sub-tests.
When run, they list the subtests as they are run. The final result code
refers to the first sub-test that failed. For more information about any
failed subtests, run them individually from rom_singles/ and
nsf_singles/.
Flashes, clicks, other glitches
-------------------------------
If a test prints "passed", it passed, even if there were some flashes or
odd sounds. Only a test which prints "done" at the end requires that you
watch/listen while it runs in order to determine whether it passed. Such
tests involve things which the CPU cannot directly test.
Alternate output
----------------
Tests generally print information on screen, but also report the final
result audibly, and output text to memory, in case the PPU doesn't work
or there isn't one, as in an NSF or a NES emulator early in development.
After the tests are done, the final result is reported as a series of
beeps (see below). For NSF builds, any important diagnostic bytes are
also reported as beeps, before the final result.
Output at $6000
---------------
All text output is written starting at $6004, with a zero-byte
terminator at the end. As more text is written, the terminator is moved
forward, so an emulator can print the current text at any time.
The test status is written to $6000. $80 means the test is running, $81
means the test needs the reset button pressed, but delayed by at least
100 msec from now. $00-$7F means the test has completed and given that
result code.
To allow an emulator to know when one of these tests is running and the
data at $6000+ is valid, as opposed to some other NES program, $DE $B0
$G1 is written to $6001-$6003.
Audible output
--------------
A byte is reported as a series of tones. The code is in binary, with a
low tone for 0 and a high tone for 1, and with leading zeroes skipped.
The first tone is always a zero. A final code of 0 means passed, 1 means
failure, and 2 or higher indicates a specific reason. See the source
code of the test for more information about the meaning of a test code.
They are found after the set_test macro. For example, the cause of test
code 3 would be found in a line containing set_test 3. Examples:
Tones Binary Decimal Meaning
- - - - - - - - - - - - - - - - - - - -
low 0 0 passed
low high 01 1 failed
low high low 010 2 error 2
NSF versions
------------
Many NSF-based tests require that the NSF player either not interrupt
the init routine with the play routine, or if it does, not interrupt the
play routine again if it hasn't returned yet. This is because many tests
need to run for a while without returning.
NSF versions also make periodic clicks to prevent the NSF player from
thinking the track is silent and thus ending the track before it's done
testing.
--
Shay Green <gblargg@gmail.com>