;
;
MICROFLOATMC.MU
;
S. MARSHALL
;
November 19, 1980 ###
;
#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
;
;--------------- BANK 0 REGISTER ASSIGNMENTS
;
$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
$FLOATCLS
$5;FLOATING-POINT CLASS
$TYPEF
$7;INDEX OF TYPE FIELD
$SPRCLSF
$5;INDEX OF SUPERCLASS FIELD
$MDICTF
$3;INDEX OF MESSAGE DICTIONARY
$SIZEF
$2;INDEX OF INSTANCE SIZE
$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;
;
$EXPMSK
$177776;
$RAMXEVEN
$177776;
$RAMXODD
$177777;
$177770
$177770;
;
;
/* GLOBAL LABEL ALLIGNMENTS */
;********BASE ADDRESS FOR BANK SWITCHING********
!200,1,X200;
;
;********RETURNS FROM NOVA********
;!1767,10,OVRET,FIRET,FLTRET,ALLOCRET,PRIMFAIL,SNDMSG,SUPRET,PRIMRET; ###
!1767,10,,,,,PRIMFAIL,,,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; ###
!1757,10,,,REF,,NOVAALLOC,,HASHL,HASH; ###
;
;********LABELS AND CONSTANTS FOR RAM SWITCHING SUBROUTINE CALLS
!607,10,RAMX0,RAMX1,RAMX2,RAMX3,RAMX4,RAMX5,RAMX6,RAMX7;
!617,10,RAMX10,RAMX11,RAMX12,,,,,;
;
$RAMRET0
$600;
$RAMRET1
$601;
$RAMRET2
$602;
$RAMRET3
$603;
$RAMRET4
$604;
$RAMRET5
$605;
$RAMRET6
$606;
$RAMRET7
$607;
$RAMRET10
$610;
$RAMRET12
$612;
;
;********ENTRY POINTS FOR RAM1 IMPLEMENTED SMALLTALK PRIMITIVES********
;********THESE ARE PRIMITIVES -01400 TO -01367********
;********WATCH THE X200 DISPATCH IN BYTERP********
!717,20,PLUS,MINUS,TIMES,OVER,LT,EQ,GT,LE,NE,GE,NEW,VNEW,,,,;
;
;********RETURNS FOR PMAP********
!1,2,PMAPX0,PMAPX1;
;
;********RETURNS FOR GCLASS********
!1,2,GCLASSX0,GCLASSX1;
;
;********RETURNS FOR SETUP********
!7,10,SETUPX0,SETUPX1,SETUPX2,SETUPX3,SETUPX4,,,;
;
; Copyright Xerox Corporation 1979

;Last bug fix by Lyle Ramshaw, changed low order mantissa compare
; in FCM from signed to unsigned -- November 26, 1979


;REGISTERS USED BY NOVA EMULATOR

$M1
$R10;
$N1
$R16;
$M2
$R35;
$N2
$R36;


$Temp
$R42;
$CRY
$R43;

$ShiftCount
$R45;
$ANSADDR
$R46;
$ANSOOP
$R41;
$SubRet
$R47;
$E1X
$R3;
$E2X
$R2;

$M1A
$R60;
$N1A
$R61;
$M2A
$R62;
$N2A
$R63;
$E1
$R64;
$E2
$R65;
$COMPREG
$R66;

;REGISTERS USED IN BANK 0

$RTMP1
$R57;

;
;
;
;
IVAL- ARG1:OOP L:RETN
;
L←VALUE OF NUMBER
;
PRESERVES ARG1
;
!1,2,NOTSI,MBSI;
!1,2,ISSI,NONINT;
!1,2,NOTNMBR,ISNMBR;
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, :ISSI;
ISSI:
NOP;
SINK← RETN2, BUS;
L← T← LREG, :IVALX0;
NONINT:
L← ONE, TASK, :GCLASS;
NOTSI:
L← ONE, TASK, :GCLASS;
GCLASSX1:
L← NUMCLS-T;TEST FOR CLASS = NUMBER
T← 11, SH=0;
L← RETN2-T, :NOTNMBR;
ISNMBR:
L← RAMRET10 + 1;HASH INTO ROT
RAMRETURN ← L, SWMODE, :HASH;
;// HASH LARGE INTEGER. NO DIRTY //
RAMX11:
L← ROT1, TASK, :ISSI;
NOTNMBR:
SWMODE, :PRIMFAIL;
;
;
;
;
GCLASS- ARG1:OOP L:RETN
;
L←OOP’S CLASS
;
PRESERVES ARG1
!1,2,PMAP,GCNIL;
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;
PMAPX0:
MAR← LREG, :PMAPX0;INDEX THE PCLASS MAP (DUMMY LABEL)
;
;
;
NOVA ALLOCATE - NEEDS OOP OF CLASS IN AC0 AND LENGTH IN AC1
;
L ← NEW OOP
;
T ← CORE ADDRESS OF NEW OOP
;
;
;ALLOCL:
RAMRETURN ← L; SAVE RETURN ADDRESS
;
L ← 3, SWMODE; 3 IS RAM RETURN ADDRESS FOR ALLOCATE
;
NOVAALLOC:RETN1 ← L, L ← T, :NOVAALLOC; SET RETURN ADDRESS, L ← OOP OF CLASS TO ALLOCATE IN
;

!1,2,AOK1,AFAIL1;
!1,2,AOK2,AFAIL2;

ALLOCL: RTMP1 ← L, L ← T, TASK; SAVE RETURN
ARG1 ← L; SAVE CLASS
L ← RAMRET3;
HASHD:
RAMRETURN ← L, SWMODE; HASH - DIRTY
L ← RAMXODD, TASK, :HASH; DIRTY CALL
RAMX3:
MAR ← CLFREE + T; ACCESS FREE LIST POINTER
ACORE ← L; SAVE CORE ADDRESS OF CLASS
L ← ARG1; OOP OF CLASS
AOOP ← L; AND PUT CLASS IN BASE REGISTER
L ← MD + 1; CHECK FOR NIL
L ← LREG - 1, SH=0, TASK;
ARG1 ← L, :AOK1; [AOK1, AFAIL1] OOP OF FREE ELEMENT
AFAIL1: L ← RTMP1, TASK, :ALLOCN; HAVE TO CALL THE NOVA
AOK1:
L ← RAMRET4, :HASHD; HASH - DIRTY
;// HASH FREE LIST HEAD. DIRTY //
RAMX4:
MAR ← T; GET OOP OF NEXT FREE ELEMENT
AC1 ← L; SAVE CORE ADDRESS OF NEW OOP
L ← MD + 1; CHECK FOR NIL
L ← LREG - 1, SH = 0;
T ← ACORE, :AOK2; [AOK2, AFAIL2] CORE ADDRESS OF CLASS
AFAIL2: L ← RTMP1, TASK, :ALLOCN; HAVE TO CALL THE NOVA
AOK2:
MAR ← CLFREE + T; FREE LIST POINTER
T← RESRPC;T: MASK FOR RES AND REPROBE COUNT
T← IMMBIT OR T;T: MASK FOR IMM BIT, RES AND RPC
MD ← LREG; NEW FREE LIST POINTER
MAR← ROTA;
T← ROT0.T;T: IMMEDIATE BIT, RES AND RPC
L← ROT0ND OR T, TASK;
MD← LREG;
T ← AC1; CORE ADDRESS OF NEW OOP
SINK ← RTMP1, BUS; RETURN
X200:
L ← ARG1, :X200; WITH OOP IN L AND ADDR IN T



ALLOCN:
RAMRETURN ← L; SAVE RETURN ADDRESS
T ← AOOP; CLASS TO ALLOCATE IN
L ← RAMXODD, SWMODE; SET RETURN FOR ALLOCATE
NOVAALLOC:
RETN1 ← L, L ← T, :NOVAALLOC; SET RETURN ADDRESS, L ← OOP OF CLASS TO ALLOCATE IN

!1,2,AOK3,AFAIL3;
!1,2,AOK4,AFAIL4;
!1,2,TOOBIG,SIZEOK;
!1,2,NILOUT,NILDONE;
!1,2,WORDS,BYTES;

VNEW:
L ← TOP, TASK; CLASS OF OBJECT TO ALLOCATE
ARG1 ← L; ARG FOR HASH
L ← RAMRET12, :HASHD;
RAMX12:
T ← STACKP - 1; RELATIVE ADDRESS OF ARGUMENT (LENGTH)
MAR ← TFRAME + T; FETCH INSTANCE SIZE REQUESTED
ACORE ← L; SAVE CORE ADDRESS OF CLASS
L ← ARG1; OOP OF CLASS
AOOP ← L; AND PUT CLASS IN BASE REGISTER
L ← MD; OOP OF SIZE REQUESTED
T ← 0, :IVALL; TURN OOP INTO INTEGER
IVALX0:
L ← 10 + T, TASK; GET FREE LIST OFFSET
RETN2 ← L; AND SAVE FREE LIST OFFSET
T ← 21; CANT DO OCTIVE SIZES
L ← RETN2 - T, T ← RETN2; SIZE OF NEW OBJECT + 8 IN T
L ← 177770 + T, SH<0; CONVERT TO INTEGER SIZE REQUESTED
TOP ← L, :TOOBIG; [TOOBIG, SIZEOK]

NEW:
L ← CLFREE, TASK; OFFSET OF FREE LIST
RETN2 ← L; SAVE FOR ALLOCATING
L ← TOP, TASK; CLASS OF OBJECT TO ALLOCATE
ARG1 ← L; ARG FOR HASH
L ← RAMRET6, :HASHD;
RAMX6:
MAR ← SIZEF + T; FETCH INSTANCE SIZE
ACORE ← L; SAVE CORE ADDRESS OF CLASS
L ← ARG1; OOP OF CLASS
AOOP ← L; AND PUT CLASS IN BASE REGISTER
T ← OOP00;
T ← 23+T+1; CANT DO OCTIVE SIZES
L ← MD - T, T ← MD; SIZE OF NEW OBJECT IN T
L ← 2000 + T, SH<0; CONVERT TO INTEGER
TOP ← L, :TOOBIG; [TOOBIG, SIZEOK]
TOOBIG: :AFAIL3;
SIZEOK:
T ← ACORE; ADDRESS OF CLASS
MAR ← RETN2 + T; ACCESS FREE LIST POINTER
NOP;
L ← MD + 1; CHECK FOR NIL
L ← LREG - 1, SH=0, TASK;
ARG1 ← L, :AOK3; [AOK3, AFAIL3] OOP OF FREE ELEMENT
AFAIL3: :AFAIL4; HAVE TO CALL THE NOVA
AOK3:
L ← RAMRET7, :HASHD; HASH - DIRTY
;// HASH FREE LIST HEAD. DIRTY //
RAMX7:
MAR ← T, AC1 ← L; GET OOP OF NEXT FREE ELEMENT AND SAVE CORE ADDRESS
NOP;
L ← MD + 1; CHECK FOR NIL
L ← LREG - 1, SH = 0;
T ← ACORE, :AOK4; [AOK4, AFAIL4] CORE ADDRESS OF CLASS
AFAIL4: T ← 10;
L ← RETN2 - T, TASK; CORRECT LENGTH TO REQUEST
RETN2 ← L;
L ← RAMRET10, TASK, :ALLOCN; HAVE TO CALL THE NOVA
AOK4:
MAR ← RETN2 + T; FREE LIST POINTER
T← RESRPC;T: MASK FOR RES AND REPROBE COUNT
T← IMMBIT OR T;T: MASK FOR IMM BIT, RES AND RPC
MD ← LREG; NEW FREE LIST POINTER
MAR← ROTA;
T← ROT0.T;T: IMMEDIATE BIT, RES AND RPC
L← ROT0ND OR T, TASK;
MD← LREG; SET REFCT, DIRTY, NEW
T ← ACORE; ADDRESS OF CLASS
MAR ← TYPEF + T; FETCH TYPE FIELD
T ← 20; WBY (WORD/BYTES) MASK
L ← MD AND T; ZERO IF BYTES ELSE WORDS
L ← TOP + 1, SH=0, TASK; GET WORDS * 2 IF BYTES
AC2 ← L RSH 1, :WORDS; [WORDS,BYTES] WORDS IN AC2 IF BYTES
BYTES:
L ← AC2, BUS = 0, TASK; MOVE TO TOP
TOP ← L, :NILOUT;
WORDS:
SINK ← TOP, BUS = 0, TASK; CHECK IF LENGTH IS ZERO
:NILOUT;
NILOUT:
T ← TOP - 1; DECREMENT LENGTH COUNTER
MAR ← AC1 + T; NEXT WORD OF NEW OBJECT TO STORE INTO
L ← T;
TOP ← L, SH = 0, TASK; END CHECK
MD ← ALLONES, :NILOUT; LOOP IF NOT DONE
NILDONE:
SWMODE; RETURN WITH OOP OF NEW OBJECT IN AC0 = ARG1
:PRIMRET; RETURN WITH OOP OF NEW OBJECT IN AC0 = ARG1

RAMX10:
SWMODE, :PRIMRET; RETURN WITH OOP OF NEW OBJECT IN L

;
;
;---------------------------------------------------------------
;Floating-point setup routine
;checks class of arg and fails if not FP
;loads arg into registers
;loads self into registers
;allocates a new FP number (only done if return is not zero)
;returns
;---------------------------------------------------------------

!1,2,ARGFAIL,ARGOK;
!1,2,SETUPA,SETUPX;
!7,10,LOADX0,LOADX1,LOADX2,LOADX3,LOADX4,LOADX5,,;

SETUP:
RETN2 ← L; SAVE RETURN
T ← STACKP-1; GET POINTER TO SECOND FROM TOP OF STACK (ARG)
MAR ← TFRAME + T; FETCH ARG OOP
T ← 0; SET RETURN
L ← MD, :GCLASSL; GET CLASS OF ARG
GCLASSX0: L ← FLOATCLS XOR T; COMPARE WITH OOP OF FLOAT CLASS
L ← RAMRET0, SH=0;
RAMRETURN ← L, :ARGFAIL;
ARGFAIL: :FAIL;
ARGOK:
SWMODE, :HASH; CALL HASH IN RAM0
HASH:
L ← RAMXEVEN, TASK, :HASH; HASH - NO DIRTY
RAMX0:
AC3 ← L; SAVE CORE ADDRESS
ESRB ← 2; CHANGE S REGISTER BANK
T ← 0, :LOAD; GET EXPONENT
LOADX0:
E2 ← L;
T ← ONE, :LOAD; GET HIGH MANTISSA
LOADX1:
M2A ← L;
T ← 2, :LOAD; GET LOW MANTISSA
LOADX2: N2A ← L;
ESRB ← 0; SMALLTALK REGISTER BANK
L ← RAMRET1, TASK;
RAMRETURN ← L;
L ← TOP, SWMODE; GET CLASS OF ARG
HASHL:
T ← RAMXEVEN, :HASHL; (LABEL USED ONLY IN RAM0)
RAMX1: AC3 ← L; SAVE CORE ADDRESS
ESRB ← 2; CHANGE S REGISTER BANK
T ← 3, :LOAD; GET EXPONENT
LOADX3:
E1 ← L;
T ← 4, :LOAD; GET HIGH MANTISSA
LOADX4:
M1A ← L;
T ← 5, :LOAD; GET LOW MANTISSA
LOADX5: N1A ← L;
ESRB ← 0; SMALLTALK REGISTER BANK
NOP;WAIT FOR 3K CRAM CARD
SINK ← RETN2,BUS=0, TASK; CHECK IF ALLOCATING FOR RESULT
:SETUPA;
SETUPA:
T ← FLOATCLS; ALLOCATE ANSWER FLOATING-POINT NUMBER
L ← RAMRET2, :ALLOCL; DO ALLOCATION
RAMX2:
ESRB ← 2; CHANGE TO FP BANK
NOP; WAIT FOR 3K CRAM CARD;
ANSOOP ← L, L ← T; STORE NEW FLOAT OOP
ANSADDR ← L; SAVE ADDRESS TO STORE ANSWER
SETUPX:
ESRB ← 2; CHANGE S REGISTER BANK
NOP;WAIT FOR 3K CRAM CARD
L ← M1A, TASK; MOVE TO R REGISTERS
M1 ← L; FOR SHIFTING
L ← N1A, TASK; MOVE TO R REGISTERS
N1 ← L; FOR SHIFTING
L ← M2A, TASK; MOVE TO R REGISTERS
M2 ← L; FOR SHIFTING
L ← N2A, TASK; MOVE TO R REGISTERS
N2 ← L; FOR SHIFTING
ESRB ← 0; WHERE RETURN ADDRESS IS STORED
NOP;WAIT FOR 3K CRAM CARD
L ← RETN2;
ESRB ← 2; CHANGE S REGISTER BANK
SINK ← LREG, BUS, TASK;
:SETUPX0; RETURN TO SPECIFIC ROUTINE


LOAD:
MAR ← AC3; FETCH WORD FROM MEMORY
L ← AC3 + 1; INCREMENT MEMORY POINTER FOR NEXT TIME
AC3 ← L, L ← T; MOVE RETURN ADDRESS
SINK ← LREG, BUS; DISPATCH ON RETURN NUMBER
L ← MD, TASK, :LOADX0; FETCH WORD TO L AND RETURN ***TASK PENDING***
;
;---------------------------------------------------------------
;multiply subroutine
;---------------------------------------------------------------


!7,10,MulRet,MulRet1,MulRet2,MulRet3;
!1,2,DOMUL,NOMUL;
!1,2,MPYL,MPYA;
!1,2,NOADDIER,ADDIER;
!1,2,NOSPILL,SPILL;
!1,2,NOADDX,ADDX;
!1,2,NOSPILLX,SPILLX;

MUL:
SubRet←L;
L←AC2-1, BUS=0;
MPYX:
XREG←L,L←0,:DOMUL;
DOMUL:
TASK,L←-10+1;
AC3←L;
MPYL:
L←AC1,BUSODD;
T←AC0,:NOADDIER;
NOADDIER:
AC1←L MRSH 1,L←T,T←0,:NOSPILL;
ADDIER:
L←T←XREG+INCT;
L←AC1,ALUCY,:NOADDIER;
SPILL:
T←ONE;
NOSPILL:
AC0←L MRSH 1;
L←AC1,BUSODD;
T←AC0,:NOADDX;
NOADDX:
AC1←L MRSH 1,L←T,T←0,:NOSPILLX;
ADDX:
L←T←XREG+INCT;
L←AC1,ALUCY,:NOADDX;
SPILLX:
T←ONE;
NOSPILLX:
AC0←L MRSH 1;
L←AC3+1,BUS=0,TASK;
AC3←L,:MPYL;
NOMUL:
T←AC0;
AC0←L,L←T,TASK;
AC1←L;
MPYA: SINK←SubRet,BUS;
NOP,:MulRet;

;---------------------------------------------------------------
;divide subroutine
;---------------------------------------------------------------

!7,10,DivRet,DivRet1,DivRet2;
!1,2,DODIV,NODIV;
!1,2,DIVL,ENDDIV;
!1,2,NOOVF,OVF;
!1,2,DX0,DX1;
!1,2,NOSUB,DOSUB;

DIV:
SubRet←L;
T←AC2;
DIVX:
L←AC0-T;Do the divide only if AC2>AC0
ALUCY,TASK,AC3←L,L←0+1;
:DODIV,AC3←L LSH 1;AC3←2, count the loop by shifting
NODIV:
SINK←SubRet,BUS;
DRET:
NOP,:DivRet;
DODIV:
L←AC0,:DIV1;
DIVL:
L←AC0;
DIV1:
SH<0,T←AC1;will the left shift of the dividend overflow?
:NOOVF,AC0←L MLSH 1,L←T←0+T;L←AC1,T←0
OVF:
AC1←L LSH 1,L←0+INCT,:NOV1;L←1: shift overflowed
NOOVF:
AC1←L LSH 1,L←T;L←0: shift ok
NOV1:
T←AC2,SH=0;
L←AC0-T,:DX0;
DX1:
ALUCY;do the test only if the shift didn’t overflow. If it did, L is still correct
T←AC1,:NOSUB;but the test would go the wrong way
DX0:
T←AC1,:DOSUB;
DOSUB:
AC0←L,L←0+INCT;do the subtract
AC1←L;and put a 1 in the quotient
NOSUB:
L←AC3,BUS=0,TASK;
AC3←L LSH 1,:DIVL;
ENDDIV:
SINK←SubRet,BUS,:DRET;

;---------------------------------------------------------------
;FLOATING COMPARE RETURNS TRUE OR FALSE (NEVER RETURNS SELF)
;---------------------------------------------------------------
LT:
L ← 4, :COMPARE; <
EQ:
L ← 2, :COMPARE; =
GT:
L ← ONE, :COMPARE; >
LE:
L ← 6, :COMPARE; <=
NE:
L ← 5, :COMPARE; #
GE:
L ← 3, :COMPARE; >=

COMPARE:
ESRB ← 2; SET OUR REGISTER BANK
NOP; WAIT FOR 3K CRAM CARD
COMPREG ← L; SAVE COMPARISON DESIRED
ESRB ← 0, L ← 0; RESET BANK REGISTER AND GO SETUP ARGUMENTS
TASK, :SETUP; WAIT FOR 3K CRAM CARD

!1,2,BOTHNZ,ONEZ;
!1,2,POS1,NEG1;
!1,2,POS1POS2,POS1NEG2;
!1,2,NEG1POS2,NEG1NEG2;
!1,2,POSNE,POSEQ;
!1,2,NEGNE,NEGEQ;
!1,2,POSGE,POSLT;
!1,2,NEGGE,NEGLT;
!1,2,POSMNE,POSMEQ;
!1,2,NEGMNE,NEGMEQ;
!1,2,POSNNE,POSNEQ;
!1,2,NEGNNE,NEGNEQ;
!1,2,M1NZ,M1Z;
!1,2,M1ZM2NZ,M1ZM2Z;
!1,2,TRUERET,FALSERET;
!1,1,POSMCOMP;
!1,1,NEGMCOMP;
!1,1,ENDCOMP;
!1,1,ONEZ1;
!1,1,M1NZM2X;
!1,1,POSMEQ1;
!1,1,NEGMEQ1;

; NOTE - EXPONENT COMPARE FAILS FOR VERY LARGE DIFFERENCES (NOT TRUE SIGNED COMPARE)

SETUPX0:
T ← M1; TEST FOR EITHER ARGUMENT ZERO
L ← M2 AND T; NONZERO RESULT IF BOTH NONZERO
SH=0;
T ← E1, BUSODD, :BOTHNZ; CHECK SIGN OF ARG1
BOTHNZ:
L←E2 - T,BUSODD, :POS1; CHECK SIGN OF ARG2
POS1:
SH=0, :POS1POS2; COMPARE EXPONENTS
NEG1:
SH=0, :NEG1POS2; COMPARE EXPONENTS

POS1NEG2:
T ← ONE, :ENDCOMP; ARG1 (SELF) > ARG2
NEG1POS2:
T ← 4, :ENDCOMP; ARG1 (SELF) < ARG2
POS1POS2:
T ← M1, SH<0, :POSNE; SEE IF EXPONENTS EQUAL
NEG1NEG2:
T ← M1, SH<0, :NEGNE; SEE IF EXPONENTS EQUAL

POSNE:
:POSGE; ARG1 (SELF) < ARG2
NEGNE:
:NEGGE; ARG1 (SELF) > ARG2
POSEQ:
L ← M2 - T, :POSMCOMP; COMPARE M
NEGEQ:
L ← M2 - T, :NEGMCOMP; COMPARE M

POSMCOMP:
SH=0; SEE IF THE SAME
T ← N1, ALUCY, :POSMNE;
POSMNE:
:NEGGE; M NOT EQUAL SO CHECK IF ARGS + OR -
POSMEQ:
L ← N2 - T; COMPARE N’S
POSMEQ1:
SH=0; SEE IF THE SAME
ALUCY, :POSNNE;
POSNNE:
:NEGGE;
POSNEQ:
T ← 2, :ENDCOMP; EQUAL!

NEGMCOMP:
SH=0; SEE IF THE SAME
T ← N1, ALUCY, :NEGMNE;
NEGMNE:
:POSGE; M NOT EQUAL SO CHECK IF ARGS + OR -
NEGMEQ:
L ← N2 - T; COMPARE N’S
NEGMEQ1:
SH=0; SEE IF THE SAME
ALUCY, :NEGNNE;
NEGNNE:
:POSGE;
NEGNEQ:
T ← 2, :ENDCOMP; EQUAL!

ONEZ:
SINK ← M1, BUS=0, :ONEZ1; SEE IF FIRST ARG IS ZERO
ONEZ1:
SINK ← M2, BUS=0, :M1NZ; SEE IF SECOND ARG IS ZERO

M1Z:
SINK ← E2, BUSODD, :M1ZM2NZ; HERE IF ARG1 = 0
M1NZ:
SINK ← E1, BUSODD, :M1NZM2X; HERE IF ARG1 NOT 0

M1ZM2Z:
T ← 2, :ENDCOMP; HERE IF BOTH ZERO
M1ZM2NZ:
:POSGE; HERE IF ARG1 = 0, ARG 2 NOT 0

M1NZM2X:
:NEGGE; HERE IF ARG1 NOT 0, ARG 2 (ASSUMED) = 0

NEGGE:
T ← ONE, :ENDCOMP; ARG1 (SELF) > ARG2
NEGLT:
T ← 4, :ENDCOMP; ARG1 (SELF) < ARG2
POSGE:
T ← 4, :ENDCOMP; ARG1 (SELF) < ARG2
POSLT:
T ← ONE, :ENDCOMP; ARG1 (SELF) > ARG2

ENDCOMP: L ← COMPREG AND T; SEE WHAT TO TEST FOR
SH=0, TASK;
:TRUERET;
TRUERET: L ← TRUEOOP, SWMODE, :PRIMRET; RETURN TRUE
FALSERET: L ← FALSEOOP, SWMODE, :PRIMRET; RETURN FALSE

;---------------------------------------------------------------
;FMP floating point multiply
;---------------------------------------------------------------

!1,2,FMPNonZero,FMPZero;
!1,2,FMPNonZero1,FMPZero1;
!1,2,LowNonZero1,LowZero1;
!1,2,MEVEN,MODD;
!1,2,MSOV,MSNOV;

TIMES: L←3, TASK,:SETUP;

;add exponents, like in any multiply
SETUPX3:
T←E1;
L←E2+T, BUSODD, TASK;
E1←L, :MEVEN;
MODD:
T ← E1, BUSODD; CHECK IF ADDITION OF SIGNS CARRIED OUT TO EXPONENT
L ← -2 + T, TASK, :MSOV; MULTIPLY SIGN OVERFLOW
MSOV:
E1 ← L, :MEVEN; CORRECT EXPONENT FOR SIGN CARRY
MSNOV:
NOP;

;first multiply: high*low
MEVEN:
L←M1;
AC1←L,SH=0;
L←N2,:FMPNonZero;
FMPZero:
L←0,:LowZero1;return 0
FMPNonZero:
AC2←L,L←0;
AC0←L,:MUL;L must be 0 for SubRet
MulRet: L←AC0,TASK;
Temp←L;

;second multiply: other high*other low
L←M2;
AC1←L,SH=0;
L←N1,:FMPNonZero1;
FMPZero1:
L←0,:LowZero1;
FMPNonZero1:
AC2←L,L←0;
AC0←L,L←0+1,:MUL;L must have 1 for Subroutine Return
MulRet1: T←AC0;

!1,2,NoCarry,Carry;

;add results, set carry if overflow
L←Temp+T;
AC0←L,ALUCY;
L←0,:NoCarry;
Carry:
L←ONE;
NoCarry:
CRY←L;

!1,2,Carry1,NoCarry1;

;last multiply: high*high (plus stuff left in AC0)
L←M1,TASK;
AC1←L;
L←M2;
AC2←L;
L←2,:MUL;
MulRet2: SINK←CRY,BUS=0;
L←AC0,:Carry1;!1,2,Carry1,NoCarry1
Carry1:
L←AC0+1;low+low resulted in a carry, add it now
NoCarry1:
M1←L,SH<0;now, check normalization

!1,2,Normalize,NoNormalize;

T←AC1,:Normalize;7 instructions since last TASK
Normalize:
M1←L MLSH 1;8
L←AC1;9
N1←L LSH 1;10
L←E1-1;decrement exponent to account for shift
L ← LREG - 1,TASK; -2 TO LEAVE SIGN UNCHANGED
E1←L,:STORE;

NoNormalize:
L←AC1,TASK;
N1←L,:STORE;

;---------------------------------------------------------------
;FDV floating point divide
;---------------------------------------------------------------

OVER: L←4, TASK,:SETUP;

!1,2,DivOK,DivErr;
!1,2,DivOK1,DIV0;
!1,2,DEVEN,DODD;
!1,2,DSNB,DSB;


SETUPX4: SINK←M2,BUS=0;
NOP,:DivOK;

DivErr:
:DIVFAIL;

;first, subtract exponents
DivOK:
T←E2;
L←E1-T, BUSODD, TASK;
E1←L, :DEVEN;

DEVEN:
T ← E1, BUSODD; CHECK IF SUBTRACTION OF SIGNS BORROWED FROM EXPONENT
L ← 2 + T, TASK, :DSNB; DIVIDE SIGN BORROW
DSB:
E1 ← L, :DODD; CORRECT EXPONENT FOR BORROW
DSNB:
NOP;

;first, (M1,N1)/M2
DODD:
L←T←M1,BUS=0;check for zero dividend
AC0←L,:DivOK1;
DIV0:
E1 ← L,TASK,:STORE;dividend is already 0, just return
DivOK1:
L←ALLONES XOR T,TASK;NOT AC0
Temp←L;
L←N1,TASK;
AC1←L;
L←T←M2;
AC2←L;

;unsigned test for AC0<AC2: ADCZ# 0,2,SZC
L←Temp+T;(NOT AC0)+AC2
NOP,ALUCY;

!1,2,DivC,D0;

L←T←AC0,:DivC;
DivC:
AC0←L RSH 1;divide dividend by two (rshift)
L←AC1;
AC1←L MRSH 1;
L←E1+1;bump exponent
L ← LREG + 1; +2 TO LEAVE SIGN UNCHANGED
E1←L;
D0:
L←0,:DIV;
DivRet:
L←AC1;
M1←L,L←0;save high order results
AC1←L,L←0+1,:DIV;now AC0,1 have remainder,0
DivRet1:
L←AC1;
N1←L,L←0,TASK;save low order result

;now, answer is "too big" because low order bits of divisor were not included.
;so, we form correction term (N2/M2)*HighAnswer
AC0←L;
L←N2,TASK;
AC1←L;low order divisor
L←M1,TASK;
AC2←L;high order answer so far
L←3,:MUL;(N2*M1)
MulRet3:
T←AC0;
L←ALLONES XOR T;NOT AC0;
T←M2;ADCZ# 0,2,SZCcheck for divide overflow
L←LREG+T;JMP D2divide won’t overflow
L←M2,ALUCY;

!1,2,DivC2,D2;
AC2←L,:DivC2;
DivC2:
L←M1-1,TASK;decrement high order part of answer (because correction is to low order part)
M1←L;
T←M2;and subtract "one" from dividend
L←AC0-T,TASK;
AC0←L;
D2:
L←2,:DIV;(N2*M1)/M2
DivRet2:
T←AC1;
L←N1-T;(uncorrected low order result)-(second correction)
AC0←L,ALUCY;5if zero carry, then decrease high order part too

!1,2,Dec,NoDec;
!1,2,Norm,D1;

L←M1,:Dec;6
Dec:
L←M1-1;7
M1←L;8
NoDec:
NOP,SH<0;9get high order part of answer (could be unnormalized from either DSZ above)
T←AC0,:Norm;10!1,2,Norm,D1;
Norm:
M1←L MLSH 1;11
L←E1-1;decrement exponent to account for shift
L ← LREG - 1,TASK; -2 BECAUSE OF SIGN
E1←L;
L←AC0,TASK;
N1←L LSH 1,:STORE;

D1:
L←AC0,TASK;
N1←L,:STORE;

;----------------------------------------------------
;floating point add and subtract
;----------------------------------------------------

PLUS:
L←ONE, TASK, :SETUP;
MINUS:
L←2, TASK, :SETUP;
SETUPX2:
T ← ONE; CHANGE SIGN AND ADD
L ← E2 XOR T, TASK;
E2 ← L;
;
SETUPX1:
T ← 100000; OFFSET FOR EXPONENTS IN THIS ROUTINE
L ← E1 + T; OFFSET FIRST EXPONENT
E1X ← L RSH 1; GET OFFSET EXPONENT
L ← E2 + T, TASK; OFFSET SECOND EXPONENT
E2X ← L RSH 1; GET OFFSET EXPONENT

;Preshift arguments until they match
T←M1;mantissa zero check
L←M2 AND T;
SINK←LREG,BUS=0;

!1,2,Sh,NoShz;

T←E1X,:Sh;
Sh:
L←E2X-T;if exponents are the same, no shift either
SINK←LREG,BUS=0;

!1,2,Sh1,NoSh;
!1,2,E1lsE2,E1grE2;
ShiftCount←L,:Sh1;
Sh1:
TASK,SH<0;

NOP,:E1lsE2;

E1lsE2:
T ← EXPMSK;E1 ← E2 WITH SIGN PRESERVED
L ← E2 AND T;we’ll shift until exponent matches E2
T ← 0 + 1; GET A ONE
T ← E1.T; GET SIGN
L ← LREG OR T; PUT E1 SIGN WITH E2 VALUE
E1 ← L; AND STORE
T←ShiftCount;
L←37-T;
TASK,SH<0;37 is max number of shifts, if SH ge 0 then fix

!1,2,NoFix,Fix;
!1,2,More,Shifted;

NOP,:NoFix;
NoFix:
L←T←M1;
More:
M1←L RSH 1;
L←N1,TASK;
N1←L MRSH 1;
NOP;ALU←SReg after TASK;
L←ShiftCount-1;
ShiftCount←L,SH=0;
L←T←M1,:More;

Fix:
L←0;set both words of mantissa1 to 0
M1←L,TASK;
N1←L,:EndShift;

Shifted:
NOP,:EndShift;
NoSh:
NOP,:EndShift;

!1,2,ExpOK,ExpWrite;

NoShz:
SINK←M1,BUS=0;if first arg is zero, then E1X←E2X
L←E2X,TASK,:ExpOK;
ExpWrite:
E1X←L;
L ← E2;
E1 ← L;
ExpOK:
NOP,:EndShift;

E1grE2:
T←ShiftCount;actually, negative shift count
L←37+T;
TASK,SH<0;

!1,2,NoFix1,Fix1;
!1,2,More1,Shifted1;

NOP,:NoFix1;
NoFix1:
L←T←M2;
More1:
M2←L RSH 1;
L←N2,TASK;
N2←L MRSH 1;
NOP;ALU←SReg after TASK;
L←ShiftCount+1;
ShiftCount←L,SH=0;
L←T←M2,:More1;

Fix1:
L←0;
M2←L,TASK;
N2←L,:EndShift;

Shifted1:
NOP,:EndShift;

;end of PRESHIFT
;now: ADD1 is Add(+ +), Add(- -), Sub(+ -), Sub(- +)
;and ADD2 is Add(+ -), Add(- +), Sub(+ +), Sub(- -)
; so: ADD1 if (S1 XOR S2) EVEN, and ADD2 otherwise

EndShift: T←E1;
L←E2+T;EVEN if ADD1, ODD if ADD2
SINK ← LREG, BUSODD, TASK;

!1,2,ADD1,ADD2;

NOP,:ADD1;

ADD1:
T←N2;
L←N1+T;
N1←L,ALUCY;
!1,2,A1NoCarry,A1Carry;
T←M1,:A1NoCarry;
A1Carry:
L←M2+T+1,:A1Store;
A1NoCarry:
L←M2+T;
A1Store:
M1←L,ALUCY,TASK;
!1,2,A1xNoCarry,A1xCarry;
NOP,:A1xNoCarry;
A1xCarry:
T←L←M1;post shift
M1←L RSH 1;
L←N1,TASK;
N1←L MRSH 1;
T←100000;
L←M1 OR T;high order bit should have been shifted in
M1←L;
L←E1+1;
L←LREG+1,TASK; BECAUSE EXPONENT SHIFTED LEFT ONE BIT
E1←L,:STORE;
A1xNoCarry:
NOP,:STORE;

ADD2:
T←N2;
L←N1-T;
N1←L,ALUCY;low order result

!1,2,Add2NoCarry,Add2Carry;

T←M2,:Add2NoCarry;
Add2NoCarry:
L←M1-T-1,:Add2C;no carry, do one’s complement subtract
Add2Carry:
L←M1-T;carry, do two’s complement subtract
Add2C:
M1←L,ALUCY;

!1,2,Add2Sign,Add2NoSign;
!1,2,LowNonZero,LowZero;

L←0,:Add2Sign;if no carry, sign changed!!!!

Add2Sign:
T←N1,BUS=0;double length negate starts here
L←0-T,:LowNonZero;
LowNonZero:N1←L,T←0-1;
L←M1 XOR T,:Add2Cx;complement
LowZero:
T←M1;
L←0-T;negate (note that N1 is already 0, so no need to update it)
Add2Cx:
M1←L,T←0+1;
L←E1 XOR T,TASK;complement sign
E1←L;
L←0;

Add2NoSign:
ShiftCount←L;
L←M1,BUS=0;

!1,2,HiNonZero,HiZero;

NOP,:HiNonZero;

HiNonZero:
TASK,SH<0;

!1,2,Add2Norm,Add2NoNorm;

NOP,:Add2Norm;
Add2Norm:
L←N1;
NOP,SH<0;
!1,2,Add2NoCarryL,Add2CarryL;
N1←L LSH 1,T←0,:Add2NoCarryL;
Add2CarryL:
T←ALLONES;
Add2NoCarryL:
L←M1;
M1←L MLSH 1;
L←ShiftCount+1,TASK;
ShiftCount←L;
L←M1,:HiNonZero;

Add2NoNorm:T←ShiftCount;
L←E1-T;
E1←L;
L←E1-T,TASK;
E1←L,:STORE;

HiZero:
L←N1,BUS=0;

;!1,2,LowNonZero1,LowZero1;
defined above

M1←L,L←0,:LowNonZero1;
LowNonZero1:
N1←L;zero out low order
L←20,TASK;
ShiftCount←L;16 shifts done like wildfire
L←M1,:HiNonZero;

LowZero1:E1←L;
M1←L,TASK;
N1←L,:STORE;

STORE: MAR ← ANSADDR;
TASK;
MD ← E1;
MAR ← L ← ANSADDR + 1;
ANSADDR ← L, TASK;
MD ← M1;
MAR ← ANSADDR + 1;
TASK;
MD ← N1;
L ← ANSOOP, SWMODE;
PRIMRET:
AC0 ← L, ESRB ← 0, :PRIMRET; AND RETURN TO THE INTERPRETER WITH OOP IN AC0 = ARG1

FAIL:
ESRB ← 0;
SWMODE, :PRIMFAIL;

DIVFAIL:
L ← ANSOOP; GET FLOAT FOR ANSWER
ARG1 ← L, ESRB ← 0; AND SAVE
L ← RAMRET5, TASK;
RAMRETURN ← L, SWMODE; RAM RETURN ADDRESS
REF:
L ← RAMXODD, :REF; ODD RETURN FOR REFD - THROW AWAY UNUSED FLOAT
RAMX5:
SWMODE;
PRIMFAIL:
:PRIMFAIL;LET THE SMALLTALK METHOD DO IT (LABEL USED ONLY IN RAM0)

DUMP:
T ← OOP00; ********DEBUG********
L ← LREG OR T, SWMODE, :PRIMRET; ********DEBUG********