; Alto 1822 Interface microcode
; Larry Stewart
; Last modified April 19, 1978 9:41 PM
#AltoConsts23.mu;
; Address definition for Emulator main loop in ROM
$START $L004020,000000,000000 ; Start of emulator main loop
; Task Specific Function Definitions
$IREAD $L000000,070017,000100 ; F1-17Input data
$IWRITE$L020016,000000,124000 ; F1-16Output data
$IOCLR $L016015,000000,000000 ; F1-15Clear hardware output wakeup
$IPOSTF$L016014,066014,000100 ; F1-14Post (gate status to bus)
$ISWAKC$L024014,000000,000000 ; F2-14Clear SIO generated wakeup
$IBRNCH$L024013,000000,000000 ; F2-134-way branch on wakeup
$IIENBL$L024012,000000,000000 ; F2-12Start read (turn on RFNIB)
$ISETCS$L024011,000000,000000 ; F2-11Set control functions from bus
$IPTMOD$L024010,000000,000000 ; F2-102-way branch on throwaway mode
;R (S) registers
$ICBPTR$R76;Control Block Pointer
$MTEMP $R25;Temporary storage
$AC1 $R2;Emulator register
$NWW $R4;Interrupt system reg
; Task constants
$ISDON $777;done
$ISOVF $1377;buffer overflow (input only)
$ISIBLZ$1777;block length zero (input only)
; Initialization for putting this code in the RAM, including
; ’silent boot’ code
!17,20,LOC0,,,,,IMLOOP,,,,,,,,,,;
;Silent Boot code, branches to ROM immediately
LOC0:SWMODE;
:START;
;Main loop. Task waits here when not processing anything.
;IBRNCH gates two bits onto NEXT6 and NEXT7
; 00 - Start input 01 - Set Control
; 10 - Output data wakup 10 - Input data wakeup
; 4-way branch using NEXT6,NEXT7 (Caused by IBRNCH)
%14,14,0,IISTRT,ICTST,IODATA,IIDATA;
IMLOOP:T← ICBPTR,IBRNCH;test wakeup conditions
L← ISDON,:IISTRT;[IISTRT,ICTST,IODATA,IIDATA]
;Common Post routine
; Expects offset of post location in T
;and task status in M
;IPOSTF gates hardware status bits to the bus
; 2-way branch using NEXT9 (Caused by SH=0)
!1,2,IIBLOK,IPOST;
IPOST:MAR← ICBPTR+T;Start double reference
T← NWW;
MD← M,IPOSTF;Bus AND hardware status
L← MD OR T,TASK;NWW OR interrupt bits
INXT:NWW← L,:IMLOOP;
;Read status and set control register
;ISWAKC clears a wakeup caused by an SIO instruction
;ISETCS loads hardware control flops from the bus
ICTST:MAR← L← AC1;Start fetch of args
ICBPTR← L;Save ctl block pointer
T← 6,ISWAKC;post location offset
SINK← MD,ISETCS;Control function
INEND:L← ISDON,:IPOST;Set control flops
;Input initialization
;IIENBL enables the hardware to receive a 16 bit word (turns it on)
IISTRT:MAR← 2+T;
ISWAKC;clear wakeup
T← MD;read data pointer
L← MD-T;
L← ISIBLZ,SH=0;
T←10,:IIBLOK;[IIBLOK,IPOST]
IIBLOK:L← NWW,IIENBL,TASK,:INXT;length ok,start reader
;Input Main loop
;IPTMOD gates the state of the Throwaway mode flop to NEXT7
; The branch is taken if the flop was set (by an ISETCS)
;IREAD gates the receiver shift register to the bus
; and the PAD flop to NEXT7
; If the branch is taken (which happens when the last word of
; a packet is read), the wakeup will not be cleared, otherwise
; the wakeup will be cleared
; 2-way branch using NEXT9 (Caused by SH=0)
!1,2,IIDMOR,IIDFUL;
; 2-way branch using NEXT7 (Caused by IPTMOD)
%4,4,0,IIACPT,IIDISC;
; 2-way branch using NEXT7 (Caused by IREAD)
%4,4,0,IIDCON,IIDLST;
; another 2-way branch using NEXT7 (Caused by IREAD)
%4,4,0,IIFINS,IIDPST;
IIDATA:MAR← L← 2+T;Start fetch
MTEMP← L,IPTMOD;save cb ptr,test mode
T← MD;get pointer [IIACPT,IIDISC]
IIACPT:L← MD-T;past end of buffer?
MAR← T,SH=0;start data fetch
L← ONE+T,:IIDMOR;[IIDMOR,IIDFUL]
IIDMOR:MD← IREAD;Read and branch on last word.
;Except on the last word, this
;clears the wakeup
IICLNU:MAR← MTEMP,:IIDCON;[IIDCON,IIDLST]
IIDCON:IIENBL,TASK;enable receiver
IDCON:MD← M,:IMLOOP;update ptr,restart
IIDLST:TASK;this TASK only works
;because the hardware doesn’t really clear the
;wakeup until the next IREAD in this case
MD← M;update pointer
L← ISDON;
IIDPST:SINK← IREAD;clear wakeup (again)
IIFINS:T← 10,:IPOST;
IIDISC:L← T, T← IREAD,:IICLNU;throwaway word,branch if last
IIDFUL:SINK← IREAD;overflow status
L← ISOVF,:IIFINS;[IIFINS,IIDPST]
;Main output loop
;IWRITE loads the output shift register from the bus,
; clears the (hardware generated) wakeup if there was one,
; and starts the output hardware
;IOCLR resets the output hardware. This is how you clear the
; wakeups without restarting the output hardware
; 2-way branches using NEXT9 (both caused by SH=0)
!1,2,IODMOR,IODEND;
!1,2,IONLST,IOLST;
IODATA:MAR← L← 4+T;start pointer fetch
MTEMP← L;save cb ptr
T← MD,IOCLR;get pointer, clear wakeup
L← MD-T;past end of buffer?
MAR← T,SH=0;start data fetch
L← M-1,:IODMOR;[IODMOR,IODEND]
IODMOR:IWRITE← MD,SH=0;send data,last?
MAR← MTEMP,:IONLST;start update [IONLST,IOLST]
IOLST:SINK← 2,ISETCS;set last word function
IONLST:L← ONE+T,TASK,:IDCON;finish
IODEND:T← 11+1,:INEND;offset of post loc