/ LSI11 Multi-tasking kernel v0.5 / Adding filesystem interface / Martin Young 10/3/94 - 21/3/94 & 19/4/94 - 6/6/94 jmp go / Start of kernel bootstrap / **** I/O vectors **** . = 34^. / Software trap (OS_call) oscl 200 . = 60^. crcv / Console receive 200 . = 64^. cscv / Console send 200 . = 100^. clcv / Clock receive 200 . = 300^. trcv / Transmission line receive 200 . = 304^. tsnv / Transmission line send 200 / Insert other vector stuff . = 400^. / **** Process table **** ptbl: 0^. / Status - dead 0 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 1 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 2 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 3 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 4 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 5 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 6 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 7 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 8 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 9 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 10 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 11 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 12 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 13 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data 0^. / Status - dead 14 0^. / Stack 0^. / Messages 0^. / Pinfo 0^. / Notification 0^. / Priority count 0^. / Priority reload 0^. / Further data . = 760^. 100000^. / Stack got regs on it... 2^. / Status - to run 15 0^. / Messages senv / Base of stack / ppda 0^. / Notification 20^. / Priority count 20^. / Priority reload 0^. / Cookie table pointer . = 1200^. / **** Initial memory map **** mmap: 140041 / 0-8Kb used, 8Kb-56Kb free 441 / 56Kb-64Kb used + end marker . = 1400^. / **** OS_call jump table **** jptb: ohcn / OS_hear_con ohtm / OS_hear_trm ohcl / OS_hear_clk ohtr / OS_hear_trn ohip / OS_hear_IPC osip / OS_say_IPC oslp / OS_sleep ocms / OS_clear_mess orms / OS_read_mess ospt / OS_set_ptab orpt / OS_read_ptab ostr / OS_start ostp / OS_stop osnk / OS_nonkernel osfc / OS_free_cookie osmr / OS_mem_req osmf / OS_mem_free ocke / OS_make_cookie ofmt / OS_find_msg_type ofmc / OS_find_msg_cookie ofmb / OS_find_msg_both nkjt: lwrt / LIB_write lred / LIB_read lhxo / LIB_hex_output lsto / LIB_string_output lsti / LIB_string_input lcct / LIB_clear_cookies lact / LIB_add_cookie lrct / LIB_remove_cookie lopn / LIB_open_file lclo / LIB_close_file . = 2000^. / **** Start of kernel bootstrap **** go: mtps $0 / Clear the PSW clr *$1050 / Priority level clr *$1006 / Set system time to 0 clr *$1040 / Allow the clock to swap clr *1060 / No switches imminent movb $101,*$mmap / Set up the memory list movb $240,*$mmap+1 movb $41,*$mmap+2 movb $1,*$mmap+3 mov $760,*$1000 mov $150000,sp jsr pc,sve sve: mov r0,-(sp) / Save all the registers mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov r5,-(sp) mov *$1000,r0 mov sp,(r0) / ...and SP gb1: mov $boot,14(sp) jsr pc,next / Pick ourselves (we hope) mov (r0),sp mov (sp)+,r5 mov (sp)+,r4 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r1 mov (sp)+,r0 rts pc boot: mov $40,-(sp) / 4Kb for messages mov $17,-(sp) / OS_req_mem 104434 add $4,sp mov r0,*$1012 / Bottom of message space mov $17770,*$1010 / Length of message space - 10 mov $20000,r1 / Size of message space lp1: clrb (r0) inc r0 dec r1 bne lp1 mov $2,-(sp) / 512 bytes for cookies mov $17,-(sp) / OS_req_mem 104434 add $4,sp mov r0,*$1020 / Base of cookie table mov $1000,*$1022 / Size of table mov $2,*$1024 / up to 2 used already mov $400,r1 / Count down mov $1,(r0) add $2,r0 lp2: clr (r0) / Clear cookie table add $2,r0 / Next entry dec r1 bne lp2 mov *$1020,r0 / Get base of cookie table mov $1,(r0) / Make 1 (console) already used mov $2,2(r0) / Make 2 (term) already used mov $0,-(sp) / No new environment mov $tlvo,-(sp) / Trans_device lowlev output mov $2,-(sp) / Minimal (512byte) stack mov $13,-(sp) / OS_start 104434 / Enter the kernal add $10,sp mov $0,-(sp) / No new environment mov $tlvi,-(sp) / Trans_device lowlev input mov $2,-(sp) / Minimal (512byte) stack mov $13,-(sp) / OS_start 104434 / Enter the kernal add $10,sp mov $0,-(sp) / No new environment mov $ttdv,-(sp) / Trans_char_device process mov $2,-(sp) / Minimal (512byte) stack mov $13,-(sp) / OS_start 104434 / Enter the kernal add $10,sp mov $0,-(sp) / No new environment mov $txdv,-(sp) / Terminalx_device process mov $2,-(sp) / Minimal (512byte) stack mov $13,-(sp) / OS_start 104434 / Enter the kernal add $10,sp mov $0,-(sp) / No new environment mov $fsys,-(sp) / File system process mov $2,-(sp) / Minimal (512byte) stack mov $13,-(sp) / OS_start 104434 / Enter the kernal add $10,sp mov $0,-(sp) / No new environment mov $fsy2,-(sp) / File system part 2 mov $2,-(sp) / Minimal (512byte) stack mov $13,-(sp) / OS_start 104434 / Enter the kernal add $10,sp mov $2,-(sp) / Sleep for a bit mov $6,-(sp) 104434 add $4,sp / Display a startup message mov $btms,r0 / Address of boot message mov $1,r1 / Using stdout jsr pc,lsto / That's enough for now mov $0,-(sp) / No new environment mov $user,-(sp) / Initial user program mov $2,-(sp) / Mimimal (512byte) stack mov $13,-(sp) / OS_start 104434 / Enter the kernel add $10,sp mov $nenv,-(sp) / Starting in a new place mov $user,-(sp) / Initial user program mov $2,-(sp) / Mimimal (512byte) stack mov $13,-(sp) / OS_start 104434 / Enter the kernel add $10,sp / Done booting mov $0,-(sp) / Remove the fake stack base mov $6,-(sp) / Stack base offset mov $11,-(sp) / OS_set_ptab 104434 / Enter the kernel add $6,sp / Fix the stack mov $17,-(sp) / That's our process number mov $14,-(sp) / OS_stop 104434 / Enter the kernel / We are now dead :-( br . / Just in case :-) / Boot message btms: <\n\nMartin's Rather Dubious OS v0.5\n> .even / Initial environment (console) senv: 10 / stdin channel (req * 4) 1 / stdin cookie 4 / stdout channel 1 / stdout cookie 4 / stderr channel 1 / stderr cookie 0 / parent signal chan 0 / parent signal cookie 0 / No files.... 0 0 0 0 / No files.... 0 0 0 0 / No files.... 0 0 0 0 / No files.... 0 0 0 1 / Console cookie 0 / Terminator / New environment (for second shell) nenv: 10 / stdin channel (req * 4) 2 / stdin cookie 4 / stdout channel 2 / stdout cookie 4 / stderr channel 2 / stderr cookie 0 / parent signal chan 0 / parent signal cookie 0 / No files.... 0 0 0 0 / No files.... 0 0 0 0 / No files.... 0 0 0 0 / No files.... 0 0 0 2 / Trans_term cookie 0 / Terminator / Termx I/O storage / 1: Hardware buffer flags t0of: 0 t1of: 0 / 2: Out_Buffer read offsets t0rb: 0 t1rb: 0 / 3: Out_Buffer write offsets t0wb: 0 t1wb: 0 / 4: Out_buffer base addresses t0bf: 0 t1bf: 0 / 5: Request remaining count t0rr: 0 t1rr: 0 / 6: In_buffer read offsets t0ir: 0 t1ir: 0 / 7: In_buffer write offsets t0iw: 0 t1iw: 0 / 8: In_buffer base address t0b2: 0 t1b2: 0 / 9: Output hardware address / type flag t0oa: 177566 t1oa: 0 / Not used; on trans line / **** Task switcher stuff *** / **** This is the scheduler, it / runs IO pending tasks first, / then message pending tasks with / messages then pre-empted tasks / then message pending tasks that / have no messages, just for something / to do. / next: tst *$1060 / Should we switch? bne nxtd / Yes - Do next mov *$1000,r1 / Current ptab entry dec 12(r1) / Priority countdown beq nxtl / Time to switch br nxpo / Continue nxtd: dec *$1060 / We've done it nxtl: mov $3,r4 / IO pending clr r5 / Always has msgs anyway jsr pc,pfnd / find tst r0 / found? bne nxgt / yes - run it mov $1,r4 / Message pending mov $1,r5 / ...with message waiting jsr pc,pfnd / find tst r0 / found? bne nxgt / Yes mov $2,r4 / Pre-empted mov $1,r5 / with messages jsr pc,pfnd / find tst r0 / found? bne nxgt / Yes mov $2,r4 / Pre-empted clr r5 / with or without messages jsr pc,pfnd / find tst r0 / found? bne nxgt / Yes mov $5,r4 / Slop sucker clr r5 / with or without messages jsr pc,pfnd / find tst r0 / found? bne nxgt / Yes br nxtl / waste time until something turns up nxgt: mov r0,*$1000 / Do this process mov 14(r0),12(r0) / Priority countdown cmp 2(r0),$1 / Was it waiting? bne nxpo / no - carry on mov $2,2(r0) / It isn't waiting any more nxpo: mov $1,*$1040 / We've swapped, so the clock doesn't rts pc / r4 - required status / r5 - msg status !=0 => need msg pfnd: mov *$1000,r0 / pointer for loop mov $21,r2 / countdown br nxt3 nxt2: cmp 2(r0),r4 / Right status? bne nxt3 / no -skip this one tst r5 / Are messages significant? beq nxt6 / no - select regardless tst 4(r0) / check for pending messages bne nxt6 / messages - keep this one nxt3: add $20,r0 / next slot cmp $1000,r0 / check for flop over bne nxt4 mov $ptbl,r0 nxt4: dec r2 / count down ... bne nxt2 clr r0 nxt6: rts pc load: mov *$1000,r0 mov (r0),sp mov (sp)+,(r0) mov (sp)+,r5 mov (sp)+,r4 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r1 mov (sp)+,r0 clr *$1050 rti ild: mov *$1000,r0 mov (r0),sp mov (sp)+,(r0) mov (sp)+,r5 mov (sp)+,r4 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r1 mov (sp)+,r0 rti / **** Where the traps come **** oscl: mov r0,-(sp) / Save all the registers mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov r5,-(sp) mov *$1000,r0 mov (r0),-(sp) mov sp,(r0) / ...and SP tst *$1050 / Test the software priority beq lwt / Free user level - continue sub $2,16(sp) / Move back to the trap cmp $3,2(r0) / if IO pending... bne oscp / none - return inc *$1060 / Cause a switch mov $2,2(r0) / Lower status, so no holding kernel oscp: jsr pc,next jmp load lwt: inc *$1050 / Change priority to kernel user level mtps $0 / Allow interrupts mov 22(sp),r1 / Function num asl r1 / Times 2 (to words) add $jptb,r1 mov (r1),pc / Jump to the function / **** OS system functions **** ohcn: jsr pc,next / OS_hear_con jmp load ohtm: jsr pc,next / OS_hear_term jmp load ohcl: jsr pc,next / OS_hear_clock jmp load ohtr: jsr pc,next / OS_hear_trans jmp load ohip: jsr pc,next / OS_hear_IPC jmp load / OS_say_IPC osip: mov 30(sp),r1 / Read mask mov 26(sp),r2 / ...data mov 24(sp),r3 / ...cookie jsr pc,amsg / Send the message jsr pc,next / Swap jmp load / OS_sleep oslp: mov 24(sp),2(r0) / Reason for sleep inc *$1060 / Cause a switch jsr pc,next jmp load ocms: mov 4(r0),r1 / Start of message list ocml: tst r1 / Found a NULL? beq ocmy / Yes! clr (r1) / Free the slot mov 4(r1),r1 / Follow that link... br ocml ocmy: jsr pc,next / swap jmp load / OS_read_message orms: mov 4(r0),r1 / Get the pointer mov r1,14(sp) / Move to process's r0 tst r1 / Got a NULL? beq orme / yes - leave mov 4(r1),4(r0) / Move the links up... orme: jsr pc,next jmp load / OS_set_ptab ospt: mov r0,r1 / Save r0 add 24(sp),r1 / Get offset mov 26(sp),(r1) / Move the word jsr pc,next jmp load / OS_read_ptab orpt: mov r0,r1 / Save r0 add 24(sp),r1 / Get offset mov (r1),14(sp) / Set process's r0 jsr pc,next jmp load / OS_start ostr: mov $ptbl,r1 / Start of process table mov $20,r2 / Max tasks osrc: mov 2(r1),r3 tst r3 / Is it spare? beq osrg / Yes - got one add $20,r1 / Next entry dec r2 / countdown bne osrc / Check the next one clr 14(sp) / Fail, so NULL -> r0 jsr pc,next jmp load osrg: mov $4,2(r1) / Grab it! Hope for no race mov 10(r0),10(r1) / Same IPC by default clr 6(r1) / No info clr 4(r1) / No messages mov 14(r0),12(r1) / Same pri. as parent mov 14(r0),14(r1) / Same reload, too clr 16(r1) / Cookie filter pointer mov $20,r3 / Max number of tasks sub r2,r3 / task number => r3 mov r3,14(sp) / Give pid to parent in r0 mov 24(sp),r0 / Stack size mov r1,-(sp) mov r3,-(sp) jsr pc,mreq mov (sp)+,r3 mov (sp)+,r1 tst r0 bne osso / Got a stack clr 14(sp) / Tell parent we failed clr 2(r1) / ...and free the process slot jsr pc,next jmp load / exit osso: mov r0,6(r1) / Store the stack base to free on death mov 24(sp),r3 / Size of stack in blocks swab r3 / size in bytes add r0,r3 / Top of stack (rounded up) sub $30,r3 / Real place in stack (minus regs) mov 2(sp),2(r3) / Copy r5 mov 4(sp),4(r3) mov 6(sp),6(r3) mov 10(sp),10(r3) mov 12(sp),12(r3) mov 14(sp),14(r3) / Copy r0 (child's pid) mov 20(sp),20(r3) / Copy PSW mov 26(sp),16(r3) / Child's PC mov r3,(r1) mov $2,2(r1) / Run it next time tst 30(sp) / A new environment? beq oss2 / no - same one mov 30(sp),r4 / 3rd argument br oss1 oss2: mov *$1000,r0 / Our ptab entry mov 6(r0),r4 / Our base of stack (i.e. parent's) oss1: mov 6(r1),r2 / Base of stack == ppda mov $70,r3 / 56 words to copy ossc: mov (r4),(r2) / Copy a word add $2,r4 / Move on (source) add $2,r2 / Move on (dest) dec r3 / Countdown bne ossc / Loop mov 6(r1),r4 / Base of stack again add $60,r4 / Start of cookies mov r4,16(r1) / Point to the new cookie list jsr pc,next jmp load / OS_stop ostp: mov 24(sp),r1 / Get the argument asl r1 asl r1 asl r1 asl r1 / Times 16 add $ptbl,r1 / Ptab entry mov r1,-(sp) / save the ptab mov 6(r1),r0 / Base address of stack jsr pc,mfre / Free the memory mov (sp)+,r1 mov $0,2(r1) / It's dead jmp ocms / Clear messages and exit / OS_nonkernel osnk: mov $nkjt,14(sp) / Put address in r0 jsr pc,next jmp load / OS_free_cookie osfc: jsr pc,next jmp load / OS_mem_req osmr: mov 24(sp),r0 / Get the argument jsr pc,mreq / Try to get some mov r0,14(sp) / Put into processes r0 jsr pc,next jmp load / OS_mem_free osmf: mov 24(sp),r0 / Get the argument jsr pc,mfre / Try to free it jsr pc,next jmp load / OS_make_cookie / Makes it as unique as possible ocke: mov *$1024,r2 / Possible cookie (next) ockn: inc r2 oclc: mov *$1020,r0 / Base of cookie table mov *$1022,r1 / Size of cookie table ockl: cmp r2,(r0) / Is it in use? beq ockn / Yes - try again add $2,r0 / Next position sub $2,r1 / Countdown bne ockl / Loop and check next mov *$1020,r0 / Base of cookie table mov *$1022,r1 / Size of cookie table ockf: tst (r0) / Is this slot free? beq ockg / Yes - got one add $2,r0 sub $2,r1 bne ockf / Find clr 14(sp) / failed br ockb / Back ockg: mov r2,(r0) / Write it mov r2,14(sp) / Return it (CHECK!!!) mov r2,*$1024 / Use the next one next time ockb: jsr pc,next jmp load / OS_find_message_type ofmt: mov 4(r0),r1 / First message mov r0,r2 add $4,r2 / Keep the location of the last link oftl: mov r1,14(sp) / Intermediate result tst r1 / Null? beq ofte cmp (r1),24(sp) / Is it the right type? beq oftf / yes - keep it mov r1,r2 add $4,r2 / Keep the last link mov 4(r1),r1 / no - try next br oftl oftf: mov 4(r1),(r2) / Move the links up ofte: jsr pc,next jmp load / OS_find_message_cookie ofmc: mov 4(r0),r1 / First message mov r0,r2 add $4,r2 / Keep the location of the last link ofcl: mov r1,14(sp) / Intermediate result tst r1 / Null? beq ofce cmp 6(r1),24(sp) / Is it the right cookie? beq ofcf / yes - keep it mov r1,r2 add $4,r2 / Keep the last link mov 4(r1),r1 / no - try next br ofcl ofcf: mov 4(r1),(r2) / Move the links up ofce: jsr pc,next jmp load / OS_find_message_both ofmb: mov 4(r0),r1 / First message mov r0,r2 add $4,r2 / Keep the location of the last link ofbl: mov r1,14(sp) / Intermediate result tst r1 / Null? beq ofbe cmp 6(r1),24(sp) / Is it the right cookie? bne ofbn / no - check next cmp (r1),26(sp) / Is it the right type? beq ofbf / Yes - keep it ofbn: mov r1,r2 add $4,r2 / Keep the last link mov 4(r1),r1 / no - try next br ofbl ofbf: mov 4(r1),(r2) / Move the links up ofbe: jsr pc,next jmp load / **** Interrupt handlers **** / Term0_device receive crcv: mov r0,-(sp) / Save all the registers mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov r5,-(sp) mov *$1000,r0 mov (r0),-(sp) mov sp,(r0) / ...and SP movb *$177562,r2 / Store the character mtps $0 / We are now interruptable mov $1,r1 / Our message type mov $1,r3 / Cookie 1, console jsr pc,amsg / Add the message inc *$1050 / Now done earlier cmp *$1050,$1 / In free mode? bne crcl / no jsr pc,next / Swap processes crcl: dec *$1050 jmp ild / Continue to process / Term0_device send cscv: mov r0,-(sp) / Save all the registers mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov r5,-(sp) mov *$1000,r0 mov (r0),-(sp) mov sp,(r0) / and the SP mtps $0 / Allow interrupts mov *$t0wb,r1 / Write offset mov *$t0rb,r2 / Read offset cmp r1,r2 / Anything to output? beq csnc / no - so clear flag add *$t0bf,r2 / Read address mov $1,*$t0of / Buffer is now busy movb (r2),*$177566 / Write character to device mov *$t0rb,r2 / Get the offset back again inc r2 / Move on one byte cmp $2000,r2 / loop over? bne csno mov $0,r2 / yes - reset to 0 csno: mov r2,*$t0rb / Write back the offset jmp csgb / carry on csnc: clr *$t0of csgb: inc *$1050 / Now done earlier cmp *$1050,$1 / are we in free mode? bne csgl / no jsr pc,next / switch csgl: dec *$1050 jmp ild / continue / Clock_device receive clcv: mov r0,-(sp) / Save all registers mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov r5,-(sp) mov *$1000,r0 mov (r0),-(sp) mov sp,(r0) / ...and SP mtps $0 / We are now interruptable inc *$1006 / Move the clock up mov $100000,r1 / Mesg type:clock_tick mov *$1006,r2 / Msg is system time clr r3 / Send always - IPC cookie jsr pc,amsg / Send the message tst *$1040 / Have we already swapped? bne cfr2 / yes - don't do it again inc *$1050 / Now done earlier cmp *$1050,$1 / are we in free mode? bne cfre / no jsr pc,next / Switch contexts cfre: dec *$1050 cfr2: clr *$1040 / Allow clock swapping jmp ild / Continue / Trans_device recieve trcv: mov r0,-(sp) / Save all the registers mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov r5,-(sp) tst *$1044 beq trnf mov *$1042,r1 movb *$176502,(r1) / Store the character inc r1 mov r1,*$1042 dec *$1044 / finished transfer? bne trno / no - return normally mov $20,r1 / Our message type mov *$1046,r2 / Buffer base clr r3 / send always - IPC cookie jsr pc,amsg / Add the message br trno trnf: movb *$176502,r5 / Just get it out the buffer trno: mov (sp)+,r5 mov (sp)+,r4 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r1 mov (sp)+,r0 rti / Trans_device send tsnv: mov r0,-(sp) / Save all the registers mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov r5,-(sp) tst *$1054 beq tsnf mov *$1052,r1 movb (r1),*$176506 / Write the character inc r1 mov r1,*$1052 dec *$1054 / finished transfer? br tsno / no - return normally tsnf: mtps $0 / This may take some time mov $40,r1 / Our message type mov *$1056,r2 / Buffer base clr r3 / send always - IPC cookie jsr pc,amsg / Add the message tsno: mov (sp)+,r5 mov (sp)+,r4 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r1 mov (sp)+,r0 rti / **** Low level messaging code / r1 - type mask / r2 - data / r3 - cookie amsg: mov $ptbl,r0 / Start of process table mov $20,r4 / Loop counter ch1: bit r1,10(r0) / Does it want our message? beq no1 / It doesn't - skip past stuff tst 2(r0) / It is dead? beq no1 / ...and it is... tst r3 / Is it a general cookie? beq msgs / yes - send it regardless mov 16(r0),r5 / Get the cookie filter list tst r5 / Is it empty? beq no1 / yes - nothing but general wanted tck: tst (r5) / End of list? beq no1 / Yes - we don't want this cmp (r5),r3 / the right cookie? beq msgs / yes - send the message cmp (r5),$177777 / Is this the magic cookie? beq msgs / yes - send the message add $2,r5 / otherwise move along the list br tck msgs: mov *$1012,r5 / Get base of msg space add $7770,r5 / ...gives addr of first slot flp: inc (r5) / This is an atomic grab cmp $1,(r5) / If free (n=0) then n+1=1 beq fnd1 / Found one dec (r5) / Repair the mask sub $10,r5 cmp r5,*$1012 / Have we reached the bottom? beq fmsf / yes - find message fail jmp flp / no - go look for the next one fnd1: mov r1,(r5) / Construct mesg. mov r2,2(r5) mov $0,4(r5) mov r3,6(r5) mov r1,-(sp) mov r2,-(sp) bit $100125,r1 beq nio1 mov $3,2(r0) / Bump up status if IO inc *$1060 / Cause a switch nio1: mov r0,r1 mov 4(r1),r2 / Start of message list llp: tst r2 / Found a NULL? beq yes1 / Yes! mov r2,r1 / Follow that link... mov 4(r1),r2 jmp llp yes1: mov r5,4(r1) / That adds our new message mov (sp)+,r2 mov (sp)+,r1 no1: add $20,r0 dec r4 bne ch1 rts pc fmsf: clr r0 rts pc / **** Low level memory management **** / Request: / Returns (in r0) a pointer to a block / of memory. Uses a list of holes/used / and looks for the first fit. / r0 - requested block size / 256 / Even numbers only! mreq: bic $1,r0 / Force r0 to be even :-) tstb r0 beq mrfl mov $mmap,r1 / Start of allocation map clr r3 / Initial position in memory mrlp: movb (r1),r2 / Get the entry bic $177400,r2 cmpb $1,r2 / Is this the end marker? beq mrfl / yes - request fail tstb r2 / is it an unused entry? beq mrnx / yes - look at next slot bitb $1,r2 / Is is free or used? beq mrfr / Free - check size mrnx: bicb $1,r2 / Leaves us with a length/256 swab r2 / Now a real length in bytes add r2,r3 / New address inc r1 / Next entry br mrlp / check next mrfr: cmp r0,r2 / Is it big enough? bgt mrnx / no - look for another slot bne mrex / too big - shift table around bisb $1,(r1) / Just right - grab it mov r3,r0 rts pc mrex: mov r1,r4 / temporary pointer mrn1: inc r4 / next slot cmpb (r4),$1 / end marker beq mrsu / found a space - shift up tstb (r4) / unused entry bne mrn1 / try again... dec r4 mrsu: cmp r4,r1 beq mrfd / Found a slot and shifted movb (r4),1(r4) / shift up once dec r4 br mrsu / keep moving mrfd: movb (r4),r5 / length available bic $177400,r5 sub r0,r5 / length left over movb r5,1(r4) / and remember this... movb r0,(r4) / length used bisb $1,(r4) / and mark it as used mov r3,r0 / return the pointer the the space rts pc mrfl: clr r0 rts pc / Free: addr is in r0 / De-allocates a previously / allocated block of memory. It / also concatonates adjacent block / of the same type (hole/used) mfre: tst r0 / Is it NULL? beq mffl / yes - don't try to free it clr r1 / Start of memory mov $mmap,r2 / Start of memory map mflp: cmp r1,r0 / Is this the associated entry? beq mffn / yes, found - free it movb (r2),r3 / Get an entry bic $177400,r3 cmpb r3,$1 / Is this the end marker? beq mffl / Free failed bicb $1,r3 / Change to pure length (blocks) swab r3 / now into bytes add r3,r1 / Add to current position inc r2 / move to next entry br mflp / and loop round mffn: bicb $1,(r2) / Actually make the block free mov $mmap,r2 / Compact the list. Dest of slots mov $mmap+1,r3 / Source of slots mfns: tstb (r3) / Is the source a blank? beq mfdb / yes - move it on cmpb $1,(r3) / Is it the end marker? beq mfem / yes - stop movb (r2),r4 / Get the last slot bic $177400,r4 movb (r3),r5 / and the current slot bic $177400,r5 bitb $1,r4 / Is the first one free? bne mfdt / no - goto next entry bitb $1,r5 / Is the second one free? bne mfdt / no - goto next entry bicb $1,r5 / pure length of soruce movb (r2),r4 / get the last slot back again bic $177400,r4 add r5,r4 / Make the dest the total length movb r4,(r2) / Write the new stretched slot clrb (r3) / Remove the second slot entry mfdb: inc r3 / Move the source on br mfns / ...and loop round mfdt: inc r2 / Move the dest on movb (r3),(r2) / Copy the slot down inc r3 / and the destination, too br mfns / next slot mfem: movb (r3),1(r2) / That's the end marker copied mffl: rts pc / everything done. / Library support lbsv: sub $14,sp mov 14(sp),(sp) / Save registers and return mov r0,14(sp) mov r1,12(sp) mov r2,10(sp) mov r3,6(sp) mov r4,4(sp) mov r5,2(sp) rts pc lbld: mov 14(sp),r0 mov 12(sp),r1 mov 10(sp),r2 mov 6(sp),r3 mov 4(sp),r4 mov 2(sp),r5 mov 0(sp),14(sp) add $14,sp rts pc / **** Non-kernel library / All re-entrant, I hope / Write a character (r0) to a / stream (r1) lwrt: jsr pc,lbsv mov r0,r2 mov $6,-(sp) / Stack base/ ppda mov $12,-(sp) / OS_read_ptab 104434 / Enter kernel add $4,sp / Fix the stack tst r1 / Is this stdin? beq lwrf / Yes - fail cmp $1,r1 / Is this stdout? bne lwro / No - check next mov 4(r0),r3 / stdout chan mov 6(r0),r4 / stdout cookie br lwrw / do the write lwro: cmp $2,r1 / Is this stderr? bne lwre / No - check next mov 10(r0),r3 / stderr chan mov 12(r0),r4 / stderr cookie br lwrw / do the write lwre: asl r1 / multiplied by 2 asl r1 / ...by 4 add r0,r1 / Base of file desciptor mov 6(r1),r3 / file chan mov (r1),r4 / file cookie lwrw: mov r3,-(sp) / Message type: channel mov r2,-(sp) / Data - character mov r4,-(sp) / Cookie mov $5,-(sp) / OS_sayIPC 104434 add $10,sp / Fix the stack cmp r2,$12 / Is it a LF? bne lwrf / no - ignore mov r3,-(sp) / Message type: channel mov $15,-(sp) / send a CR mov r4,-(sp) / cookie mov $5,-(sp) / OS_say_IPC 104434 add $10,sp lwrf: jsr pc,lbld / Retrieve the regesters rts pc / Return to caller / Read a character from stream r1 lred: jsr pc,lbsv mov $6,-(sp) / Stack base/ppda mov $12,-(sp) / OS_read_ptab 104434 / Enter kernel add $4,sp / Fix the stack cmp $1,r1 / Is this stdout? beq lrdf / Yes - fail cmp $1,r1 / Is this stderr? beq lrdf / Yes - fail tst r1 / Is this stdin? bne lrde / No - check next mov 0(r0),r3 / stdin chan mov 2(r0),r4 / stdin cookie br lrdd / do the read lrde: sub $3,r1 / reduce to 0-3 asl r1 / multiplied by 2 asl r1 / ...by 4 asl r1 / ...by 8 add r0,r1 / Base of file desciptor add $20,r1 / Start of tables mov 2(r1),r3 / file chan mov (r1),r4 / file cookie lrdd: mov r3,r5 asr r5 asr r5 mov r5,-(sp) / Message type: request chan mov $1,-(sp) / Data - only 1 character mov r4,-(sp) / Cookie mov $5,-(sp) / OS_sayIPC 104434 add $10,sp / Fix the stack lrdw: mov r3,-(sp) / Read msg by this type mov r4,-(sp) / and by this cookie mov $24,-(sp) / Read by type/cookie 104434 / Enter the kernel add $6,sp / Fix the stack tst r0 / Was there anything? bne lrdg / Yes - got one mov $1,-(sp) / Wait for messages mov $6,-(sp) / OS_sleep 104434 / Enter the kernel add $4,sp / Fix the stack br lrdw / loop for messages lrdg: mov 2(r0),12(sp) / Write to the pending r0 clr (r0) / Free the message slot lrdf: jsr pc,lbld / Retrieve the regesters rts pc / Return to caller / output word in hex to dev / r0 - number / r1 - output stream lhxo: jsr pc,lbsv / Save registers mov r0,r5 / Keep the number safe mov $14,r4 / Initial number of shifts lho1: mov r5,r2 / Temp character mov r4,r3 / temp roll counter tst r3 / do zero rolls? beq lhiz lho2: asr r2 / shift dec r3 / countdown bne lho2 / loop lhiz: bic $177760,r2 / mask off all but 4 bits add $60,r2 / turn into "0"... cmp $72,r2 / gone past "9"? bgt lhad / no add $7,r2 / yes - move on to "A" lhad: mov r2,r0 / character jsr pc,lwrt / Write sub $4,r4 / less rolls next time bpl lho1 / loop four times jsr pc,lbld / Load regesters rts pc / exit / Output a nulled string / r0 - addr of string / r1 - output stream lsto: jsr pc,lbsv / Save regesters mov r0,r2 lstl: tstb (r2) / Found a NULL? beq lsbc / Yes - return movb (r2),r0 / Read the character jsr pc,lwrt inc r2 / Next character br lstl / Repeat until... lsbc: jsr pc,lbld / Load regesters rts pc / Leave / Input a string + add a NULL / r0 - address to write to / r1 - input stream / r2 - output stream (for echo) lsti: jsr pc,lbsv clr r4 / Characters read so far mov r0,r5 lsig: jsr pc,lred / Read a character mov r1,r3 mov r2,r1 cmp r0,$177 beq lsid movb r0,(r5) / Write the character into the string cmpb r0,$15 / Was it a CR? beq lsie / Yes - end cmpb $37,r0 blt lsin mov r3,r1 br lsig lsid: tst r4 / Is there anything to delete? bne lsir mov r3,r1 br lsig lsir: mov $10,r0 jsr pc,lwrt mov $40,r0 jsr pc,lwrt mov $10,r0 jsr pc,lwrt mov r3,r1 dec r4 dec r5 br lsig lsin: jsr pc,lwrt mov r3,r1 inc r5 inc r4 / One more has been read br lsig lsie: clrb (r5) / NULL the string jsr pc,lbld rts pc / and finish / LIB_clear_cookies lcct: jsr pc,lbsv / Save regesters mov $16,-(sp) / Cookie filter pointer mov $12,-(sp) / OS_read_ptab 104434 add $4,sp / Fix the stack tst r0 / Was there anything there? beq lccb / no - back clr (r0) / Put a terminator at the top lccb: jsr pc,lbld / Load regesters rts pc / and return / LIB_add_cookie lact: jsr pc,lbsv / Save regesters mov r0,r2 / Keep the new cookie safe mov $16,-(sp) / Cookie filter pointer mov $12,-(sp) / OS_read_ptab 104434 add $4,sp / Fix the stack tst r0 / Was there anything there? bne lacd / yes - do lacn: clr 12(sp) / Clear caller's r0 jsr pc,lbld / Load regesters rts pc / return lacd: mov $40,r1 / Max # of cookies (minus terminator) lacl: tst (r0) / Is this the terminator? beq lacf / yes - found add $2,r0 / Try next dec r1 / countdown bne lacl / loop br lacn / not done lacf: clr 2(r0) / Move the terminator on mov r2,(r0) / Put the new cookie in jsr pc,lbld / Load regesters rts pc / and return / LIB_remove_cookie lrct: jsr pc,lbsv / Save regesters mov r0,r3 / Keep the cookie safe mov $16,-(sp) / Cookie filter pointer mov $12,-(sp) / OS_read_ptab 104434 add $4,sp / Fix the stack tst r0 / Was there anything there? bne lrcy / yes - deal with it lrcf: jsr pc,lbld / Load regesters rts pc / and return lrcy: mov (r0),r0 / Base of cookie table mov r0,r1 / copy from pointer mov $40,r2 / Maximum copies lrcc: mov (r1),(r0) / Copy one entry tst (r0) / Was this the terminator? beq lrcf / Yes - return cmp (r0),r3 / Is this a match beq lrch / Yes - move on half (sort of) add $2,r0 / Move the source on (keep cookie) lrch: add $2,r1 / Move the desination on (next cookie) dec r2 / countdown bne lrcc / copy next br lrcf / return / LIB_open lopn: jsr pc,lbsv / Save the regesters mov r0,r3 / Keep the filename pointer safe mov $6,-(sp) / Stack base / ppda mov $12,-(sp) / OS_read_ptab 104434 add $4,sp add $20,r0 / First file handle mov $3,r1 / stream number lofs: tst (r0) / Is this handle free? beq lofh / Yes - carry on add $10,r0 / Move to next handle inc r1 / Next stream number cmp $7,r1 / have we over run? bne lofs / no - look for another lopf: clr 12(sp) / Return a fail in r0 jsr pc,lbld / Load regesters rts pc / ...and return lofh: mov r1,12(sp) / Keep the file handle mov r0,r2 / Keep the address of handle mov $21,-(sp) / OS_make_cookie 104434 add $2,sp / Fix the stack mov r0,r1 / keep the cookie safe jsr pc,lact / (add cookie) now we can hear this mov $1000,-(sp) / msg type: file control mov r1,-(sp) / data: new cookie mov $0,-(sp) / cookie: none (yet) mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack lopr: mov $2000,-(sp) / want type: file control reply mov r1,-(sp) / want cookie: the one we just sent mov $24,-(sp) / OS_find_msg_both 104434 add $6,sp / Fix the stack tst r0 / Was the anything? bne lopg / yes - got one mov $1,-(sp) / Sleep on messages mov $6,-(sp) / OS_sleep 104434 add $4,sp br lopr / Awake again lopg: tst 2(r0) / Did we get it okay? bne lopc / Yes - carry on clr (r0) / Free the message slot br lopf / Return a failed code lopc: mov $1000,-(sp) / type: file control send movb (r3),r4 mov r4,-(sp) / data: character of filename mov r1,-(sp) / cookie: file cookie mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack inc r3 / Next character tstb r4 / Was the last one a NULL? bne lopc / Send next character lowc: mov $2000,-(sp) / want type: file control reply mov r1,-(sp) / want cookie: the one we just sent mov $24,-(sp) / OS_find_msg_both 104434 add $6,sp / Fix the stack tst r0 / Was there anything? bne lofg / yes - got one mov $1,-(sp) / Sleep on messages mov $6,-(sp) / OS_sleep 104434 add $4,sp br lowc / Awake again lofg: tst 2(r0) / Success? bne lorg / Yes - really got clr (r0) / Free message slot br lopf / Return an error code lorg: clr (r0) / Free the message slot mov r1,(r2) / Write the cookie mov $20000,2(r2) / Request channel mov $20000,4(r2) / Read channel (not needed? == req*4) mov $10000,6(r2) / Write channel jsr pc,lbld / Restore regesters rts pc / and return / LIB_close lclo: jsr pc,lbsv / Save the regesters mov r0,r2 mov $6,-(sp) / Stack base / ppda mov $12,-(sp) / OS_read_ptab 104434 add $4,sp add $20,r0 / First file handle mov $3,r1 / stream number lcfh: cmp r1,r2 / Is this the right handle? beq lcfe / Yes - carry on add $10,r0 / Move to next handle inc r1 / Next stream number cmp $7,r1 / have we over run? beq lcfl / yes - return a fail code lcfe: mov r0,r2 / Keep the entry's address mov $1000,-(sp) / type: file_control_in mov $1000,-(sp) / data: 1000 - close file mov (r2),-(sp) / cookie: as in entry mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack clr (r2) / Make this entry free mov $1,12(sp) / Return a successful code jsr pc,lbld rts pc lcfl: clr 12(sp) / Put 0 into the pending r0 jsr pc,lbld / Load the regesters rts pc / **** _device processes **** / **** Termx_device txdv: mov $15,-(sp) / Library base address 104434 add $2,sp mov r0,r1 / Keep the base safe here mov 12(r1),r2 / Address of function jsr pc,(r2) / LIB_clear_cookies mov $1,r0 / Cookie for console mov 14(r1),r2 / Address of function jsr pc,(r2) / LIB_add_cookie mov $2,r0 / Cookie for term jsr pc,(r2) / LIB_add_cookie mov $7,-(sp) / Want to hear term_in & term_out mov $10,-(sp) / Inttr notification mask mov $11,-(sp) / Alter process table 104434 / Enter the kernel add $6,sp mov $20,-(sp) / Low priority mov $14,-(sp) / Priority reload offset mov $11,-(sp) / Set ptab function 104434 add $6,sp / Fix the stack mov $4,-(sp) / 1024 bytes for out_buffer (only 1 now) mov $17,-(sp) / Memory request 104434 / Enter the kernel add $4,sp / Fix the stack mov r0,*$t0bf / Keep the base of the buffer mov $4,-(sp) / 1024 bytes for in_buffer (only 1 now) mov $17,-(sp) / Memory request 104434 / Enter the kernel add $4,sp / Fix the stack mov r0,*$t0b2 / Keep the base of the buffer clr *$t0wb / Write position in out_buffer clr *$t0rb / Read position out in_buffer clr *$t0of / hw buffer is empty clr *$t0iw / Write position in in_buffer clr *$t0ir / Read position in in_buffer clr *$t0rr / No bytes requested yet / Second term add $6,sp / Fix the stack mov $4,-(sp) / 1024 bytes for out_buffer (only 1 now) mov $17,-(sp) / Memory request 104434 / Enter the kernel add $4,sp / Fix the stack mov r0,*$t1bf / Keep the base of the buffer mov $4,-(sp) / 1024 bytes for in_buffer (only 1 now) mov $17,-(sp) / Memory request 104434 / Enter the kernel add $4,sp / Fix the stack mov r0,*$t1b2 / Keep the base of the buffer clr *$t1wb / Write position in out_buffer clr *$t1rb / Read position out in_buffer clr *$t1of / hw buffer is empty clr *$t1iw / Write position in in_buffer clr *$t1ir / Read position in in_buffer bis $100,*$177560 / Enable recieve from console bis $100,*$177564 / Enable send to console txms: mov $10,-(sp) / Read a message 104434 / Enter the kernel add $2,sp tst r0 / Were there any messages? bne txgm / Yes - deal with them mov $1,-(sp) / We're waiting for a message mov $6,-(sp) / Sleep function 104434 / Enter the kernel add $4,sp br txms / We're awake again! So loop txgm: bit $1,(r0) / Check for termx_in msg bne txmi / handle that... bit $4,(r0) / Check for termx_out msg bne txmo / handle that... bit $2,(r0) / Check for termx_read msg bne txmr txbc: clr (r0) / Free the message slot jmp txms / Look for more messages txmr: mov 6(r0),r2 / Terminal number asl r2 / Word offset sub $2,r2 / Numbers start at 1, not 0 mov $t0rr,r1 / Base of request counters add r2,r1 / Real address add 2(r0),(r1) / New total br txsn / Can we send now? txmi: mov 6(r0),r2 / Terminal number asl r2 / Word offset sub $2,r2 / Numbers start at 1, not 0 mov $t0b2,r3 / Base of buffer add r2,r3 / Add offset mov (r3),r1 / Get the buffer base mov $t0iw,r3 / Base of write offsets add r2,r3 / Add offset add (r3),r1 / add the write offset movb 2(r0),(r1) / Put a character in the buffer mov (r3),r1 / Temporary copy of the offset inc r1 / Move on one byte cmp $2000,r1 / Have we reached the end? bne txin / no - continue clr r1 / yes - reset txin: mov $t0ir,r4 / Base of read buffers add r2,r4 / Add offset cmp r1,(r4) / Is the buffer full? beq txsn / Yes - don't do more mov r1,(r3) / write new write offset txsn: mov $t0rr,r5 / Base of requests remaining add r2,r5 / Add offset tst (r5) / Is there anything requested? beq txbc / No - look for more messages mov $t0iw,r4 / Base of in_write offset add r2,r4 / Add offset mov $t0ir,r1 / Read offset add r2,r1 / Add offset cmp (r4),(r1) / Anything to output? beq txbc / no - So return mov $t0b2,r3 / In buffer base add r2,r3 / Add offset mov (r3),r3 / Dereference the pointer add (r1),r3 / Read address movb (r3),r3 / Read the character mov $10,-(sp) / Notification mask (termx_read) mov r3,-(sp) / Character to send mov 6(r0),-(sp) / Term number as cookie mov $5,-(sp) / Say_IPC function 104434 / Enter the kernel add $10,sp dec (r5) / One less request to deal with inc (r1) / Move on one byte cmp $2000,(r1) / loop over? bne txio clr (r1) / yes - reset to 0 txio: br txbc / Loop for sending txmo: mov 6(r0),r2 / Terminal number asl r2 / Word offset sub $2,r2 / Numbers start at 1, not 0 mov $t0oa,r3 / Base of hardware addresses add r2,r3 / Real address of this term tst (r3) / Is it a physical device? bne txho / Yes - deal with this mov $100,-(sp) / Send char via trans_dev mov 2(r0),-(sp) / The character mov 6(r0),-(sp) / Term ID mov $5,-(sp) / OS_say_IPC 104434 / Enter the kernel add $10,sp / Fix the stack br txbc / Return (inc. free msg slot) txho: mtps $200 / Protect from interference mov $t0of,r3 / Base of flags add r2,r3 / add offset tst (r3) / Check state of buffer beq txon / Clear, so output now... mov $t0bf,r3 / Base of buffers add r2,r3 / Add offset mov (r3),r1 / Get the buffer base mov $t0wb,r3 / Base of write offsets add r2,r3 / Add offset add (r3),r1 / add the write offset movb 2(r0),(r1) / Put a character in the buffer mov (r3),r1 / Temporary copy of the offset inc r1 / Move on one byte cmp $2000,r1 / Have we reached the end? bne txno / no - continue mov $0,r1 / yes - reset txno: mov $t0rb,r4 / Base of read buffers add r2,r4 / Add offset cmp r1,(r4) / Is the buffer full? beq txgb / Yes - don't do more mov r1,(r3) / write new write offset txgb: mtps $0 / Enable send to console jmp txbc / Look for more messages txon: mov $1,(r3) / Make the hw buffer not empty mov $t0oa,r3 / Base of output addrs add r2,r3 / Add offset mov (r3),r3 movb 2(r0),(r3) / Write the character mtps $0 / Enable send to console jmp txbc / Look for more messages / Term_t device driver ttdv: mov $15,-(sp) / OS_library_base 104434 add $2,sp mov r0,r1 / Keep the base safe mov 12(r1),r2 / Address of function jsr pc,(r2) / LIB_clear_cookies mov 14(r1),r2 / Address of function mov $2,r0 / Cookie for term jsr pc,(r2) / LIB_add_cookie mov $140,-(sp) / Want to hear block_out & termt_out mov $10,-(sp) / Offset of mag mask mov $11,-(sp) / OS_alter_ptab 104434 / Enter the kernel add $6,sp / Fix the stack mov $20,-(sp) / Low priority mov $14,-(sp) / Priority reload offset mov $11,-(sp) / Set ptab function 104434 add $6,sp / Fix the stack mov $10,-(sp) / 2048 bytes for buffer mov $17,-(sp) / Memory request 104434 / Enter the kernel add $4,sp / Fix the stack mov r0,r1 / Keep that address mov $2000,r2 / Countdown (in words) ttcl: clr (r1) / Clear buffer space add $2,r1 dec r2 bne ttcl mov r0,r1 / Keep the buffer address safe ttwi: mov $1,-(sp) / We're waiting for messages mov $6,-(sp) / OS_sleep 104434 / enter kernel add $4,sp / fix the stack ttrm: mov $10,-(sp) / OS_read_message 104434 / enter kernel add $2,sp / fix the stack tst r0 / were there any? beq ttwi / no - loop back and sleep bit $100,(r0) / Is it a character to write? bne ttwc / yes - deal with it mov 2(r0),r2 sub r1,r2 / Is it in our buffer? bic $100000,r2 cmp $4000,r2 / length blt ttno / Not Our message mov 2(r0),r2 / Get the addr back clr (r2) / Free that buffer space ttno: clr (r0) / Free the message space br ttrm / continue ttwc: mov r1,r2 / Base of buffer mov $400,r3 / Number of slots ttwl: tst (r2) / Is this location free? beq ttmb / Yes - use it add $10,r2 / Next slot dec r3 / countdown bne ttwl / ...and loop br ttno / no space - lost character ttmb: mov $1,(r2) / Type: term mov 6(r0),2(r2) / Cookie: term ID clr 4(r2) / Next length: no more data mov 2(r0),6(r2) / Data: character mov $200,-(sp) / Message type start block_out mov r2,-(sp) / Data: address of block mov $1,-(sp) / Cookie: size (1=8bytes) mov $5,-(sp) / OS_sayIPC 104434 / Enter the kernel add $10,sp / Fix the stack br ttno / Continue / Transmission line low level (in) tlvi: mov $420,-(sp) / Hear block_in_ack and block_in_do mov $10,-(sp) / Mask offset mov $11,-(sp) / Set ptab function 104434 / Enter the kernel add $6,sp / Fix the stack mov $15,-(sp) / Base of non-kernel library 104434 add $2,sp / Fix the stack mov r0,r2 / Keep the base mov 12(r2),r3 / Addr of function jsr pc,(r3) / LIB_clear_cookies mov 14(r2),r3 / Addr of function mov $177777,r0 / Magic cookie to hear all others jsr pc,(r3) / LIB_add_cookie mov $4,-(sp) / medium priority mov $14,-(sp) / Priority reload offset mov $11,-(sp) / Set ptab function 104434 add $6,sp / Fix the stack mov $tlib,*$1042 / Buffer mov $tlib,*$1046 / likewise mov $10,*$1044 / One char bis $100,*$176500 clr *$tifg tliw: mov $1,-(sp) / We're waiting for messages mov $6,-(sp) / OS_sleep 104434 / enter kernel add $4,sp / fix the stack tlir: mov $20,-(sp) / type: block_in_ack mov $22,-(sp) / OS_read_message_type 104434 / enter kernel add $4,sp / fix the stack tst r0 / were there any? beq tliw / no - loop back and sleep tst *$tifg / Should we ignore this? beq tldi / no clr (r0) clr *$tifg / Read the next block mov $tlib,*$1042 / Buffer for next time mov $tlib,*$1046 mov $10,*$1044 / One char packet mov $100,-(sp) / Send a char via trans_line mov $400,-(sp) / 256=ack mov 2(r1),-(sp) / cookie mov $5,-(sp) / OS_sayIPC 104434 add $10,sp / Fix the stack br tlir tldi: mov 2(r0),r1 cmp (r1),$1 / Is it character IO? beq tlic / yes - deal with it cmp (r1),$2 / Is it file IO? beq tlif / yes - deal with it cmp (r1),$4 / Is it file opened status? beq tlis / yes - deal with it tlfl: mov $tlib,*$1042 / Buffer for next time mov $tlib,*$1046 mov $10,*$1044 / One char packet mov $100,-(sp) / Send a char via trans_line mov $401,-(sp) / 257=cack mov 2(r1),-(sp) / cookie mov $5,-(sp) / OS_sayIPC 104434 add $10,sp / Fix the stack clr (r0) br tlir / Wait for another message tlis: mov $1000,-(sp) / type: file control in mov 6(r1),-(sp) / data: as supplied mov 2(r1),-(sp) / Cookie: as supplied mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack clr (r0) / Free the message slot mov $tlib,*$1042 / Buffer mov $tlib,*$1046 mov $10,*$1044 / One char packet mov $100,-(sp) / Send a char via trans_line mov $400,-(sp) / 256=ack mov 2(r1),-(sp) / cookie mov $5,-(sp) / OS_sayIPC 104434 add $10,sp / Fix the stack br tlir tlic: mov $1,-(sp) / Fake term_in mov 6(r1),-(sp) / character mov 2(r1),-(sp) / cookie mov $5,-(sp) / OS_sayIPC 104434 add $10,sp / Fix the stack clr (r0) / Free the message slot mov $tlib,*$1042 / Buffer mov $tlib,*$1046 mov $10,*$1044 / One char packet mov $100,-(sp) / Send a char via trans_line mov $400,-(sp) / 256=ack mov 2(r1),-(sp) / cookie mov $5,-(sp) / OS_sayIPC 104434 add $10,sp / Fix the stack jmp tlir / Look for more messages tlif: mov $400,-(sp) / Type block_in mov 2(r1),-(sp) / Cookie / file ID mov $24,-(sp) / OS_read_msg_both 104434 add $6,sp / Fix the stack tst r0 / Anything? beq tlfl / no - send a cack mov 2(r0),*$1042 / Buffer mov 2(r0),*$1046 / Return value mov 4(r1),*$1044 / Length of next block mov $100,-(sp) / Send a char via trans_line mov $400,-(sp) / 256=ack mov 2(r1),-(sp) / cookie mov $5,-(sp) / OS_sayIPC 104434 add $10,sp / Fix the stack mov $1,tifg / Set the ignore_this flag jmp tlir / Look for more messages tifg: 0^. tlib: 0^. 0^. 0^. 0^. / Transmission line low level (out) tlvo: mov $15,-(sp) / OS_library_base 104434 add $2,sp / Fix the stack mov r0,r1 / Keep the base safe mov 12(r1),r2 / Addr of function jsr pc,(r2) / LIB_clear_cookies mov 14(r1),r2 / Addr of function mov $1,r0 / Cookie for character IO jsr pc,(r2) / LIB_add_cookie mov $3,r0 / Cookie for open file jsr pc,(r2) / LIB_add_cookie mov $240,-(sp) / Hear block_out_ack and block_out_do mov $10,-(sp) / Mask offset mov $11,-(sp) / Set ptab function 104434 / Enter the kernel add $6,sp / Fix the stack mov $20,-(sp) / low priority mov $14,-(sp) / Priority reload offset mov $11,-(sp) / Set ptab function 104434 add $6,sp / Fix the stack clr *$1054 / Nothing there yet bis $100,*$176504 / Enable interrupts br tlor tlow: mov $1,-(sp) / Pretended pre-emption mov $6,-(sp) / OS_sleep 104434 / enter kernel add $4,sp / fix the stack tlor: mov $10,-(sp) / OS_read_msg 104434 add $2,sp tst r0 / Get anything? beq tlow / no - wait some more bit $200,(r0) / Is it the right type? bne tloo / Okay clr (r0) / Free the message slot br tlor tloo: mov 2(r0),r1 inc r1 mov r1,*$1052 / Base of block+1 mov 2(r0),*$1056 / Return value mov $7,*$1054 / Length of trans-1 dec r1 / Real start addr again mov (r1),r5 / Keep the type for later movb (r1),*$176506 / Start off transfer clr (r0) / Free the message slot tlr: mov $40,-(sp) / type : block_out_ack mov $22,-(sp) / OS_find_msg_type 104434 add $4,sp tst r0 / Get anything? beq tlw cmp r1,2(r0) / Is it the correct ack? beq tlct / yes - continue clr (r0) / no - clear message br tlr tlw: mov $1,-(sp) / Pretended pre-emption mov $6,-(sp) / OS_sleep 104434 / enter kernel add $4,sp / fix the stack br tlr tlct: cmp $3,r5 / Was it a file open header? beq tlfo / yes - deal with it clr (r0) / otherwise free the message slot br tlor / ...and look for more messages tlfo: mov 6(r1),r2 / Address of following data mov r2,*$1056 / Message reply address inc r2 mov r2,*$1052 / Start of transfer dec r2 mov 4(r1),r3 / Length of block dec r3 mov r3,*$1054 / Length minus initiator movb (r2),*$176506 / Start the transfer clr (r0) / Free the message slot tlbw: mov $40,-(sp) / type : block_out_ack mov $22,-(sp) / OS_find_msg_type 104434 add $4,sp tst r0 / Get anything? beq tlbs cmp 2(r0),r2 / Is this the correct ack? beq tlob / yes - continue clr (r0) / no - free the message slot br tlbw / and try to read more tlbs: mov $1,-(sp) / Pretended pre-emption mov $6,-(sp) / OS_sleep 104434 / enter kernel add $4,sp / fix the stack br tlbw tlob: clr (r0) br tlor / File system emulator fsys: mov $1020,-(sp) / Only hear file control in mov $10,-(sp) / Mask offset mov $11,-(sp) / OS_set_ptab 104434 add $6,sp / Fix the stack mov $20,-(sp) / High priority mov $14,-(sp) / Priority reload offset mov $11,-(sp) / OS_set_ptab 104434 add $6,sp / Fix the stack mov $15,-(sp) / Find address of library 104434 / Enter kernel add $2,sp / Fix the stack mov r0,r3 / Address of table mov 12(r3),r4 / Addr of function jsr pc,(r4) / LIB_clear_cookies mov $2,-(sp) / 512 bytes for file descriptors mov $17,-(sp) / OS_mreq 104434 add $4,sp / Fix the stack mov r0,*$fsfd mov $20,r1 / Number of descriptors fsid: clr (r0) / Make it look free add $40,r0 / Move to the next dec r1 / countdown bne fsid / loop, or not fswt: mov $10,-(sp) / OS_read_messages 104434 add $2,sp tst r0 / Got any? bne fsgm / Yes - deal with them mov $1,-(sp) / Wait for messages mov $6,-(sp) / OS_sleep 104434 add $4,sp / Fix the stack br fswt fsgm: cmp (r0),$1000 / Is it file control? beq fsfc / yes - deal with it fsbk: clr (r0) / Free the message slot br fswt / Look for more messages fsfc: tst 6(r0) / Is it a new one? bne xx1 / Yes -deal with it jmp fsnf xx1: mov *$fsfd,r1 / Base of file desriptors mov $20,r2 / Number of fds fsff: cmp 22(r1),6(r0) / Do the cookies match? beq fsgf / Yes - got file add $40,r1 / Move to next fd dec r2 / countdown bne fsff / loop mov $2000,-(sp) / type: file control return mov $0,-(sp) / data: 0-fail mov 6(r0),-(sp) / cookie: as received mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack jmp fsbk / and return flfc: mov r0,r4 clr (r1) / Make the fd free mov 26(r1),r0 / Address of current buffer bic $400,r0 / To mreq block accuracy mov r0,-(sp) / address to free mov $20,-(sp) / OS_mem_free 104434 add $4,sp / Fix the stack mov r4,r0 / Get the message back br fsbk fsgf: tst (r1) / Is this valid? beq fsbk / No - return cmp 2(r0),$1000 / Is it file close? beq flfc cmp $1,(r1) / Is it completing filename? beq fscf / yes - do that then mov $2000,-(sp) / type: file control return mov $0,-(sp) / data: 0-fail mov 6(r0),-(sp) / cookie: as received mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack br fsbk / return fscf: mov 20(r1),r4 / Pointer into filename movb 2(r0),(r4) / Write the character inc 20(r1) / Next character tstb 2(r0) / Was this a NULL? bne fsbk / no - return mov $2,(r1) / Finished getting filename now mov $3,*$fsmb / Packet type open_file mov 6(r0),*$fsmb+2 / cookie: as internally mov $16,*$fsmb+4 / Length: max filename mov r1,r2 / Address of fd add $2,r2 / Start of filename mov r2,*$fsmb+6 / Data: address of filename mov $200,-(sp) / Message type block_out_do mov $fsmb,-(sp) / Data: address of packet mov $1,-(sp) / Cookie: 1=headered mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack mov r0,r4 fsws: mov $1000,-(sp) / Type: file control in mov 6(r4),-(sp) / Cookie: as supplied mov $24,-(sp) / OS_find_msg_both 104434 add $6,sp / Fix the stack tst r0 / Did we get anything? bne fsos / Yes - sucessfully opened mov $1,-(sp) / wait for messages mov $6,-(sp) / OS_sleep 104434 add $4,sp / Fix the stack br fsws / Awake, so read messages fsos: tst 2(r0) / Did this fail? bne fsoc / no - continue clr (r0) / Free the message slot mov $2000,-(sp) / type: file control return mov $0,-(sp) / data: 0-fail mov 6(r4),-(sp) / cookie: as received mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack jmp fsbk / return fsoc: mov 2(r0),20(r1) / Length of file mov 6(r4),22(r1) / Get the cookie clr (r0) / Free the message slot mov $2,-(sp) / Obtain a 512 byte buffer mov $17,-(sp) / OS_mem_req 104434 add $4,sp / Fix the stack clr 24(r1) / At beginning of buffer mov r0,26(r1) / current buffer add $400,r0 / other half of block mov r0,30(r1) / next buffer mov $400,32(r1) / size of two buffer halves clrb 34(r1) / current is invalid movb $1,35(r1) / next is valid mov $177400,36(r1) / At start of file mov $3,(r1) / The file is now usable mov $400,-(sp) / Type: block_in_do mov 30(r1),-(sp) / Data: addr of next buffer mov 22(r1),-(sp) / Cookie: as supplied mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack mov $5,*$fsmb / Request for a block mov 22(r1),*$fsmb+2 / Cookie as supplied mov $0,*$fsmb+4 / No extra data with this block mov 36(r1),r2 add 32(r1),r2 / position of next block, in file mov r2,*$fsmb+6 / data is position in file mov $200,-(sp) / type: block_out_do mov $fsmb,-(sp) / data: addr of packet buffer mov $1,-(sp) / cookie: headered mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack flwb: mov $20,-(sp) / type: block_in_ack mov $22,-(sp) / OS_find_msg_type 104434 add $4,sp / Fix the stack tst r0 / Did we get anything? bne flgb / yes - got buffer mov $1,-(sp) / Wait for messages mov $6,-(sp) / OS_sleep 104434 add $4,sp / Fix the stack br flwb / Awake, so loop flgb: cmp 2(r0),30(r1) / The right address? beq flrg / yes - really got clr (r0) / Free the message slot br flwb / Loop for more messages flrg: mov $2000,-(sp) / type: file control return mov $1,-(sp) / data: 1-okay mov 22(r1),-(sp) / cookie: as received mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack clr (r0) / Free the most recent message mov r4,r0 / Replace original message jmp fsbk fsnf: mov *$fsfd,r1 / Base of file desciptors mov $20,r2 / Number of fds fsnd: tst (r1) / Is this fd free? beq fsgd / yes - got desciptor add $40,r1 / next fd dec r2 / countdown bne fsnd / loop mov $2000,-(sp) / type: file control return mov $0,-(sp) / data: 0-fail mov 2(r0),-(sp) / cookie: as received in data field mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack jmp fsbk / No - out of descriptors fsgd: mov $1,(r1) / Making a filename now mov r1,r5 add $2,r5 / Start of filename mov r5,20(r1) / Make the pointer correct mov 2(r0),22(r1) / Add the associated cookie mov 14(r3),r4 / Addr of function mov r0,r5 / Keep the message pointer mov 2(r5),r0 / New cookies jsr pc,(r4) / LIB_add_cookie mov $2000,-(sp) / type: file control reply mov $1,-(sp) / data: okay mov 2(r5),-(sp) / cookie: as received mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack mov r5,r0 / Get the message pointer back jmp fsbk / and return .even fsfd: 0^. fsmb: 0 / Packet buffer 0 0 0 / The other half of the file system fsy2: mov $4020,-(sp) / Hear file_in & file_req_in mov $10,-(sp) / Mask offset mov $11,-(sp) / OS_set_ptab 104434 add $6,sp / Fix the stack mov $20,-(sp) / High priority mov $14,-(sp) / Priority reload offset mov $11,-(sp) / OS_set_ptab 104434 add $6,sp / Fix the stack mov $15,-(sp) / Find address of library 104434 / Enter kernel add $2,sp / Fix the stack mov r0,r3 / Address of table mov 12(r3),r4 / Addr of function jsr pc,(r4) / LIB_clear_cookies mov 14(r3),r4 / Addr of function mov $177777,r0 / Magic hear-all cookie jsr pc,(r4) / LIB_add_cookie f2wm: mov $10,-(sp) / Read messages 104434 add $2,sp / Fix the stack cmp (r0),$4000 / Is it the right type? beq f2rt / yes - carry on clr (r0) / Free the message slot mov $1,-(sp) / wait for a message mov $6,-(sp) / OS_sleep 104434 add $4,sp / Fix the stack br f2wm / Awake, so loop f2rt: mov *$fsfd,r1 / Base of file desriptors mov $20,r2 / Number of fds f2ff: cmp 22(r1),6(r0) / Do the cookies match? beq f2gf / Yes - got file f2nt: add $40,r1 / Move to next fd dec r2 / countdown bne f2ff / loop f2bk: clr (r0) / Free the message slot br f2wm f2gf: cmp $3,(r1) / Is this valid? bne f2nt / No - return mov r0,r5 / Keep the message safe mov 2(r0),r4 / characters to send f2cb: tstb 34(r1) / Is the current buffer valid? bne f2rb / yes - just read from it. tstb 35(r1) / Is the next buffer valid? bne f2vl / Yes - carry on mov $20000,-(sp) / type: file_read mov $403,-(sp) / data: 259 - read fail mov 6(r0),-(sp) / cookie: as supplied mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack br f2bk / ...and carry on f2vl: movb 35(r1),34(r1) / Move next buffer into current add 32(r1),36(r1) / Move on through file mov 30(r1),r2 / Keep next buffer addr mov 26(r1),30(r1) / Current becomes next (addr) mov r2,26(r1) / next becomes current clr 24(r1) / Offset in current buffer mov $400,-(sp) / Type: block_in_do mov 30(r1),-(sp) / Data: addr of next buffer mov 22(r1),-(sp) / Cookie: as supplied mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack mov $5,*$f2lb / Request for a block mov 6(r0),*$f2lb+2 / Cookie as supplied mov $0,*$f2lb+4 / No extra data with this block mov 36(r1),r2 add 32(r1),r2 / position of next block, in file mov r2,*$f2lb+6 / data is position in file mov $200,-(sp) / type: block_out_do mov $f2lb,-(sp) / data: addr of packet buffer mov $1,-(sp) / cookie: headered mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack f2wb: mov $20,-(sp) / type: block_in_ack mov $22,-(sp) / OS_find_msg_both 104434 add $4,sp / Fix the stack tst r0 / Did we get anything? bne f2gb / yes - got buffer mov $1,-(sp) / Wait for messages mov $6,-(sp) / OS_sleep 104434 add $4,sp / Fix the stack br f2wb / Awake, so loop f2gb: cmp 2(r0),30(r1) / The right address? beq f2rg / yes - really got clr (r0) / Free the message slot br f2wb / Loop for more messages f2rg: movb $1,35(r1) / Make the next buffer valid br f2cb / Now try reading again f2rb: mov 26(r1),r2 / Address of current buffer add 24(r1),r2 / Address of current character inc 24(r1) / Move the offset on cmp 24(r1),32(r1) / Reached the end yet? bne f2ro / no - read okay clrb 34(r1) / make the current buffer invalid f2ro: movb (r2),r3 / Read a character mov $20000,-(sp) / Type: file_out mov r3,-(sp) / data: character mov 6(r5),-(sp) / cookie: as given mov $5,-(sp) / OS_say_IPC 104434 add $10,sp / Fix the stack dec 20(r1) / End of file? bne f2rm clr 34(r1) / Make both buffers invalid f2rm: dec r4 / One less character to send beq f2en / maybe read some more jmp f2cb f2en: mov r5,r0 / Retrieve message pointer jmp f2bk / and carry on f2lb: 0 / Packet buffer 0 0 0 / **** System monitor / **** Just dump the memory list atm user: mov $22010,-(sp) / Only want to hear termx_read & files mov $10,-(sp) / Mask offset mov $11,-(sp) / Set ptab function 104434 / Enter the kernel add $6,sp / Fix the stack mov $2,-(sp) / Highish priority mov $14,-(sp) / Priority reload offset mov $11,-(sp) / Set ptab function 104434 add $6,sp / Fix the stack mov $15,-(sp) / Find address of library 104434 / Enter kernel add $2,sp / Fix the stack mov r0,r3 / Address of table mov $ustr,r0 / Address of startup string mov $1,r1 / Stdout mov 6(r3),r5 jsr pc,(r5) / Call the routine mov $7,-(sp) / OS_clear_messages 104434 add $2,sp ussl: mov $prmt,r0 / Prompt text mov $1,r1 / Using stdout mov 6(r3),r5 jsr pc,(r5) / Print the string mov $2,-(sp) / Get 1 block mov $17,-(sp) / OS_mreq 104434 add $4,sp / Fix the stack tst r0 / Did we get it? beq ussl / No - try again mov r0,-(sp) / Keep a handle on it mov $0,r1 / stdin mov $1,r2 / stdout mov 10(r3),r5 jsr pc,(r5) / Get a string mov (sp)+,r0 / Get the base back mov r0,-(sp) / save it again cmpb (r0),$120 / Is it a P? beq uprc / Dump the process table cmpb (r0),$115 / Is it an M? beq umem / Dump the memory map cmpb (r0),$103 / Is it a C? beq unck / Get and print new cookie cmpb (r0),$100 / Is it an @? beq uofl / Try to open as a fil tstb (r0) / Is it an empty string? bne uexc / Try to load and run ubck: mov $20,-(sp) / OS_free (r0 still on stack) 104434 / Enter the kernel add $4,sp / Don't forget about r0... br ussl / Get another key uexc: mov r3,-(sp) mov r0,-(sp) mov $1,r1 mov $12,r0 jsr pc,lwrt mov (sp)+,r0 jsr pc,lopn / Try to open mov r0,r4 tst r0 / Did we succeed? beq uexf / no - don't try to read mov $2,-(sp) / 512 bytes mov $17,-(sp) / OS_mreq 104434 add $4,sp tst r0 beq uexf mov r0,r5 / Buffer mov r0,r3 / Execution address mov r4,r1 uext: jsr pc,lred cmp $403,r0 / Was it a read fail? beq uexe / Yes - stop now movb r0,(r5)+ br uext uexe: jsr pc,lclo mov r3,-(sp) jsr pc,(r3) / Execute the code mov $20,-(sp) / OS_free_mem 104434 add $4,sp / r3 was already on the stack top uexf: mov (sp)+,r3 br ubck / and continue uofl: inc r0 mov r0,-(sp) mov $1,r1 mov $12,r0 jsr pc,lwrt mov (sp)+,r0 jsr pc,lopn / Try to open mov r0,r4 tst r0 / Did we succeed? beq uonf / no - don't try to read uost: mov r4,r1 jsr pc,lred cmp $403,r0 / Was it a read fail? beq uonc / Yes - stop now mov $1,r1 jsr pc,lwrt br uost uonc: jsr pc,lclo uonf: br ubck / and continue unck: mov $1,r1 / Print on stdout mov 0(r3),r5 / Addr of function mov $12,r0 / character 13 jsr pc,(r5) / LIB_write mov $21,-(sp) / OS_make_cookie 104434 add $2,sp / Fix the stack mov 4(r3),r5 / Output in hex jsr pc,(r5) / LIB_hex_print br ubck / and carry on uprc: mov $ptbl,r2 jsr pc,uech br ubck umem: mov $mmap,r2 jsr pc,uech br ubck uech: mov (r3),r5 mov $1,r1 mov $12,r0 / Print a character 10 mov $1,r1 jsr pc,(r5) mov $1,r1 / Use stdout mov $20,r5 / Number of entries uhvp: mov $10,r4 / Writes per entry uhvo: mov r2,-(sp) / Save position in ptab mov r5,-(sp) / Save process counter mov r4,-(sp) / Save word counter mov (r2),r0 / Move position into r0 mov $1,r1 / Using stdout mov 4(r3),r4 jsr pc,(r4) / Print a hex value to the console mov $40,r0 / Print a space mov $1,r1 / ...on stdout jsr pc,lwrt mov (sp)+,r4 / Restore above pushes mov (sp)+,r5 mov (sp)+,r2 add $2,r2 / Move the pointer on dec r4 / Countdown word counter bne uhvo / maybe print some more mov r4,-(sp) mov (r3),r4 mov $1,r1 / Using stdout mov $12,r0 / Print a character 10 mov $1,r1 jsr pc,(r4) mov (sp)+,r4 dec r5 / Countdown process counter bne uhvp / maybe output another line rts pc / ...or return ustr: <\n----\n\rSystem monitor / proto shell v0.2\n>

prmt: <\nJade% >