DataMuseum.dk

Presents historical artifacts from the history of:

Bogika Butler

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Bogika Butler

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦a6a4132fa⟧ TextFile

    Length: 47360 (0xb900)
    Types: TextFile
    Names: »KNELOP.SAA«

Derivation

└─⟦0b578df25⟧ Bits:30009789/_.ft.Ibm2.50006602.imd Mogens Pelles Zilog 80,000 / EOS projekt
    └─⟦this⟧ »KNELOP.SAA« 
└─⟦798d317aa⟧ Bits:30009789/_.ft.Ibm2.50006626.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦798d317aa⟧ Bits:30009789/_.ft.Ibm2.50006628.imd Mogens Pelles Zilog 80,000 / EOS projekt
    └─⟦this⟧ »KNELOP.SAA« 

TextFile

 
***********************************************************************
*                       Copyright 1984 by                             *
*                       NCR Corporation                               *
*                       Dayton, Ohio  U.S.A.                          *
*                       All Rights Reserved                           *
***********************************************************************
*                       EOS Software produced by:                     *
*                       NCR Systems Engineering - Copenhagen          *
*                       Copenhagen                                    *
*                       DENMARK                                       *
***********************************************************************
 
  ENDI                              END  "INDIRECT";
 
    LEA    (A1,D1),A6                 A6:=POINTER:=POINTER_STRUCT+POINTER_REL;
    MOVE.B PT_KIN(A6),D2              D2:=POINTER.KIND; "WORD CLEARED AT ENTRY"
***
    PRT_MEM C_PT,(A6),FP_SIZ
  ELSE.S                            ELSE  "VOID"
    SUB    #2,A4                      ARGUMENT ADDR:=UPDATED
  ENDI                              END;
 
    MOVE   (A7)+,D3                   RESTORE D3;
***
    PRT_REG C_PT
    CMPA.L A2,A4                      SR:=NE;  "OK"
    RTS                               RETURN
 
ER_ILLE    EQU *
    ADD    #2,A7                      RELEASE SAVED D3
    BRA    ER_ADDR                    GOTO ADDR_ILLEGAL;
 
    PAGE
C_ENT      EQU *                  CHECK ENTITY ARGUMENT, NORMAL CTX
 
*          CALL:                  RETURN:
* A1       -                      POINTER STRUCT  (UNDEF IF VOID ARG.)
* A2       CONTEXT                SAME
* A4       ARGUMENT ADDR          UPDATED
* A5       -                      ENTITY  (ENV, OBJ, OR UNDEF)
* A6       -                      POINTER  (UNDEF IF VOID ARG.)
* D1.W     -                      POINTER REL  (UNDEF IF VOID ARG.)
* D2.W     -                      POINTER KIND  (VOID KIND IF VOID ARG.)
* D4.W     -                      CALL CAP, COPY CONTROL  (AS IN PT_INF)
* D5.W     -                      ENTITY KIND  (ENV, OBJ, NIL, OR INTRPT)
* D6.W     ARGUMENT#              UPDATED
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK.
* SR       -                      NE = OK, EQ = NOT OK
 
* GETS A POINTER ARGUMENT AND RETRIEVES THE ENTITY FROM THE POINTER.
 
    BSR    C_PT                       CHECK POINTER ARG(A1:=PSTR,A6:=PT,
*                                       D1:=PREL,D2:=PT KIND);
    BEQ.S  RETURN                     IF NOT OK THEN RETURN END;
 
C_ENTCOM   EQU *
    CLR    D4                         D4:=CAPS:=0;
    MOVE   D2,D5                      D5:=POINTER_KIND*2
    LSL    #1,D5
    CASEJMP D5                     CASE POINTER_KIND OF
    CASELAB NIL_2
    CASELAB OBJ_2
    CASELAB ENV_2
    CASELAB OWN_2
    CASELAB MAN_2
    CASELAB ENV_2                     "INTERRUPT POINTER"
    CASELAB NIL_2                     "VOID"
 
OBJ_2      EQU *                  OBJ_REF:
    MOVE.B PT_INF(A6),D4              D4:=CALL CAP,COPY CONTROL;
    AND #1<<PT_CC+1<<PT_CON,D4
 
ENV_2      EQU *                  ENV_REF, INTERRUPT POINTER:
    MOVE.L PT_REF(A6),A5              A5:=ENTITY:=POINTER.REF;
    MOVE.B PT_KIN(A6),D5              D5:=ENTITY KIND:=POINTER KIND;
    EXT.W  D5                         "EXTEND TO WORD";  SR:=OK;
    RTS                               RETURN
 
NIL_2      EQU *                  NIL, VOID;
    CLR    D5                         D5:=ENTITY KIND:=NIL;
    CMPA.L A2,A4                      SR:=NE;  "OK"
    RTS                               RETURN
 
OWN_2      EQU *                  OWNER_SET:
    MOVE.L 4(A6),A5                   A5:=ENTITY:=LAST OBJ IN SET;
 
OWN_6A     EQU *                  COMMON WITH FIRST IN SET:
    BTST.B #OB_OCC,OB_STA(A5)
  IF <NE> THEN.S                    IF OBJ.OWNERS_CALL_CAP THEN
    BSET   #PT_CC,D4                  D4:=CAPS:=CALL CAP
  ENDI                              END;
  IF.B #OB_GEOB <EQ> OB_KIN(A5) THEN.S
    TST    GE_CON(A5)               IF GENERAL OBJECT
  IF <NE> THEN.S                    AND CONTROL PROC <> 0 THEN
    BSET   #PT_CON,D4                 D4:=CAPS:=CAPS+COPY CONTROL
  ENDI                              END;
  ENDI
    MOVEQ  #PT_OBJ,D5                 D5:=ENTITY KIND:=OBJ; SR:=OK;
    RTS                               RETURN
 
MAN_2      EQU *                  MAN_SET:
    MOVE.L 4(A6),A5                   A5:=ENTITY:=LAST ENV IN SET;
    MOVEQ  #PT_ENV,D5                 D5:=ENTITY KIND:=ENV; SR:=OK
 
RETURN     EQU *                  "RETURN, COMMON FOR ALL PROCEDURES"
    RTS                               RETURN
 
 
C_ENTRES   EQU *                  CHECK ENTITY, NORMAL OR RESIDENT
 
*          CALL:                  RETURN:
* D3       RESIDENT CTX (<>0)     SAME
* OTHER:   AS C_ENT
 
* IF CALLED FROM A RESIDENT CTX:  CHECKS THAT THE POINTER IS
* NIL, VOID, OR RESIDENT.  OTHERWISE AS C_ENT.
 
    BSR    C_PTRES                    CHECK POINTER RES(D3,...)
    BEQ.S  RETURN                     IF NOT OK THEN RETURN END;
    BSR    C_ENTCOM                   FIND ENTITY; "COMMON WITH C_ENT"
    TST    D3
  IF <NE> THEN.S                    IF RESIDENT CTX
    TST    D5                         AND ENTITY KIND <> NIL
  IF <NE> THEN.S                    THEN
    BTST.B #PT_RES,PT_INF(A6)         IF POINTER NOT RESIDENT
    BEQ    ER_CAP                     THEN CAPABILITY VIOLATION END;
  ENDI                              END;
  ENDI
 
    CMP.L  A2,A4                      SR:=NE; "OK"
    RTS                               RETURN
    PAGE
C_CALL     EQU *                  CHECK CALLABLE OBJECT AND FUNCTION#
 
*          CALL:                  RETURN:
* A0       EXT OR PROC OBJECT     SAME  (USED BY KERNEL OBJECTS)
* A2       CONTEXT                SAME
* A4       ARGUMENT ADDR          UPDATED  (UNDEF IF SR=RETURN)
* A5       -                      OBJECT TO CALL  (UNDEF IF SR=RETURN)
* D3.W     RESIDENT CTX (<>0)     UNDEF  (USED BY KERNEL OBJECTS)
* D4       LOW ARG ADDR (PHYS)    SAME  (UNDEF IF SR=RETURN)
* D5.L     -                      FUNCTION#  (UNDEF IF SR=RETURN)
* D6.W     ARGUMENT#              UPDATED
* D7.L     -                      RESULT IF SR=RETURN, UNDEF IF SR=ENTER
* SR       -                      NE=ENTER CONTEXT, EQ=RETURN  (IN THIS CASE
*                                 A KERNEL OBJECT MAY HAVE BEEN CALLED
*                                 AND SUSPENDED THE CONTEXT)
* OTHER    -                      UNDEF
 
* USES A POINTER ARGUMENT TO DETERMINE THE OBJECT.  CHECKS THE SIGN
* OF THE FUNCTION CODE ACCORDINGLY.  CALLS A KERNEL OBJECT DIRECTLY.
* CHECKS REENTRANCY AND CALL CAP FOR GENERAL OBJECTS.
* IF CALLED FROM A RESIDENT CTX, CHECKS THAT THE POINTER IS RESIDENT OR NIL.
 
 
    MOVE.L D4,D0                      D0:=LOW ARG ADDR;
*                                     CHECK ENTITY(A1/D1/A6:=...,A5:=ENTITY,
    BSR    C_ENTRES                     D2:=PTKIND,D4:=CAPS,D5:=ENTKIND);
    EXG.L  D4,D0                      D0:=CAPS; D4:=LOW ARG ADDR; CCR UNCHANGED
    BEQ    RETURN                     IF NOT OK THEN RETURN END;
    LSL    #1,D5                      D5:=ENTITY_KIND*2;
    CASEJMP D5                        CASE ENTITY_KIND OF
    CASELAB NIL_3
    CASELAB OBJ_3
    CASELAB ENV_3
 
NIL_3      EQU *                  NIL OR VOID:
    CMPI.B #PT_VOI,D2                 IF POINTER KIND <> VOID
    BNE    ER_VALUE                   THEN POINTER VALUE ILLEGAL END;
    MOVE.L CT_OBJ(A2),A5              A5:=OBJECT TO CALL:=CUR_OBJ;
    MOVE.L -(A4),D5                   D5:=FUNCTION#:=NEXT ARGUMENT;
    ADD    #1,D6                      D6:=ARGUMENT# :=...+1;
    RTS                               "SR=ENTER" RETURN;
 
OBJ_3      EQU *                  OBJECT:
    ADD    #1,D6                      D6:=ARGUMENT# :=...+1;
    MOVE.L -(A4),D5                   D5:=FUNCTION# :=NEXT ARGUMENT;
    BLE    ER_FUNC                  IF FUNCTION#<=0 THEN FUNC_ILLEGAL END;
    CLR    D7
    MOVE.B OB_KIN(A5),D7              D0.W :=OBJECT_KIND*2;
    LSL    #1,D7
 
    CASEJMP D7                        CASE OBJECT_KIND OF
    CASELAB GEN_1
    CASELAB GATE_OBJ
    CASELAB COND_OBJ
    CASELAB ER_STATE                  "OPEN OBJECT"
    CASELAB ER_STATE                  "DORMANT OBJECT"
    CASELAB ER_STATE                  "PROCESS OBJECT"
    CASELAB ER_STATE                  "EXTENSION OBJECT"
    CASELAB ER_STATE                  "SEGMENT OBJECT"
    CASELAB ALLOC_OB
    CASELAB SCHEDOBJ
 
* ENTRIES IN KERNEL OBJECTS:  SEE SEPARATE MODULE"
 
 
GEN_1      EQU *                  GENERAL OBJECT:
    BTST   #PT_CC,D0                IF CALL CAP=0 THEN CAP_VIOLATION
    BEQ    ER_CAP                   END;
    BTST.B #OB_REEN,OB_STA(A5)
  IF <EQ> THEN.S                    IF OBJECT.NOT_REENTRANT THEN
    LEA    GE_EX(A5),A6               A6:=OBJECT.EXECUTES_HEAD;
    CMPA.L GE_EX(A5),A6             IF CONTEXTS IN OBJ THEN CONC_ERROR
    BNE    ER_CONC                  END;
  ENDI                              END;
    CMPA.L A2,A4                      SR:=ENTER CONTEXT;  "NE"
    RTS                               RETURN
 
ENV_3      EQU *                  ENVELOPE:
    MOVE.L EN_OBJ(A5),A1              A1:=OBJECT:=ENVELOPE.HOLDING_OBJ;
    CMP.B  #OB_GEOB,OB_KIN(A1)      IF OBJECT NOT GENERAL THEN STATE_ILLEGAL
    BNE    ER_STATE                 END;
    MOVE.L OB_SPA(A1),A6              A6:=TOP_OBJ;
    LEA    SP_ENV(A6),A6              A6:=HEAD ENV CHAIN;
    CMPA.L EN_STK(A5),A6            IF ENVELOPE NOT TOP ENVELOPE
    BNE    ER_STATE                 THEN STATE_ILLEGAL END;
    MOVE.L A1,A5                      A5:=OBJECT;
    MOVE.L -(A4),D5                   D5:=FUNCTION# :=NEXT ARGUMENT;
    ADD    #1,D6                      ARGUMENT#:=...+1; SR:=ENTER;
    RTS                               RETURN;
 
    PAGE
C_SUB      EQU *                  CHECK SUBSEGM ARGUMENT  (NOT VOID)
 
*          CALL:                  RETURN:
* A1       -                      POINTER STRUCT
* A2       CONTEXT                SAME
* A4       ARGUMENT ADDR          UPDATED
* A5       -                      BASE SEGM DESCRIPTOR
* D0.L     -                      TOP RELATIVE ADDR IN BASE SEGM
* D1.W     -                      POINTER REL
* D2.L     -                      LENGTH OF SUBSEGM
* D4.W     -                      CAPS  (READ,WRITE,EXECUTE AS IN OB_STA)
* D5.L     -                      FIRST RELATIVE ADDR IN BASE SEGM
* D6.W     ARGUMENT#              UPDATED
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK
* SR       -                      NE = OK, EQ = NOT OK
 
* GETS AND CHECKS A SUBSEGMENT ARGUMENT.  CHECK FOR POSSIBLE VOID
* ARGUMENT MUST BE DONE BY CALLER.
 
    MOVEM.L A6,-(A7)                  SAVE A6;
    BSR    C_ENT                      CHECK ENTITY (A1:=PSTR,A5:=BASE SEGM,
*                                       A6:=PT,D1:=PREL,D5:=ENTKIN,D2/D4:=...);
    MOVEM.L (A7)+,A6                  RESTORE A6;
    BEQ    RETURN                     IF NOT OK THEN RETURN END;
    CMP.B  #PT_OBJ,D5                 IF ENTKIN <> OBJECT THEN
    BNE    ER_VALUE                     REJECT END;
    CMP.B  #OB_SEOB,OB_KIN(A5)        IF BASE_SEGM.OBJKIN <> SEGMENT THEN
    BNE    ER_STATE                     REJECT END;
    MOVE.W -(A4),D4                   D4:=NEXT ARGUMENT BITS 2:0;
    AND    #7,D4
    LSL    #OB_READ,D4                D4:=CAPS:=
    AND.B  OB_STA(A5),D4                USE BITS AND BASE_SEGM.CAPS;
    MOVE.L -(A4),D5                   D5:=FIRST REL:=NEXT ARGUMENT;
    CMP.L  SE_LEN(A5),D5              IF FIRST REL >= BASE_SEGM.LENGTH "UNSIGNED
    BCC    ER_DATA                    THEN REJECT END;
    MOVE.L -(A4),D2                   D2:=LENGTH:=NEXT ARGUMENT;
    BLE    ER_DATA                    IF LENGTH <= 0 THEN REJECT END;
    MOVE.L D2,D0                      D0:=TOPREL:=
    ADD.L  D5,D0                        LENGTH+FIRST REL;
    CMP.L  SE_LEN(A5),D0              IF TOP REL > BASE_SEGM.LENGTH
    BHI    ER_DATA                    THEN REJECT END;
***
    PRT_REG C_SUB
    TST    D6                         SR:=NE;  "OK"
    RTS                               RETURN;
    PAGE
C_OPEN     EQU *                  CHECK OWNER POINTER AND OPEN OBJECT
 
*          CALL:                  RETURN:
* A0       -                      OBJECT
* A1       -                      POINTER STRUCT
* A2       CONTEXT                SAME
* A4       ARGUMENT ADDR          UPDATED
* A5       -                      OBJECT (=A0)
* A6       -                      POINTER ADDR
* D1.W     -                      POINTER REL
* D2.W     -                      POINTER KIND  ("OWN_SET" IF OK)
* D6.W     ARGUMENT#              UPDATED
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK
* SR       -                      NE = OK, EQ = NOT OK
* D4/D5    -                      UNDEF
 
* GETS AN ENTITY ARGUMENT AND CHECKS FOR OWNER POINTER AND OPEN OBJECT.
* (TYPICALLY USED WHEN ADDING ENV OR KERNEL ENVELOPE TO AN OBJECT).
 
    BSR    C_ENT                      CHECK ENTITY(A1:=PT_STR,A5:=OBJ,A6:=PT,
*                                       D1:=PT_REL,D2:=PTKIND,D4/D5:=...);
    BEQ    RETURN                     IF NOT OK THEN RETURN END;
    CMP.B  #PT_OWN,D2                 IF POINTER KIND <> OWN SET
    BNE    ER_VALUE                   THEN REJECT END;
    CMP.B  #OB_OPOB,OB_KIN(A5)        IF OBJECT KIND <> OPEN
    BNE    ER_STATE                   THEN REJECT END;
    MOVE.L A5,A0                      A0:=A5:=OBJ;
    CMPA.L A2,A4                      SR:=NE; "OK"
    RTS                               RETURN
    PAGE
C_PRIM     EQU *                  CHECK AND GET PRIMARY ENVELOPE
 
*          CALL:                  RETURN:
* A0       -                      OBJECT HOLDING PRIMARY ENVELOPE
* A1       -                      POINTER STRUCT (UNDEF IF VOID ARG)
* A2       CONTEXT                SAME
* A4       ARGUMENT ADDR          UPDATED
* A5       -                      ENVELOPE (PRIMARY OF GENERAL OBJECT)
* A6       -                      UNDEF
* D1       -                      POINTER REL
* D2.W     -                      POINTER KIND
* D6.W     ARGUMENT#              UPDATED
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK
* SR       -                      NE = OK, EQ = NOT OK
* D4/D5    -                      UNDEF
 
* GETS AN ENTITY ARGUMENT AND CHECKS FOR VOID OR PRIMARY ENVELOPE.
* (TYPICALLY USED WHEN MODIFYING A GENERAL OBJECT).
 
    BSR    C_ENT                      CHECK ENTITY(A1:=PSTR,A5:=ENV,D1:=PREL,
*                                       D2:=PT_KIND,A6/D4/D5:=UNDEF);
    BEQ    RETURN                     IF NOT OK THEN RETURN END;
    BTST.B D2,ENV_MAN                 IF POINTER KIND <> VOID, REF_ENV,MAN_SET
    BEQ    ER_VALUE                   THEN REJECT END;
  IF.B #PT_VOI <EQ> D2 THEN.S       IF POINTER KIND = VOID ARGUMENT THEN
    MOVE.L CT_OBJ(A2),A0              A0:=OBJ:=CTX.CURRENT_OBJ;
    MOVE.L OB_SPA(A0),A6              A6:=TOP OBJ;
    MOVE.L SP_ENV+4(A6),A5            A5:=ENV:=OBJECT.TOP_ENVELOPE;
    LEA    -EN_STK(A5),A5             "OFFSET"
  ELSE.S                            ELSE
    MOVE.L EN_OBJ(A5),A0              A0:=OBJ:=ENV.HOLDER;
    MOVE.L OB_SPA(A0),A6              A6:=TOP OBJ;
    LEA    SP_ENV(A6),A6              A6:=HEAD ENV CHAIN;
    CMP.L  EN_STK(A5),A6              IF ENV NOT TOP ENVELOPE
    BNE    ER_VALUE                   THEN REJECT END;
    CMP.B  #OB_GEOB,OB_KIN(A0)        IF OBJ.KIND <> GENERAL OBJECT
    BNE    ER_STATE                   THEN REJECT END;
  ENDI                              END;
    CMPA.L A2,A4                      SR:=NE; "OK"
    RTS                               RETURN
 
ENV_MAN    DC.B 1<<PT_VOI+1<<PT_ENV+1<<PT_MAN    MASK FOR POINTER KIND
    DS.W   0
    PAGE
C_TOPOWN   EQU *                  CHECK TOP STACK, OWNER OR SIMPLE POINTER
 
*          CALL:                  RETURN:
* A0       -                      HOLDER  (OBJECT HOLDING POINTER STRUCT)
* A1       -                      POINTER STRUCT
* A2       CONTEXT                SAME
* A4       ARGUMENT ADDR          UPDATED
* A6       -                      POINTER ADDR
* D1       -                      POINTER REL
* D2.W     -                      POINTER KIND
* D6.W     ARGUMENT#              UPDATED
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK
* SR       -                      NE = OK, EQ = NOT OK
 
* GETS A POINTER ARGUMENT AND CHECKS FOR TEMP (I.E. TOP CONTEXT) OR
* LOCAL IN TOP ENVELOPE.  CHECKS THAT POINTER CAN BECOME OWN_SET.
* (TYPICALLY USED WHEN CREATING EMBEDDED OBJECTS).
 
    BSR    C_PT                       CHECK POINTER(A1:=PSTR,A6:=PT,D1:=PREL,
*                                       D2:=PT_KIND);
    BEQ    RETURN                     IF NOT OK THEN RETURN END;
    BTST.B D2,SIM_OWN                 IF PT_KIND <> SIMPLE, OWN_SET
    BEQ    ER_VALUE                   THEN REJECT END;
    BTST.B #PT_LSC,PT_INF(A6)
  IF <NE> THEN.S                    IF LOCAL POINTER THEN
    MOVE.L EN_OBJ(A1),A0              A0:=OBJECT HOLDING ENV;
    MOVE.B OB_KIN(A0),D7              D7.B:= OBJ.KIND;
    BTST.B D7,OBJUSER1                IF OBJ IS NOT A "USER OBJECT"
    BEQ    ER_SCOPE                   THEN REJECT;"TOP_ENV BELONGS TO KERNEL"
    MOVE.L OB_SPA(A0),A0              A0:=TOP OBJ;
    LEA    SP_ENV(A0),A0              A0:=HEAD ENV CHAIN
    CMP.L  EN_STK(A1),A0              IF POINTER STRUCTURE NOT TOP ENVELOPE
    BNE    ER_SCOPE                   THEN REJECT END;
  ELSE.S                            ELSE
    BTST.B #PT_TSC,PT_INF(A6)         IF NOT TEMP POINTER
    BEQ    ER_SCOPE                   THEN REJECT END;
  ENDI                              END;
    MOVE.L ST_HOLD(A1),A0             A0:=POINTER STRUCTURE.HOLDING OBJ;
    TST.W  D6                         SR:=<NE> "=OK";
    RTS                               RETURN
 
SIM_OWN    DC.B 1<<PT_NIL+1<<PT_OBJ+1<<PT_ENV+1<<PT_OWN    MASK FOR PT_KIND.
OBJUSER1   DC.B 1<<OB_GEOB+1<<OB_OPOB+1<<OB_DOOB  "USER TOP MANAGED OBJECTS"
    DS.W   0
    PAGE
C_PTS      EQU *                  CHECK #POINTERS
 
*          CALL:                  RETURN:
* A4       ARGUMENT ADDR          UPDATED
* D0.L     -                      NUMBER OF POINTERS (< = MAX, >0)
* D6.W     ARGUMENT#              UPDATED
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK
* SR       -                      NE = OK, EQ = NOT OK
 
* GETS AND CHECKS AN INTEGER ARGUMENT SERVING AS NUMBER OF POINTERS.
 
    ADD.W  #1,D6                      D6:=NEXT ARGUMENT#;
    MOVE.L -(A4),D0                   D0:=#POINTERS:=NEXT ARG;
    BLE    ER_DATA                    IF #POINTERS <= 0 THEN REJECT END;
    CMP.L  #PT_MASK-1,D0              IF #POINTERS >= MAX THEN REJECT END;
    BGE    ER_DATA                    "INCLUDE POSSIBLE T(0)".  "SR = OK"
    RTS                               RETURN
 
 
C_ADDR     EQU *                  CHECK ADDRESS
 
*          CALL:                  RETURN:
* A4       ARGUMENT ADDR          UPDATED
* D0.L     -                      ADDRESS (< 24BIT, >= 0)
* D6.W     ARGUMENT#              UPDATED
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK
* SR       -                      NE = OK, EQ = NOT OK
 
* GETS AND CHECKS AN INTEGER ARGUMENT SERVING AS ADDRESS.
 
    ADD    #1,D6                      D6:=NEXT ARGUMENT#;
    MOVE.L -(A4),D0                   D0:=ADDRESS:=NEXT ARG;
    BLT    ER_DATA                    IF ADDRESS < 0 THEN REJECT END;
    CMP.L  #1<<24,D0                  IF ADDRESS >= 2**24 THEN REJECT END;
    BGE    ER_DATA                    "SR = OK"
    RTS                               RETURN
    PAGE
C_SIZ      EQU *                  CHECK SIZE ARGUMENT
 
*          CALL:                  RETURN:
* A4       ARGUMENT ADDR          UPDATED
* D0.L     -                      SIZE USER PART (2**24-1 IF VOID)
* D1.W     -                      SIZE KERNEL PART (2**16-1 IF VOID)
* D6.W     ARGUMENT#              UPDATED
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK
* SR       -                      NE = OK, EQ = NOT OK
 
* GETS AND CHECKS A SIZE ARGUMENT.  IF BOTH COMPONENTS OF THE
* SIZE ARE < 0, A VOID ARGUMENT IS ASSUMED.
 
    ADD    #1,D6                      D6:=NEXT ARGUMENT#;
    MOVE   -(A4),D1                   D1:=SIZE_K_PART:=NEXT ARG WORD;
  IF <GE> THEN.S                    IF NOT VOID THEN
    MOVE.L -(A4),D0                   D0:=SIZE_U_PART:=NEXT ARG LONG;
    BLT    ER_DATA                    IF SIZE_U_PART < 0 THEN REJECT END;
    CMP.L  #1<<24,D0                  IF SIZE_U_PART >= 2**24
    BGE    ER_DATA                    THEN REJECT END;  "SR=OK"
  ELSE.S                            ELSE  "VOID:"
    MOVE.L -(A4),D0                   D0:=SIZE_U_PART:=NEXT ARG LONG;
    BGE    ER_DATA                    IF SIZE_U_PART >= 0 THEN REJECT END;
    MOVE.L #1<<24-1,D0                D0:=SIZE_U_PART:=MAX;
    MOVE.L #1<<15-1,D1                D1:=SIZE_K_PART:=MAX;
  ENDI                              END;
    RTS                               RETURN;
 
    TTL    STACK CHECK
    PAGE
S_MOVE     EQU *                  STACK CHECK FOR MOVE OWNER
 
*          CALL:                  RETURN:
* A1       POINTER STRUCT         SAME  (NEW OWNER POINTER)
* A5       OBJECT                 SAME  (OBJECT TO GET NEW OWNER)
* D1.W     POINTER REL            SAME  (NEW OWNER POINTER)
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK
* SR       -                      NE = OK, EQ = NOT OK
* A0/A6/D0/D4/D5:   -             UNDEF
 
* CHECKS WHETHER STACK REQUIREMENTS WOULD BE VIOLATED IF OBJECT
* GOT THE NEW OWNER POINTER.  ALSO CHECKS WHETHER OBJECT IS AN ANCESTOR
* OF THE NEW OWNER (NORMALLY A PROCESS), SINCE THAT WOULD BE SELF-DELETION.
* (TYPICALLY USED FROM RET_FP, C_NXT_M (KERNEL ENVELOPE), AND MOVE_OWN).
 
    MOVEM.L A1/A2/D1,-(A7)            SAVE A1,A2,D1; "INITIAL PSTR, PREL"
    BTST.B #OB_EMB,OB_STA(A5)         TEST FOR EMBEDDED OBJECT;
  IF <EQ> THEN.S                    IF NOT EMBEDDED THEN "ENV MAY BE PRESENT"
    MOVE.L OB_SPA(A5),A6              A6:=TOP OBJECT;
    MOVE.L SP_ENV+4(A6),A0            A0:=ENV:=OBJ.TOP ENVELOPE
    LEA    SP_ENV(A6),A2              A2:=HEAD ENV STACK;
  IF.L A2 <NE> A0 THEN.S            IF TOP ENVELOPE EXISTS THEN
    LEA    -EN_STK(A0),A0             A0:=ENV  "OFFSET";
    MOVE.L EN_TERMU(A0),D4            D4/D5:=ENV.TERM REQUIREMENT;
    MOVE   EN_TERMK(A0),D5
 
COM_MOV    EQU *                  COMMON WITH S_TERM:
    BSR    S_GROW                     CHECK GROWTH (TERM REQ, PSTR, PREL
*                                       A2/A6/D0:=UNDEF,
*                                       A1:=PSTR, D1:=PREL "FOR STOP SEARCH");
    BEQ.S  RET_S4                     IF NOT OK THEN REJECT END;
  ENDI                              END  "ENVELOPE EXISTS"
  ENDI                              ENDI;"NOT EMBEDDED"
 
    TST    D1                     "TEST FOR SELF DELETION:"
  WHILE <NE> DO.S                   WHILE PREL <> 0  "NOT INITIAL POINTER" DO
***
    PRT_REG SELF_DELETE
    MOVE.L ST_HOLD(A1),A0             A0:=PARENT OBJ:=PSTR.HOLDER;
    CMPA.L A0,A5                      IF PARENT OBJ = OBJ
    BEQ.S  ER_SELF1                   THEN REJECT "SELF DELETE" END;
    MOVE.L OB_OWN(A0),A1              A1:=PSTR:=PARENT OBJ.OWNER STRUCT;
    MOVE   OB_OFF(A0),D1              D1:=PREL:=PARENT OBJ.OWNER REL;
  ENDW                              END  "INITIAL POINTER REACHED"
 
RET_S1     EQU *                  RETURN OK:
    CMPA.L A1,A5                      SE:=NE; "OK"
 
RET_S4     EQU *                  REJECT:
    MOVEM.L (A7)+,A1/A2/D1            RESTORE A1,A2,D1;  "INITIAL PSTR, PREL"
    RTS                               RETURN
 
ER_SELF1   EQU *                  REJECT, SELF DELETION:
 
    MOVEM.L (A7)+,A1/A2/D1            RESTORE;
    BRA    ER_SELF                    REJECT;
    PAGE
S_TERM     EQU *                  STACK CHECK BEFORE TERM PROC ENTRY
 
* CALL AND RETURN:  LIKE S_MOVE.
 
* SIMILAR TO S_MOVE, BUT CONTEXT AND TEMP DATA (T(1)) HAVE BEEN
* CREATED.  THUS THE REMAINING TERMINATION REQUIREMENT IS SMALLER.
* (USED BY C_NXT_M BEFORE ENTERING TERM PROC).
 
    MOVEM.L A1/A2/D1,-(A7)            SAVE AS IN S_MOVE;
    MOVE.L OB_SPA(A5),A6              A6:=TOP OBJECT;
    MOVE.L SP_ENV+4(A6),A0            A0:=ENV:=OBJ.TOP ENVELOPE; "EXISTS ALWAYS"
    LEA    -EN_STK(A0),A0             "OFFSET"
    BSR    S_CTX                      GET_TERM_CTX_REQ(ENV,D4/D5:=CTX_REQ,
*                                       A6:=...);
* CTX_REQ IS SPACE FOR CONTEXT WITH DEFAULT PARAMS PLUS TEMP DATA.
    NEG.L  D4
    NEG    D5                         D4/D5:=TERM REQUIREMENT:=
    ADD.L  EN_TERMU(A0),D4              ENV.TERM REQUIREMENT - CTX_REQ;
    ADD    EN_TERMK(A0),D5
    BRA    COM_MOV                    GOTO COMMON WITH S_TERM;
    PAGE
S_GROW     EQU *                  STACK CHECK FOR GROWTH
 
*          CALL:                  RETURN:
* A1       POINTER STRUCT(NEW OWNER)  PSTR FOR STOP CHECK
* D1       POINTER REL (NEW OWNER)    PREL FOR STOP CHECK
* D4       TERM REQUIREMENT, USER     UNDEF  (TERM REQ FOR ENVELOPE DELETION)
* D5       TERM REQUIREMENT, KERNEL   UNDEF  (  -   -   -     -        -    )
* D7.L     -                          UNDEF IF OK, RESULT IF NOT OK
* SR       -                          NE = OK, EQ = NOT OK
* A2/A6/D0:   -                   UNDEF
 
* CHECKS WHETHER STACK REQUIREMENTS WOULD BE VIOLATED IF AN
* OBJECT HAD THE TERM REQUIREMENTS SPECIFIED AND THE OWNER SPECIFIED.
* (USED BY S_MOVE, S_TERM, S_ENV).
 
    TST    D1
  WHILE <NE> DO.S                   WHILE PREL <> 0  "NOT INITIAL POINTER" DO
***
    PRT_REG S_GROW
    BTST.B #PT_LSC,PT_INF(A1,D1)
  IF <EQ> THEN.S                    IF POINTER TEMP OR FORMAL THEN
    LEA    CT_STKU(A1),A6             "POINTER STRUCT = CTX"
    BSR    S_MAX                      D4/D5:=MAX(CTX.FREE STACK,TERM REQ);
    BGT    ER_CONLIM                  IF TERM REQ > CTX.FREE STACK
*                                       THEN REJECT END;
    BRA.S  RET_S2                     RETURN OK;
  ENDI                              END;
 
    MOVE.L EN_OBJ(A1),A2          "LOCAL POINTER: A1 = ENVELOPE"
    MOVE.L OB_SPA(A2),A2              A2:=TOP OBJ HOLDING ENV;
    LEA    SP_ENV(A2),A2              A2:=HEAD ENV STACK;
  REPEAT                            REPEAT "SCAN ENV AND YOUNGER ENV:"
    MOVEM.L D4/D5,-(A7)               SAVE TERM REQ;
    LEA    EN_MAXU(A1),A6             "CHECK AGAINST MAX STACK:"
    BSR    S_MAX                      D4/D5:=MAX(ENV.MAX STACK,TERM REQ);
    MOVEM.L (A7)+,D4/D5               D4/D5:=RESTORE TERM REQ;
    BGT    ER_ENVLIM                  IF TERM REQ > ENV.MAX STACK
*                                       THEN REJECT END;
    ADD.L  EN_FIXU(A1),D4             D4/D5:=TERM REQ:=
    ADD    EN_FIXK(A1),D5               TERM REQ+ENV.FIXED REQUIREMENTS;
    LEA    EN_TERMU(A1),A6            D4/D5:=MAX(ENV.TERM REQ, TERM REQ);
    BSR    S_MAX                      IF TERM REQ <= ENV.TERM REQ
    BLE.S  RET_S2                     THEN RETURN OK END;
    MOVE.L EN_STK(A1),A6              A6:=NEXT ENV(ENV);
    LEA    -EN_STK(A6),A1             A1:=ENV:="OFFSET NEXT ENV";
  UNTIL.L A6 <EQ> A2                UNTIL ENV = HEAD ENV STACK;
 
    MOVE.L (A2),A2                    A2:=FIRST ENV;
    MOVE.L EN_OBJ-EN_STK(A2),A2       A2:=OBJ HOLDING FIRST ENV;
    MOVE.L OB_OWN(A2),A1              A1:=POINTER STRUCT:=OBJ.OWNER STRUCT;
    MOVE   OB_OFF(A2),D1              D1:=POINTER REL:=OBJ.OWNER REL;
  ENDW                              END  "INITIAL POINTER REACHED"
 
RET_S2     EQU *                  RETURN OK:  "ALSO USED FROM S_LOC"
    CMPA   #0,A7                      SR:=NE;  "OK"
    RTS                               RETURN;
    PAGE
S_UPDATE   EQU *                  STACK REQUIREMENT UPDATE
 
*          CALL:                  RETURN:
* A5       OBJECT                 SAME
* A6/D0    -                      UNDEF
 
* UPDATES THE STACK REQUIREMENTS FOR ANCESTORS OF THE OBJECT.
* (USED BY MOVE_OWN, RET_FP, CRE_ENV, DECL_GEN).
 
    MOVEM.L A1/A2/A5/D4/D5,-(A7)      SAVE REGISTERS;
    BTST.B #OB_EMB,OB_STA(A5)         TEST FOR EMBEDDED OBJ;
  IF <EQ> THEN.L                    IF NOT EMBEDDED THEN "ENV MAY BE PRESENT"
    MOVE.L OB_SPA(A5),A6              A6:=TOP OBJ;
    MOVE.L SP_ENV+4(A6),A1            A1:=TOP ENV:=OBJ.TOP ENV;
    LEA    SP_ENV(A6),A2              A2:=HEAD ENV STACK;
  IF.L A1 <NE> A2 THEN.S            IF TOP ENV EXISTS THEN
    MOVE.L EN_TERMU-EN_STK(A1),D4     D4/D5:=TERM REQ:=TOP ENV.TERM REQ;
    MOVE   EN_TERMK-EN_STK(A1),D5
  REPEAT                            REPEAT  "NEXT ANCESTOR:"
    MOVE.L OB_OWN(A5),A1              A1:=POINTER STRUCT:=OBJ.OWNER STRUCT;
    MOVE   OB_OFF(A5),D0              D0:=POINTER REL:=OBJ.OWNER REL;
***
    PRT_REG S_UPDATE
    BEQ.S  RET_S3                     IF INITIAL POINTER
    BTST.B #PT_LSC,PT_INF(A1,D0)      OR TEMP POINTER OR FORMAL POINTER
    BEQ.S  RET_S3                     THEN RETURN END;
 
*                                   "A1=ENV=OWNER ENVELOPE"
    MOVE.L EN_OBJ(A1),A5              A5:=OBJ:=OBJ HOLDING OWNER ENV;
    MOVE.L OB_SPA(A5),A6              A6:=TOP OBJ;
    LEA    SP_ENV(A6),A2              A2:=HEAD ENV STACK;
  REPEAT                            REPEAT  "ENV AND YOUNGER ENVELOPES:"
    ADD.L  EN_FIXU(A1),D4             D4/D5:=TERM REQ:=
    ADD    EN_FIXK(A1),D5               TERM REQ+ENV.FIXED REQUIREMENTS;
    CLR    D0                         INCREMENT:=0;
  IF.L D4 <GE> EN_TERMU(A1) THEN.S  IF TERM REQ >= ENV.TERM REQ
  IF D5 <GE> EN_TERMK(A1) THEN.S      "BOTH COMPONENTS" THEN
    MOVE   #1,D0                      INCREMENT:=1
  ENDI                              END;
  ENDI
    LEA    EN_TERMU(A1),A6            D4/D5:=
    BSR    S_MAX                      MAX(ENV.TERM REQ, TERM REQ);
  IF <LE> THEN.S                    IF TERM REQ <= ENV.TERM REQ "BOTH COMPONENTS
    ADD    D0,EN_COU(A1)            THEN ENV.TERM COUNT:=...+INCREMENT
    BRA.S  RET_S3                     RETURN
  ENDI                              END;
    MOVE   D0,EN_COU(A1)              ENV.TERM COUNT:=INCREMENT;
    MOVE.L D4,EN_TERMU(A1)            "AT LEAST ONE NEW COMPONENT IN MAX"
    MOVE   D5,EN_TERMK(A1)            ENV.TERM REQ:=TERM REQ;
    MOVE.L EN_STK(A1),A6              A6:=NEXT ENV(ENV);
    LEA    -EN_STK(A6),A1             A1:=ENV:="OFFSET NEXT ENV";
  UNTIL.L A6 <EQ> A2                UNTIL ENV = HEAD ENV STACK;
  UNTIL <NE>                        UNTIL FALSE;  "ALL ANCESTORS"
  ENDI                              END  "TOP ENV EXISTS";
  ENDI                              ENDI;"NOT EMBEDDED"
 
RET_S3     EQU *                  RETURN:
    MOVEM.L (A7)+,A1/A2/A5/D4/D5      RESTORE REGISTERS;
    RTS                               RETURN;
    PAGE
S_SHRINK   EQU *                  SHRINK STACK REQUIREMENTS
 
*          CALL:                  RETURN:
* A5       OBJECT                 SAME (NOT IN OWN_SET,BUT HAS REF TO OLD OWNSET
* A6/D0    -                      UNDEF
 
* UPDATES THE STACK REQUIREMENTS FOR ANCESTORS OF THE OBJECT, CORRESPONDING
* TO MOVING THE OBJECT TO ANOTHER OWNER.
* (USED BY M_OWN_OK).
 
    MOVEM.L A1/A2/A5/D4/D5,-(A7)      SAVE REGISTERS;
    BTST.B #OB_EMB,OB_STA(A5)         TEST FOR EMBEDDED OBJ;
  IF <EQ> THEN.L                    IF NOT EMBEDDED THEN "ENV MAY BE PRESENT"
    MOVE.L OB_SPA(A5),A6              A6:=TOP OBJ
    MOVE.L SP_ENV+4(A6),A1            A1:=TOP ENV:=OBJ.TOP ENV;
    LEA    SP_ENV(A6),A2              A2:=HEAD ENV STACK;
  IF.L A1 <NE> A2 THEN              IF TOP ENV EXISTS THEN
    MOVE.L EN_TERMU-EN_STK(A1),D4     D4/D5:=TERM REQ:=TOP ENV.TERM REQ;
    MOVE   EN_TERMK-EN_STK(A1),D5
  REPEAT                            REPEAT  "NEXT ANCESTOR:"
***
    PRT_REG S_SHRINK
    MOVE.L OB_OWN(A5),A1              A1:=POINTER STRUCT:=OBJ.OWNER STRUCT;
    MOVE   OB_OFF(A5),D0              D0:=POINTER REL:=OBJ.OWNER REL;
    BEQ    RET_S3                     IF INITIAL POINTER
    BTST.B #PT_LSC,PT_INF(A1,D0)      OR TEMP POINTER OR FORMAL POINTER
    BEQ    RET_S3                     THEN RETURN END;
 
*                                   "A1=ENV=OWNER ENVELOPE"
    MOVE.L EN_OBJ(A1),A5              A5:=OBJ:=OBJ HOLDING OWNER ENV;
    MOVE.L OB_SPA(A5),A6              A6:=TOP OBJ;
    LEA    SP_ENV(A6),A2              A6:=HEAD ENV STACK;
  REPEAT                            REPEAT  "ENV AND YOUNGER ENVELOPES:"
    ADD.L  EN_FIXU(A1),D4             D4/D5:=TERM REQ:=
    ADD    EN_FIXK(A1),D5               TERM REQ+ENV.FIXED REQUIREMENTS;
 
  IF.L D4 <EQ> EN_TERMU(A1) THEN.S  IF TERM REQ = ENV.TERM REQ
  IF   D5 <EQ> EN_TERMK(A1) THEN.S    "BOTH COMPONENTS" THEN
    SUB    #1,EN_COU(A1)              ENV.TERM COUNT:=...-1;
  ENDI                              END;
  ENDI
    TST    EN_COU(A1)                 IF ENV.TERM COUNT <> 0
    BNE    RET_S3                     THEN RETURN END;
  IF.L D4 <LT> EN_TERMU(A1) THEN.S  IF TERM REQ < ENV.TERM REQ
    CMP    EN_TERMK(A1),D5            "BOTH COMPONENTS" THEN
    BLT    RET_S3                     RETURN
  ENDI                              END;
 
* NO LOCALS ETC. HAVE TERM REQ = MAX FOR BOTH COMPONENTS.
* RECOMPUTE ENV.TERM REQ USING THE NEW VALUES FOR LOCALS AND OLDER ENVELOPES:
 
    MOVEM.L D4/D5/A0,-(A7)            SAVE "OLD" TERM REQ, A0;
    MOVE.L A1,A0                      A0:=ENV;
    BSR    S_CTX                      GET_TERM_CTX_REQ(ENV,D4/D5:=CTX_REQ,
*                                       A6:=MANAGER OBJ);
    BSR    S_INITENV                  INIT TERM REQ(ENV,MANAGER OBJ,CTX_REQ,
*                                       D4/D5:=TERM REQ NO LOCALS,D0:=UNDEF);
    BSR    S_MAXLOC                   MAX REQ WITH LOCALS(ENV,TERM REQ NO LOCALS
*                                       D4/D5:=TERM REQ,D0:=TERM COUNT);
    MOVE   D0,EN_COU(A0)              ENV.TERM COUNT:=TERM COUNT;
    MOVE.L D4,EN_TERMU(A0)            ENV.TERM REQ:=TERM REQ;
    MOVE   D5,EN_TERMK(A0)
    MOVEM.L (A7)+,D4/D5/A0            D4/D5:=RESTORE OLD TERM REQ, A0;
    MOVE.L EN_STK(A1),A6              A6:=NEXT ENV(ENV);
    LEA    -EN_STK(A6),A1             A1:=ENV:="OFFSET NEXT ENV";
  UNTIL.L A6 <EQ> A2                UNTIL ENV = HEAD ENV STACK;
  UNTIL <NE>                        UNTIL FALSE;  "ALL ANCESTORS"
  ENDI                              END  "TOP ENV EXISTS"
  ENDI                              ENDI;"NOT EMBEDDED"
 
    BRA    RET_S3                     RETURN;
 
 
S_ENV      EQU *                  INIT ALL ENVELOPE TERM REQUIREMENTS
 
*          CALL:                  RETURN:
* A3       ENVELOPE               SAME  (NO LOCALS ASSUMED)
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK
* SR       -                      NE = OK, EQ = NOT OK
* ENV_FIXED REQ: DEALLOC STACK    CTX REQUIREMENT+DEALLOC STACK
 
* INITIALIZES TERM REQUIREMENT, TERM COUNT.  UPDATES FIXED REQUIREMENT.
* CHECKS THAT ANCESTOR REQUIREMENTS ARE NOT VIOLATED. (USED BY CRE_ENV).
 
    MOVEM.L A0-A2/A6/D0/D1/D4/D5,-(A7)  SAVE REGISTERS
    MOVE.L A3,A0                      A0:=ENVELOPE;
    BSR    S_CTX                      GET_TERM_CTX_REQ(ENV,D4/D5:=CTX_REQ,
*                                       A6:=MANAGER OBJ);
    ADD.L  D4,EN_FIXU(A0)             ENV.FIXED REQUIREMENTS:=
    ADD    D5,EN_FIXK(A0)             ... "DEALLOC" + CTX_REQ;
    BSR    S_INITENV                  INIT ENV NO LOCALS(ENV,MANAGER OBJ,
*                                       CTX_REQ,D4/D5:=TERM REQ,D0:=UNDEF);
    MOVE.L EN_OBJ(A0),A6              A6:=OBJECT HOLDING ENV;
    MOVE.L OB_OWN(A6),A1              A1:=OBJ.OWNER STRUCT;
    MOVE   OB_OFF(A6),D1              D1:=OBJ.OWNER REL;
    BSR    S_GROW                     CHECK GROWTH(PSTR,PREL,TERM REQ,
*                                       A2/A6/D0:=UNDEF); SR:=...
    MOVEM.L (A7)+,A0-A2/A6/D0/D1/D4/D5  RESTORE REGISTERS;
    RTS                               RETURN
    PAGE
S_LOC      EQU *                  CHECK FREE STACK FOR DELETE LOCALS
 
*          CALL:                  RETURN:
* A2       CONTEXT                SAME
* A3       ENVELOPE               SAME
* D7.L     -                      UNDEF IF OK, RESULT IF NOT OK
* SR       -                      NE = OK, EQ = NOT OK
* A0/A6/D0/D4/D5:  -              UNDEF
 
* CHECKS THAT THE FREE STACK IN "CONTEXT" IS SUFFICIENT FOR DELETING ALL
* LOCALS IN "ENVELOPE".
* A FAST CHECK IS MADE FIRST TO SEE WHETHER FREE STACK WOULD
* SUFFICE TO "EXECUTE" THE TERMINATION PROCEDURE OF THE ENVELOPE - FROM
* THE POINT WHERE IT HAS USED ITS "DEALLOC STACK".  THIS CHECK IS
* PESSIMISTIC SINCE OLDER ENVELOPES AND CALL STACK REQUIREMENT IS INCLUDED.
* IF THE CHECK FAILS, A SLOWER BUT EXACT CHECK IS MADE.
* (USED BY DEL_ENV).
 
    MOVE.L EN_TERMU(A3),D4            D4/D5:=ENV.TERM REQ - ENV.FIXED REQ;
    MOVE   EN_TERMK(A3),D5
    SUB.L  EN_FIXU(A3),D4
    SUB    EN_FIXK(A3),D5
    LEA    CT_STK(A2),A6              D4/D5:=MAX(...,CTX.FREE STACK);
    BSR    S_MAX                      IF ENV.TERM REQ - ENV.FIXED REQ <=
    BLE    RET_S2                     CTX.FREE STACK THEN RETURN OK END;
 
    MOVE.L EN_FIXU(A3),D4       "OLDER ENVELOPES OR CALL STACK MIGHT BE LARGER"
    MOVE   EN_FIXK(A3),D5               D4/D5:=INITIAL TERM REQ:=ENV.FIXED REQ;
    MOVE.L A3,A0                      A0:=ENV;
    BSR    S_MAXLOC                   MAX REQ WITH LOCALS(ENV,INITIAL TERM REQ,
*                                       D4/D5:=TERM REQ,D0:=TERM COUNT);
    SUB.L  EN_FIXU(A3),D4             D4/D5:=TERM REQ:=...-ENV.FIXED REQ;
    SUB    EN_FIXK(A3),D5             "D4/D5=MAXIMUM OF LOCALS"
    BSR    S_MAX                      D4/D5:=MAX(TERM REQ,CTX.FREE STACK);
    BLE    RET_S2                     IF TERM REQ <= CTX.FREE STACK
*                                     THEN RETURN OK END;
    BRA    ER_PROSP                   REJECT, PROCESS SPACE LIMITED
    PAGE
S_MAX      EQU *                  FIND MAX SIZE AND COMPARE
 
*          CALL:                  RETURN:
* A6       SIZE ADDR              SAME (ADDR OF CT_STKU, EN_MAXU, ETC.)
* D4       TERM REQUIREMENT,USER  MAX(TERM REQ, SIZE)
* D5       TERM REQUIREMENT,KERNEL MAX(TERM REQ, SIZE)
* SR       -                      GT: TERM REQ > SIZE, LE: TERM REQ <= SIZE
 
* FINDS MAXIMUM OF TWO SIZES AND COMPARES THEM.  EACH SIZE CONSISTS
* OF A USER SIZE AND A KERNEL SIZE.  ONE SIZE IS GIVEN BY "SIZE ADDR",
* THE OTHER AS "TERM REQUIREMENT".
* TERM REQ <= SIZE MEANS: TERM REQ USER <= SIZE USER AND
*                         TERM REQ KERNEL <= SIZE KERNEL
* TERM REQ > SIZE IN ALL OTHER CASES.
 
  IF.L D4 <LE> (A6) THEN.S          IF TERM REQ USER <= SIZE USER THEN
    MOVE.L (A6),D4                    D4:=MAX USER:=SIZE USER;
  IF D5 <LE> SZ_K(A6) THEN.S        IF TERM REQ KERNEL <= SIZE KERNEL THEN
    MOVE   SZ_K(A6),D5                D5:=MAX KERNEL:=SIZE KERNEL;
    MOVE   #4,CCR                     SR:=LE, "BOTH ARE <= "
  ELSE.S                            ELSE
    MOVE   #0,CCR                     SR:=GT; "ONE IS >"
  ENDI                              END
 
  ELSE.S                            ELSE  "TERM REQ USER > SIZE USER:"
  IF D5 <LE> SZ_K(A6) THEN.S        IF TERM REQ KERNEL <= SIZE KERNEL THEN
    MOVE   SZ_K(A6),D5                D5:=MAX KERNEL:=SIZE KERNEL
  ENDI                              END;
    MOVE   #0,CCR                     SR:=GT;  "ONE OR TWO ARE >"
  ENDI                              END;
***
    PRT_REG S_MAX
    RTS                               RETURN
    PAGE
S_INITENV EQU *                   INIT ENVELOPE TERM WITHOUT LOCALS
 
*          CALL:                  RETURN:
* A0       ENVELOPE               SAME
* A6       MANAGER OBJ(MAYBE DUMMY) UNDEF
* D4.L     CTX REQUIREM, USER     TERM REQUIREM, USER "WITHOUT LOCALS"
* D5.W     CTX REQUIREM, KERNEL   TERM REQUIREM, KERNEL "WITHOUT LOCALS"
* D0       -                      UNDEF
* ENV.FIXED REQUIREMENT:  CTX REQUIREMENT+DEALLOC     (UNCHANGED)
 
* INITS THE TERMINATION REQUIREMENT OF THE ENVELOPE, DISREGARDING LOCALLY
* OWNED OBJECTS.  THUS THE FOLLOWING IS INCLUDED:
*   ROOM FOR CTX REQUIREMENT+DEALLOC+OLDER ENVELOPES
*   ROOM FOR CTX REQUIREMENT+CALL STACK
 
    ADD.L  GE_STK(A6),D4              D4/D5:=CALL REQ:=CTX REQUIREMENT
    ADD    GE_STK+SZ_K(A6),D5           +MANAGER OBJ.CALL_STACK_REQ;
    MOVE.L EN_FIXU(A0),EN_TERMU(A0)   ENV.TERM REQ:=ENV.FIXED REQUIREMENT;
    MOVE   EN_FIXK(A0),EN_TERMK(A0)   "CTX REQUIREMENT+DEALLOC"
    MOVE.L EN_OBJ(A0),A6              A6:=OBJ HOLDING ENV;
    MOVE.L OB_SPA(A6),A6              A6:=TOP OBJ;
    LEA    SP_ENV(A6),A6              A6:=HEAD ENVELOPE STACK;
  IF.L A6 <NE> EN_STK+4(A0) THEN.S  IF OLDER ENVELOPE EXISTS THEN
    MOVE.L EN_STK+4(A0),A6            A6:=OLDER ENVELOPE; "OFFSET"
    MOVE.L EN_TERMU-EN_STK(A6),D0     D0:=OLDER ENV.TERM REQUIREMENT;
    ADD.L  D0,EN_TERMU(A0)            ENV.TERM REQ:=ENV.TERM REQ
    MOVE   EN_TERMK-EN_STK(A6),D0       + OLDER ENV.TERM REQ;
    ADD    D0,EN_TERMK(A0)
  ENDI
    LEA    EN_TERMU(A0),A6
    BSR    S_MAX                      D4/D5:=MAX(CALL REQ, ENV.TERM REQ);
    MOVE.L D4,EN_TERMU(A0)            ENV.TERM REQ:=MAX(...);
    MOVE   D5,EN_TERMK(A0)
    MOVE   #1,EN_COU(A0)              ENV.TERM COUNT:=1;
    RTS                               RETURN;
    PAGE
S_CTX      EQU *                  GET TERMINATION CTX REQUIREMENTS
 
*          CALL:                  RETURN:
* A0       ENVELOPE               SAME
* A6       -                      MANAGER OBJECT (MAY BE THE DUMMY MANAGER)
* D4.L     -                      CONTEXT REQUIREMENT, USER PART
* D5.W     -                      CONTEXT REQUIREMENT, KERNEL PART
 
* FINDS THE MANAGER OBJECT.  COMPUTES SPACE FOR TERM CONTEXT WITH DEFAULT
* PARAMS PLUS TEMP DATA.
 
    TST    EN_TERM(A0)
  IF <GE> THEN.S                    IF ENV.TERM_PROC >= 0  "DUMMY" THEN
    MOVE.L #DUM_MAN,A6                A6:=MAN_OBJ:=DUMMY MANAGER
  ELSE.S                            ELSE
    MOVE.L EN_MAN(A0),A6              A6:=ENV.MANAGER STRUCT;
    MOVE   EN_OFF(A0),D4              D4:=ENV.MANAGER REL;
    BTST.B #PT_LSC,PT_INF(A6,D4)
 IF <EQ> THEN.S                     IF NON LOCAL MAN_SET THEN
*                                   "A6=CTX.  MANAGER MAY BECOME CURRENT OBJ."
    MOVE.L CT_OBJ(A6),A6              A6:=MAN_OBJ:=CTX.CURRENT OBJ;
  IF A6 <EQ> #0 THEN.S              IF CTX ABORTED THEN
    MOVE.L #DUM_MAN,A6                A6:=MAN_OBJ:=DUMMY MANAGER
  ENDI                              END
  ELSE.S                            ELSE
    MOVE.L EN_OBJ(A6),A6              A6:=MAN OBJ:=MANAGER STRUCT.HOLDER
  ENDI                              END
  ENDI                              END  "MANAGER OBJECT FOUND".
 
    MOVE.L GE_TEMD(A6),D4             D4:=CTX REQ USER PART:=
    ADD.L  #255,D4                      ROUND (MAN_OBJ.TEMP DATA SIZE);
    CLR.B  D4
    MOVE   GE_TEMP(A6),D5             D5:=CTX REQ KERNEL PART:=
    MULU   #PT_SIZ,D5                   MAN_OBJ.TEMP POINTERS * POINTER SIZE
    ADD    #CT_SIZ+2*FP_SIZ+SE_SIZ,D5   +CTX SIZE + 2 FORMALS + SEGM DESCR;
    RTS                               RETURN
 
 
S_MAXLOC   EQU *                  FIND MAX TERM REQUIREMENT OF LOCALS
 
*          CALL:                  RETURN:
* A0       ENVELOPE               SAME
* D0.W     -                      TERM COUNT  (NUMBER OF OCCURRENCES OF MAX)
* D4.L    INITIAL TERM REQ, USER     TERM REQ, USER
* D5.W    INITIAL TERM REQ, KERNEL  TERM REQ, KERNEL
 
* FINDS MAXIMUM OF THE INITIAL TERM REQ AND THE TERM REQUIREMENT OF
* ALL LOCALS.  KEEPS TRACK OF OCCURRENCES OF MAXIMUM.
* (USED BY S_SHRINK AND DEL_ENV (THROUGH S_LOC)).
 
 
    MOVEM.L A2/A3/A5/A6/D1/D2,-(A7)   SAVE REGISTERS;
    MOVE   D5,-(A7)                   MAX TERM REQ:=INITIAL TERM REQ;
    MOVE.L D4,-(A7)                   "SAVED IN SIZE FORMAT"
    MOVEA.L A7,A6                     A6:=ADDR OF MAX TERM REQ;
    MOVE   #1,D0                      D0:=COUNT:=1;
    MOVE   #EN_SIZ,D1                 D1:=CURRENT PREL:=L(1);
  WHILE D1 <NE> EN_TOPL(A0) DO.S    WHILE CURRENT PREL <> TOP LOCALS DO
  IF.B PT_KIN(A0,D1) <EQ> #PT_OWN THEN.S
    LEA    (A0,D1),A3               IF CURRENT POINTER = OWN SET THEN
    MOVE.L (A3),A5                    A3:=PT ADDR; A5:=OBJ:=FIRST OBJ;
  REPEAT                            FOR ALL OBJECTS IN OWN SET DO
    BTST.B #OB_EMB,OB_STA(A5)
  IF <EQ> THEN.S                    IF NOT EMBEDDED OBJECT THEN
    MOVE.L OB_SPA(A5),A2              A2:=TOP OBJ;
    LEA    SP_ENV(A2),A2              A2:=HEAD ENV STACK;
 
  IF.L A2 <NE> 4(A2) THEN.S         IF ENVELOPE EXISTS THEN
    MOVE.L 4(A2),A2                   A2:=CUR ENV:=OBJ.TOP ENVELOPE;
    MOVE.L EN_TERMU-EN_STK(A2),D4     D4/D5:=TERM REQ:=
    ADD.L  EN_FIXU(A0),D4               CUR ENV.TERM REQ + ENV.FIXED REQ;
    MOVE   EN_TERMK-EN_STK(A2),D5
    ADD    EN_FIXU(A0),D5
    CLR    D2                         INCREMENT:=0;
  IF.L D4 <GE> (A6) THEN.S          IF TERM REQ >= MAX TERM REQ
  IF D5 <GE> 4(A6) THEN.S             "BOTH COMPONENTS" THEN
    MOVE   #1,D2                      INCREMENT:=1
  ENDI                              END;
  ENDI
    BSR    S_MAX                      D4/D5:=MAX(TERM REQ,MAX TERM REQ);
  IF <GT> THEN.S                    IF TERM REQ > MAX TERM REQ
    MOVE   D2,D0                      "EITHER COMPONENT" THEN
    MOVE.L D4,(A6)                    D0:=COUNT:=INCREMENT
    MOVE   D5,4(A6)                   MAX TERM REQ:=NEW MAX
  ELSE.S                            ELSE
    ADD    D2,D0                      D0:=COUNT:=COUNT + INCREMENT
  ENDI                              END
  ENDI                              END  "ENVELOPE PRESENT";
 
  ENDI                              END  "NON-EMBEDDED OBJECT"
    MOVE.L (A5),A5                    A5:=OBJ:=NEXT (OBJ);
  UNTIL.L A5 <EQ> A3                END  "FOR ALL OBJECTS IN OWN SET";
  ENDI                              END "OWNSET";
    ADD    #PT_SIZ,D1                 D1:=CURRENT PREL:=NEXT;
  ENDW                              END  "FOR ALL LOCALS";
    MOVE.L (A7)+,D4                   D4/D5:=TERM REQ:=
    MOVE   (A7)+,D5                     POP MAX TERM REQ;
    MOVEM.L (A7)+,A2/A3/A5/A6/D1/D2   RESTORE REGISTERS;
    RTS                               RETURN
 
  END !                             END KERNEL OPERATIONS
 
«eof»