EXTERNALROUTINESPEC  CHANGECONTEXT
SYSTEMROUTINESPEC  DUMP(INTEGER  A, B)
SYSTEMROUTINESPEC  PHEX(INTEGER  I)
! UPDATED 27/07/78    15.30
!*
!*
!*2900
SYSTEMROUTINESPEC  SSERR(INTEGER  N)
!*
OWNINTEGER  SSOPTION, SVFLAG
!*
!*
!*
!*
SYSTEMINTEGERMAPSPEC  COMREG(INTEGER  I)
!%SYSTEMROUTINESPEC SET WORK(%INTEGERNAME A, F)
!%SYSTEMROUTINESPEC WEXTEND(%INTEGERNAME LEN, FLAG)
SYSTEMROUTINESPEC  OUTFILE(STRING  (15) S,  C 
   INTEGER  LENGTH, MAXBYTES, PROTECTION,  C 
   INTEGERNAME  CONAD, FLAG)
!%SYSTEMROUTINESPEC PSYSMES(%INTEGER ROOT, FLAG)
SYSTEMROUTINESPEC  MOVE(INTEGER  LEN, FROM, TO)
SYSTEMROUTINESPEC  FILL(INTEGER  LEN, FROM, PATTERN)

SYSTEMROUTINE  LPUT(INTEGER  TYPE, P1, P2, P3)
RECORDFORMAT  RF0(INTEGER  TYPE, LA, DATALEN, FILLER)
RECORDFORMAT  RF1(INTEGER  TYPE, LINK, LOC, STRING  (31) NAME)
RECORDFORMAT  RF4(INTEGER  TYPE, LINK, DISP, L, AREA,  C 
      STRING  (31) NAME)
RECORDFORMAT  RF6(INTEGER  TYPE,  C 
      INTEGERARRAY  AREALEN(1 : 7), INTEGER  TOTLEN)
RECORDFORMAT  RF7(INTEGER  TYPE, LINK, AREALOC, BASELOC)
RECORDFORMAT  RF8(INTEGER  TYPE, LINK, CODEADDR, ADDRFIELD)
RECORDFORMAT  RF9(INTEGER  TYPE, LINK, L, REFLINK, COUNT,  C 
      STRING  (31) NAME)
RECORDNAME  R0(RF0)
RECORDNAME  R1(RF1)
RECORDNAME  R4(RF4)
RECORDNAME  R6(RF6)
RECORDNAME  R7(RF7)
RECORDNAME  R8(RF8)
RECORDNAME  R9(RF9)
INTEGER  I, J, K, L, FLAG
OWNINTEGER  TBASE, TON, TMAX, TYPE6, WORKAD, LMAX, WORKMAX
OWNINTEGER  FBASE, CODEBASE, CODEMAX, RECLEN
OWNINTEGER  NULLFLAG
OWNINTEGERARRAY  HEAD(11 : 25)
OWNINTEGERARRAY  H(0 : 14)
OWNINTEGERARRAY  BASE(1 : 7)
OWNINTEGERARRAY  AREALENGTH(1 : 7)
OWNINTEGERARRAY  AREASTART(1 : 7)
OWNINTEGER  RCOUNT
OWNINTEGER  TYPE19NUM
OWNSTRING  (15) FILE
OWNINTEGER  STACKMODE
OWNINTEGER  LANGUAGE
OWNINTEGER  COMREG57
OWNINTEGER  NAMESET
OWNINTEGER  NUMEXT
OWNINTEGER  NUMFIXUPS
INTEGER  OBJLEN
INTEGER  LDSTART
STRING  (31) CHANGEDNAME, EPNAME
CONSTBYTEINTEGERARRAY  CHANGE(0 : 47) =   C 
0(10),1(6),0(8),1,0(23)
SWITCH  EP(0 : 47)
SWITCH  LSW(0 : 47)
   IF  TYPE = 0 THEN  START 
      LANGUAGE = P1
      STACKMODE = 0
!*EMAS;      FILE <- STRING(COMREG(52))
!*EMAS;      %IF FILE = '.NULL' %THEN %START
!*EMAS;         NULLFLAG = 1
!*EMAS;         %RETURN
!*EMAS;      %FINISH %ELSE NULLFLAG = 0
!*2900   NULLFLAG=COMREG(40)
!*2900   FILE='SS#TMPOB'
      CODEBASE = COMREG(15)+32
      CODEMAX = CODEBASE+X'40000'
      WORKAD = COMREG(14)
      TBASE = WORKAD+32
      TYPE6 = TBASE
      TON = TBASE+40;                   ! RESERVE SPACE FOR TYPE6 RECORD RELATING TO 1ST RTN
      WORKMAX = INTEGER(WORKAD+8);      !SIZE OF WORK FILE
      TMAX = WORKMAX
      IF  TMAX > X'40000' THEN  TMAX = X'40000'
      TMAX = WORKAD+TMAX-64
      RCOUNT = 0;                       ! NO OF RELOCATION VALUES
      TYPE19NUM = 0;                    ! NO OF GENERALISED RELOCATION RECORDS
      LMAX = 144;                       ! SIZE OF LDATA+HEAD(16) RECORD
      LMAX = LMAX+2048;                 !TEMPORARY - FAULT IN CALCULATION OF LMAX
      CYCLE  I = 11,1,25
         HEAD(I) = 0
      REPEAT 
      CYCLE  I = 1,1,7
         BASE(I) = 0
      REPEAT 
      COMREG57 = COMREG(57)
      NAMESET = 0
      NUMEXT = 0
      NUMFIXUPS = 0
      RETURN 
   FINISH 
   RETURN  UNLESS  NULLFLAG = 0
   IF  CHANGE(TYPE) = 1 START 
      IF  STRING(P3) -> ("ICL9CM").EPNAME C 
         THEN  CHANGEDNAME = "M#".EPNAME C 
         ELSE  CHANGEDNAME = STRING(P3)
   FINISH 
   -> EP(TYPE)

   ROUTINE  CHECKWORK(INTEGER  N)
   INTEGER  J, F
L1:   IF  TON+N > TMAX THEN  START 
         IF  WORKMAX > X'40000' THEN  START 
            INTEGER(TON) = (WORKAD+X'40000'-TON)!X'19000000'
                                        ! TYPE/SIZE OF FILLER RECORD
            !THIS MAKES A PSEUDO RECORD TYPE 25 TO  BE SKIPPED
            TMAX = WORKAD+WORKMAX-64
            TON = WORKAD+X'40000'
            WORKMAX = 0
         FINISH  ELSE  START 
SELECTOUTPUT(0)
COMREG(24)=1;       !TO GIVE COMILATION FAULTY MESSAGE
PRINTSTRING("WORK FILE TOO SMALL")
MONITOR 
STOP 
            NULLFLAG = -1;              ! WILL GENERATE FAILURE LATER
            TON = TBASE+40;             ! AVOID ERROR MEANTIME
         FINISH 
      FINISH 
   END ;                                ! CHECKWORK
   MONITOR ;  STOP 
EP(37):

   STACKMODE = 1
EP(31):


EP(32):


EP(33):


EP(34):


EP(35):


EP(36):


EP(1):                                  ! CODE
EP(2):                                  ! GLA
EP(3):                                  ! PLT
EP(4):                                  ! SST
EP(5):                                  ! UST
   CHECKWORK(P1+12)
   R0 == RECORD(TON)
   R0_LA = P2
   IF  0 <= P3 < 256 THEN  START 
      I = 20
      R0_DATALEN = -P1
      R0_FILLER = P3
   FINISH  ELSE  START 
      I = (P1+15)&X'FFFFFFFC'
      R0_DATALEN = P1
      MOVE(P1,P3,TON+12)
   FINISH 
   R0_TYPE = TYPE<<24!I;                ! TYPE,RECLEN
   TON = TON+I
   RETURN 
EP(41):


EP(42):


EP(43):


EP(44):


EP(45):


EP(46):


EP(47):

   CHECKWORK(P1>>24+16)
   R0 == RECORD(TON)
   R0_LA = P2
   I = (P1>>24+19)&X'FFFFFFFC'
   R0_TYPE = TYPE<<24!I;                ! TYPE,RECLEN
   R0_DATALEN = P1>>24
   R0_FILLER = (P1<<8)>>8;              ! NO. OF COPIES
   MOVE(P1>>24,P3,TON+16)
   TON = TON+I
   RETURN 
EP(24):                                 ! OLD STYLE ENTRY DEFN USED BY LINK
   TYPE = 11
   P2 = INTEGER(P2+8)
EP(11):                                 ! ENTRY POINT DEFN
   IF  CHANGEDNAME = 'S#GO' THEN  EPNAME = 'ICL9CEMAIN' C 
      ELSE  EPNAME = CHANGEDNAME
   IF  COMREG57 # 0 THEN  START 
      IF  EPNAME = 'ICL9CEMAIN' OR  P1>>31 # 0 THEN  START 
         COMREG(60) = COMREG(60)!2;     ! EXISTENCE OF MAIN EP
SET57:   STRING(COMREG57) = EPNAME
      FINISH  ELSE  START 
         IF  NAMESET = 0 THEN  -> SET57
      FINISH 
      NAMESET = 1
   FINISH 
L3:NUMEXT = NUMEXT+1
   CHECKWORK(44)
   R1 == RECORD(TON)
   IF  P1&3 = 0 THEN  P1 = P1!2
   IF  P1 < 0 THEN  P1 = P1!128;        ! MAINEP BIT
   R1_LOC = P1<<24!(BASE(2)+P2)
   LMAX = LMAX+44
   R1_NAME <- CHANGEDNAME
   I = (LENGTH(R1_NAME)+16)&X'FC'
   R1_TYPE = TYPE<<24!I
   R1_LINK = HEAD(TYPE)
   HEAD(TYPE) = TON
   TON = TON+I
   RETURN 
EP(12):                                 ! EXTERNAL ROUTINE REF
EP(13):                                 ! DYNAMIC ROUTINE REF
   -> L3
EP(10):                                 ! COMMON AREA REFERENCE
EP(15):                                 ! DATA REF
!*  P1 = AREA<<24 ! MIN LENGTH
!*  P2 = LOC IN AREA OF REF
!*  P3 = ADDR(DATA NAME)
!*
   CHECKWORK(60);                       ! ALLOW FOR NEW HEAD + VALUE RECORD
   I = HEAD(15)
   WHILE  I # 0 CYCLE 
      R9 == RECORD(I)
      IF  R9_NAME = STRING(P3) THEN  START 
EP15A:   R9_COUNT = R9_COUNT+1
         INTEGER(TON) = R9_REFLINK
         INTEGER(TON+4) = (P1>>24)<<24!(P2+BASE(P1>>24))
         R9_REFLINK = TON-WORKAD
         TON = TON+8
         J = (P1<<8)>>8
         IF  R9_L < J THEN  R9_L = J
         LMAX = LMAX+8
         RETURN 
      FINISH 
      I = R9_LINK
   REPEAT 
   R9 == RECORD(TON)
   R9_L = 0
   R9_REFLINK = 0
   IF  TYPE = 10 THEN  J = X'80000000' ELSE  J = 0
   R9_COUNT = J
   R9_NAME <- STRING(P3)
   I = (LENGTH(R9_NAME)+24)&X'FC'
   R9_TYPE = 15<<24!I
   R9_LINK = HEAD(15)
   HEAD(15) = TON
   TON = TON+I
   LMAX = LMAX+I-12
   NUMEXT = NUMEXT+1
   -> EP15A
!*
EP(14):                                 ! DATA ENTRY IN GLA
   K = P1>>24
   P1 = P1&X'00FFFFFF'
   -> A
EP(17):                                 ! DATA ENTRY IN GLA ST
   K = 5
   TYPE = 14
A: CHECKWORK(52)
   NUMEXT = NUMEXT+1
   R4 == RECORD(TON)
   LMAX = LMAX+52
   R4_L = P1
   R4_AREA = K
   R4_NAME <- CHANGEDNAME
   I = (LENGTH(R4_NAME)+28)&X'FC'
   R4_TYPE = TYPE<<24!I
   R4_LINK = HEAD(TYPE)
   HEAD(TYPE) = TON
   R4_DISP = BASE(R4_AREA&255)+P2
   TON = TON+I
   RETURN 
EP(18):                                 ! MODIFY 18 BIT ADDRESS FIELD
                                        ! P2  @ IN CODE AREA OF 32 BIT INSTRUCTION
                                        ! P3  18 BIT VALUE TO BE ADDED TO ADDRESS FIELD
   CHECKWORK(16)
   R8 == RECORD(TON)
   R8_TYPE = (18<<24)!16
   R8_LINK = HEAD(18)
   HEAD(18) = TON
   R8_CODEADDR = P2
   R8_ADDRFIELD = P3&X'3FFFF'
   TON = TON+16
   RETURN 
EP(20):


EP(21):

   P1 = 2
   P3 = TYPE-19
EP(19):                                 ! RELOCATE WORD AT P2 IN AREA P1 BY BASE OF AREA P3
   NUMFIXUPS = NUMFIXUPS+1
   CHECKWORK(16)
   R7 == RECORD(TON)
   R7_TYPE = (19<<24)!16
   R7_LINK = HEAD(19)
   HEAD(19) = TON
   R7_AREALOC = P1<<24!P2
   R7_BASELOC = P3<<24
   TON = TON+16
   TYPE19NUM = TYPE19NUM+1
   LMAX = LMAX+8
   RETURN 
EP(25):                                 ! OLD STYLE RELOCATION BLOCK(16 BYTES/ENTRY)
   P1 = (P1-4)>>1+4
EP(26):                                 ! GENERALISED RELOCATION BLOCK
                                        ! P1   NO OF BYTES IN BLOCK
                                        ! P3     @ OF BLOCK
   CHECKWORK(P1+8)
   LMAX = LMAX+P1
   R7 == RECORD(TON)
   R7_TYPE = 25<<24!(P1+8)
   R7_LINK = HEAD(25)
   HEAD(25) = TON
   IF  TYPE = 25 THEN  START 
      I = INTEGER(P3)
      P3 = P3+4
      INTEGER(TON+8) = I
      J = TON+12
      WHILE  I # 0 CYCLE 
         INTEGER(J) = INTEGER(P3)<<24!INTEGER(P3+4)
         INTEGER(J+4) = INTEGER(P3+8)<<24!INTEGER(P3+12)
         J = J+8
         P3 = P3+16
         I = I-1
      REPEAT 
   FINISH  ELSE  MOVE(P1,P3,TON+8)
   I = INTEGER(TON+8)
   J = TON+12
   WHILE  I # 0 CYCLE 
      K = INTEGER(J)
      INTEGER(J) = K+BASE(K>>24)
      K = INTEGER(J+4)
      INTEGER(J+4) = K+BASE(K>>24)
      J = J+8
      I = I-1
   REPEAT 
   TON = TON+P1+8
   RETURN 
EP(6):                                  ! SUMMARY DATA FOR PREVIOUS ROUTINE
   R6 == RECORD(TYPE6)
   R6_TYPE = 6<<24!40
   MOVE(32,P3,TYPE6+4)
   IF  STACKMODE = 0 THEN  START 
      R6_TOTLEN = R6_AREALEN(6)
      R6_AREALEN(6) = 0
      R6_AREALEN(7) = 0
   FINISH 
   RCOUNT = 0
   CYCLE  I = 1,1,7
      BASE(I) = (BASE(I)+R6_AREALEN(I)+7)&X'FFFFFFF8'
   REPEAT 
   CHECKWORK(40)
   TYPE6 = TON
   TON = TON+40;                        ! RESERVE SPACE FOR NEXT DESCRIPTOR
   RETURN 
EP(7):                                  ! END OF FILE
   IF  NULLFLAG < 0 THEN  SSERR(228);   ! PROGRAM TOO LARGE
   IF  P1 = 32 THEN  STACKMODE = 1
   IF  TYPE6 = TBASE THEN  LPUT(6,32,0,P3)
   R6 == RECORD(TYPE6)
   R6_TYPE = 7<<24;                     ! TO TERMINATE LAYOUT
   OBJLEN = LMAX+16
   CYCLE  I = 1,1,7
      OBJLEN = OBJLEN+BASE(I)
   REPEAT 
   OUTFILE(FILE,OBJLEN,0,0,FBASE,FLAG)
   IF  FLAG # 0 THEN  SSERR(FLAG) ;       ! PROGRAM TOO LARGE
   CYCLE  I = 1,1,7
      AREALENGTH(I) = BASE(I)
   REPEAT 
   AREASTART(1) = 32
   AREASTART(4) = AREASTART(1)+AREALENGTH(1);! CST AFTER CODE
   AREASTART(3) = AREASTART(4)+AREALENGTH(4);! PLT AFTER CST
AREASTART(2)=AREASTART(3)+AREALENGTH(3);     !GLA AFTER PLT
   AREASTART(5) = AREASTART(2)+AREALENGTH(2);! GLAST AFTER GLA
   AREASTART(6) = AREASTART(5)+AREALENGTH(5)
   AREASTART(7) = AREASTART(6)+AREALENGTH(6)
   LDSTART = AREASTART(7)+AREALENGTH(7)
   LDSTART = LDSTART+FBASE
   INTEGER(FBASE+4) = AREASTART(1);     ! START OF CODE
   INTEGER(FBASE+12) = 1;               ! OBJECT FILE CODE
   INTEGER(FBASE+24) = LDSTART-FBASE;   ! START OF LDATA
   H(0) = 14
   CYCLE  I = 1,1,14
      H(I) = 0
   REPEAT 
   H(12) = LDSTART-FBASE+68;            ! START OF OBJDATA RECORD
   TON = TBASE
   CYCLE  I = 1,1,7
      BASE(I) = FBASE+AREASTART(I)
   REPEAT 
   -> LSWITCH
LSW(41):


LSW(42):


LSW(43):


LSW(44):


LSW(45):


LSW(46):


LSW(47):

   R0 == RECORD(TON)
   J = R0_FILLER;                       ! NO. OF COPIES
   L = R0_DATALEN
   K = BASE(I-40)+R0_LA
   WHILE  J > 0 CYCLE 
      MOVE(L,TON+16,K)
      K = K+L
      J = J-1
   REPEAT 
   -> NEXT
LSW(31):


LSW(32):


LSW(33):


LSW(34):


LSW(35):


LSW(36):


LSW(37):

   I = I-30
LSW(1):


LSW(2):


LSW(3):


LSW(4):


LSW(5):

   I = BASE(I)
   R0 == RECORD(TON)
   IF  R0_DATALEN < 0 THEN  START ;     ! FILL
      FILL(-R0_DATALEN,R0_LA+I,R0_FILLER)
   FINISH  ELSE  START 
      MOVE(R0_DATALEN,ADDR(R0_FILLER),R0_LA+I)
   FINISH 
LSW(11):


LSW(12):


LSW(13):


LSW(14):


LSW(15):


LSW(16):


LSW(18):


LSW(19):


LSW(25):


NEXT:

   TON = TON+RECLEN
LSWITCH:

   IF  BYTEINTEGER(TON) = X'81' START 
      MONITOR 
      DUMP(TON-20000,TON+32)
      STOP 
   FINISH 
   I = INTEGER(TON)
   RECLEN = (I<<8)>>8
   I = I>>24
   -> LSW(I)
LSW(0):

   TON = TON+8;                         ! DATA REF LIST ENTRY
   -> LSWITCH
LSW(6):


LSW(7):

CHANGECONTEXT;      !FINISHED WITH COMPILER - LOOSE FROM WORKING SET
   UNLESS  TON = TBASE THEN  START ;    ! NOTFIRST R6 REFERS TO LAST T6
      CYCLE  I = 1,1,7
         BASE(I) = (BASE(I)+R6_AREALEN(I)+7)&X'FFFFFFF8'
      REPEAT 
   FINISH 
   R6 == RECORD(TON)
   -> NEXT UNLESS  R6_TYPE>>24 = 7
   L = LDSTART+132;                     ! SPACE FOR LISTHEADS+OBJDATA
   J = HEAD(11)
   WHILE  J # 0 CYCLE 
      R1 == RECORD(J)
      INTEGER(L) = H(1)
      H(1) = L-FBASE
      INTEGER(L+4) = R1_LOC
      STRING(L+8) = R1_NAME
      L = (L+12+LENGTH(R1_NAME))&X'FFFFFFFC'
      J = R1_LINK
   REPEAT 
   J = HEAD(14)
   WHILE  J # 0 CYCLE 
      R4 == RECORD(J)
      INTEGER(L) = H(4)
      H(4) = L-FBASE
      MOVE(12,ADDR(R4_DISP),L+4)
      STRING(L+16) = R4_NAME
      L = (L+20+LENGTH(R4_NAME))&X'FFFFFFFC'
      J = R4_LINK
   REPEAT 
   CYCLE  I = 7,1,8;                    ! EXREF, DYNAMIC XREF
      J = HEAD(I+5)
      WHILE  J # 0 CYCLE 
         R1 == RECORD(J)
         INTEGER(L) = H(I)
         H(I) = L-FBASE
         INTEGER(L+4) = R1_LOC
         STRING(L+8) = R1_NAME
         L = (L+12+LENGTH(R1_NAME))&X'FFFFFFFC'
         J = R1_LINK
      REPEAT 
   REPEAT 
!*
   J = HEAD(15);                        ! DATA REFS
   WHILE  J # 0 CYCLE 
      R9 == RECORD(J)
      INTEGER(L) = H(9)
      H(9) = L-FBASE
      I = L+4
      INTEGER(L+8) = R9_L
      STRING(L+12) = R9_NAME
      L = (L+16+LENGTH(R9_NAME))&X'FFFFFFFC'
      K = R9_COUNT
      INTEGER(I) = (L-FBASE)!(K>>31)<<31
      K = (K<<1)>>1
      INTEGER(L) = K
      I = R9_REFLINK
      WHILE  I # 0 CYCLE 
         I = I+WORKAD
         INTEGER(L+K<<2) = INTEGER(I+4);! STORE FROM END TO GIVE ORDERED ARRAY
         I = INTEGER(I)
         K = K-1
      REPEAT 
      L = L+INTEGER(L)<<2+4
      J = R9_LINK
   REPEAT 
!*
   J = HEAD(18);                        ! MODIFY ADDRESSES IN CODE
   WHILE  J # 0 CYCLE 
      R8 == RECORD(J)
      IF  R8_CODEADDR < AREALENGTH(1) THEN  START 
         I = FBASE+AREASTART(1)+R8_CODEADDR
         IF  I&2 = 0 THEN  START ;      ! 1 WORD ALLIGNED
            K = (INTEGER(I)<<14+R8_ADDRFIELD<<14)>>14
            INTEGER(I) = (INTEGER(I)&X'FFFC0000')!K
         FINISH  ELSE  START 
            K = ((INTEGER(I-2)&3)<<30)!(INTEGER(I+2)>>2)
            K = (K+R8_ADDRFIELD<<14)>>14
            INTEGER(I-2) = (INTEGER(I-2)&X'FFFFFFFC')!(K>>16)
            INTEGER(I+2) = (INTEGER(I+2)&X'0000FFFF')!(K<<16)
         FINISH 
      FINISH 
      J = R8_LINK
   REPEAT 
!*
   J = HEAD(19);                        ! INDIVIDUAL RELOCATION BLOCKS
   IF  J # 0 THEN  START 
      H(14) = L-FBASE
      INTEGER(L) = 0
      INTEGER(L+4) = TYPE19NUM
      L = L+8
   FINISH 
   WHILE  J # 0 CYCLE 
      R7 == RECORD(J)
      INTEGER(L) = R7_AREALOC
      INTEGER(L+4) = R7_BASELOC
      L = L+8
      J = R7_LINK
   REPEAT 
   J = HEAD(25);                        ! GENERALISED RELOCATION BLOCKS
   WHILE  J > 0 CYCLE 
      R7 == RECORD(J)
      INTEGER(L) = H(14)
      H(14) = L-FBASE
      K = INTEGER(J+8)<<3+4
      MOVE(K,J+8,L+4)
      L = L+K+4
      J = R7_LINK
   REPEAT 
!******* AREA SUMMARY
   INTEGER(FBASE+28) = L-FBASE
   INTEGER(L) = 7;                      ! NO. OF AREAS
   L = L+4
   CYCLE  I = 1,1,7
      INTEGER(L) = AREASTART(I)
      INTEGER(L+4) = AREALENGTH(I)
      INTEGER(L+8) = 0
      L = L+12
   REPEAT 
   L = (L+11)&X'FFFFFFF8'
   INTEGER(FBASE) = L-FBASE
!      OBJDATA_LENGTH = 68
                                        ! LENGTH OF CURRENT RECORD FORMAT
!      MOVE(68,ADDR(OBJDATA_LENGTH),LDSTART+68)
   H(2) = NUMEXT
   H(3) = NUMFIXUPS
   MOVE(60,ADDR(H(0)),LDSTART)
   RETURN 
END ;                                   ! LPUT
!*
ENDOFFILE