WAI instruction
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
WAI instruction
I'm rather confused as to the handling of the WAI instruction.
As I understand the WAI instruction halts the CPU until an interrupt has occurred (it's never specified but I imagine any interrupt) and then I assume after the interrupt is finished execution continues with the next instruction after the WAI.
The docs also mention that if the I flag is set (interrupts disabled) that it functions a bit differently. While it still halts the CPU waiting on an interrupt, when one does occur it simply resumes on the next instruction, no jump/RTI ect...
Now does that apply to all interrupts, or only the IRQ (ie. maskable) one? For example what happens if the CPU hits WAI and then a NMI is called? Do we jump to it's handler like normal or just continue on with the instruction following the WAI? What about ABORT or RESET? Is the I flag implicitly cleared?
Any ideas or thoughts?
As I understand the WAI instruction halts the CPU until an interrupt has occurred (it's never specified but I imagine any interrupt) and then I assume after the interrupt is finished execution continues with the next instruction after the WAI.
The docs also mention that if the I flag is set (interrupts disabled) that it functions a bit differently. While it still halts the CPU waiting on an interrupt, when one does occur it simply resumes on the next instruction, no jump/RTI ect...
Now does that apply to all interrupts, or only the IRQ (ie. maskable) one? For example what happens if the CPU hits WAI and then a NMI is called? Do we jump to it's handler like normal or just continue on with the instruction following the WAI? What about ABORT or RESET? Is the I flag implicitly cleared?
Any ideas or thoughts?
Re: WAI instruction
It's both NMI and IRQ, otherwise it wouldn't be very useful. It also includes ABORT but probably not BRK because it says external hardware interrupts only. I assume it only ignores IRQs when the I-flag is set, NMIs always happens. It says that the IRQ can still wake the CPU up if the I-flag is set and an IRQ is pending before the WAI instruction is executed (the IRQ isn't serviced though).
Re: WAI instruction
So if WAI has I set (interrupts disabled) and it's woken up with an NMI... is the NMI interrupt executed, or do we just wake and go? Since the I flag is really only supposed to apply to IRQ.
Re: WAI instruction
NMI can not be prevented with SEI (i flag).
If an NMI does occur, it will jump to the NMI handler, and the NMI code will be executed. When an RTI is reached, it will return to the WAI instruction, and move to the next line beyond it.
If an NMI does occur, it will jump to the NMI handler, and the NMI code will be executed. When an RTI is reached, it will return to the WAI instruction, and move to the next line beyond it.
nesdoug.com -- blog/tutorial on programming for the NES
-
- Posts: 611
- Joined: Mon Jan 23, 2006 7:47 am
- Location: Germany
- Contact:
Re: WAI instruction
Perhaps you could think of it like this: P.i doesn't actually prevent the CPU from detecting IRQs, it just prevents the IRQ interrupt sequence (save PC, load vector etc).
Last edited by creaothceann on Wed Apr 28, 2021 6:22 am, edited 1 time in total.
My current setup:
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
-
- Posts: 1565
- Joined: Tue Feb 07, 2017 2:03 am
Re: WAI instruction
sei
wai
This will halt until any interrupt source.
If its a RESET it will reset the chip as normal.
Any other, IRQ, NMI, ABORT it will not run the interrupt handler and it will continue to the next instruction.
Since you are in a WAI state you can't trigger a COP or BRK hence "hardware only"
cli
wai
will run the handler then continue to the next instruction
wai
This will halt until any interrupt source.
If its a RESET it will reset the chip as normal.
Any other, IRQ, NMI, ABORT it will not run the interrupt handler and it will continue to the next instruction.
Since you are in a WAI state you can't trigger a COP or BRK hence "hardware only"
cli
wai
will run the handler then continue to the next instruction
Re: WAI instruction
Kind of the opposite of what I said about NMI. I believe the only way to prevent an NMI is to reset bit 7 of the $4200 register (NMITIMEN).
If bit 7 is set, it will jump to the NMI handler and execute that code.
CLI and SEI do no affect NMIs.
If bit 7 is set, it will jump to the NMI handler and execute that code.
CLI and SEI do no affect NMIs.
nesdoug.com -- blog/tutorial on programming for the NES
Re: WAI instruction
Yeah the I-flag should only affect IRQ right? But from what Oziphantom is saying it sounds like NMI and ABORT are also affected by the I-flag during a WAI?
I'm using WAI in my SNES homebrews when waiting for the next NMI, and NMIs seems to happen as expected (I might have used CLI though).
I'm using WAI in my SNES homebrews when waiting for the next NMI, and NMIs seems to happen as expected (I might have used CLI though).
-
- Posts: 1565
- Joined: Tue Feb 07, 2017 2:03 am
Re: WAI instruction
The Programming the 65816, 6502, 65C02 and 65802 book says "interrupt" which to me means IRQ/NMI/Abort rather than just IRQ. Also this page http://sbc.bcstechnology.net/65c816interrupts.html specifies "any".
However looking at the Datasheet, its goes into more detail.
It also points out that an ABORTB will still fire and will return to the WAI ( presumably from the handler?? ) but if you don't have I set, then it aborts the WAI but doesn't wake up the processor, so "dead lock"?
With no mention of what happens with a NMI with I set.
So it could be IRQB only, and an NMI is handled as per normal. However does it exit the WAI upon completion of the handler or does it stay in the WAI state as ABORTB does?
Sadly the VICE emulator test benches don't test this logic. As best I can tell none of the SNES test roms do either. Anomie's docs talk about IRQ and various pipelines issues that are caused buy a few instructions in reqards to IRQs and WAI but don't mention anything about what happens on an NMI in said state.
Looking at BSNES source code I can't find any special handling of WAI except both IRQ and NMI set the custom flag to 0.
From this I conclude I was wrong, it is only IRQB, however I'm unsure if there is any special treatment of NMI with regards to if it returns and holds the WAI or not.
However looking at the Datasheet, its goes into more detail.
It only mentions IRQB.7.13 Wait for Interrupt (WAI) Instruction
The WAI instruction pulls RDY low and places the processor in the WAI "low power" mode. NMIB, IRQB or RESB will terminate the WAI condition and transfer control to the interrupt handler routine. Note that an ABORTB input will abort the WAI instruction, but will not restart the processor. When the Status Register I flag is set (IRQB disabled) the IRQB interrupt will cause the next instruction (following the WAI instruction) to be executed without going to the IRQB interrupt handler. This method results in the highest speed response to an IRQB input. When an interrupt is received after an ABORTB which occurs during the WAI instruction, the processor will return to the WAI instruction. Other than RESB (highest priority), ABORTB is the next highest priority, followed by NMIB or IRQB interrupts.
It also points out that an ABORTB will still fire and will return to the WAI ( presumably from the handler?? ) but if you don't have I set, then it aborts the WAI but doesn't wake up the processor, so "dead lock"?
With no mention of what happens with a NMI with I set.
So it could be IRQB only, and an NMI is handled as per normal. However does it exit the WAI upon completion of the handler or does it stay in the WAI state as ABORTB does?
Sadly the VICE emulator test benches don't test this logic. As best I can tell none of the SNES test roms do either. Anomie's docs talk about IRQ and various pipelines issues that are caused buy a few instructions in reqards to IRQs and WAI but don't mention anything about what happens on an NMI in said state.
Looking at BSNES source code I can't find any special handling of WAI except both IRQ and NMI set the custom flag to 0.
From this I conclude I was wrong, it is only IRQB, however I'm unsure if there is any special treatment of NMI with regards to if it returns and holds the WAI or not.
Re: WAI instruction
I appreciate the thoughts guys. It's too bad edge cases like this aren't properly documented in the official documentation.
The only logical interpretation I can come to is that WAI with interrupts disabled handles interrupts normally (ie. jumps to the interrupt vector table) unless it's an IRQ, and only IRQ triggers the 'short circuit'. This is the only way a programmer could actually make use of this feature.
No whether execution continues after a NMI/ABORT or waits in WAI for an IRQ... that I have no clue (so I guess I have come to the same conclusion as Oziphantom).
Given the different interpretations in this thread... I'm guessing the WAI instruction doesn't come up often in roms?
From reading other docs it seems to suggest WAI with interrupts disabled is designed to make interrupt handling faster (ie. you don't have to wait for a full instruction to finish before the interrupts triggers). Since ABORT doesn't even finish the full instruction, it seems silly to even use WAI with I disabled. Also there would be no way to determine which interrupt woke the WAI instruction.So it could be IRQB only, and an NMI is handled as per normal. However does it exit the WAI upon completion of the handler or does it stay in the WAI state as ABORTB does?
The only logical interpretation I can come to is that WAI with interrupts disabled handles interrupts normally (ie. jumps to the interrupt vector table) unless it's an IRQ, and only IRQ triggers the 'short circuit'. This is the only way a programmer could actually make use of this feature.
No whether execution continues after a NMI/ABORT or waits in WAI for an IRQ... that I have no clue (so I guess I have come to the same conclusion as Oziphantom).
Given the different interpretations in this thread... I'm guessing the WAI instruction doesn't come up often in roms?
Re: WAI instruction
Sometimes (although maybe not on the SNES), all you actually want is the "wake up from the low-power state" part, and not the interrupt handler.
Re: WAI instruction
To try and put it simply:
- An NMI or RESET always ends a WAI instruction, and always calls the interrupt handler
- An IRQ always ends a WAI instruction, but only calls the interrupt handler if I=0
- An ABORT always calls the interrupt handler, but does not end a WAI instruction
-
- Posts: 1565
- Joined: Tue Feb 07, 2017 2:03 am
-
- Posts: 611
- Joined: Mon Jan 23, 2006 7:47 am
- Location: Germany
- Contact:
Re: WAI instruction
"Upon executing an RTI instruction, the above sequence will be logically reversed to return the 65C816 to the state it was in at the time of the interrupt, and unless the address that was pushed to the stack in steps 2 and 3 is altered within the interrupt service routine, the 65C816 will return to and again execute the aborted instruction in the interrupted program."Oziphantom wrote: ↑Thu Apr 29, 2021 1:37 amBut that is the thing, the datasheet states the ABORTB does end a WAI instruction, when I is set. So the I does modify behavior other than IRQB.
- Investigating 65c816 Interrupts
So the WAI instruction ends, the ABORT handler runs, and the CPU is paused again.
My current setup:
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
-
- Posts: 1565
- Joined: Tue Feb 07, 2017 2:03 am
Re: WAI instruction
However from the same website
emphasis mine. This is where I go my any idea from. Thus for this matter I treat that sites info as suss and hence are looking for actual hardware test confirmation to clear up the matter. I've reached at to CSDB and a known SuperCPU owner to see if they have any insights.Consider the following code:
sei ;IRQs off
wai ;wait for interrupt
lda via001 ;start of interrupt handler
The above sequence disables IRQs with SEI and then stalls the microprocessor with WAI. WAI actually stops the 65C816's internal clock in the Ø2 high state, putting the microprocessor into a sort of catatonia, reducing its power consumption to micro-amperes and halting all processing (hardware note: executing WAI also causes the 65C816's bi-directional RDY pin to go low—knowing that is a clue to what is going on inside while the 65C816 is WAIting). The system will appear to have gone completely dead.
However, as soon as any hardware interrupt other than a reset occurs the microprocessor will restart and exactly one Ø2 cycle after the interrupt was received, the LDA VIA001 instruction will be executed. In other words, interrupt latency in this scenario will always equal exactly one Ø2 cycle—70 nanoseconds at the 65C816's maximum officially-rated Ø2 frequency of 14 MHz. Unlike the usual behavior when a hardware interrupt input is asserted, there is no delay while the current instruction finishes execution (there is no "current instruction" while WAIting) and the 65C816 performs no stack operations upon awakening.