**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];