**Dorado Smalltalk Microcode -- Model 1, XM version
** last edited July 9, 1979 10:03 AM by Deutsch
** Code for handling trapped messages
Title[DsmallTrapped.MC];
Top Level;
KnowRBase[State];
* Subroutine to save bytecode in Ireg and StackP in SavSp
* Enter with T = offset of bytecode from Id
Subroutine;
IregId:
Global, Ireg ← (Id) + T;
T ← StackP;
SavSp ← T, Return;
Top Level;
** Arithmetic messages
MIFU[260,10,IFU1[==,TFrameBr,I.ATrapMsgs,=]];
MIFU[270,6,IFU1[==,TFrameBr,I.Apply10,=]];* * / \ | min: max:
MIFU[276,2,IFU1[==,TFrameBr,I.ATrapMsgs10,add[=,6]]];
I.ATrapMsgs10:
T ← 270c, Call[IregId];
Branch[RedoATrapMsg];
I.ATrapMsgs:
T ← 260c, Call[IregId];
RedoATrapMsg:
T ← Top, Call[Ivall];
Temp2 ← T, Call[PopTop];*Temp2 ← receiver (1st operand)
Call[Ivall];
Temp3 ← T, RBase ← RBase[AemRegs];*Temp3 ← 2nd operand
T ← IReg, RBase ← RBase[State];
BigBDispatch ← T, T ← A ← Temp3;
Temp4 ← (Temp2) - T, Branch[ArithDispatch];
*Entry conditions for arithmetic messages below:
* Temp2 = 1st operand, T = Temp3 = 2nd operand,
* Alu = Temp4 = Temp2 - Temp3
ArithDispatch:* location 0 in dispatch
Addarith:At[Dispatch5, 0],
T ← (Temp2) + T;
DblBranch[.YesOf, ArithOut, Overflow];
Subarith:At[Dispatch5, 1],
T ← (Temp2) - T, DblBranch[.YesOf, ArithOut, Overflow];
ArithOut:
Nop;*Placement
Call[Intn];
Top ← T, Branch[RefX4];
.YesOf:
Branch[Apply];
Les:At[Dispatch5, 2],
PD ← Temp4, DblBranch[.PosTrue, .NegTrue, Overflow];
.NegTrue:
DblBranch[TTrue, FFalse, Alu<0];
.PosTrue:
DblBranch[TFalse, FTrue, Alu<0];
Gtr:At[Dispatch5, 3],
Temp4 ← T - (Temp2), Branch[Les];
Leq:At[Dispatch5, 4],
Temp4 ← (Temp2) - T - 1, Branch[Les];
Geq:At[Dispatch5, 5],
Temp4 ← T - (Temp2) - 1, Branch[Les];
Eql:At[Dispatch5, 6],
DblBranch[TTrue, FFalse, Alu=0];
Neq:At[Dispatch5, 7],
DblBranch[TFalse, FTrue, Alu=0];
Land:At[Dispatch5, 16];
T ← (Temp2) and T, Branch[ArithOut];
Lor:At[Dispatch5, 17];
T ← (Temp2) or T, Branch[ArithOut];
* Two sets of true/false are needed because of branching constraints--checking signs in compares
TTrue:
T ← Top, Branch[Shove];*Put receiver on top of stack
FFalse:
T ← FalseOop.c, Branch[Shove];*Put False on top of stack
FTrue:
T ← Top, Branch[Shove];*Put receiver on top of stack
TFalse:
T ← FalseOop.c, Branch[Shove];*Put False on top of stack
** Other messages trapped by the microcode interpreter
IFU1[300,TFrameBr,I.Subscript,0];
IFU1[301,TFrameBr,I.SubscriptGets,1];
IFU1[302,TFrameBr,I.Next,2];
IFU1[303,TFrameBr,I.NextGets,3];
IFU1[304,TFrameBr,I.Len,4];
IFU1[305,TFrameBr,I.Eq,17];*cares about MemBase, doesn’t use Id
MIFU[306,12,IFU1[==,TFrameBr,I.Apply26,=]];* ? ? class and: or: new new: to: oneToMeAsStream asStream cares about MemBase
* Subscript store
I.SubscriptGets:
T ← 300c, Call[IregId];
RedoSubscriptGets:
Call[PopTop];*pop top off
SavR1 ← T, Branch[.SubCmn];*Fetch new val for Dot←
* Subscript fetch
I.Subscript:
T ← 300c, Call[IregId];
RedoSubscript:
.SubCmn:
Call[GtopCls];*Get class of top of stack (sets Arg1)
Name ← T, Call[TestVecStr];*Check to make sure arg is vec or str
T ← Arg1, Call[Ilong];
Temp4 ← T;
AOop ← AllOnes.c, Call[PopTop];
Call[Ivall];
Branch[IvalX3];
* Stream next←
I.NextGets:
T ← 300c, Call[IregId];
RedoNextGets:
Call[PopTop];*Fetch new val for Next←
SavR1 ← T, Branch[.NextCmn];
* Stream next
I.Next:
T ← 300c, Call[IregId];
RedoNext:
.NextCmn:
Call[GtopCls];
PD ← T - (StmCls.c);
Branch[.NotStm, Alu#0];*Not a stream
Call[Hash];*T ← Core Add of stream
Call[Dirty];*dirty stream being accessed
MemBase ← ACoreBr;*Referencing ACore
BrLo ← T;
ACoreBase ← T;
AOop ← Top;
Fetch ← 0s;*Fetch stream contents
Top ← Md, Fetch ← 1s;*Fetch stream index
Temp3 ← Md, Fetch ← 2s;*Fetch stream length
T ← Md, Call[Ivall];
Temp4 ← T;
T ← Top, Call[GclassL];
Name ← T;
T ← Temp3, Call[Ivall];
T ← (T) + 1;
IvalX3:
PD ← (Temp4) - (T);*Alu ← val of length-val of index
Temp2 ← T - 1, Branch[.IToBg, Alu<0];*check index >= length
T ← Top, Branch[.INeg, Alu<0];*Check index <= 0
BOop ← T;
Arg1 ← T, Call[Hash];
MemBase ← BCoreBr;*referencing BCore
BrLo ← T;
BCoreBase ← T;
RBase ← RBase[AemRegs];
A ← Ireg, RBase ← RBase[State], Branch[.SeqFetch, R Even];
MemBase ← RotBaseBr, Call[Dirty];*dirty strector being indexed
T ← Name, Call[TestVecStr];*returns type code in T and Alu
MemBase ← BCoreBr, DblBranch[VcSt, StSt, Alu=0];
.SeqFetch:
T ← Name;*placement
Call[TestVecStr];
MemBase ← BCoreBr, DblBranch[VcLd, StLd, Alu=0];
.NotStm:
Branch[Apply];
.IToBg:
Branch[Apply];
.INeg:
Branch[Apply];
StLd:
T ← (Temp2) rsh 1;*T ← word index in string
Fetch ← T;
A ← Temp2, T ← Md, DblBranch[.StLdEv, .StLdOd, R Even];*T ← word with byte
.StLdEv:
T ← Rsh[T, 10], Branch[.StLdOut];*Left byte
.StLdOd:
T ← T and (377c), Branch[.StLdOut];*Right byte
.StLdOut:
Top ← T + (Oop00.c), Branch[RefX12];*Fast intern
StSt:
T ← (Temp2) rsh 1;
Temp3 ← T, RBase ← RBase[SavR1];
T ← SavR1, RBase ← RBase[State];
Top ← T, Call[Ivall];*Save new byte on Top, T ← value of new byte
MyTemp ← T and (377c);*MyTemp ← masked value of new byte
T ← Temp3, MemBase ← BCoreBr;
Fetch ← T, B ← Temp2, DblBranch[.StStEv, .StStOd, R Even];
.StStEv:
MyTemp ← DPF[MyTemp, 10, 10, Md], Branch[.StStCm];*Deposit in left byte
.StStOd:
MyTemp ← DPF[MyTemp, 10, 0, Md];*Deposit in right byte
.StStCm:
Store ← T, DBuf ← MyTemp, Branch[RiSubEnd];
VcLd:
Fetch ← Temp2;
Top ← Md, Branch[RiSubEnd];
VcSt:
RBase ← RBase[SavR1];
T ← SavR1, RBase ← RBase[State];*New oop
Top ← T;
T ← Temp2, Branch[Pull];*Top ← Oop in vec
RiSubEnd:
T ← Top, Call[RefCkLInc];
RefX12:
MemBase ← ACoreBr, PD ← (AOop) + 1;
Fetch ← 1s, DblBranch[.ImDone, .PostStm, Alu=0];*Check for stream op
.PostStm:
Arg1 ← Md;
Name ← Md, Call[Ival];
T ← (T) + 1, Call[Intn];
MemBase ← ACoreBr;
Store ← 1s, DBuf ← T;*Address stream index
T ← Name, Call[RefCkLDec];
Branch[RefX4];
.ImDone:
T ← Md, Branch[RefX4];*Can’t abandon Md (not used)
* Length
I.Len:
T ← 300c, Call[IregId];
RedoLen:
Call[GTopCls];
Call[TestVecStr];*Arg1 loaded by GTopCls, not smashed by TestVecStr
T ← Arg1, Call[Ilong];
Branch[ArithOut];
* Identity
I.Eq:
StackP ← (StackP) - 1;
Fetch ← StackP;
PD ← (Top) - (Md);
T ← TrueOopm1.c, Branch[.IsEq, Alu=0];
T ← FalseOop.c, Branch[Shove];
.IsEq:
T ← T + 1, Branch[Shove];
* Redispatch on trapped msg after going up to superclass
* Enter with T = bytecode
RedoTrappedMsg:
PD ← T - (300c);
MemBase ← TFrameBr, Branch[.+2, Alu>=0];
Branch[RedoATrapMsg];*placement
BDispatch ← T;
Branch[.RedoDispatch];
.RedoDispatch:
Branch[RedoSubscript], At[Dispatch11, 0];
Branch[RedoSubscriptGets], At[Dispatch11, 1];
Branch[RedoNext], At[Dispatch11, 2];
Branch[RedoNextGets], At[Dispatch11, 3];
Branch[RedoLen], At[Dispatch11, 4];