The NMI is (almost) a lie!

bbc micro/electron/atom/risc os coding queries and routines
Post Reply
tom_seddon
Posts: 426
Joined: Tue Aug 30, 2005 12:42 am
Contact:

The NMI is (almost) a lie!

Post by tom_seddon » Thu Sep 03, 2020 11:50 pm

The CMOS CPUs have a lot of NOPs, with the 1 cycle ones being particularly interesting. 1-cycle instructions aren't super easy to fit into the 6502's execution model, so clearly a bit of shoehorning was required, and they had to shave off some bits to make them fit. Like the bit where it checks for incoming IRQs or NMIs...

The attached program runs on a Master 128. It sets up an 6522 timer IRQ and runs a bunch of NOPs with interrupts enabled, then sets up a FDC reset NMI and runs a bunch of NOPs with interrupts disabled, then checks to see when each interrupt occurred. And it runs this test for all the various NOPs available and prints the results.

For the 2+-cycle NOPs, you get the expected result: both IRQ and NMI occur at the expected times, somewhere shortly after starting the sequence of NOPs.

But for the 1-cycle NOPs, both IRQs *and* NMIs end up deferred! As long as the run of 1-cycle NOPs continues, the NMI/IRQ status never gets checked. Only once the run ends, and another normal instruction runs, does the interrupt get spotted and handled.

Not quite a mask for your non-maskable interrupts, but I thought it close enough to one to be surprising :lol:

FAQs

Q: What use is this?
A: No idea

--Tom

Code: Select all

10REM>:3.$.NOP1
20REM
30REM CAN IRQS INTERRUPT 1-CYCLE CMOS NOPS?
40MODE128:SWIDTH%=80
50IRQ1V=&204
60NNOPS=900:REM MUST BE A MULTIPLE OF 2 AND 3
70CODESIZE%=4000:DIMCODE%CODESIZE%
80PROCASM
90:
100PROCTEST(&EA)
110REPEAT
120READTYPE$:IFTYPE$="":GOTO180
130PRINTTYPE$" "STRING$(SWIDTH%-2-LENTYPE$,"-")
140REPEAT
150READNOP%:IFNOP%=-1:GOTO170
160PROCTEST(NOP%)
170UNTILNOP%=-1
180UNTILTYPE$=""
190END
200:
210DEFPROCASM
220FORPASS%=0TO2STEP2:P%=CODE%:[OPTPASS%
230.START
240:
250LDA#0:STAIRQHIT
260LDA#0:STANMIHIT
270:
280SEI
290LDAIRQ1V+0:STAOIRQ1V+0
300LDAIRQ1V+1:STAOIRQ1V+1
310LDA#IRQROUT MOD256:STAIRQ1V+0
320LDA#IRQROUT DIV256:STAIRQ1V+1
330LDA#0:STAIRQHIT
340CLI
350:
360LDA#&7F:STA&FE6E:\DISABLE ALL
370LDA#&7F:STA&FE6D:\ACKNOWLEDGE ALL
380LDA#&C0:STA&FE6E:\ENABLE T1 ONLY
390:
400LDA&FE6B:AND#&3F:STA&FE6B:\T1=1 SHOT
410:
420LDAT1VAL+0:STA&FE64
430LDAT1VAL+1:STA&FE65
440.IRQNOPSBEGIN:]P%=P%+NNOPS:[OPTPASS%:.IRQNOPSEND
450:
460SEI
470LDAOIRQ1V+0:STAIRQ1V+0
480LDAOIRQ1V+1:STAIRQ1V+1
490CLI
500:
510LDA#&00:STA&FE24
520LDA#&05:STA&FE24
530.WAIT1770IDLE:LDA&FE28:AND#1:BNEWAIT1770IDLE
540:
550LDA#&4C\JMPABS:STA&D00
560LDA#NMIROUT MOD256:STA&D01
570LDA#NMIROUT DIV256:STA&D02
580LDA#&D8:STA&FE28
590SEI
600.NMINOPSBEGIN:]P%=P%+NNOPS:[OPTPASS%:.NMINOPSEND
610CLI
620LDA#&40:STA&D00
630RTS
640:
650.NMIROUT
660STANMIRELOADA+1
670STXNMIRELOADX+1
680TSX
690LDA&102,X:STANMIPC+0
700LDA&103,X:STANMIPC+1
710LDA#1:STANMIHIT
720.NMIRELOADX:LDX#&FF
730.NMIRELOADA:LDA#&FF
740RTI
750:
760.IRQROUT
770LDA#&40:BIT&FE6D:BEQIRQDONE
780STA&FE6D
790STXIRQRELOADX+1
800TSX
810LDA&102,X:STAIRQPC+0
820LDA&103,X:STAIRQPC+1
830LDA#1:STAIRQHIT
840.IRQRELOADX:LDX#&FF
850.IRQDONE:JMP(OIRQ1V)
860:
870.OIRQ1V:EQUW0
880.T1VAL:EQUW10
890.IRQPC:EQUW0
900.IRQHIT:EQUB0
910.NMIPC:EQUW0
920.NMIHIT:EQUB0
930]IFP%>CODE%+CODESIZE%:STOP
940NEXT
950PRINT"CODE: &";~CODE%" - &";~P%
960ENDPROC
970:
980DEFPROCTEST(N%)
990PRINT"&"RIGHT$("0"+STR$~N%,2)": ";
1000FORI%=IRQNOPSBEGIN TOIRQNOPSEND-1:?I%=N%:NEXT
1010FORI%=NMINOPSBEGIN TONMINOPSEND-1:?I%=N%:NEXT
1020REPEAT
1030CALLSTART
1040IF?IRQHIT=0:PRINT"GOT WRONG IRQ - WILL RETRY"
1050IF?NMIHIT=0:PRINT"NO NMI?!":STOP
1060UNTIL?IRQHIT<>0
1070PROCOUTPUT("IRQ",IRQNOPSBEGIN,IRQNOPSEND,!IRQPC AND&FFFF)
1080PRINT", ";
1090PROCOUTPUT("NMI",NMINOPSBEGIN,NMINOPSEND,!NMIPC AND&FFFF)
1100PRINT
1110ENDPROC
1120:
1130DEFPROCOUTPUT(TYPE$,B%,E%,PC%)
1140PRINTTYPE$" ";
1150IFPC%>=B%ANDPC%<=E%:PRINT"NOT DELAYED";:ELSE:PRINT"DELAYED";
1160ENDPROC
1170:
1180DEFFNNOPS(NOP%)
1190IFPASS%>1:FORI%=0TONNOPS-1:P%?I%=NOP%:NEXT
1200P%=P%+NNOPS
1210=PASS%
1220:
1230DATA "1 CYCLES, 1 BYTES"
1240DATA &03,&13,&23,&33,&43,&53,&63,&73,&83,&93,&A3,&B3,&C3,&D3,&E3,&F3,-1
1250:
1260DATA "1 CYCLES, 1 BYTES (NOT ROCKWELL)"
1270DATA &07,&17,&27,&37,&47,&57,&67,&77,&87,&97,&A7,&B7,&C7,&D7,&E7,&F7,-1
1280:
1290DATA "1 CYCLES, 1 BYTES"
1300DATA &0B,&1B,&2B,&3B,&4B,&5B,&6B,&7B,&8B,&9B,&AB,&BB,&EB,&FB,-1
1310:
1320DATA "1 CYCLES, 1 BYTES (NOT WDC)"
1330DATA &CB,&DB,-1
1340:
1350DATA "1 CYCLES, 1 BYTES (NOT ROCKWELL)"
1360DATA &0F,&1F,&2F,&3F,&4F,&5F,&6F,&7F,&8F,&9F,&AF,&BF,&CF,&DF,&EF,&FF,-1
1370:
1380DATA "2 CYCLES, 2 BYTES"
1390DATA &02,&22,&42,&62,&82,&C2,&E2,-1
1400:
1410DATA "3 CYCLES, 2 BYTES"
1420DATA &44,-1
1430:
1440DATA "4 CYCLES, 2 BYTES"
1450DATA &54,&D4,&F4,-1
1460:
1470DATA "4 CYCLES, 3 BYTES"
1480DATA &DC,&FC,-1
1490:
1500DATA "8 CYCLES, 3 BYTES"
1510DATA &5C,-1
1520:
1530DATA ""
Attachments
nop1nmis.ssd
(3.75 KiB) Downloaded 4 times

User avatar
hoglet
Posts: 9437
Joined: Sat Oct 13, 2012 7:21 pm
Location: Bristol
Contact:

Re: The NMI is (almost) a lie!

Post by hoglet » Fri Sep 04, 2020 7:29 am

There's some discussion of the 1-cycle NOPs over on 6502.org:
http://forum.6502.org/viewtopic.php?f=1&t=5918

dominicbeesley
Posts: 1162
Joined: Tue Apr 30, 2013 12:16 pm
Contact:

Re: The NMI is (almost) a lie!

Post by dominicbeesley » Fri Sep 04, 2020 10:37 am

That is interesting.

Post Reply

Return to “programming”