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