        .TITLE  IMP PERM ROUTINES
;
; R.D. EAGER
; UNIVERSITY OF KENT AT CANTERBURY
; MARCH 1976
;
        .SBTTL  MANIFEST CONSTANTS
;
; ASSEMBLY OPTIONS
;
;
; THE FOLLOWING SYMBOL SHOULD BE DEFINED IF THE TARGET
; MACHINE HAS THE EXTENDED INSTRUCTION SET (EIS) OPTION
;
;       EIS     = 1
;
        .ENABL  ABS             ;ELIMINATES LINKING, AND THUS THE DOS HEADER
;
; REGISTER NAMES
;
        R0      = %0
        R1      = %1
        R2      = %2
        R3      = %3
        R4      = %4
        R5      = %5
        SP      = %6
        PC      = %7
        GLA     = %4            ;GLOBAL LINKAGE AREA POINTER
        LNB     = %5            ;LOCAL NAMEBASE POINTER
;
; CHARACTER CODES
;
        LF      = 12
        CR      = 15
        SPACE   = 40
;
; TRAP CODES
;
        MONITOR = 0             ;MONITOR ENTRY
        RDSYM   = 1             ;READSYMBOL -> R0
        NXTSYM  = 2             ;NEXTSYMBOL -> R0
        PRSYM   = 3             ;R0 -> PRINTSYMBOL
        SEL.IN  = 4             ;SELECTINPUT(R0)
        SEL.OUT = 5             ;SELECTOUTPUT(R0)
        ILLEGAL = 6             ;TRAPS ABOVE THIS ARE ILLEGAL
;
; PROGRAM TERMINATION CODES
;
        ABORT   = -1            ;(-VE). GIVES 'ABORT' MESSAGE
        NORMAL  = 0             ;NO MESSAGE
        EXB     = 1             ;STACK OVERFLOW
        SID     = 2             ;SYMBOL IN DATA
        OFAIL   = 3             ;CHANNEL OPEN FAILURE
        NOTRAP  = 4             ;UNKNOWN TRAP CODE
        NSL     = 5             ;NON-EXISTENT SWITCH LABEL
        EOF     = 8.            ;READ PAST END-OF-FILE
        ILLIO   = 9.            ;MISUSE OF I/O SYSTEM
        INVSEL  = 10.           ;INVALID CHANNEL SELECTION
;
; OFFSETS OF ITEMS IN GLOBAL LINKAGE AREA
;
        PROG    = 2             ;PROGRAM BASE
        LIMIT   = 4             ;STACK LIMIT
       .SBTTL  ENTRY VECTOR
;
        .ASECT
        .=-2
;
TOP:    LAST-TOP/2
        ENTER1/2
        ENTER2/2
        ENTER3/2
        ENTER4/2
        ENTER5/2
        EXIT1/2
        EXIT2/2
        EXIT3/2
        EXIT4/2
        EXIT5/2
        TEXIT1/2
        TEXIT2/2
        TEXIT3/2
        TEXIT4/2
        TEXIT5/2
        RSHIFT/2
        SJUMP/2
        MON/2
        STOP/2
        RMOVE/2
        RCLEAR/2
        0
        PXOR/2
        PMUL/2
        PDIV/2
        LSHIFT/2
        0
        0
        0
        0
        0
;
; PERM ROUTINES
;
        0                       ;31 - DISPLAY
        0                       ;32 - PROMPT
        SELOUT/2                ;33 - SELECT OUTPUT
        SELIN/2                 ;34 - SELECT INPUT
        0                       ;35 - MATCH
        0                       ;36 - FROM STRING
        0                       ;37 - CHARNO
        0                       ;38 - TO STRING
        0                       ;39 - LENGTH
        READ/2                  ;40 - READ
        SSYM/2                  ;41 - SKIP SYMBOL
        RSYM/2                  ;42 - READ SYMBOL
        NSYM/2                  ;43 - NEXT SYMBOL
        SPACS/2                 ;44 - SPACES
        SPAC/2                  ;45 - SPACE
        NEWLS/2                 ;46 - NEWLINES
        NEWL/2                  ;47 - NEWLINE
        PSTR/2                  ;48 - PRINT STRING
        PSYM/2                  ;49 - PRINT SYMBOL
        WRIT/2                  ;50 - WRITE
        0                       ;51 - CLOSE INPUT
        0                       ;52 - CLOSE OUTPUT
        SVC/2                   ;53 - SVC (EMT CALL)
        INT/2                   ;54 - INTEGER
        INT/2                   ;55 - BYTEINTEGER
        INT/2                   ;56 - ADDR
        ACC/2                   ;57 - ACC
LAST:
       .SBTTL  LOGICAL SHIFT ROUTINES
;
RSHIFT: ENDB-RSHIFT-2/2
        MOV     (SP)+,R3        ;RETURN LINK
        MOV     (SP)+,R0        ;NUMBER OF PLACES TO SHIFT
        MOV     (SP)+,R1        ;WORD TO BE SHIFTED
RS1:    DEC     R0
        BLT     RS2
        CLC
        ROR     R1
        BR      RS1
RS2:    MOV     R3,PC
ENDB:
;
LSHIFT: ENDLSH-LSHIFT-2/2
        MOV     (SP)+,R3        ;RETURN LINK
        MOV     (SP)+,R0        ;NUMBER OF PLACES TO SHIFT
        MOV     (SP)+,R1        ;WORD TO BE SHIFTED
LS1:    DEC     R0
        BLT     LS2
        ASL     R1
        BR      LS1
LS2:    MOV     R3,PC
ENDLSH:
       .SBTTL  SWITCH HANDLER
;
; ON ENTRY :-
;    R1 = SWITCH INDEX
;    R0 = DISPLACEMENT OF SWITCH VECTOR WITHIN GLA
;
; SWITCH VECTOR IS OF THE FORM :-
;    <UB>, <LB>, <SW1>, <SW2>, ....... , <SWN>
;
SJUMP:  ENDC-SJUMP-2/2
        ADD     GLA,R0
        CMP     R1,(R0)+        ;SWITCH INDEX OVER UPPER BOUND?
        BGT     SWERR           ;YES - ERROR
        CMP     R1,(R0)         ;SWITCH INDEX BELOW LOWER BOUND?
        BLT     SWERR           ;YES - ERROR
        SUB     (R0)+,R1        ;NORMALISE SWITCH INDEX RELATIVE TO ZERO
        ASL     R1              ;CONVERT TO A BYTE OFFSET
        ADD     R1,R0           ;CONSTRUCT INDEX INTO SWITCH VECTOR
        MOV     (R0),R2         ;GET NEW PC VALUE FROM SWITCH VECTOR
        BEQ     SW1             ;DROP THROUGH SWITCH IF ENTRY IS ZERO
        ADD     PROG(GLA),R2    ;RELOCATE PC VALUE RELATIVE TO PROGRAM BASE
        MOV     R2,(SP)         ;PUT NEW PC VALUE ON STACK FOR RTS
SW1:    RTS     PC              ;GO TO SELECTED CODE OR DROP THROUGH
SWERR:  MOV     #NSL,R0         ;SWITCH VALUE OUT OF RANGE ...
        TRAP    MONITOR         ;... SO GIVE SUITABLE TERMINATION CODE
ENDC:
       .SBTTL  PROGRAM TERMINATION ROUTINES
;
;
; %STOP OPERATION
;
STOP:   ENDE-STOP-2/2
        CLR     R0              ;CODE FOR SUCCESSFUL TERMINATION IS ZERO
        TRAP    MONITOR
ENDE:
;
; %MONITOR OPERATION
;
MON:    ENDD-MON-2/2
        TRAP    MONITOR         ;TERMINATION CODE IS IN R0 ON ENTRY
ENDD:
       .SBTTL  I/O CHANNEL SELECTION ROUTINES
;
; %ROUTINE SELECT INPUT(%INTEGER N)
;
SELIN:  ENDJ-SELIN-2/2
        MOV     2(SP),R0        ;CHANNEL NUMBER
        MOV     (SP)+,(SP)
        TRAP    SEL.IN
        RTS     PC
ENDJ:
;
; %ROUTINE SELECT OUTPUT(%INTEGER N)
;
SELOUT: ENDK-SELOUT-2/2
        MOV     2(SP),R0        ;CHANNEL NUMBER
        MOV     (SP)+,(SP)
        TRAP    SEL.OUT
        RTS     PC
ENDK:
       .SBTTL  SYMBOL I/O ROUTINES
;
; %ROUTINE READ SYMBOL(%INTEGERNAME N)
;
RSYM:   ENDG-RSYM-2/2
        TRAP    RDSYM
        MOV     (SP)+,R1
        MOV     R0,@(SP)+
        MOV     R1,PC
ENDG:
;
; %ROUTINE PRINT SYMBOL(%INTEGER N)
;
PSYM:   ENDH-PSYM-2/2
        MOV     (SP)+,R1
        MOV     (SP)+,R0
        TRAP    PRSYM
        MOV     R1,PC
ENDH:
;
; %INTEGERFN NEXT SYMBOL
;
NSYM:   ENDI-NSYM-2/2
        TRAP    NXTSYM
        MOV     R0,R1
        RTS     PC
ENDI:
;
; %ROUTINE SKIP SYMBOL
;
SSYM:   ENDS-SSYM-2/2
        TRAP    RDSYM
        RTS     PC
ENDS:
       .SBTTL  SPACE AND NEWLINE OUTPUT ROUTINES
;
; %ROUTINE SPACE
;
SPAC:   ENDT-SPAC-2/2
        MOV     #SPACE,R0
        TRAP    PRSYM
        RTS     PC
ENDT:
;
; %ROUTINE NEWLINE
;
NEWL:   ENDU-NEWL-2/2
        MOV     #CR,R0          ;ADD A CARRIAGE RETURN
        TRAP    PRSYM
        MOV     #LF,R0
        TRAP    PRSYM
        RTS     PC
ENDU:
;
; %ROUTINE SPACES(%INTEGER N)
;
SPACS:  ENDV-SPACS-2/2
        MOV     2(SP),R2        ;NUMBER OF SPACES TO OUTPUT
        MOV     (SP)+,(SP)
SP1:    DEC     R2
        BLT     SP2
        MOV     #SPACE,R0
        TRAP    PRSYM
        BR      SP1
SP2:    RTS     PC
ENDV:
;
; %ROUTINE NEWLINE(%INTEGER N)
;
NEWLS:  ENDW-NEWLS-2/2
        MOV     2(SP),R2        ;NUMBER OF NEWLINES TO OUTPUT
        MOV     (SP)+,(SP)
NL1:    DEC     R2
        BLT     NL2
        MOV     #CR,R0          ;ADD A CARRIAGE RETURN
        TRAP    PRSYM
        MOV     #LF,R0
        TRAP    PRSYM
        BR      NL1
NL2:    RTS     PC
ENDW:
       .SBTTL  MOVE BLOCK AND CLEAR BLOCK (OF STORE)
;
; BLOCK MOVE ROUTINE
; ON ENTRY :-
;    R0 = LENGTH OF BLOCK (IN WORDS)
;    R1 = START ADDRESS OF DESTINATION AREA
;    R2 = START  ADDRESS OF SOURCE AREA
;
RMOVE:  ENDL-RMOVE-2/2
RM1:    MOV     (R2)+,(R1)+
        DEC     R0
        BGT     RM1
        RTS     PC
ENDL:
;
; CLEAR BLOCK ROUTINE
; ON ENTRY :-
;    R0 = LENGTH OF BLOCK (IN WORDS)
;    R1 = START ADDRESS OF BLOCK
;
RCLEAR: ENDM-RCLEAR-2/2
RC1:    CLR     (R1)+
        DEC     R0
        BGT     RC1
        RTS     PC
ENDM:
       .SBTTL  ROUTINE ENTRY AND EXIT CODE
;
ENTER1: END1-ENTER1-2/2
        TST     (SP)+           ;REMOVE UNWANTED PREVIOUS R0 VALUE
        MOV     (SP),-(LNB)     ;SAVE RETURN LINK
        MOV     -(GLA),-(LNB)
        MOV     (R0)+,-(LNB)
        ADD     SP,(LNB)
        MOV     LNB,(SP)
        MOV     SP,LNB
        MOV     LNB,(GLA)+
        ADD     (R0)+,SP
        CMP     SP,LIMIT(GLA)   ;STACK OVERFLOW?
        BLOS    E1EXB           ;YES
        MOV     R0,PC           ;NO - ENTER ROUTINE
E1EXB:  MOV     LNB,SP          ;ENSURE ERROR ROUTINES HAVE A STACK
        MOV     #EXB,R0
        TRAP    MONITOR         ;FORCE TERMINATION
END1:
;
EXIT1:  END2-EXIT1-2/2
        MOV     (LNB),LNB
        MOV     (LNB)+,SP
        MOV     (LNB)+,-2(GLA)
        MOV     (LNB)+,PC
END2:
;
ENTER2: END3-ENTER2-2/2
        TST     (SP)+           ;REMOVE UNWANTED PREVIOUS R0 VALUE
        MOV     (SP),-(LNB)     ;SAVE RETURN LINK
        MOV     -4(GLA),-(LNB)
        MOV     (R0)+,-(LNB)
        ADD     SP,(LNB)
        MOV     LNB,(SP)
        MOV     SP,LNB
        MOV     LNB,-4(GLA)
        ADD     (R0)+,SP
        CMP     SP,LIMIT(GLA)   ;STACK OVERFLOW?
        BLOS    E2EXB           ;YES
        MOV     R0,PC           ;NO - ENTER ROUTINE
E2EXB:  MOV     LNB,SP          ;ENSURE ERROR ROUTINES HAVE A STACK
        MOV     #EXB,R0
        TRAP    MONITOR         ;FORCE TERMINATION
END3:
;
EXIT2:  END4-EXIT2-2/2
        MOV     (LNB),LNB
        MOV     (LNB)+,SP
        MOV     (LNB)+,-4(GLA)
        MOV     (LNB)+,PC
END4:
;
ENTER3: END5-ENTER3-2/2
        TST     (SP)+           ;REMOVE UNWANTED PREVIOUS R0 VALUE
        MOV     (SP),-(LNB)     ;SAVE RETURN LINK
        MOV     -6(GLA),-(LNB)
        MOV     (R0)+,-(LNB)
        ADD     SP,(LNB)
        MOV     LNB,(SP)
        MOV     SP,LNB
        MOV     LNB,-6(GLA)
        ADD     (R0)+,SP
        CMP     SP,LIMIT(GLA)   ;STACK OVERFLOW?
        BLOS    E3EXB           ;YES
        MOV     R0,PC           ;NO - ENTER ROUTINE
E3EXB:  MOV     LNB,SP          ;ENSURE ERROR ROUTINES HAVE A STACK
        MOV     #EXB,R0
        TRAP    MONITOR         ;FORCE TERMINATION
END5:
;
EXIT3:  END6-EXIT3-2/2
        MOV     (LNB),LNB
        MOV     (LNB)+,SP
        MOV     (LNB)+,-6(GLA)
        MOV     (LNB)+,PC
END6:
;
ENTER4: END7-ENTER4-2/2
        TST     (SP)+           ;REMOVE UNWANTED PREVIOUS R0 VALUE
        MOV     (SP),-(LNB)     ;SAVE RETURN LINK
        MOV     -10(GLA),-(LNB)
        MOV     (R0)+,-(LNB)
        ADD     SP,(LNB)
        MOV     LNB,(SP)
        MOV     SP,LNB
        MOV     LNB,-10(GLA)
        ADD     (R0)+,SP
        CMP     SP,LIMIT(GLA)   ;STACK OVERFLOW?
        BLOS    E4EXB           ;YES
        MOV     R0,PC           ;NO - ENTER ROUTINE
E4EXB:  MOV     LNB,SP          ;ENSURE ERROR ROUTINES HAVE A STACK
        MOV     #EXB,R0
        TRAP    MONITOR         ;FORCE TERMINATION
END7:
;
EXIT4:  END8-EXIT4-2/2
        MOV     (LNB),LNB
        MOV     (LNB)+,SP
        MOV     (LNB)+,-10(GLA)
        MOV     (LNB)+,PC
END8:
;
ENTER5: END9-ENTER5-2/2
        TST     (SP)+           ;REMOVE UNWANTED PREVIOUS R0 VALUE
        MOV     (SP),-(LNB)     ;SAVE RETURN LINK
        MOV     -12(GLA),-(LNB)
        MOV     (R0)+,-(LNB)
        ADD     SP,(LNB)
        MOV     LNB,(SP)
        MOV     SP,LNB
        MOV     LNB,-12(GLA)
        ADD     (R0)+,SP
        CMP     SP,LIMIT(GLA)   ;STACK OVERFLOW?
        BLOS    E5EXB           ;YES
        MOV     R0,PC           ;NO - ENTER ROUTINE
E5EXB:  MOV     LNB,SP          ;ENSURE ERROR ROUTINES HAVE A STACK
        MOV     #EXB,R0
        TRAP    MONITOR         ;FORCE TERMINATION
END9:
;
EXIT5:  ENDA-EXIT5-2/2
        MOV     (LNB),LNB
        MOV     (LNB)+,SP
        MOV     (LNB)+,-12(GLA)
        MOV     (LNB)+,PC
ENDA:
       .SBTTL  EXIT ROUTINES
;
TEXIT1: ENDN-TEXIT1-2/2
        MOV     (LNB),LNB
        MOV     (LNB)+,SP
        MOV     (LNB)+,-2(GLA)
        SEZ
        JMP     @(LNB)+
ENDN:
;
TEXIT2: ENDO-TEXIT2-2/2
        MOV     (LNB),LNB
        MOV     (LNB)+,SP
        MOV     (LNB)+,-4(GLA)
        SEZ
        JMP     @(LNB)+
ENDO:
;
TEXIT3: ENDP-TEXIT3-2/2
        MOV     (LNB),LNB
        MOV     (LNB)+,SP
        MOV     (LNB)+,-6(GLA)
        SEZ
        JMP     @(LNB)+
ENDP:
;
TEXIT4: ENDQ-TEXIT4-2/2
        MOV     (LNB),LNB
        MOV     (LNB)+,SP
        MOV     (LNB)+,-10(GLA)
        SEZ
        JMP     @(LNB)+
ENDQ:
;
TEXIT5: ENDR-TEXIT5-2/2
        MOV     (LNB),LNB
        MOV     (LNB)+,SP
        MOV     (LNB)+,-12(GLA)
        SEZ
        JMP     @(LNB)+
ENDR:
       .SBTTL  EXCLUSIVE 'OR' OPERATION
;
PXOR:   ENDXOR-PXOR-2/2
        MOV     (SP)+,R3        ;RETURN ADDRESS
        MOV     (SP)+,R0        ;B
        MOV     (SP)+,R1        ;A
        MOV     R0,R2
        BIC     R1,R2           ;B & \A
        BIC     R0,R1           ;\B & A
        BIS     R2,R1           ;(B & \A) ! (\B & A)
        MOV     R3,PC
ENDXOR:
       .SBTTL  MULTIPLY AND DIVIDE OPERATIONS
;
PMUL:   ENDMUL-PMUL-2/2
        MOV     (SP)+,R1        ;RETURN ADDRESS
        MOV     (SP)+,R0        ;B
        MOV     (SP),R2         ;A
        MOV     R1,(SP)         ;SAVE RETURN ADDRESS FOR 'RTS'
        MOV     #20,R3          ;LOOP COUNT
        CLR     R1              ;INITIALISE RESULT
MUL1:   ROR     R0
        BCC     MUL2            ;-> IF CARRY = 0
        ADD     R2,R1           ;ACCUMULATE RESULT
MUL2:   ASL     R2
        DEC     R3
        BGT     MUL1
        RTS     PC
ENDMUL:
;
PDIV:   ENDDIV-PDIV-2/2
        MOV     (SP)+,R1        ;RETURN ADDRESS
        MOV     #1,R0           ;SIGN OF EVENTUAL RESULT
        MOV     (SP)+,R3        ;B
        BGE     DIV1
        NEG     R3              ;OBTAIN ABSOLUTE VALUE OF B
        NEG     R0              ;AND SET SIGN INDICATION
DIV1:   MOV     (SP),R2         ;A
        BGE     DIV2
        NEG     R2              ;OBTAIN ABSOLUTE VALUE OF A
        NEG     R0              ;AND SET SIGN INDICATION
DIV2:   MOV     R1,(SP)         ;SAVE RETURN ADDRESS FOR 'RTS'
        MOV     R0,-(SP)        ;SIGN OF RESULT
        MOV     #20,-(SP)       ;LOOP COUNT
        CLR     R0              ;REMAINDER
        CLR     R1              ;RESULT
DIV3:   ASL     R0
        ASL     R1
        ROL     R2
        ADC     R0
        CMP     R0,R3
        BLT     DIV4
        INC     R1
        SUB     R3,R0
DIV4:   DEC     (SP)
        BNE     DIV3
        TST     (SP)+           ;REMOVE COUNT (NOW ZERO)
        TST     (SP)+           ;EXAMINE SIGN (AND REMOVE)
        BGE     DIV5
        NEG     R1              ;CHANGE SIGN OF RESULT IF NECESSARY
DIV5:   RTS     PC
ENDDIV:
       .SBTTL  %ROUTINE PRINTSTRING(%STRING S)
;
PSTR:   ENDPST-PSTR-2/2
        MOV     (SP)+,R3        ;RETURN ADDRESS
        MOV     (SP)+,R1        ;ADDRESS OF STRING
        MOVB    (R1)+,R2        ;STRING LENGTH
        BIC     #177400,R2      ;REMOVE RUBBISH
        BEQ     PST3            ;CASE OF NULL STRING
PST1:   MOVB    (R1)+,R0        ;GET NEXT CHARACTER FROM STRING
        CMPB    #LF,R0          ;IS IT A LINEFEED?
        BNE     PST2            ;NO - JUST PRINT IT
        MOV     #CR,R0          ;YES - ADD A CARRIAGE RETURN
        TRAP    PRSYM
        MOV     #LF,R0          ;NOW THE LINEFEED ITSELF
PST2:   TRAP    PRSYM
        DEC     R2
        BNE     PST1
PST3:   MOV     R3,PC           ;RETURN
ENDPST:
       .SBTTL  %ROUTINE READ(%NAME A)
;
READ:   ENDRD-READ-2/2
READ1:  TRAP    NXTSYM
        CMPB    #CR,R0
        BEQ     READ2           ;IGNORE CARRIAGE RETURN
        CMPB    #LF,R0
        BEQ     READ2           ;AND LINEFEED
        CMPB    #SPACE,R0
        BNE     READ3
READ2:  TRAP    RDSYM           ;SKIP THAT CHARACTER
        BR      READ1           ;AND TRY AGAIN
READ3:  CLR     -(SP)           ;CLEAR MINUS FLAG
        CLR     R3              ;CLEAR 'FOUND DIGIT' FLAG
        CLR     R1
        CMPB    #'-,R0          ;MINUS SIGN?
        BNE     READ5           ;NO
        COM     (SP)            ;YES - SET MINUS FLAG
READ4:  TRAP    RDSYM
        TRAP    NXTSYM
READ5:  CMPB    #'0,R0
        BGT     READ6           ;BRANCH IF NOT DIGIT
        CMPB    #'9,R0
        BLT     READ6           ;BRANCH IF NOT DIGIT
        SUB     #'0,R0
        INC     R3              ;REMEMBER AT LEAST ONE DIGIT WAS FOUND
        MOV     R1,R2
        ASL     R2
        ASL     R2
        ADD     R2,R1
        ASL     R1
        ADD     R0,R1
        BR      READ4
READ6:  TST     R3              ;FOUND AT LEAST ONE DIGIT?
        BNE     READ7           ;BRANCH IF YES
        MOV     #SID,R0
        TRAP    MONITOR         ;ERROR - SYMBOL IN DATA
READ7:  TST     (SP)+
        BEQ     READ8
        NEG     R1
READ8:  MOV     (SP)+,R3
        MOV     R1,@(SP)+
        MOV     R3,PC
ENDRD:
       .SBTTL  %ROUTINE WRITE(%INTEGER I, J)
;
WRIT:   ENDWRIT-WRIT-2/2
        MOV     2(SP),R3        ;NUMBER OF PLACES
        MOV     4(SP),R1        ;VALUE TO PRINT
        BGE     WRIT0           ;< 0?
        NEG     R1              ;MAKE IT POSITIVE
WRIT0:  MOV     SP,R2           ;REFERENCE POINTER
WRIT1:
.IF DF EIS
        CLR     R0              ;EXTEND TO 32 BITS
        DIV     #12,R0          ; //10
        MOV     R0,-(SP)        ;REMAINDER AND QUOTIENT ARE REVERSED
        MOV     R1,R0
        MOV     (SP)+,R1
.IFF
        MOV     R2,-(SP)
        MOV     R3,-(SP)
        MOV     R1,-(SP)
        MOV     #12,-(SP)
        JSR     SP,#30          ;SPECIAL - FILLED IN BY CODE GENERATOR
        MOV     (SP)+,R3
        MOV     (SP)+,R2
.ENDC
        ADD     #'0,R0
        MOV     R0,-(SP)        ;TOSTRING IT
        DEC     R3              ;REMOVE ONE PLACE
        TST     R1              ;= 0?
        BNE     WRIT1           ;NO, => MORE LEFT
        MOV     #SPACE,-(SP)    ;NULL SIGN
        TST     4(R2)
        BGE     WRIT2
        MOV     #'-,(SP)        ;IT'S NEGATIVE
WRIT2:  DEC     R3
        BLT     WRIT3           ;ENOUGH PLACES
        MOV     #SPACE,-(SP)
        BR      WRIT2
WRIT3:  MOV     (SP)+,R0
        TRAP    PRSYM
        CMP     SP,R2           ;BACK TO REFERENCE YET?
        BNE     WRIT3           ;NO
        MOV     (SP)+,(SP)
        MOV     (SP)+,(SP)
        RTS     PC
ENDWRIT:
       .SBTTL  SVC, MAPS, ADDR, ACC AND RECORD
;
; %ROUTINE SVC(%INTEGER EP, %BYTEINTEGERNAME R0, R1)
;
SVC:    ENDSVC-SVC-2/2
        MOV     (SP)+,R3        ;RETURN ADDRESS
        MOV     (SP)+,R1        ;R1 VALUE
        MOV     (SP)+,R0        ;R0 VALUE
        MOVB    (SP)+,6(GLA)    ;EMT CODE (EMT 0 IN GLA)
        JSR     PC,6(GLA)       ;GO DO THE EMT
        MOV     R3,PC           ;RETURN
ENDSVC:
;
; %INTEGERMAP INTEGER(%INTEGER N)
; %BYTEINTEGERMAP BYTEINTEGER(%INTEGER N)
; %INTEGERFN ADDR(%INTEGERNAME N)
;
; THE CODE IS IDENTICAL FOR ALL THREE!!!
;
INT:    ENDINT-INT-2/2
        MOV     (SP)+,R3        ;RETURN ADDRESS
        MOV     (SP)+,R1        ;ADDRESS -> RESULT REGISTER
        MOV     R3,PC           ;RETURN
ENDINT:
;
; %INTEGERFN ACC
;
ACC:    ENDACC-ACC-2/2
        MOV     R0,R1           ;R0 -> RESULT REGISTER
        RTS     PC              ;RETURN
ENDACC:
;
        .END

