; ; Byterp.mu ; November 19, 1980 10:41 AM ### ; Fixed double TASK in IVAL at label NONINT ### ; Add additional bank microcode hooks ### ; all modified lines contain "###" ; June 9, 1980 4:25 PM ; Add DUP and POP2D ; #AltoConsts23.MU; DEFINITIONS AND CONSTANTS FOR ALTOS ; ; /* REGISTERS ;/// RED ALERT....RED ALERT /// ;/// BEFORE CHANGING ANY REGISTER ASSIGNMENTS CONSULT ;/// THE SACRED TEXTS (SMALL.OPS) SO THAT YE MAY ;/// CONTINUE TO SPEAK THE TRUTH AND LIVE IN HARMONY ;/// WITH THE VIRTUAL MACHINE (I.E. THE NOVACODE KNOWS ;/// THE NUMBERS OF CERTAIN OF THE REGISTERS ALL DULY ;/// NOTED IN AN APPROPRIATELY TITLED SECTION OF SMALL.OPS ;/// AND CHANGES SHOULD BE REFLECTED THERE) ;/// RED ALERT....RED ALRET /// $AC3 $R0; $NAMES $R0; <LITMSGS,SUBS> $AC2 $R1; $CYCOUT2 $R1; <SUBS,ALLOC> $AC1 $R2; $AC0 $R3; $ARG1 $R3; <ALLOC(LITMSGS,INTN)>**ARGUMENT TO OOZE ROUTINES $NWW $R4; $TEMP1 $R5; <SUBS,LITMSGS,ALLOC(LITMSGS,INTN)> $CYRET $R5; $PC $R6; $XREG $R7; <PMAP> $RETN0 $R10; <PMAP, ; HASH(IVL,ILNG,REF,SUBS,ALLOC(LITMSGS,INTN),LITMSGS)> $COREBASE $R14; FIRST CORE LOCATION (MUST BE CLASS CONTEXT) $PCB $R15; **BYTE PC IN CODE $MODE $R16; MODE MUST BE A R REG BECAUSE OF BUS=0 TIMING PROBLEM ; AT REFX10: ; MODE=0 IN NORMAL EXECUTION ; MODE=1 WHILE DOING SMASH OPERATION $AOOP $R17; <LITMSGS,SUBS>OOP OF BASE REGISTER A $CYCOUT $R35; ; <NEXTBYTE,JMPS,SUBS,LITMSGS,MAPCODE(RETURN),GCLASS(IVAL)> $RHO $R35; ; <HASH(IVAL,ILONG,REF,SUBS,ALLOC(LITMSGS,INTN),LITMSGS)> $RESIDUE $R36; ; <HASH(IVAL,ILONG,REF,SUBS,ALLOC(LITMSGS,INTN),LITMSGS)> ;--------------- REGS ABOVE ARE VOLATILE W/RESPECT TO NOVA EMULATOR $LREG $R40; RAM'S COPY OF LREG $TEMP2 $R41; <REF,ALLOC(LITMSGS,INTN),LITMSGS,ARITHOPS,SUBS> $TEMP4 $R42; <SUBS> $TEMP3 $R43; <ALLOC(LITMSGS,INTN),LITMSGS,ARITHOPS,SUBS,REF> $NAME $R44; **DOUBLE NAME* <LITMSGS,SUBS> $CNT $R44; **DOUBLE NAME* <SUBS> $ROTA $R45; <HASH(IVAL,ILONG,REF,SUBS,LITMSGS,ALLOC(...,INTN))> $ROT0 $R46; <HASH(IVAL,ILONG,REF,SUBS,LITMSGS,ALLOC(...,INTN))> $ROT1 $R47; <HASH(IVAL,ILONG,REF,SUBS,LITMSGS,ALLOC(...,INTN))> $RPC $R50; <HASH(IVAL,ILONG,REF,SUBS,LITMSGS,ALLOC(...,INTN))> $RETN1 $R51; <GCLASS(IVAL(LITMSGS),SUBS),ILONG(SUBS),REF,ALLOC(...,INTN),REGMAP> ;--------------- REGS ABOVE ARE VOLATILE W/RESPECT TO BITBLT $ACORE $R52; CORE ADDRESS OF BASE REGISTER A $FATHER $R53; RAM STATE - FATHER (NIL WHEN NOT IN RECUF) $MINAT $R54; RAM STATE - ATOM BOUND $PMBASE $R55; RAM STATE - PMAP CORE ADDR $ROTBASE $R56; RAM STATE - ROT CORE ADDR ;--------------- REGS BELOW SAVE STATE ACROSS NOVACALL $SAVR1 $R57; **DOUBLE NAME* <REF,INTN> $WRAPFL $R57; **DOUBLE NAME* <LITMSGS> $AREC $R60; ACTIVATION CORE ADDRESS $SAVPC $R61; $SAVDISP $R62; $BCORE $R63; CORE ADDRESS OF BASE REGISTER B $SAVR0 $R64; <HASH(IVAL,ILONG,REF,SUBS,ALLOC(LITMSGS,INTN),LITMSGS)> ; SAVE RETN0 ACROSS FAULTS $BOOP $R65; OOP OF BASE REGISTER B $LOCFRAME $R66; **LITERAL VECTOR CORE ADDRESS $STACKP $R67; **INDEX OF TOP OF STACK $TOP $R70; OOP ON TOP OF STACK $CADDR $R71; $TFRAME $R72; TEMPORARY FRAME CORE ADDRESS $SELF $R73; ACTIVE INSTANCE CORE ADDRESS $SUPMOD $R74; -1 EXCEPT WHEN ACCESSING SUPERCLASS $RETN2 $R75; <IVAL(SUBS,LITMSGS),LITMSGS,INTN> $CTXT $R76; OOP OF CURRENT CONTEXT $SAVSP $R77; STACK POINTER SAVER $RAMRETURN $R77; RETURN ADDRESS FOR OTHER RAM BANK CALLS ### ; ; /* CONSTANTS $RCT1BIT $20; REFCT 1-BIT $RCT8BIT $200; REFCT 8-BIT $RCTM1BIT $177760; MINUS REFCT 1-BIT $ROTMSK $7777; ROT SIZE MASK ### $ROT0EM $360; ROT EMPTY PATTERN $ROT0ND $L0,12000,100; CONSTANT 0 IS SUPER-SPECIAL ; ROT0 FOR NEW, NOT CLEAN, REF=1, NOT IMMED (I.E. NO BITS ON) $CLNMSK $177775; DIRTY MASK - TURNS OFF CLEAN (=2) BIT $RCTMSK $360; REFCT MASK - MORE IMBEDDED IN REFI/REFD $HKRMSK $174000; ROT HKR BIT MASK $RPCBIT $400; LOW BIT OF ROT RPC FIELD FOR INC-IN-PLACE $IMMBIT $4; IMMEDIATE BIT MASK FOR ROT0 $MSINT $174000; $OOP00 $176000; $M2001 $175777; $12 $12; $500 $500; $RESRPC $177400; ROT HKR-RPC BIT MASK $ROTABASEM1 $177777; RAM BASE FOR BASEREG ROTA $OOPBASEM1 $1777; RAM BASE FOR BASEREG OOP $CPTMSK $100; MASK FOR IS-POINTER IN PMAP $ISCMSK $37; MASK FOR INSTANCE SIZE IN PMAP $RCIMSK $177600; REAL CLASS PART OF PMAP $SENDERF $L0,12000,100; CONSTANT 0 IS SUPER-SPECIAL; $INSTF $1; $CODEF $3; $TFRAMEF $4; ***WARNING BEFORE CHANGING SEE PUTX4 IN LITMSGS $PCF $5; ***WARNING PCF AND STACKPF MUST BE TOGETHER $STACKPF $6; ***WARNING PCF AND STACKPF MUST BE TOGETHER $PMRETI $L0,12000,100; CONSTANT 0 IS SUPER-SPECIAL; $HFRETI $1; $EIRETI $2; $IJRETI $3; $CASCME $177774; ; (CoreAddressofSmalltalkConstantsMinusEight = 4-8 =-4) $OCTV $24; ISC OF FIRST OCTAVE $VARCLS $600; OOP WHERE VAR-LEN CLASSES START $NUMCLS $4; NUMBER CLASS OOP $OBJCLS $27; NIL CLASS OOP $SPRCLSF $5; INDEX OF SUPERCLASS FIELD $MDICTF $3; INDEX OF MESSAGE DICTIONARY $CLFREE $10; OFFSET OF FREELISTHEAD IN CLASSES $CLFREE2 $21; CLFREE OF SECOND CLASS $CLFREE3MT $31; CLFREE OF THIRD CLASS MINUS TWO $STMCLS $10; $CNTXCLS $2; OOP OF CLASS CONTEXT (NOTE: SEE "BYTE:") $INTCLS $12; $VECCLS $600; $STRCLS $601; $FALSEOOP $2000; $TRUEOOP $2001; $ERRPRG $3; ADDRESS OF OOP OF ERROR METHOD $PRIMTABLOC $100; $SELFLOC $101; ; ; /* GLOBAL LABEL ALLIGNMENTS */ ; SO WE CAN USE CYCLE IN THE ROM !3,4,,HFRET,,; ******THIS MUST REMAIN FIRST !7,1,STRT; ******THIS MUST REMAIN SECOND FOR REG WRITER !165,1,L5; !22,1,RAMCYCX; ; !637,1,TRAPX10; FIRST BUILD ONLY !645,1,TRAPX13; SECOND BUILD ONLY !37,1,TRAPX20; >= X20 !20,1,START; BOTH BUILDS, THANK GOD !1,1,TRAPOP; SO THAT OR1 WONT AFFECT :TRAPOP ; ;********DISPATCH ON BYTE TYPE******** %360,377,17,IVARS,TVARS,LVARS,LVARS2,ILVARS,ILVARS2,ILVARS3,AVARS, PRIMOPS,SJMPS,LJMPS,ATRAPMSGS,OTRAPMSGS,LITMSGS,LITMSGS2,LITMSGS3; ; ;********RETURNS TO OTHER RAM BANKS********### !1777,2,X1776,X1777; ### ; ;********TARGET FOR RAM BANK SWITCHING********### !200,1,X200; ### ; ;********RETURNS FROM NOVA******** !1767,10,OVRET,FIRET,FLTRET,ALLOCRET,PRIMFAIL,SNDMSG,SUPRET,PRIMRET; ### ; AT TOP OF MEMORY SO RAM1, RAM2 CAN GET TO PRIMFAIL AND PRIMRET ### ; ;********FIX USEFUL ENTRY POINTS SO RAM1, RAM2 CAN JUMP TO THEM ### ;********HASH AND REFLAST MUST BE ODD ### !1757,10,REFCK,REFCKL,REF,REFLAST,NOVAALLOC,,HASHL,HASH; ### ; ;********RETURNS FOR REF AND REFCK******** !17,20,REFX0,REFX1,,REFX3,REFX4,REFX5,REFX6,REFX7,REFX10, REFX11,REFX12,REFX13,,,,; !17,1,REFA; ; !3,1,ILONG; BECAUSE OF RETURNS FROM TST IN SUBS ; !3,1,HASH; BECAUSE OF RETURNS FROM TST IN SUBS ### ; ;********RETURNS FOR HASH******** ;CALL 0 CAN FAIL TO HFAIL0 !1,2,FAULT,HFAIL0; ; !37,40,HSHX0,HSHX1,HSHX2,HSHX3,,HSHX5,,HSHX7, HSHX10,HSHX11,HSHX12,HSHX13,HSHX14,HSHX15,HSHX16,HSHX17, HSHX20,HSHX21,HSHX22,HSHX23,HSHX24,HSHX25,HSHX26,HSHX27, HSHX30,HSHX31,,,,,,; ; ;********RETURNS FOR IVAL******** !17,20,IVALX0,IVALX1,IVALX2,IVALX3,IVALX4,IVALX5,IVALX6,IVALX7,IVALX10,IVALX11,,,,,,; ; ;********RETURNS FOR INTN******** !3,4,INTNX0,INTNX1,INTNX2,; ; !1,2,PMAP,GCNIL; ;********RETURNS FOR GCLASS******** !7,10,GCLASSX0,GCLASSX1,GCLASSX2,GCLASSX3,GCLASSX4,GCLASSX5,,; !1,1,GCLASS; ; ;********RETURNS FOR PMAP******** !3,4,PMAPX0,PMAPX1,PMAPX2,PMAPX3; ; [ILONG,GCLASS,REF,QFINST] ; ;********RETURNS FOR ILONG******** !3,4,ILONGX0,ILONGX1,ILONGX2,ILONGX3; ; ;********RETURNS FOR ALLOC******** !3,4,ALLOCX0,ALLOCX1,ALLOCX2,; ; ;********RETURNS FOR PTNXT******** !7,10,PUTX0,PUTX1,PUTX2,PUTX3,PUTX4,,,; ; ;********RETURNS FOR POPTOP******** !7,10,POPTX0,POPTX1,POPTX2,POPTX3,POPTX4,,,; ; ;********RETURNS FOR TST******** !7,10,TSTX0,TSTX1,TSTX2,,TSTX4,,,; ; ;********RETURNS FOR STASH******** !1,2,STASHX0,STASHX1; ; ;********RETURNS FOR NXTBYTE******** !7,10,NBX0,NBX1,NBX2,NBX3,NBX4,NBX5,,; ; ;********RETURNS FOR MAPCODE******** !1,2,MCX0,MCX1; ; ;********MISC. DECLARATIONS******** !1,2,NOTNIL,NOTIND; !1,2,APPLY,HIT2; ; ; ; ; *********************************** ; * BYTECODE INTERPRETER MICROCODE * ; *********************************** ; ; /* ENTER RAM */ ; TRAPX10: T← 17, :TRPX; TRAPX13: T← 17, :TRPX; (IR←LREG FASTER??) (NEW ALTOS) TRAPX20: T← 17, :TRPX; (IR←LREG FASTER??) (NEW ALTOS) TRPX: L← XREG.T; SINK← LREG, TASK, BUS, :WHICHOP; !17,20,EXTRACT,INJECT,REFCT,NOVATRPS,SUNDRY,NOOPTRAP,,,,,BYTERP,,,,NOVARET,; WHICHOP: :EXTRACT; DISPATCH ON 16 OP CODES NOVATRPS: :TRAPOP; NOOPTRAP: :STRT; ; !17,20,IVALTP,HASHT,,,SNAT,,,,,,,,,,,; SUNDRY: SINK← DISP, BUS, TASK; :IVALTP; 72000 OPS DISPATCH HERE ; ; BYTERP- START BYTECODE INTERPRETATION ; BYTERP: L← ALLONES; SUPMOD← L; AOOP← L, TASK; BOOP← L; L← 0; MODE← L, :NEXTBYTE; ; ; NEXTBYTE- INTERPRET NEXT BYTECODE ; ; !1,2,DOINT,NOINT; !1,2,OUTANDIN,NOINT1; !1,1,OAI1; !1,2,LBYT,RBYT; NEXTBYTE: L← NWW, BUS=0; CHECK FOR INTERRUPTS T← MAR← CADDR, SH<0, :DOINT; FETCH INSTR WORD DOINT: L← PCB+1, BUSODD, :OUTANDIN; OUTANDIN: SINK← MD, :OAI1; OAI1: L← 2, :SPC; ; NOINT: L← PCB+1, BUSODD, :NOINT1; TEST WHICH BYTE NOINT1: PCB← L, L← 0+T+1, :LBYT; ; LBYT: T← 177400; LEFT BYTE L← MD.T, TASK; MASK CYCOUT← L LCY 8, :DOSYL; (TASK HAPPENS HERE) SWAP ; RBYT: T← 377; RIGHT BYTE T← MD.T; MASK CADDR← L, L← T, TASK; STEP WORD ADDR CYCOUT← L, :DOSYL; (TASK HAPPENS HERE) ; ; /* DISPATCH ON HIGH 4 BITS */ !1,2,DISPATCH,NOMSG; DOSYL: IR← CYCOUT; DISPATCH: SINK← DISP, SINK← disp.377, BUS; DISPATCH ON HIGH 4 BITS L← T← DISP, SINK← X17, :IVARS; L← T← LOW 4 BITS ; ; ; /* LOAD DATA FOR STACK */ !1,2,LCONST,LMEM; IVARS: L← SELF+T, :LMEM; LOAD REL TO SELF ; TVARS: L← TFRAME+T, :LMEM; LOAD REL TO TEMPFRAME ; LVARS: L← LOCFRAME+T, :LMEM; LOAD REL TO LOCALFRAME LVARS2: T← 17+T+1, :LVARS; ; ILVARS: MAR← LOCFRAME+T; LOAD INDIRECT REL TO LOCALFRAME T← 23; L← MD, :HASHL; ;// HASH INDIRECT LITERAL OBJECT REFERENCE. DIRTY // HSHX23: :LMEM; ILVARS2: T← 17+T+1, :ILVARS; ILVARS3: T← 37+T+1, :ILVARS; ; AVARS: SINK← DISP, SINK← lgm10, BUS=0; LOAD REL TO AREC L← AREC+T, :LCONST; OR LOAD CONSTANTS ; LCONST: L← CASCME+T, :LMEM; ;(CoreAddressofSmalltalkConstantsMinusEight = 3-8 =-5) ; !1,2,PULL,PUSH; Data TO Stack or Stack TO Data LMEM: SINK← MODE, BUS=0, TASK; :PULL; PUSH: MAR← LREG; L← STACKP+1, :STSTAK; ; ; SHOVE- REPLACE TOP OF STACK WITH L (SAME AS POP AND PUSH) ; SHOVE: TOP← L; T← 4, :REFCKL; ; ; STSTAK- MEMORY PENDING: NEW OOP TO BE STORED ON STACK ; L: INDEX ON STACK TO STORE ; ;//SPEED UP// !1,2,DOREFI,NOREFI; ;//SPEED UP//STSTAK: STACKP← L; ;//SPEED UP// T← MINAT; ;//SPEED UP// L← MD-T, T← MD; ;//SPEED UP// L← T, ALUCY; ;//SPEED UP// TOP← L, TASK, :DOREFI; ;//SPEED UP//DOREFI: ARG1← L; ;//SPEED UP// L← 4, TASK, :REF; ;//SPEED UP//REFX4: T← STACKP, :STOR; ;//SPEED UP//NOREFI: :REFX4; STSTAK: STACKP← L; L← MD; TOP← L; T← 4, :REFCKL; REFX4: T← STACKP, :STOR; ; ; STOR- T: NEW STACK POINTER ; TOP: NEW OOP ; TEMPFRAME[STACKP←T]←TOP ; ;//SPEED UP// !1,2,DOREFD,NOREFD; ;//SPEED UP//STOR: L← MAR← TFRAME+T; ;//SPEED UP// ARG1← L, L← T; ;//SPEED UP// STACKP← L; ;//SPEED UP// T← MINAT; ;//SPEED UP// L← MD-T, T← MD; ;//SPEED UP// MAR← ARG1; ;//SPEED UP// L← T, ALUCY; CHECK FOR NEED TO REFD ;//SPEED UP// ARG1← L, :DOREFD, TASK; ;//SPEED UP//; ;//SPEED UP//; /* REFD AFTER STORING ;//SPEED UP//DOREFD: MD← TOP; (TASK HAPPENS HERE) ;//SPEED UP// L← 3, TASK, :REF; ;//SPEED UP//REFX3: L← 0, TASK; ;//SPEED UP// SUPMOD← L, :NEXTBYTE; ;//SPEED UP//NOREFD: MD← TOP, :REFX3; STOR: L← MAR← TFRAME+T; ARG1← L, L← T; STACKP← L; L← MD; MAR← ARG1; T← 3; MD← TOP, :REFCKL; REFX3: :BYTERP; ; ; ; **** THE PRIMITIVE OPERATIONS ; !17,20,SMASHPOP,SMASH,POP,RETURN,REND,CURRENT,SUPER,SENDAGAIN, XIVARS,XTVARS,XLVARS,XILVARS,XLITMSGS,DUP,POP2D,; ;***** ATTENTION!!! RETURN AND END MUST REMAIN ODD AND EVEN*****///// ;***** BECAUSE OF DISPATCH OUT OF DORETURN. RED ALERT *****///// ;***** BOTH THE NOVACODE(IN SMALL.OPS) AND OTHER MICROCODE *****///// ;***** (FOR XLITMSGS) KNOW THAT SENDAGAIN IS 0207. *****///// PRIMOPS: SINK← DISP, SINK← X17, BUS, TASK; :SMASHPOP; ; ; SMSHPOP: TOP: DATA TO BE STORED ; STORE L INTO LOCATION DESCRIBED BY NEXT BYTE ; AND POP STACK ; SMASHPOP: L← STACKP-1; STACKP← L, :SMASH; ; ; SMASH: TOP: DATA TO BE STORED ; STORE L INTO LOCATION DESCRIBED BY NEXT BYTE ; SMASH: L← ONE; MODE← L; T← MAR← CADDR, :NOINT; FETCH INSTR WORD ; ; PULL(Stack TO Data): ; LREG: ADDRESS OF DATA ; TOP: NEW OOP TO BE STORED IN DATA ; !1,2,GOON,RISUBEND; PULL: MAR← L← LREG; ADDRESS LOC TO BE SMASHED TEMP3← L; TEMP3← ADDRESS OF LOC TO BE SMASHED L← MD; L← OOP BEING DESTROYED MAR← TEMP3; ADDRESS LOC TO BE SMASHED T← 11; MD← TOP, :REFCKL; STORE NEW OOP & REFD OLD OOP REFX11: L← TOP; T← 10, :REFCKL; REFI NEW OOP REFX10: SINK← MODE, BUS=0; L← 0, :GOON; GOON: MODE← L, :NEXTBYTE; (JUMPED TO FROM NOOP:) ; ; POP- POP TOP VALUE OFF STACK ; POP: L← STACKP-1, TASK; STACKP← L, :NEXTBYTE; ; ; RETURN- RETURN CONTROL TO SENDER ; !1,2,ENDEND,RETURNEND; !1,2,LP1,LP2; !1,2,DOHASH,NOHASH; RETURN: T← SENDERF; MAR← L← AREC+T, :DORETURN; ADDRESS SENDER RETURNEND: L← CTXT; T← 5, :HASHL; L← CORE ADD OF CURRENT AREC ;// HASH CURRENT CONTEXT. DIRTY // HSHX5: AREC← L; AREC← CORE ADD OF CURR AREC T← PCF; DOSP: MAR← L← AREC+T; ADDRESS PC/SP FIELD OF AREC L← PCF-T; TEST IF IT WAS PC OR SP T← OOP00; L← MD-T, SH<0; IVAL PC/SP TASK, :LP1; [LP1,LP2] LP1: PCB← L; PCB← IVAL[AREC[PC]] T← STACKPF, :DOSP; LP2: STACKP← L; STACKP← IVAL[AREC[SP]] MAR← AREC+1; T← MINAT; L← MD-T, T← MD; L← T, ALUCY; ARG1← L, :DOHASH; [DOHASH,NOHASH] DOHASH: L← ONE, TASK, :HASH; L← C.A.[AREC[INST]] NOHASH: L← ALLONES, TASK, :HSHX1; ;// HASH INSTANCE. DIRTY // HSHX1: SELF← L; SELF← C.A.[INST], T← 2, :GETTPO; L← T← C.A.[AREC[METHOD]] ;// HASH METHOD. NO DIRTY // HSHX2: L← 0, :MAPCODE; GENERATE LOCFRAME AND CADDR MCX0: T← 3, :GETTPO; L← C.A.[AREC[TFRAME]] ;// HASH TEMPFRAME. DIRTY // HSHX3: TFRAME← L; TFRAME← C.A.[AREC[TFRAME]] L← NAME; T← 7, :REFCKL; ZAP ME REFX7: T← STACKP+1, :STOR; AND PUSH TOP OF OLD STACK ON NEW ; ; GETTPO L← COREADD OF FIELD #(T+1) IN AREC ; GETTPO: MAR← AREC+T+1; NOP; L← MD, :HASHL; ; ; REND- RETURN CONTROL TO CALLER (I.E. RETURN FROM EVAL) ; REND: T← STACKP-1; MAR← L← TFRAME+T, :DORETURN; ADDRESS CALLER ENDEND: T← ONE; L← STACKP-T-1; STACKP← L, L← T, TASK, :STASH; STASHX1: :RETURNEND; ; ; DORETURN PERFORM AN ACTUAL CONTROL RETURN ; L and MEMORY PENDING= ADDRESS OF CONTEXT TO RETURN TO ; DORETURN: TEMP1← L; L← CTXT; NAME← L; NAME← CURRENT CONTEXT L← MD; MAR← TEMP1; CTXT← L, TASK; CTXT← MY SENDER MD← ALLONES; NIL MY SENDER T← STACKP; MAR← TFRAME+T; ADDRESS VALUE ON STACK SINK← DISP, BUSODD; MD← ALLONES, :ENDEND; NIL REF TO VALUE (REFI) ; ; CURRENT- PUSH CURRENT CONTEXT ; CURRENT: L← STACKP+1, TASK; STACKP← L; L← CTXT, :SHOVE; ; ; SUPER ; SUPER: T← 26, :NCPF; NOVACALL 33, CALLFLT HAS NCPF SUPRET: T← MAR← CADDR, :NOINT; FETCH INSTR WORD ; ; SENDAGAIN ; SENDAGAIN: :SNDMSG; ; ; EXTENDED LOADS ; XIVARS: L← ONE, TASK, :NXTBYTE; NBX1: L← SELF+T, :LMEM; ; XTVARS: L← 2, TASK, :NXTBYTE; NBX2: L← TFRAME+T, :LMEM; ; XLVARS: L← 3, TASK, :NXTBYTE; NBX3: L← LOCFRAME+T, :LMEM; ; XILVARS: L← 4, TASK, :NXTBYTE; NBX4: :ILVARS; ; XLITMSGS: T← 7; L← 200+T; IR← LREG; L← 5, TASK, :NXTBYTE; NBX5: MAR← LOCFRAME+T, :OPSA; ; DUP: T← STACKP, :TVARS; ; POP2D: L← STACKP-1; STACKP← L, :SHVSELF; ; ; !1,2,BFP,DOJMP; !1,2,EVENPCB,ODDPCB; !1,2,EVENINC,ODDINC; !1,2,PJMP,NJMP; !1,2,NOTFALSE,ISFALSE; !1,1,INCADDR; !1,2,LBYTB,RBYTB; ; ; SJMPS- CONTROL TRANSFER OPERATIONS OF ONE TO EIGHT ; SJMPS: L← DISP+1, SINK← M7, TASK, :JMPCMN; ; ; LJMPS- CONTROL TRANSFER OPERATIONS OF -1024 TO 1023 ; LJMPS: L← 0, TASK, :NXTBYTE; NBX0: L← DISP, SINK← M7; L: BIAS INDEX CYCOUT← L LCY 8; L: HI-BIAS ; (256*B.I.=TRUE BIAS+02000) T← CYCOUT+T+1; T: HI-BIAS+OFFSET+1 L← M2001+T, TASK; L: TRUE BIAS+OFFSET JMPCMN: ARG1← L; ARG1: NUMBER OF BYTES TO BE SKIPPED L← DISP, SINK← lgm10, BUS=0; T← FALSEOOP, :BFP; DOJMP: T← ARG1; L← PCB+T; L← NEW PCB PCB← L, L← T; PCB← NEW PCB, L← BYTES SKIPED ARG1← L, SH<0; ARG1← BYTES SKIPED, TEST NEG T← 0, :PJMP; NJMP: T← ONE, :PJMP; NEG JUMP, SET SIGN FOR RSHIFT PJMP: SINK← PCB, BUSODD; TEST NEW PCB IS LEFT/RIGHT SINK← LREG, BUSODD, TASK, :EVENPCB;TEST BYTES SKIPED IS ODD/EVEN EVENPCB: CYCOUT← L MRSH 1, :EVENINC; CYCOUT← WORDS SKIPED ODDPCB: CYCOUT← L MRSH 1, :INCADDR; CYCOUT← WORDS SKIPED EVENINC: :INCADDR; LEFT BYTE & EVEN SKIP, NO INC ODDINC: T← CYCOUT+1, :INCADDR1; LEFT BYTE & ODD SKIP, INC CADDR INCADDR: T← CYCOUT; RIGHT BYTE, NO INC INCADDR1: L← CADDR+T, TASK; CADDR← L, :NEXTBYTE; CADDR← CORE ADDRESS OF NEXT BYTE ; BFP: L← TOP-T; L← STACKP-1, SH=0, TASK; TEST TOP OF STACK IS FALSE STACKP← L, :NOTFALSE; POP STACK ISFALSE: :DOJMP; NOTFALSE: :NEXTBYTE; ; NXTBYTE: RETN0← L; MAR← T← CADDR; FETCH NEXT BYTE L← PCB+1, BUSODD; TEST WHICH BYTE PCB← L, L← 0+T+1, :LBYTB; ; LBYTB: T← 177400; LEFT BYTE L← MD.T, TASK; MASK CYCOUT← L LCY 8, :NBX; SWAP, CYCOUT: OFFSET ; RBYTB: T← 377; RIGHT BYTE T← MD.T; MASK CADDR← L, L← T, TASK; STEP WORD ADDR CYCOUT← L, :NBX; CYCOUT: OFFSET ; NBX: SINK← RETN0, BUS; L← T← CYCOUT, :NBX0; ; ; ; **** THE 16 TRAPPED ARITHMETIC MESSAGES ; !17,20,ADD,SUB,LES,GTR,LEQ,GEQ,EQL,NEQ,,,,,,,,; !1,2,AUNIMP,AIMP; !1,2,CHKOF1,NOOF1; !1,2,NOOF2,CHKOF2; !1,2,NOOF,OFLO; !1,2,YESISFLS,YESISTRU; !1,2,FALS,YTRUE; !1,2,TRUE,YFALS; !1,2,MBTRUA,TRULE; !1,2,MBTRUB,TRUGE; ATRAPMSGS: SINK← DISP, SINK← lgm10, BUS=0; L← STACKP, :AUNIMP; AUNIMP: SAVSP← L, :APPLY; STASH STACKP IN REG AIMP: SAVSP← L; STASH STACKP IN REG T← 0; L← TOP, :IVALL; IVALX0: TEMP2← L; L← 4, TASK, :POPTOP; POPTX4: T← ONE, :IVALL; L← T← VALUE OF ARG IVALX1: TEMP3← L; T← TEMP3; SINK← DISP, SINK← X17, BUS; L← TEMP2 XOR T, :ADD; ; ADD: L← TEMP2+T, SH<0; ARG1← L, :CHKOF1; [CHKOF1,NOOF1] NOOF1: L← 0, TASK, :INTN; OPERAND SIGNS DIFFERENT CHKOF1: L← ARG1 XOR T, :CKOFCMN; OPERAND SIGNS SAME ; SUB: L← T← TEMP2-T, SH<0; ARG1← L, :NOOF2; [NOOF2,CHKOF2] NOOF2: L← 0, TASK, :INTN; OPERAND SIGNS SAME CHKOF2: L← ARG1 XOR T, :CKOFCMN; OPERAND SIGNS DIFFERENT ; CKOFCMN: SH<0, TASK; CHECK FOR OVERFLOW :NOOF; [NOOF,OFLO] NOOF: L← 0, TASK, :INTN; SIGNS SAME INTNX0: TOP← L, :REFX4; OFLO: :APPLY; SIGNS DIFFERENT ; LES: L← TEMP2-T, SH<0, :OCOM; GTR: T← TEMP2; L← TEMP3-T, SH<0, :OCOM; EQL: SH=0, :YESISTRU; NEQ: SH=0, :YESISFLS; LEQ: SH=0; :MBTRUA; MBTRUA: :LES; TRULE: :SHVSELF; ; GEQ: SH=0; :MBTRUB; MBTRUB: :GTR; TRUGE: :SHVSELF; ; OCOM: ALUCY, TASK, :YESISFLS; YESISFLS: :TRUE; TRUE: :SHVSELF; YFALS: :SHVFALS; YESISTRU: :FALS; FALS: :SHVFALS; YTRUE: :SHVSELF; SHVFALS: L← FALSEOOP, :SHOVE; SHVSELF: L← TOP, :SHOVE; ; ; ; **** OTHER MESSAGES TRAPPED BY THE MICROCODE INTERPRETER ; !17,20,LBKT,RBKT,NEXT,LARO,LEN,EQ,,,,,,,,,,; !1,2,OUNIMP,OIMP; OTRAPMSGS: SINK← DISP, SINK← lgm10, BUS=0; L← STACKP, :OUNIMP; OIMP: SINK← DISP, SINK← X17, BUS; SAVSP← L, :LBKT; STASH STACKP IN REG OUNIMP: SAVSP← L, :APPLY; STASH STACKP IN REG ; ; SUBS [LBKT,RBKT,NEXT,LARO] ; MESSAGES WHICH REFER TO THE PARTS OF COLLECTION OBJECTS ; ([] and []← FOR STRINGS AND VECTORS, next and ← FOR STREAMS) ; !1,2,TST,HIT0; !1,2,ILTL,ITOBG; !1,2,IPOS,INEG; !3,4,INT,VEC,STR,; !1,2,STST,STLD; !1,2,VCLD,VCST; !1,2,STLDEV,STLDOD; !1,2,STSTEV,STSTOD; LBKT: L← 0, TASK, :GTOPCLS; RBKT: L← ONE, TASK, :POPTOP; FETCH NEW VAL FOR DOT← POPTX1: SAVR1← L, :LBKT; ; GCLASSX0: NAME← L; L← VECCLS-T, :DBLTST; TSTX0: L← 3, TASK, :ILONG; ILONGX3: TEMP4← L; L← ALLONES, TASK; AOOP← L; L← 0, :POPTOP; FETCH INDEX FOR DOT AND DOT← POPTX0: T← 3, :IVALL; SEE BELOW FOR IVALX3 ; NEXT: L← 2, TASK, :GTOPCLS; LARO: L← 2, TASK, :POPTOP; FETCH NEW VAL FOR NEXT← POPTX2: SAVR1← L, :NEXT; ; GCLASSX2: L← STMCLS-T, :TST; TSTX2: L← 7, TASK, :HASH; L← CORE ADD OF STREAM ;// HASH STREAM ON TOP OF STACK. DIRTY // HSHX7: MAR← LREG+1; ADDRESS STREAM INDEX ACORE← L; ACORE← CORE ADD OF STREAM L← TOP; AOOP← L; L← MD, TASK; TEMP3← L; TEMP3← STREAM INDEX MAR← ACORE; ADDRESS STREAM CONTENTS (STRECTOR) T← 2; L← MD; MAR← ACORE+T; ADDRESS STREAM LENGTH TOP← L; TOP← STREAM CONTENTS (STRECTOR) L← MD, :IVALL; IVALX2: TEMP4← L; TEMP4← VALUE OF STREAM LENGTH L← TOP; T← ONE, :GCLASSL; GCLASSX1: NAME← L; L← TEMP3; L← STREAM INDEX T← 7, :IVALL; IVALX7: T← 0+T+1, :IVALX3; ; IVALX3: L← TEMP4-T; L← VALUE OF LENGTH-VALUE OF INDEX L← ALLONES+T, SH<0; CHECK INDEX LESS THAN LENGTH TEMP2← L, SH<0, :ILTL; TEMP2← OFFSET(INDEX-1) & CHECK POS ILTL: L← TOP, :IPOS; L← OOP OF STRECTOR IPOS: BOOP← L; T← 25, :HASHL; L← CORE ADD OF STRECTOR ;// HASH STRECTOR BEING INDEXED. DIRTY // HSHX25: BCORE← L; BCORE← CORE ADD OF STRECTOR L← ONE, TASK; RETN1← L; L← T← NAME; L← T← CLASS OF STRECTOR L← INTCLS-T, :TRITST; DISTINGUISH STR, VEC AND INT TSTX1: L← TEMP2, TASK, :INT; L← VALUE OF OFFSET ; !1,2,NOADD,DOADD; !1,2,MULLP,INTNSTOR; ; !1,2,GTI,INTLARO; INT: CYCOUT2← L; CYCOUT2← INDEX OF INTERVAL ; SINK← DISP, BUSODD; CHECK FOR next OR ← T← 2, :GTI; L← T← VALUE OF INT STEP IVALX10: TEMP4← L; TEMP4← VALUE OF INT STEP T← 0, :GTI; ; L← T← VALUE OF INT START IVALX6: ARG1← L; ARG1← VALUE OF INT START L← TEMP4, TASK; TEMP1← L; MULLP: L← TEMP1, BUSODD; TEST LO BIT OF MULTIPLIER TEMP1← L RSH 1, :NOADD; HALVE MULTIPLIER NOADD: L← CYCOUT2, SH=0, TASK; L← MULTIPLICAND, TEST DONE DBL: CYCOUT2← L LSH 1, :MULLP; DOUBLE MULTIPLICAND DOADD: T← CYCOUT2; T← MULTIPLICAND L← ARG1+T; L← SUM+NEW TERM ARG1← L, L← T, TASK, :DBL; ARG1←NEW SUM, L← MULTIPLICAND INTNSTOR: L← 2, TASK, :INTN; ARG1←INTRNED SUM INTNX2: TOP← L, :REFX12; ; ;INTLARO: :APPLY; ; GTI: MAR← BCORE+T; ADDRESS ELEMENT T OF INTERVAL T← 5+T+1; MAP T FOR IVAL RETURN; L← MD, :IVALL; ; STR: CYCOUT2← L RSH 1; CYCOUT2← WORD INDEX IN STRING T← CYCOUT2; MAR← L← BCORE+T; ADDRESS WORD WITH BYTE L← DISP, SINK← lgm1; L← MD, SH=0, TASK; TEST LOAD OR STORE? CNT← L, :STST; CNT← WORD WITH BYTE ; STLD: SINK ←TEMP2, BUSODD; TEST WHICH BYTE L← T← CNT, :STLDEV; L← T← WORD WITH BYTE ; STLDEV: CYCOUT← L LCY 8; SWAP WORD WITH BYTE T← CYCOUT, :STLDOD; T← SWAPPED WORD WITH BYTE ; STLDOD: L← 377 AND T; ARG1← L, :INTNSTOR; STORE INTRNED BYTE ON STACK ; STST: L← SAVR1; L← NEW BYTE TOP← L; TOP← NEW BYTE T← 5, :IVALL; L← T← VALUE OF NEW BYTE IVALX5: SINK← TEMP2, BUSODD; TEST WHICH BYTE L← 377.T, TASK, :STSTEV; L← MASKED VALUE OF NEW BYTE ; STSTEV: CYCOUT← L LCY 8; CYCOUT← NEW BYTE IN LEFT BYTE T← 377, :STSTCM; T← RIGHT BYTE MASK ; STSTOD: CYCOUT← L; CYCOUT← NEW BYTE IN RIGHT BYTE T← 177400, :STSTCM; T← LEFT BYTE MASK ; STSTCM: L← CNT.T; L← REMAINING BYTE FROM WORD T← CYCOUT2; MAR← BCORE+T; ADDRESS WORD WITH BYTE T← LREG; T← REMAINING BYTE FROM WORD L← CYCOUT+T; L← NEW BYTE AND REMAINING BYTE MD← LREG, :RISUBEND; STORE NEW BYTE AND REMAINING BYTE ; VEC: NOP; SINK← DISP, BUSODD; TEST LOAD OR STORE? T← TEMP2, :VCLD; T← OFFSET IN VECTOR ; VCLD: MAR← L← BCORE+T; ADDRESS OOP IN VECTOR NOP; L← MD, TASK; TOP← L, :RISUBEND; ; VCST: L← SAVR1; L← NEW OOP TOP← L, TASK; TOP← OOP IN VEC L← BCORE+T, :PULL; L← OOP IN VECTOR ; NOTE: PULL RETURNS TO RISUBEND IF MODE IS 0 !1,2,POSTSTM,IMDONE; RISUBEND: L← TOP; T← 12, :REFCKL; REFX12: L← AOOP+1; MAR← ACORE+1, SH=0; ADDRESS STREAM INDEX T← 4, :POSTSTM; POSTSTM: L← MD; NAME← L, :IVALL; IVALX4: L← ONE+T, T← ONE, :INTNL; INTNX1: MAR← ACORE+1; ADDRESS STREAM INDEX T← 13; MD← LREG; L← NAME, :REFCKL; REFX13: :REFX4; IMDONE: SINK← MD, TASK, :REFX13; ; ITOBG: :INEG; INDEX OUT OF RANGE INEG: :APPLY; OFFSET NEGATIVE ; ; !1,2,TST,HIT0; (APPEARS ABOVE) !1,2,TST1,HIT1; ; !1,2,APPLY,HIT2; (APPEARS ABOVE) !1,1,TXIT; TRITST: L← VECCLS-T, SH=0, :DBLTST; FIRST TEST DBLTST: L← STRCLS-T, SH=0, :TST; (SECOND) TEST, (FIRST BRANCH) TST: L← ONE, SH=0, :TST1; (THIRD) TEST, (SECOND BRANCH) TST1: L← 2, :APPLY; (THIRD) BRANCH HIT0: L← 0; WAS FIRST CLASS HIT1: SINK← RETN1, BUS, :TXIT; WAS (SECOND) CLASS HIT2: SINK← RETN1, BUS, :TXIT; WAS (THIRD) CLASS TXIT: SINK← LREG, BUS, :TSTX0; ; ; APPLY -DO IT THE SLOW GENERAL WAY ; APPLY: L← T← SAVSP; MAR← TFRAME+T; ADDRESS TOP OF STACK STACKP← L; L← MD, TASK; TOP← L; RESTORE TOP REGISTER FROM STACK T← 177034-1; (T← -744-1) T← 500+T+1; (L← -244 I.E. DIFFERENCE BETWEEN ; PLUS BYTE CODE AND ADDRESS OF ; PLUS ATOM) MAR← DISP+T; :OPSA; ; POPTOP: RETN0← L; L← T← STACKP-1; DECREMENT STACK POINTER MAR← TFRAME+T; ADDRESS ELEMENT ON TOP OF STACK STACKP← L; RESTORE STACK POINTER SINK← RETN0, BUS; RETURN DISPATCH L← T← MD, :POPTX0; L← ELEMENT ON TOP OF STACK ; ; **** LENGTH LEN: L← 4, TASK, :GTOPCLS; GCLASSX4: L← VECCLS-T, :DBLTST; TSTX4: L← 0, TASK, :ILONG; ILONGX0: T← 0, :INTNL; SEE ARITH OPS FOR INTNX0: ; ; **** EQ TOP OF STACK=NEXT ON STACK? ; !1,2,NTEQ,ISEQ; EQ: L← 3, TASK, :POPTOP; POPTX3: L← TOP-T; SH=0, TASK; :NTEQ; NTEQ: L← FALSEOOP, :SHOVE; ISEQ: L← TRUEOOP, :SHOVE; ; ; ;*** LITMSGS- NON TRAPPED MESSAGES ; !1,2,DICTOK,DICTNIL; !1,2,SIZOK,SIZE0; !1,2,DLULP,GOTIT; !1,2,STNIL,STARGS; !1,2,STORIT,DONEIT; LITMSGS: MAR← LOCFRAME+T; ADDRESS LITERAL OPERATOR OPSA: NOP; L← MD; L← LITERAL OPERATOR NAME← L; SNDMSG: L← 5, TASK, :GTOPCLS; L← CLASS OF TOP OF STACK GCLASSX5: SUPMOD← L; T← 16, :HASHL; L← CORADD OF CLASS OF T.O.S. ;// HASH CLASS OF TARGET. NO DIRTY // HSHX16: MAR← MDICTF+T; ADDRESS MDICT OF C.O.T.O.S. NOP; L← MD+1; L← LREG-1, SH=0; L← OOP OF DICT, TEST NULL BOOP← L, :DICTOK; DICTOK: T← 12, :HASHL; ;// HASH MESSAGE DICTIONARY OF TARGET. NO DIRTY // HSHX12: MAR← L← LREG; BCORE← L; L← T← ONE; WRAPFL← L; L← MD, :ILONGL; ILONGX1: TEMP2← L; TEMP2: LENGTH L← 20, TASK, :HASH; ;// HASH LEFT SIDE OF DICTIONARY. NO DIRTY // HSHX20: NAMES← L; NAMES: CORE ADD OF NAMEVEC T← TEMP2-1, SH=0; L← NAME.T, TASK, :SIZOK; SIZOK: TEMP1← L; INITIAL HASH=NAME AND LEN-1 !1,2,INCIX,WRAP; !1,2,DLUL1,WRAP2; ; !1,2,NOTNIL,NOTIND; (APPEARS ABOVE) DLULP: T← TEMP1; /* LOOKUP LOOP L← TEMP2-T-1; MAR← NAMES +T, SH=0; LOOK AT NAMES[INDEX] L← WRAPFL-1, :INCIX; INCIX: L← 0+T+1, :NEWIX; INDEX ← INDEX + 1 WRAP: WRAPFL← L, SH<0, :NEWIX; FIRST WRAP LEAVES 0 IN L! NEWIX: TEMP1← L, T← 0+1, :DLUL1; SECOND WRAP GOES TO WRAP2 DLUL1: L← MD+T, T← MD; L← NAME-T, SH=0; TEST FOR EMPTY SLOT :NOTNIL, SH=0, TASK; TEST FOR HIT NOTNIL: :DLULP; LOOP IF NEITHER ; !1,2,PRIM,BYTES; !1,2,IXOK,UNWRAP; GOTIT: L← TEMP1-1, BUS=0; UN-INC HASHI :IXOK; UNWRAP: L← TEMP2-1; UN-WRAP IF WAS ZERO IXOK: MAR ← BCORE+1; TEMP2← L; T← 22; L← MD, :HASHL; /* FOUND NAME - GET VALUE ;// HASH RIGHT SIDE OF DICTIONARY. NO DIRTY // HSHX22: MAR← TEMP2+T; RPROG: T← 26; L← MD; BOOP← L, :HASHL; BOOP← MDICT[LITERAL OPERATOR] ;// HASH METHOD. NO DIRTY // HSHX26: MAR← LREG; BCORE← L; CORE ADDR OF B BASE REG L← MD-1, BUS=0; (L← MD-1, T← MD) L← LREG+1, SH=0, :PRIM; [PRIM,BYTES] ; !1,2,DO,NOOP; !1,2,DO1,RAMCALL; ### !1,2,NCSTOR,NCDONE; ; !1,1,REFLAST; ### PRIM: TEMP3← L, :DO; [DO,NOOP] NOOP: :BYTERP; DO: MAR← BCORE+1, SH<0; ALSO SEE IF EXTENDED PRIMITIVE ### L← STACKP, :DO1; [DO1,RAMCALL] ### DO1: TEMP2← L; T← 7; L← MD AND T, TASK; TEMP1← L; T← ALLONES; L← TOP; NCLOOP: MAR← SELFLOC+T+1; SINK← TEMP1, BUS=0, TASK; MD← LREG, :NCSTOR; [NCSTOR,NCDONE] NCSTOR: L← T← TEMP2-1; MAR← TFRAME+T; TEMP2← L; L← T← TEMP1-1; TEMP1← L; L← MD, :NCLOOP; NCDONE: MAR← PRIMTABLOC; T← TEMP3; L← MD; MAR← LREG+T; TASK; L← MD; MAR← LREG, :MEMPC; ; RAMCALL: SINK ← TEMP3,BUS,SWMODE; DISPATCH ON PRIMITIVE NUMBER ### X200: :X200; AND JUMP (LABEL USED FOR OTHER RAM BANKS) ### ; PRIMRET: L← ARG1; TOP← L; MAR← BCORE+1; T← 7; T← MD.T; L← STACKP-T; T← LREG, :STOR; ; PRIMFAIL: L← BOOP; T← 6, :REFCKL; ; BYTES: L← 6, :REFLAST; REFX6: L← 0, :ACTXT; ; NOTE: THE RETURN FOR THE CONTEXT ALLOCATOR MUST BE 0 ; L← OOP[NEW AREC] ; T← CORADD[SAME] ALLOCX0: AOOP← L, L← T, TASK; AOOP← OOP[NEW AREC] ACORE← L; ACORE← CORE ADD OF NEW AREC L← CTXT; L← OOP OF RETIRING AREC ARG1← L, L← T← 0, :PTATT; NEW AR[SENDER]← RETIRING AREC PUTX0: L← TOP, :PTNXT; NEW AR[INST]←TOP OF OLD STACK PUTX1: L← ALLONES, :PTNXT; NEW AR[CLASS]← NIL PUTX2: L← BOOP, :PTNXT; NEW AR[CODE]← MDICT[LIT OP] PUTX3: MAR← BCORE+1; ADDRESS SECOND WORD OF CODE T← 177400; T← LEFT BYTE MASK L← MD AND T, T← MD; L← LEFT BYTE ARG1← L LCY 8; ARG1← TSIZE (BYTE #2 OF CODE) L← T← 377.T; T← L← RIGHT BYTE NAME← L; NAME← NARGS (BYTE #3 OF CODE) L← STACKP-T-1, TASK; STACKP← L; POP THE OBJECT AND ITS ARGS L← T← ARG1; RETN2← L, :AVEC; RETN2← TSIZE ; NOTE: THE RETURN FOR THE VECTOR ALLOCATOR IS 2 (SET INTERNALLY) ; ARG1← VECTOR TSIZE ; TEMP1← COREADD ALLOCX2: L← T← 4, :PTATT; NEW AREC[TFRAME]← NEW VECTOR ; ; LOOP TO STORE ARGS AND NIL STACK AND TEMP PART OF TFRAME ; RETN2 IS THE OFFSET IN TFRAME WHICH POINTS AT THE LAST ; SLOT FILLED, STARTS OUT AS SIZE OF TFRAME ; PUTX4: T← NAME; T← NARGS L← RETN2-T; L← T← RETN2-1, SH=0; L← T← OFFSET OF NEXT ELEMENT, ; TEST IF REST ARE ARGS RETN2← L, :STNIL; RETN2← OFFSET OF CURR ELEMENT STNIL: MAR← TEMP1+T; ADDRESS CURRENT ELEMENT TASK; (IN STACK OR TEMPS) MD← ALLONES, :PUTX4; NIL CURRENT ELEMENT ; ; THE REST OF THE TFRAME IS TAKEN UP BY ARGS ; STARGS: T← STACKP; T← OLD STACKP L← T← TFRAME+T+1; L← ADD OF LOWEST ARG IN OLD STACK MAR← NAME+T; ADDRESS OF REF TO TARGET TFRAME← L, :NILTOP; TFRAME← ADD OF LOW ARG IN ; O.S., AND NIL REF TO TARGET STORIT: T← NAME-1; T← OFFSET IN NEW STACK-1 MAR← TEMP1+T+1; ADDRESS ARG ON NEW STACK T← TFRAME+T+1; T← ADD OF ARG ON OLD STACK MD← LREG, L← T; STORE ARG ON NEW STACK MAR← LREG; ADDRESS ARG ON OLD STACK NILTOP: TASK; MD← ALLONES; NIL ARG ON O.S.(FOR REFCT) L← T← NAME-1; L← T← OFFSET OF NEXT ARG MAR← TFRAME+T; ADDRESS NEXT ARG ON OLD STACK NAME← L, TASK, SH<0; NAME← OFF OF NEXT ARG L← MD, :STORIT; L← NEXT ARG FROM OLD STACK DONEIT: L← 0, TASK, :STASH; STASHX0: T← 2; MAR← BCORE+T; ADDRESS THIRD WORD OF CODE T← 177400; T← LEFT BYTE MASK L← MD AND T, T← MD; L← LEFT BYTE CYCOUT← L LCY 8; CYCOUT← OFF OF 1ST STACK LOC ; (INITIAL STACKP+1, BYTE #4) L← 377.T, TASK; L← INITIAL PCB (BYTE #5) PCB← L; PCB← INITIAL PCB L← CYCOUT-1; STACKP← L; STACKP← INITIAL STACKP L← AOOP; CTXT← L; L← ACORE; AREC← L; L← TEMP1, TASK; TFRAME← L; T← BCORE; T← CORE ADDRESS OF CODE L← ONE, :MAPCODE; GENERATE LOCFRAME AND CADDR !1,2,HASHSELF,NILSELF; MCX1: T← MINAT; L← TOP-T; ALUCY; L← TOP, :HASHSELF; [HASHSELF,NILSELF] HASHSELF: T← 27, :HASHL; L← CORE ADDRESS OF NEW SELF NILSELF: L← ALLONES, :HSHX27; ;// HASH NEW SELF. DIRTY // HSHX27: SELF← L, :BYTERP; ;HEIGH HO SILVER, AWAY!!! ; "WHO WAS THAT MASKED MAN?" ; !1,1,NID1; SIZE0: :NID1; ZERO MDICT SIZE FAILS DICTNIL: :NID1; NULL MDICT FAILS WRAP2: SINK← MD, :NID1; 2ND WRAP-AROUND FAILS NOTIND: :NID1; NID1: L← SUPMOD; T← 24, :HASHL; ;// HASH CURRENT MCLASS. NO DIRTY // HSHX24: MAR← SPRCLSF+T; NOP; L← MD+1; L← LREG-1, SH=0; SUPMOD← L, :DISPATCH; [DISPATCH,NOMSG] NOMSG: MAR← ERRPRG, :RPROG; ; ;*** PTNXT- PUT OOP IN L INTO NEXT LOC WITHOUT REFI-ING IT ; PTNXT: ARG1← L; L← T← TEMP2+1; L← INCREMENTED INDEX PTATT: MAR← ACORE+T; ADDRESS NEXT LOC TEMP2← L; CURRENT INDEX← INC-ED INDEX SINK← TEMP2, BUS, TASK; RETURN IS INDEX MD← ARG1, :PUTX0; STORE OOP ; ; //SUBROUTINE TO STASH PC AND STACKP IN AREC// ; STASH: RETN0← L; T← OOP00; L← STACKP+T; STACKP← L; L← PCB+T; T← PCF; MAR← AREC+T; T← STACKPF; MD← LREG; MAR← AREC+T; SINK← RETN0, BUS, TASK; MD← STACKP, :STASHX0; ; ; MAP CODE GENERATE LOCFRAME AND CADDR ; MAPCODE: RETN0← L; L← 3+T; L← C.A. OF 3RD WORD OF CODE LOCFRAME← L ; L← PCB; L← PTR TO NEXT BYTE IN CODE CYCOUT← L RSH 1; CYCOUT← WORD IDX OF THAT BYTE L← CYCOUT+T; L← C.A.[NEXT BYTE] SINK← RETN0, BUS, TASK; CADDR← L, :MCX0; CADDR← C.A.[NEXT BYTE] ; ; SECOND AND THIRD SET OF NON TRAPPED MESSAGES ; LITMSGS2: T← 17+T+1, :LITMSGS; ADDRESS LITERAL OPERATOR LITMSGS3: T← 37+T+1, :LITMSGS; ADDRESS LITERAL OPERATOR ; ; ; ; ************************************ ; * BYTE-INTERPRETER/OOZE MICROCODE * ; ************************************ ; ; ; IVAL- ARG1:OOP L:RETN ; L←VALUE OF NUMBER ; PRESERVES ARG1 ; !1,2,NOTSI,MBSI; !1,2,ISSI,NONINT; !1,2,NOTNMBR,ISNMBR; !1,2,RAMCLL,NOVCLL; IVALL: ARG1← L, L← T, TASK; IVAL: RETN2← L; (TASK HAPPENS HERE) T← MSINT; L← ARG1-T; L← ARG1+1, ALUCY; TEST >= MIN SMALL INTEGER T← OOP00, SH=0, :NOTSI; TEST FOR NIL IF SO MBSI: L← ARG1-T, TASK, :ISSI; ISSI: NOP; SINK← RETN2, BUS; L← T← LREG, :IVALX0; NONINT: NOP; TASK PENDING HERE ### NOTSI: L← 3, TASK, :GCLASS; GCLASSX3: L← NUMCLS-T; TEST FOR CLASS = NUMBER T← 11, SH=0; L← RETN2-T, :NOTNMBR; ISNMBR: L← 10, TASK, :HASH; HASH INTO ROT ;// HASH LARGE INTEGER. NO DIRTY // HSHX10: L← ROT1, TASK, :ISSI; NOTNMBR: SH=0; :RAMCLL; RAMCLL: :APPLY; NOVCLL: :PRIMFAIL; ; ; INTN- ARG1:VALUE L:RETN ; L←T←NUMBERS OOP ; !1,2,OUTOFRANGE,INRANGE; !1,2,NTNL,OOR1; INTNL: ARG1← L, L← T, TASK; INTN: RETN2← L; T← OOP00; L← ARG1+T; L: OOP IF IT IS SMALL INT T← MSINT; L← LREG-T; L← LREG+T+1, ALUCY; IS IT > THAN MIN SMALL INT? T← LREG-1, SH=0, :OUTOFRANGE; IS IT NIL? ; INRANGE: L← ARG1, TASK, :NTNL; NTNL: L← T; IRT: SINK← RETN2, BUS; L← T← LREG, :INTNX0; ; OUTOFRANGE: L← ARG1, TASK, :OOR1; OOR1: SAVR1← L; L← ONE, :AINT; ; NOTE: THE RETURN FOR THE INTEGER ALLOCATOR MUST BE 1 ; ARG1← OOP OF NEW INTEGER ; TEMP1← CORE ADDRESS OF NEW INTEGER ALLOCX1: MAR← TEMP1; TASK; MD← SAVR1, :IRT; ; ; ; ILONG- ARG1:OOP L:RETN ; L←OOP'S LENGTH ; PRESERVES ARG1 ; ; /* ILONG */ AC0 ← LENGTH (OOP IN AC0) !1,2,GOTSIZ,ISOCT; ILONGL: ARG1← L, L← T, TASK; ILONG: RETN1← L; (TASK HAPPENS HERE) T← ARG1; L← 0, :PMAP; PMAPX0: T← ISCMSK; T← MD.T; EXTRACT INST SIZE L← OCTV-T-1; L← T, SH<0, TASK; TEST FOR OCTAVE SIZE; :GOTSIZ; GOTSIZ: SINK← RETN1, BUS; L← T← LREG, :ILONGX0; RETURN WITH SIZE IN L ; ISOCT: L← 14, TASK, :HASH; CALL HASH TO FIND OBJ ;// HASH OBJECT. NO DIRTY // HSHX14: MAR← ROT1-1; TASK; L← MD, :GOTSIZ; REAL LENGTH IN FIELD -1; ; ; ; ; GTOPCLS- L:RETN ; L←TOP'S CLASS ; PRESERVES ARG1 ; !1,2,GTRN,DOGC; GTOPCLS: RETN1← L; L← SUPMOD+1; L← TOP, SH=0, TASK; ARG1← L, :GTRN; GTRN: SINK← RETN1, BUS; L← T← SUPMOD, :GCLASSX0; ; ; ; ; GCLASS- ARG1:OOP L:RETN ; L←OOP'S CLASS ; PRESERVES ARG1 ; GCLASSL: ARG1← L, L← T, TASK; GCLASS: RETN1← L; (TASK HAPPENS HERE) DOGC: L← ARG1+1; T← ARG1, SH=0; TEST FOR NIL L← ONE, :PMAP; PMAPX1: T← RCIMSK; L← T← MD.T; EXTRACT RCI CYCOUT← L MLSH 1; L← CYCOUT, TASK; CYCOUT← L LCY 8; FIN: SINK← RETN1, BUS; L← T← CYCOUT, :GCLASSX0; GCNIL: L← OBJCLS, TASK; CYCOUT← L, :FIN; ; ; ; PMAP- T:OOP L:RETN ; RETURNS AFTER MAR← PMAP ENTRY ADDRESS ; PMAP: RETN0← L, L← T; XREG← L LCY 8; L← T← XREG, TASK; XREG← L MLSH 1; L← T← XREG, TASK; XREG← L MLSH 1; T← 1777-1; 1776 T← XREG.T, TASK; L← PMBASE+T; SINK← RETN0, BUS; MAR← LREG, :PMAPX0; INDEX THE PCLASS MAP ; ; ALLOCATORS FOR CONTEXT, INTEGER AND VECTOR ; ARG1← L← NEW OOP ; TEMP1← T← CORE ADDRESS OF NEW OOP ; !1,2,SZOK,TOOLONG; !1,2,GOTONE,NILFL; !1,2,LINKUP,NXNIL; !3,4,CTXTF,INTF,VECF,; ACTXT: T← CLFREE, :ALLOC; AINT: T← CLFREE2, :ALLOC; AVEC: L← 10-T; T← CLFREE3MT+T+1, SH<0; L← 2, :SZOK; [SZOK,TOOLONG] SZOK: T← 0+T+1, :ALLOC; TOOLONG: RETN1← L, :VECF; ; ; AT THIS POINT, T CONTAINS THE OFFSET FROM THE BASE OF CORE ; OF THE RELEVENT FREELIST ; ALLOC: RETN1← L; MAR← L← COREBASE+T; TEMP2← L; L← MD+1; L← LREG-1, SH=0; TEST NULL FREELIST ARG1← L, :GOTONE; [GOTONE,NILFL] NILFL: SINK← RETN1, BUS, :ALLOCFAIL; GOTONE: L← 31, TASK, :HASH; ;// HASH FREE LIST HEAD. DIRTY // HSHX31: MAR← L← LREG; TEMP1← L; TEMP1← CORE LOC OF NEW OBJECT L← MD+1; L← LREG-1, SH=0, TASK; :LINKUP; [LINKUP,NXNIL] NXNIL: SINK← RETN1, BUS, :ALLOCFAIL; LINKUP: MAR← TEMP2; T← RESRPC; T: MASK FOR RES AND REPROBE COUNT T← IMMBIT OR T; T: MASK FOR IMM BIT, RES AND RPC MD← LREG; MAR← ROTA; T← ROT0.T; T: IMMEDIATE BIT, RES AND RPC L← ROT0ND OR T, TASK; MD← LREG; ALRT: L← ARG1; SINK← RETN1, BUS; T← TEMP1, :ALLOCX0; [ALLOCX0,ALLOCX1,ALLOCX2,] ; ALLOCFAIL: :CTXTF; [CTXT,INT,VEC,] CTXTF: L← CNTXCLS, :NOVAALLOC; INTF: L← NUMCLS, :NOVAALLOC; VECF: L← VECCLS, :NOVAALLOC; ; NOVAALLOC: ARG1← L; L← AC1; TEMP3← L; L← RETN2; AC1← L; L← 30, :NOVACALL; ; ... ALLOCRET: L← ARG1, TASK; TEMP1← L; L← TEMP3; AC1← L; L← TEMP1; T← 21, :HASHL; ;// HASH NEW INSTANCE. DIRTY // HSHX21: TEMP1← L, :ALRT; ; ; REFLAST- L:RETN ; REFERENCE COUNT LAST OBJECT HASHED ; REFLAST: RETN1← L, :HSHX30; ; ; REFCK- ARG1:OOP L:RETN ; SMASHES ARG1 ; ; !17,1,REFA; !1,2,RNAT,RISAT; !1,2,REFI,REFD; REFCKL: ARG1← L, L← T, TASK; REFCK: RETN1← L; EVEN CALLS REFI, ODD REFD! T← MINAT; CHECK FOR SPECIAL L← ARG1-T; L← LREG+T, ALUCY; (RESTORE L) SINK← RETN1, BUS, :RNAT, TASK; RISAT: :REFX0; IF SPECIAL, THEN DONE RNAT: :REFA; ; ; REF- ARG1:OOP L:RETN ; SMASHES ARG1 ; REF: RETN1← L; EVEN CALLS REFI, ODD REFD! REFA: L← 30, TASK, :HASH; HASH INTO ROT ;// HASH OBJECT BEING REFERENCE COUNTED. NO DIRTY // HSHX30: L← T← ROT0; SINK← RETN1, BUSODD, TASK; TEST REFI OR REFD :REFI; ; !1,2,DECIT,DEALOC; !1,2,DCKOV,DNOV; REFD: T← LREG; /* REFD L← RCTMSK.T; MAR← ROTA, SH=0; TEST IF DEC ZERO L← RCT8BIT.T, :DECIT; CHECK IF COUNT>7 DECIT: L← RCTM1BIT+T, SH=0; HERE IS THE DECREMENT MD← LREG, :DCKOV; AND STORE-BACK DNOV: SINK← RETN1, BUS, :RISAT, TASK; DONE DCKOV: L← ROT0, :CKOV, TASK; GO TEST FOR 14 (BEFORE DEC) ; !1,2,ICKOV,INOV; REFI: T← LREG; /* REFI MAR← ROTA; L← RCT8BIT.T; CHECK IF COUNT>7 L← RCT1BIT+T, SH=0; HERE IS THE INCREMENT MD← LREG, :ICKOV; AND STORE-BACK INOV: SINK← RETN1, BUS, :RISAT, TASK; DONE ICKOV: :CKOV, TASK; TEST FOR 14 OR 15 (AFTER INC) ; !1,2,WASOV,NOTOV; CKOV: NOP; /* CHECK FOR OV T← LREG; T← RCTMSK.T; T← 177400+T+1; L← 37+T; L ← RCT - 14 (340) SH<0; SINK← RETN1, BUSODD, :WASOV; NOTOV: SINK← RETN1, BUS, :RISAT, TASK; DONE (!1,1,RISAT!) ; !1,2,INCOV,DECOV; !1,2,OLDINC,NEWINC; !1,1,OLDDEC; WASOV: L← AC1, SH=0, :INCOV; /* PREPARE TO CALL NOVA INCOV: TEMP3← L, :OLDINC; NEWINC: L← 2, :OVCALL, TASK; AC1=2 - INC NEEDS NEW OV ENTRY OLDINC: L← ONE, :OVCALL, TASK; AC1=1 - INC OLD OV ENTRY DECOV: TEMP3← L, :OLDDEC; OLDDEC: L← 0, :OVCALL, TASK; AC1=0 - INC OLD OV ENTRY ; OVCALL: AC1← L; MAR← ROTA; HAVE TO RESTORE ROT TASK; MD← ROT0; L← 37-1, :NOVACALL; THEN CALL OVREF (OOP, CODE) ; ... OVRET: L← TEMP3; AC1← L, :NOTOV; AND RETURN ; DEALOC: L← RCT1BIT+T, TASK; BUMP REFCT TO 1 FOR FREER MD← LREG, :RECUF; AND CALL THE RECURSIVE FREER ; ; /* RECURSIVE FREER */ ENTER WITH REFCT=1 !1,2,NOSAV,SAVRS; !1,2,HERE,RTOP; RECUF: L← FATHER+1; FATHER = -1 <==> TOP-LEVEL ENTRY L← RETN1, SH=0; :NOSAV, TASK; SAVRS: SAVR1← L, :GPCL; TOP LEVEL ENTRY HAS TO SAVE NOSAV: :GPCL; NO SAVE FOR RECURSIVE ENTRY ; !1,2,ISPT,NOTPT; !1,2,DOFLD0,QFINST; GPCL: L← T← ARG1; TEMP3← L; L← 2, :PMAP; INDEX INTO PCLASS MAP PMAPX2: T← CPTMSK; L← MD AND T, T← MD; EXTRACT CPT L← ISCMSK.T, SH=0; EXTRACT ISC :ISPT, SH=0, TASK; BRANCH ON WHETHER POINTERS ISPT: :DOFLD0; BRANCH IF SIZE ZERO NOTPT: :QFINST; (TASK,OR-1) ; DOFLD0: L← 11, TASK, :HASH; ;// HASH OBJECT BEING FREED. NO DIRTY // HSHX11: MAR← L← LREG; TEMP3← L; (CORE ADDR OF FIELD 0) L← MD; MAR← TEMP3; T← ARG1; ARG1← L, L← T; ARG1 ← FIELD 0 MD← FATHER, TASK; FIELD 0 ← FATHER FATHER← L; FATHER ← OOP MAR← ROTA; T← RCT1BIT; L←ROT0+T, TASK; MD← LREG; BUMP REFCT TO 2, FLAG FIRST TIME ; FFF: L← 5, TASK, :REFCK; /* HERE'S THE RECURSIVE REFD ; !1,2,DONXT,FTIME; REFX5: L← FATHER; /* RESUME (INSTANCE IN FATHER) HERE: ARG1← L; L← 15, TASK, :HASH; ;// HASH OBJECT BEING FREED. DIRTY // HSHX15: MAR← L← LREG+1; TEMP3← L; (CORE ADDR OF FIELD 1) T← ROT0; L← RCT1BIT.T; L← MD, SH=0, TASK; TEST EVEN RCT (MEANS FIRST TIME) TEMP2← L, :DONXT; FIELD 1 HOLDS FIELD OFFSET ; !1,2,GTFLD,OUT1; !1,2,SAVST,QLOOP; DONXT: L← T← TEMP2-1; /* LOOK AT THE NEXT FIELD DONX1: TEMP2← L, SH=0; TEST IF DONE L← TEMP3+T, :GTFLD; GTFLD: MAR← LREG; T← MINAT; L← MD-T, T← MD; GTF1: L← T, ALUCY, TASK; TEST IF SPECIAL (NO NEED TO REFD) ARG1← L, :SAVST; QLOOP: L← T← TEMP2-1, :DONX1; QUICK LOOP TO GET NEXT FIELD ; SAVST: MAR← TEMP3; /* SAVE STATE AND REFD IT NOP; STORE NEW OFFSET BACK MD← TEMP2; INTO FIELD 1 L←5, TASK, :REF; (NOTE RETURN IS SAME AS ABOVE!) ; !1,2,NOTONE,OUT2; FTIME: MAR← ROTA; /* DONE FIELD 0 T← RCT1BIT; L←ROT0-T, TASK; MD← LREG; UNBUMP REFCT TO 1, NOT FIRST TIME ;(NOTE ARG1←FATHER AT HERE:) L← 2, TASK, :ILONG; GET LENGTH OF THIS OBJECT ILONGX2: L← LREG-1; T← TEMP2, SH=0; TEST IF HAD ONLY 1 FIELD TEMP2← L, L←T, :NOTONE; NOTONE: T← MINAT; L← LREG-T, T← LREG, :GTF1; JUMP INTO INNER LOOP ; /* FREE THE INSTANCE OUT2: :OUT1; OUT1: MAR← TEMP3-1; LOAD FATHER STACHED IN FIELD 0 L← FATHER; TEMP3← L; L← MD, TASK; O2A: FATHER← L, :QFINST; AND FREE THE INSTANCE ; ; ; /* QUICK FINST FOR EXACT-SIZE OBJECTS */ !1,2,NOTVAR,VAROOP; !1,2,EXACT,OCTL; QFINST: T← TEMP3; L← 3, :PMAP; PMAPX3: T← RCIMSK; L← MD AND T, T← MD; ARG1← L LCY 8, L← T; TEMP2← L; L← T← ARG1; ARG1← L MLSH 1; T← VARCLS; L← ARG1-T; COMPARE TO VARLEN CLASS T← TEMP2, ALUCY; T← ISCMSK.T, :NOTVAR; ; VAROOP: L← 10-T; L← CLFREE+T, SH<0, :CHK; ; NOTVAR: L← OCTV-T-1; EXTRACT INST SIZE L← CLFREE, SH<0; CHK: TEMP2← L, :EXACT; ; EXACT: L← 17, TASK, :HASH; ;// HASH CLASS OF OBJECT BEING FREED. DIRTY // HSHX17: T← TEMP2; (MIGHT CAUSE A PURGE) MAR← L← LREG+T; TEMP2← L; L← TEMP3; ARG1← L; L← MD; MAR← TEMP2; TEMP2← L; TEMP2 ← CLASS[FREELISTHEAD] MD← TEMP3; CLASS[FREE] ← REFOOP L← 13, TASK, :HASH; ;// HASH OBJECT BEING FREED. DIRTY // HSHX13: MAR← LREG; TASK; MD← TEMP2, :FIRET; REFOOP[0] ← TEMPX1 ; ; /* HAVE TO CALL REAL FINST IN NOVA OTHERWISE OCTL: L← TEMP3; CALL FINST WITH REFOOP IN AC0 ARG1← L; T← 27; L← 5+T+1, :NOVACALL; 35 TRAPS TO 76400 ; ... FIRET: L← FATHER+1; /* FINST RETURNS HERE VIA TRAP L← FATHER, SH=0; :HERE; IF FATHER NOT NIL, THEN MORE RECUF RTOP: L← SAVR1, BUS, TASK; IS NIL - RESTORE RETN1 RETN1← L, :REFX0; AND RETURN TO ORIGINAL CALLER! ; ; HASH- ARG1:OOP L:RETN ; ROTA←ROT ADDRESS OF OOP ; <ROT0,ROT1>←ROT ENTRY OF OOP ; L←CORE LOCATION OF OBJECT REFERRED TO BY OOP ; !1,2,PROBX,EMP; !1,2,AGAIN,HASX; !1,2,HASXX,ZOTP; !1,2,IMMDAT,REMDAT; !1,2,NODIRT,SETDIRT; HASHL: ARG1← L, L← T, TASK; HASH: RETN0← L; (TASK HAPPENS HERE) T← ARG1; L← 377.T; RHO← L LCY 8; L← RHO XOR T, TASK; FORM ROOT HASH = (LO,0) XOR (HI,LO) RHO← L; T← RHO; L← HKRMSK.T; RESIDUE← L; SAVE <RESIDUE,RPC> L← 0, :PROBS0, TASK; PROBE THE ROT ; PROBX: T← RESIDUE; OCCUPIED MEANS HIT OR TRY AGAIN L← LREG-T; COMPARE <RESIDUE,RPC> L← RPCBIT+T, SH=0; RESIDUE← L, :AGAIN; STEP <RESIDUE,RPC>! AGAIN: L← RPC+1, :PROBS, BUS, TASK; STEP RPC, AND LOOP ; HASX: L← ROT0, BUSODD; HAVE A HIT, TEST OTP! RESIDUE← L, :HASXX; HASXX: SINK← RETN0, BUSODD; SHOULD WE DIRTY T← CLNMSK, :NODIRT; THE DIRTY MASK SETDIRT: MAR← ROTA; DO THE DIRTY L ← ROT0 AND T; AND OFF THE DIRTY BIT MD← LREG; AND PUT IT BACK IN THE ROT NODIRT: T← 4; L← ROT0.T; TASK, SH=0; TEST IMMEDIATE BIT L← ROT1, :IMMDAT; IMMDAT: L← ROTA+1; REMDAT: SINK← RETN0, BUS; L← T← LREG, :HSHX0 ; (NOTE: THE FIRST INSTRUCTION AFTER A HASH WILL BE THE THIRD ; IN A TASK FOR REMOTE DATA AND THE FOURTH FOR IMMEDIATE DATA) ; ZOTP: MAR← ROTA; IF IT WAS SET, L← ROT0-1; CLEAR OTP ROT0← L, TASK; MD← ROT0, :HASXX; ; ; ; /* HASH PROBE ROUTINE !7,10,DEL1,DEL2,DEL3,DEL4,DEL5,DEL6,DEL7,DEL8; PROBS0: RPC← L, :DEL0; CALL HERE FOR RPC=0 PROBS: RPC← L, :DEL1; OTHERWISE HERE WITH L←RPC+1, BUS ; DEL1: T← 15, :DELX; 13 GET DELTA FOR THIS REPROBE DEL2: T← 21, :DELX; 17 DEL3: T← 23, :DELX; 19 DEL4: T← 27, :DELX; 23 DEL5: T← 27; T← 5+T+1, :DELX; 29 DEL6: T← 37, :DELX; 31 DEL7: T← 37; T← 5+T+1, :DELX; 37 DEL8: T← RPCBIT; HAVE TO UN-INC RPC (WHICH HAS OV'ED) L← RESIDUE-T, TASK; RESIDUE← L, :EMP; AND FAIL EXIT DUE TO OV REPROBE ; DELX: L← RHO+T, TASK; RHO← L; ADD TO RHO DEL0: T← ROTMSK; L← T← RHO.T, TASK; L← LREG+T; (A LSH 1 WITHOUT AN R-REG) T← LREG; MAR← L← ROTBASE+T; ROTA← L; ROTA ← ROT ADDRESS T← MD; L← MD; ROT1← L, L← T; ROT0,ROT1 ← ENTRY ROT0← L; L← ROT0EM-T; TEST ROT0EM SH=0, TASK; **LEAVE <RESIDUE,RPC> IN LREG L← RESRPC.T, :PROBX; RETN TO HASH IF OCCUPIED ; EMP: SINK← RETN0, BUS=0; FAIL EXIT :FAULT; CALL 0 CAN FAIL ; ; /* HASH FAULT SAVES STATE THEN CALLS NOVA */ FAULT: L← RETN0; SAVR0← L; DO WE NEED THIS????? T← 27; NCPF: L← 4+T+1, :NOVACALL; 34 TRAPS TO 76000 ; ... FLTRET: L← SAVR0, TASK, :HASH; BLITHELY RESUME HASHING... ; ; NOVACALL ; /* CALL TO NOVA AND RETURN */ ; NOVACALL: XREG← L; LOAD TRAP OP FROM L L← DISP, SINK← disp.377, TASK; SAVDISP← L, :TRAPOP; SAVE DISP ; NOVARET: SINK← DISP, BUS, TASK; RETURN DEPENDS ON THIS DISP IR← SAVDISP, :OVRET; RESTORE PREVIOUS DISP ; ; ; /* RETURN TO NOVA IN ROM TRAPOP: MAR← TRAPPC; T← 37; COPY OF TRAP'S CODE IN ROM T← XREG.T; SINCE WE DON'T KNOW WHERE IT IS MD← PC; MAR← TRAPPC+T+1; MEMPC: NOP; L← MD, TASK; SPC: PC← L; STRT: SWMODE; JSTART: :START; (AT LEAST WE KNOW WHERE START IS) RSPC: L← SAVPC, :SPC; ; START: L← ONE, :SPC; ONLY USED IN ROM ; ; ; ***************************** ; * NOVA OOZE TRAP MICROCODE * ; ***************************** ; ; ; /* NOVA HASH TRAP */ HASHT: L← PC; SAVPC← L; L← 0, TASK, :HASH; THIS IS CALLER 0 OF HASH, CYCLE ; ;// HASH OBJECT. NO DIRTY // HSHX0: L← SAVPC+1, TASK; HASH HIT DOES NOVA SKIP-RETN SAVPC← L; L← RESIDUE, TASK; AC3← OLD ROT0 FOR HITS LACS: AC3← L; L← RPC, TASK; AC1← L; L← ROTA, TASK; AC2← L, :RSPC; ; HFAIL0: L← HFRETI, :RAMCYCX; RAMCYCX: PC← L, L← 0+1; L5: CYRET← L, SWMODE; LABEL USED ONLY IN JMP TO ROM L← T← RESIDUE, :L5; ACTUALLY JUMP TO L5 IN ROM HFRET: T← 37; RETURN FROM L5 IN ROM L← XREG.T, TASK, :LACS; AC3← RES FOR MISS (INSERT) ; ; /* NOVA REFCT TRAP */ REFCT: L← PC; SAVSP← L; L← DISP, TASK, :REFCK; REFX0: L← SAVSP, :SPC; REFX1: L← SAVSP, :SPC; ; ; ; /* NOVA IVAL TRAP */ IVALTP: L← PC; SAVSP← L; L← 11, TASK, :IVAL; IVALX11: AC0← L, :REFX0; ; ; ; /* SKIP IF AC0 IS NOT SPECIAL (IE, IS REFCT'ED) !1,2,NAT,ISAT; SNAT: T← MINAT; L← AC0-T; ISAT1: ALUCY; L← PC+1, TASK, :NAT; NAT: PC← L, :STRT; ISAT: :STRT; ; ; /* EXTRACT */ (70000) DISP=<WIDTH><SHIFT> EXTRACT: :TRAPOP; ; /* INJECT */ (70400) DISP=<WIDTH><SHIFT> INJECT: :TRAPOP; ; ### ; // RETURNS TO OTHER RAM BANKS ### X1776: SINK ← RAMRETURN, SWMODE, BUS, :X200; ### X1777: SINK ← RAMRETURN, SWMODE, BUS, :X200; ###