SVC routines are defined in a SVC Table Module.  The SVC table is a two-level index to the SVC routine.  The first level is a 256 byte table.  Each byte corresponds to a SVC number. If the corresponding byte in the table is zero then the SVC routine is not defined.  If the value is non-zero it is an index into a vector table that points to the SVC routine.

For example the first level table of x’00 02 03 01 00…’ would define three SVC’s.  SVC 0 is not defined, but 1,2 and 3 are.  The values in the table are not the SVC number but they are an index.  The vector table would have A(SVC02, SVC03, SVC01).  The order of the pointers in the vector table correspond with the values in the first level table.

The vector table entry also indicates if the SVC routine should be called enabled or disabled for interrupts.  If the high-order bit in the address is one, the routine is called with interrupts disabled.

X’80’,VL3(SVC-Disabled)  or X’00’,VL3(SVC-Enabled)

The first thing the SVC Interrupt Handler does is to look up the SVC in the first level table:

000000                                8 TXXSVCIR CSECT ,
000000 18CF                           9          LR    R12,R15            ESTABLISH
                            00000    10          USING TXXSVCIR,R12                BASE REGISTER
                                     11 *
                            00000    12          USING @TCB,R4
                                     13 *
000002 1FBB                          14          SLR   R11,R11
000004 BFB3 401A      0001A          15          ICM   R11,B'0011',TCBPSW+2   GET INTERRUPT CODE
000008 58A0 0014      00014          16          L     R10,20                 MVT
00000C 58A0 A014      00014          17          L     R10,MVTSVCTB-@MVT(,R10)  POINT TO SVC TABLE
000010 5AB0 A000      00000          18          A     R11,0(,R10)            SVC TABLE INDEX
000014 1F11                          19          SLR   R1,R1
000016 4310 B000      00000          20          IC    R1,0(,R11)             GET INDEX PTR
00001A 1211                          21          LTR   R1,R1                  CHECK IF DEFINED
00001C 4780 C084      00084          22          BZ    BADSVC                 NO - BAD SVC
                                     23 *
000020 8910 0002      00002          24          SLL   R1,2                   MULTIPLY BY 4
000024 58B0 A004      00004          25          L     R11,4(,R10)            SVC VECTOR TABLE
000028 1AB1                          26          AR    R11,R1                 INDEX INTO TABLE

The SVC interrupt number is obtained from the SVC Old PSW that was stored in the TCB.  This value is used as an index into the first level table.  If the indexed byte is zero the SVC is not defined.  The indexed byte is then multiplied by 4 to become an index into the vector table.

00002A 4110 0050      00050          28          LA    R1,RBLEN               GET LENGTH OF RB
00002E BF18 C0A0      000A0          29          ICM   R1,B'1000',=AL1(128)   SP=128
                                     30          @CALL GETMAIN                GETMAIN STORAGE
000032 58F0 0014      00014          31+         L     R15,20             MVT ADDRESS
000036 58F0 F018      00018          32+         L     R15,MVTGMAIN-@MVT(,R15) ROUTINE ADDRESS
00003A 05EF                          33+         BALR  R14,R15
00003C 12FF                          34          LTR   R15,R15                CHECK RC
00003E 4770 C094      00094          35          BNZ   GETMFAIL                 BRANCH IF FAILED

A new RB is now needed to create a new execution environment for the SVC code to run under while preserving the calling environment.  A branch entry to GETMAIN is made to allocate the storage for the new RB.

000042 1851                          37          LR    R5,R1                  COPY ADDRESS OF NEW RB
                            00000    38          USING @RB,R5
                                     39 *
000044 D74F 5000 5000 00000 00000    40          XC    0(RBLEN,R5),0(R5)      CLEAR STORAGE
00004A D207 5008 4018 00008 00018    41          MVC   RBPSW,TCBPSW           COPY IN CURRENT PSW
000050 D23F 5010 4020 00010 00020    42          MVC   RBREGS,TCBREGS         COPY IN REGISTERS

The storage for the new RB is cleared and the registers and PSW from the TCB are copied into the new RB.

000056 5810 4008      00008          44          L     R1,TCBRB               CURRENT RB PTR
00005A 5010 5000      00000          45          ST    R1,RBNEXT              CHAIN ON
00005E 5050 4008      00008          46          ST    R5,TCBRB                       NEW RB
000062 5810 5014      00014          47          L     R1,RBREG1              RESTORE REG 1
000066 5800 5010      00010          48          L     R0,RBREG0              RESTORE REG 0

The new RB is added to the top of the RB chain.  The RB chain is a push-down stack with the TCB pointing to the top of the stack.

00006A 58F0 B000      00000          50          L     R15,0(,R11)            GET SVC EP
00006E 58E0 0014      00014          51          L     R14,20                 MVT ADDRESS
000072 58E0 E024      00024          52          L     R14,MVTEXIT-@MVT(,R14) SET EXIT AS RETURN ADDR

Now the SVC routine entry point is loaded into Register 15.  The Exit Routine address is loaded into Register 14 as the return point from the SVC routine.

000076 9180 B000      00000          54          TM    0(R11),X'80'           DISABLED EXECUTION
00007A 4710 C082      00082          55          BO    SVCHND00               YES - BRANCH
                                     56 *
00007E 8000 C0A1      000A1          57          SSM   =X'FF'                 ENABLE FOR INTERRUPTS
                                     58 *
000082                               59 SVCHND00 DS    0H
000082 07FF                          60          BR    R15

Now the high-level bit in the vector entry is checked to determine if the SVC routine should be called with interrupts enabled or disabled.  If the bit is not set, indicating interrupts enabled, the Set System Mask (SSM) instruction is used to enable interrupts.

000084                               63 BADSVC   DS    0F
000084 4110 0FFF      00FFF          64          LA    R1,X'FFF'          ABEND CODE
                                     65          @CALL ABEND              CALL ABEND
000088 58F0 0014      00014          66+         L     R15,20             MVT ADDRESS
00008C 58F0 F020      00020          67+         L     R15,MVTABEND-@MVT(,R15) ROUTINE ADDRESS
000090 05EF                          68+         BALR  R14,R15
                                     70 *
000094                               71 GETMFAIL DS    0F
000094 8200 C098      00098          72          LPSW  ERRPSW             ERROR - OUT OF MEMORY
                                     73 *
000098                               76          DS    0D
000098 0002000000EE0004              77 ERRPSW   DC    AL1(0,2,0,0),A(@E@SVCM)      DISABLED WAIT PSW

Finally if the SVC is not defined in the SVC table the Abend routine is called (actually branched to since it does not return to the caller).  The abend code is set to x’FFF’ to indicate an undefined SVC.  If the Getmain request failed a disabled wait PSW is loaded.

[Next – TXXEXIT – Exit Routine]