Our first version of a nucleus will not do much – but it will do something! It will set a value in the Interval Timer. The CPU will subtract from this value several times every second. When the value goes to zero an External Interrupt will be generated. This will cause the CPU to save the current PSW into the External Old PSW area in low core and load a new PSW from the External New PSW location. In our interrupt routine we will reset the Interval Timer and load a PSW with the wait bit set – but enabled for interrupts.
TXXNUC CSECT ,
DC X'00',X'00',AL2(0),AL4(DISPINIT) INITIAL PSW
DC D'0' RST NEW PSW
*
DC A(CVT) COMM VECT TABLE
DC A(MVT) MOD VECT TABLE
*
DC D'0' EXT OLD PSW
DC D'0' SVC OLD PSW
DC D'0' PGM OLD PSW
DC D'0' MCK OLD PSW
DC D'0' I/O OLD PSW
*
DC D'0' CHANNEL STATUS WORD
DC F'0' CHANNEL ADDRESS WORD
DC F'0'
DC F'0' INTERVAL TIMER
DC F'0'
*
DC X'00',X'00',AL2(0),AL4(EXTHNDLR) EXT NEW PSW
DC X'00',X'00',AL2(0),AL4(SVCHNDLR) SVC NEW PSW
DC X'00',X'00',AL2(0),AL4(PGMHNDLR) PGM NEW PSW
DC X'00',X'00',AL2(0),AL4(@E@MCK) MCK NEW PSW
DC X'00',X'00',AL2(0),AL4(IOHNDLR) I/O NEW PSW
*
*
LOWCLEN EQU *-TXXNUC
LOWCFILL EQU 1024-LOWCLEN
DC (LOWCFILL)X'00'
We begin by filling in some low core values needed by the CPU. We specify the PSW’s to be loaded when the corresponding interrupt occurs. Finally we pad low core up to 1k (1024) with binary zeros.
EXTREGS DC 16F'0' EXT INTERRUPT REG SAVE IOREGS DC 16F'0' I/O INTERRUPT REG SAVE SVCREGS DC 16F'0' SVC INTERRUPT REG SAVE PGMREGS DC 16F'0' PGM INTERRUPT REG SAVE * * CVT DC A(0) +++ PLACE HOLDER +++ MVT DC A(0) +++ PLACE HOLDER +++
Next we go ahead and define some data areas. These will not be used right now but they will be needed in later versions of our nucleus code.
USING TXXNUC,0
*
SVCHNDLR DS 0H
PGMHNDLR DS 0H
IOHNDLR DS 0H
LPSW WAITPSW
*
DS 0D
WAITPSW DC X'00',X'02',AL2(0),A(X'EE9999')
If an SVC, Program, or I/O interrupt occurs we load a disabled wait PSW.
EXTHNDLR DS 0H
L R1,=A(X'80') INTERVAL TIMER VALUE
ST R1,ITIMER-@LOWCORE SAVE INTO TIMER
*
LPSW IWAIT LOAD WAIT PSW
*
DS 0D
IWAIT DC AL1(255,2,0,0),AL4(X'FEAD')
*
*
DISPINIT DS 0H
B EXTHNDLR
When an External interrupt occurs we store a new value into the interval timer and then load an Enabled Wait PSW. The PSW must be enabled for External interrupts so our interrupt routine will be invoked when the timer expires.
@LOWCORE ,
*
@REGS ,
@@ERR ,
END ,
Finally we include our macros for mapping low core and registers. I have also created a new macro called @@ERR to contain wait state codes.
Once the nucleus is assembled and link edited as TXXNUC we can fire up Hercules and IPL from our DASD volume. We should see our enabled wait PSW with the code ‘FEAD’ and we should observe the CPU waking up and performing a few instructions before going back into the wait state.
[Next – Dispatcher]