;Alto microcode file, incorporating jasmine, halftoning, and long pointer ops
;Free Registers (bold if it stays around):
;careful: low regs used by MUL,DIV
;1,2,3,5,7,14,41-47,51,55-57,(60-67 = stack),71-77
#AltoConsts23.MU;
!17,20,Emulator,L1,L2,L3,L4,L5,L6,L7,MRT,L11,L12,L13,L14,L15,L16,L17;
%1,1777,120,MUL;
%1,1777,121,DIV;
%1,1777,40,mulret1;
%1,1777,41,divret1;
%1,1777,42,mulret2;
%1,1777,43,divret2;
%1,1777,440,Read;
%1,1777,441,Write;
;halftone stuff
%1,1777,442,print;
%1,1777,443,init;
%1,1777,444,interpolate;
;defined under Misc.: %1,1777,453,scream; --super fast 4 bit stuff
;ReadLong,WriteLong
%1,1777,445,ReadLong;
%1,1777,446,WriteLong;
;MoveBlock (BLT)
%1,1777,447,BLT;
%1,1777,450,SetBlock;
;Misc.
%1,1777,451,GetTime;
%1,1777,452,DoRun;
%1,1777,453,scream; --super fast 4 bit halftone
%1,1777,454,Shift2;
%1,1777,477,SetBLV;
;funny locations for stepper control branch
%1,1777,520,fstep0;
%1,1777,521,fstep1;
%1,1777,522,fstep2;
%1,1777,523,fstep3;
%1,1777,1520,bstep0;
%1,1777,1521,bstep1;
%1,1777,1522,bstep2;
%1,1777,1523,bstep3;
#XMesaRAM.MU;
;-----------------------------------------------------------------
; MISC - Miscellaneous instructions specified by alpha
;alpha=11 => RCLK has been handled by ROM
;T contains alpha on arrival at MISC in RAM
;-----------------------------------------------------------------
; Precisely one of the following lines must be commented out.
MISC:L←0, SWMODE, :Setstkp;dummy MISC implementation
;#MesaMisc.mu;real implementation
$START$L004020,0,0;
Emulator: SWMODE;
L1: NOP,:START;location 20= Nova emulator start (StartIO from NovaCode);
L2: TASK,:L2;
L3: TASK,:L3;
L4: TASK,:L4;
L5: TASK,:L5;
L6: TASK,:L6;
L7: TASK,:L7;
L11: TASK,:L11;
L12: TASK,:L12;
L13: TASK,:L13;
L14: TASK,:L14;
L15: TASK,:L15;
L16: TASK,:L16;
L17: TASK,:L17;
;one of the next two lines must be commented out
#JasmineMC.MU;
;MRT: TASK,:MRT;
;#xhalftone.mu;
#D0Halftone.mu;
;#DoRunMC.MU;
;#MiscMC.MU;
SetBLV: L←0;
stkp←L,SWMODE;
RMR←stk0,:romnextA;
;SetBlock[dest,destBank,value,nwords];
SetBlock: MAR ← 177740;
NOP;
L ← MD,TASK;
temp ← L;
MAR ← 177740;
NOP,TASK;
MD ← stk1;
;now, rearrange nwords to count down to 0
T←stk3;
L ← stk0+T;
stk0←L;
L ← 0 - T;
stk3 ← L;
!1,2,moreSetBlock,doneSetBlock;
contSetBlock: T ← stk3,BUS=0;
XMAR ← stk0 + T,:moreSetBlock;
moreSetBlock: L←stk3+1;
stk3←L,TASK;
MD ← stk2,:contSetBlock;
doneSetBlock: MAR ← 177740;
L ← 0;
stkp ← L,SWMODE;
MD ← temp,:romnextA;
;MoveBlock[dest,destBank,src,srcBank,nwords];
BLT: L←stk1,TASK;
temp2 ← L LSH 1;
MAR ← 177740;
L ← temp2;
temp2 ← L LSH 1;
L ← MD,TASK;
temp ← L;
MAR ← 177740;
T ← stk3;
L ← temp2 + T,TASK;
MD ← LREG;
;now, rearrange nwords to count down to 0
!1,2,bothEven,destEvenSrcOdd;
!1,2,destEven,destOdd;
!1,2,destOddSrcEven,bothOdd;
T ← stk4;
L ← stk0 + T,BUSODD;
stk0 ← L,:destEven;
destEven: L ← stk2 + T,BUSODD;
stk2 ← L,:bothEven;
destOdd: L ← stk2 + T,BUSODD;
stk2 ← L,:destOddSrcEven;
!1,2,MoreBLTEE,BLTDoneEE;
!1,2,MoreBLTOO,BLTDoneOO;
!1,2,MoreEE,PerhapsDoneEE;
!1,2,MoreBLT,BLTDone;
bothOdd: L ← 0 - T;
stk4 ← L,SH=0,TASK;
NOP,:MoreBLTOO;
MoreBLTOO: L ← T ← stk4;
XMAR ← stk2 + T;
L ← stk4 + 1;
stk4 ← L;
L ← MD;
MAR ← stk0 + T;
SINK ← stk4,BUS=0,TASK;
MD ← LREG,:MoreBLTEE;
bothEven: L ← 0-T;
stk4 ← L,SH=0,TASK;
NOP,:MoreBLTEE;
MoreBLTEE: L ← T ← stk4;
ContBLTEE: XMAR ← stk2 + T;
stk4 ← L;
L ← 2 + T;
stk5 ← L,ALUCY;
L ← MD,:MoreEE;
MoreEE: T ← MD,TASK;
temp2 ← L,L ← T;*****M preserved across task
T ← stk4;
MAR ← stk0 + T;
T ← stk5;
MD ← temp2;
MD ← LREG,L ← T,:ContBLTEE;
PerhapsDoneEE: temp2 ← L,L ← T,:PerhapsDone;
PerhapsDone: MAR ← stk0 + T;
L ← LREG + 1;
stk4 ← L,SH=0,TASK;
MD ← temp2,:MoreBLT;
destOddSrcEven: NOP;
destEvenSrcOdd: L ← 0-T;
stk4 ← L,SH=0,TASK;
NOP,:MoreBLT;!1,2,MoreBLT,BLTDone;
;and the tight ass loop
MoreBLT: T ← stk4;
XMAR ← stk2 + T;
L ← stk4 + 1;
stk4 ← L;
L ← MD;
MAR ← stk0 + T;
SINK ← stk4,BUS=0,TASK;
MD ← LREG,:MoreBLT;!1,2,MoreBLT,BLTDone;
BLTDoneEE: NOP,:BLTDone;
BLTDoneOO: NOP,:BLTDone;
BLTDone: MAR ← 177740;
L ← 0;
stkp ← L,SWMODE;
MD ← temp,:romnextA;
;Read[address,bank] RETURNS [value];
!7,10,r0,r1,r2,r3;
Read: MAR ← 177740;--bank register for task 0 (emulator)
L←stkp - 1;
stkp ← L;
L ← MD;
MAR ← 177740;--hardware registers don’t do double word, or exchange
SINK ← stkp,BUS;
temp ← L,TASK,:r0;
r1: MD ← stk1;
XMAR ← stk0;
NOP;
L ← MD;
MAR ← 177740;
stk0 ← L,SWMODE,:r0;
r2: MD ← stk2;
XMAR ← stk1;
NOP;
L ← MD;
MAR ← 177740;
stk1 ← L,SWMODE,:r0;
r3: MD ← stk3;
XMAR ← stk2;
NOP;
L ← MD;
MAR ← 177740;
stk2 ← L,SWMODE,:r0;
r0: MD ← temp,:romnextA;
;Write[address,bank,value];
Write: MAR ← 177740;--bank register for task 0 (emulator)
L ← 0;
stkp ← L;
L←MD;
MAR ← 177740;
temp ← L,TASK;
MD ← stk1;
XMAR ← stk0;
TASK;
MD ← stk2;
MAR ← 177740;
SWMODE;
MD ← temp,:romnextA;
;ReadLong[address,bank] RETURNS [2 word value];
!7,10,rL0,,rL2,rL3,rL4,rL5;
ReadLong: MAR ← 177740;--bank register for task 0 (emulator)
NOP;
L←MD;
MAR ← 177740;
SINK ← stkp,BUS;
temp ← L,TASK,:rL0;
rL2: MD ← stk1;
XMAR ← stk0;
NOP;
L ← MD;
XMAR ← stk0 + 1;
stk0 ← L;
L ← MD;
MAR ← 177740;
stk1 ← L,SWMODE,:rL0;
rL3: MD ← stk2;
XMAR ← stk1;
NOP;
L ← MD;
XMAR ← stk1 + 1;
stk1 ← L;
L ← MD;
MAR ← 177740;
stk2 ← L,SWMODE,:rL0;
rL4: MD ← stk3;
XMAR ← stk2;
NOP;
L ← MD;
XMAR ← stk2 + 1;
stk2 ← L;
L ← MD;
MAR ← 177740;
stk3 ← L,SWMODE,:rL0;
rL5: MD ← stk4;
XMAR ← stk3;
NOP;
L ← MD;
XMAR ← stk3 + 1;
stk3 ← L;
L ← MD;
MAR ← 177740;
stk4 ← L,SWMODE,:rL0;
rL0: MD ← temp,:romnextA;
;WriteLong[address,bank,val1,val2];
WriteLong: MAR ← 177740;--bank register for task 0 (emulator)
L ← 0;
stkp ← L;
L←MD;
!1,2,WriteLongDouble,WriteLongSingle;
MAR ← 177740;
SINK ← stk0,BUSODD;
temp ← L,TASK,:WriteLongDouble;
WriteLongDouble: MD ← stk1;
XMAR ← stk0;
NOP;
MD ← stk2,TASK;
MD ← stk3,: WriteLongDone;
WriteLongSingle: MD ← stk1;
XMAR ← stk0;
TASK;
MD ← stk2;
XMAR ← stk0 + 1;
TASK;
MD ← stk3;
WriteLongDone: MAR ← 177740;
SWMODE;
MD ← temp,:romnextA;