Note that NMI here is special, not like a 6502. In particular, you can't necessarily return from an NMI. It's meant for watchdog resets, power brownouts, and the like.
Edit: I see this as a valid and interesting design choice.
Yeah, this was something that I ran into when examining how RISC-V does interrupts. NMIs are explicitly non-recoverable. I personally consider this to be, well, basically just *correct*; since disabling interrupts then provides true critical (uninterruptible) sections. Unrecoverable NMIs allow as much NMI-ey-ness as possible without breaking that, since if they interrupt a critical section, it doesn't matter for the most part, since the main program is basically toast. In some of my 6502 code, I had to do this awful hardware dance to check if I was interrupted by a NMI, then retry the critical section in a loop. Truly gross. Or worse, an *additional* hardware mechanism to mask "non maskable interrupts". Madness!
But, this also made it quite a bit faster to enter or exit un-interruptible interrupt handlers! Like RISC-V, entering a interrupt handler (IRQ or NMI) copies PC (program counter) and ST (status) to EPC and EST (shadow regs in the CPU). NMI does the same thing, so it can clobber them, but it doesn't matter, while still giving a sense of where the NMI happened (say, on an illegal MMIO write). But, since interrupts are disabled upon entry, if you never need to reenable interrupts, you can just RETI to restore PC and ST without ever touching memory! If you do want to reenable interrupts, you can pull out EPC and EST into registers in a couple instructions. Since interrupts preserve all registers, that's all that's needed! (You can also stack them to free the registers; that's 9 extra cycles from the below for each of save, restore)
Code: Select all
SRR r1 ; 2 cycles
EPCR r2 ; 2 cycles
CLI ; 2 cycles — nested interrupts live from here
; ... body ...
SEI ; 2 cycles
EPCW r2 ; 2 cycles
SRW r1 ; 2 cycles
RETI ; 3 cycles
ADD Add rd = rs1 + rs2
ADDI Add immediate rd += sext(imm8)
I don't like addressing modes being specified in the instruction, I always find it painful trying to read MASM code. It's much clearer specified in the operands.
Yeah, I waffled on the spelling of this. But they're not.. uh, "combinatorially complete"
ADD r1, r2, r3 is totally valid, as is ADD r1, r1, 5, but ADD r1, r2, 5 isn't. You could spell it ADD r1, 5, but this doesn't make it very explicit that this is mutating r1. ADDI r1, 5 makes this clearer.
I'd love to hear more about the prior art, the names for the instructions are waaaay more mutable than silicon.