@X @~ %`
~V7 56 2 -5
~D10
~H                 MUSS
~
~
~D10
~H           SYS501
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL~
~
~
                                                             ISSUE 11~
~V9 -1
~P
~V9 1
~YSYS501
~S1~M~OSYS IMPLEMENTATION DESCRIPTION~
~S1~M~OSection 50 Version 1~
~S1~OSection 50.1 Basic Monitor and Bootstrap Facilities for MC68000(RTV)~
~S1~O1. General Description
~BThis module implements the monitor code which is resident in ROM
on microcomputers supporting MUSS.
It provides communication between a host computer and the
micro-computer, and provides facilities to activate
the downline loading of binary files
from the host to the DISC or RAM
of the micro-computer, in addition to giving bootstrap facilities and the basic
capability to inspect and alter the store and/or
the machines internal registers.
It occupies 8K of ROM,
and is entered when the reset or monitor switches are operated,
and when the interrupts associated with
trap and single step occur.
 Communication to/from the user and/or host machine is achieved
through imported VSTORE, but this will normally
relate to RS232 lines running at 9600 baud.  Another
facility of the monitor, on machines which have discs, is to provide
access to system maintenance utilities stored on disc, such as the
disc copy utility.
~BThe monitor operates in one of two modes. Initially, it is in a 'local'
mode, prompting the user for one of a number of 'commands' with which he
may inspect and alter the machines store and/or registers. In addition,
one of these commands(L) causes the monitor to display a menu
from which the options of~
~
~MEnter Remote Mode
~NBoot MUSS V1
~NBoot MUSS V2
~NBoot ROM MUSS
~NBoot RAM MUSS
~NRecall Monitor
~NChange Disc Type
~NFormat Disc
~NCopy Disc
~Netc
~
may be selected.
In fact the monitor goes automatically to this menu
state after a reset
and if local mode is required the
recall monitor must be selected.
The second mode (termed
remote) is the means
by which the user terminal connects to the host
computer.
~S1~O2. Interfaces
~S1~O2.1 Hardware Interface
~S1~O2.2 Software Interface
~S1~O3. Implementation
~S1~O3.1 Outline of Operation
~S~O3.1.1. Local mode commands
~BThe following commands are obeyed by the monitor when in local mode.~
~
~MA Display/alter the contents of an 'A' register.
~NB Set BREAKPOINT.
~NC Display/alter contents of the status register.
~ND       "        "     "     of a 'D' register.
~NE Examine the contents of a block of store.
~NG 'GO' (Enter a user program).
~NL Display Menu.
~NM Modify the contents of one or more BYTEs of store.
~NP Display/alter the contents of the program counter.
~NR Display all register values.
~NS Execute one instruction of the user program (Single STEP)
~NU Display/alter contents of the user stack pointer (USP).
~NX Restore instruction from breakpoint (clearing it).
~BThese commands are ~Ousually~O followed by values to indicate which
register or location is to be displayed, and to give new values.
With the exeption of the "L" (Display Menu),
"R" (Display Registers) and "G" (GO) commands,
the completion of one command causes the monitor to prompt for
another.
~S~O3.1.2. Local Mode Commands specifications
~BThe monitor prompts for each command with the single character "-",
after which the user must type the ~Osingle~O letter identifying the command
without any preceeding spaces. The two commands "A" and "D", respectively
to inspect/modify an "A" or a "D" register, must then be followed by a number (0
-7)
to identify which register. At this point the command has been identified
and is enacted.
~BThe commands "G", "L", "R" and "X" require no further input and are completed
at this point (note that only the "R", display register values, and
"X", clear breakpoint, commands cause a return to the monitor).
~BThe command "M" (modify memory) must be followed by a hexadecimal value
giving the address of the first location to be modified. It will then
display the address and value of each successive ~Obyte~O starting at that
point, and wait for input from the terminal after each such display.
At this point the user has the option of typing a new value in hexadecimal
or a non-hex character. In the first case the stored value is updated
to the value of the least significant 8 bits of the new value. In the
latter case, the stored value is not changed. If the last character
typed is a 'return' character, the modify command finishes, otherwise
the next location is diplayed and may be altered similarly.
(N.B. This is different from the UNIVAC monitor).
~BThe "E" command (examine memory) is followed by one or two hexadecimal
numbers, the first giving the start address of the area of store to
be displayed. The second is optional, and if specified gives the end address
for the display. If it is omitted, 16 bytes only will be displayed.
The start, and end, addresses are adjusted so that the display always
begins, and ends, on a 16 byte boundary.
The store is displayed in hexadecimal and character form
with 16 bytes to each line, preceeded by the address of the first
byte.
~BThe commands "An", "C", "Dn", "P", "U" each display the contents of a single r
egister
(respectively: 'A' register 'n', the status register, 'D' register 'n',
the program counter, and the user stack pointer as saved by the monitor).
The user may enter a new hexadecimal value to alter the existing one,
or may type any non-hex character to terminate the command without
changing the saved value.
~BThe "R" command displays, in a tabulated form, the contents of all
the internal registers that can individually be inspected by the above
commands, but does not allow any to be altered.
~BThe "G" (GO) command enters a program at the place specified by the
(saved) program counter, first setting the other registers to the values
saved by the executive. The "S" (Single step) command is similar, except
that only one instruction is obeyed, the new register values are saved and
the monitor in re-entered.
~BThe user may set a single ~Obreakpoint~O in the program by use of the "B"
instruction. This is followed by a hexadecimal value giving the address at
which it is to be placed. This causes the instruction at that point to be
saved, and replaced by a TRAP (15) instruction, which will cause an entry
to the monitor when it is obeyed. The breakpoint may be cleared by typing
an "X" instruction, replacing the original instruction. ~ONo~O checks are made
that a previous breakpoint has been cleared when another is set, and failure
to do this will result in a number of TRAP instructions being left in store,
that can only be cleared by use of the "M" (modify memory) instruction.
Similarly, it is the ~Ousers~O responsibility to ensure that the breakpoint
address is that of the start of an instruction, not the middle of one.
~BIn each case where a hexadecimal value is required, a suitable
value may be entered by typing any sequence of hexadecimal digits
followed by any non-hex character. The appropriate number of ~Oleast~O
significant digits only will be used as the new value.
~BAt any stage during the entry of a command, the user may abort (cancel)
it by typing CONTROL/X.
~S1~O3.2 Data Structures
~S1~O3.3 Special Notes
~S~O3.3.1 Store usage
~BThe following store locations are reserved by the monitor:~
~
~M%00000 - %01FFF (0 - 8K) ROM monitor code.
~N%80000 - %803FF User interrupt vectors.
~N  (These are a copy of those usually at zero).
~N%80180 - %801CB Saved register values.
~N%801CC - %80201 Workspace.
~N%80202 - %80205 Breakpoint address.
~N%80206 - %80207 Breakpoint instruction.
~N%80208 - %803FF Workspace and monitor stack area.
~BOnly the 6 bytes relating to the breakpoint setting are retained
from one monitor entry to the next, the other values being computed
on each entry.
~S2~O3.3.2 Device Initialisation
~BThe following devices are used by the monitor:~
~
~MThe console and host communication links.
~NA fixed or floppy disc.
~BThe console link is initialised whenever the monitor is entered, i.e.
on a reset or any interrupt causing entry to the monitor. The previous
settings cannot, and are not, restored. The host communications link
is initialised when the TRANSMIT sequence is entered, and the appropriate
disc is initialised at the start of a load operation. If no use is made
of these other devices through the monitor, the previous settings will,
therefor, remain valid.
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H               SYS501
~V9 -1
~F
@TITLE SYS50(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
BASIC BOOTSTRAP FACILITIES
@BOX 2.0
THIS MODULE CONTAINS
 - DECLARATIONS
 - THE MONITOR
 - ROM RESIDENT MONITOR FUNCTIONS
@BOX 3.0
END
@BOX 1.1
IMPORT LITERAL NUM.D.TYPES, DEFAULT.D;
IMPORT LITERAL ADDR MUSS.ROM.START, OLAY.ADDR;
ADDR [LOGICAL8] [NUM.D.TYPES] DISC.TYPES;
IMPORT LITERAL SUPPT.SIZE, SUPP.OPTIONS;
LOGICAL8 [SUPPT.SIZE] SUPP.MENU;
INTEGER [SUPP.OPTIONS] OPTION.ADDRS;
LOGICAL32 [8] D.REG, A.REG;
LOGICAL32 PC, STATUS, USP;
LOGICAL8 MAX.MEM.MODULES, EDC.STATUS;
INTEGER LAST.CH;
IMPORT VSTORE LOGICAL8 V.CONS.RX.BUFF;
IMPORT VSTORE LOGICAL8 V.CONS.TX.BUFF;
IMPORT VSTORE LOGICAL8 V.CONS.STAT;
IMPORT VSTORE LOGICAL8 V.HOST.RX.BUFF;
IMPORT VSTORE LOGICAL8 V.HOST.TX.BUFF;
IMPORT VSTORE LOGICAL8 V.HOST.STAT;
PSPEC GO ();
PSPEC SERVICE.ROUTINE ();
PSPEC FORMAT (INTEGER);
PSPEC INIT.DISC () / INTEGER;
PSPEC DISC.TRAN (LOGICAL32, LOGICAL32, LOGICAL, LOGICAL, LOGICAL) / INTEGER;
PSPEC READ.SYSTEM (INTEGER, INTEGER) / ADDR;
PSPEC INIT.IO.LINES (INTEGER);
PSPEC PUT.CONS (LOGICAL);
PSPEC PRINT (ADDR [LOGICAL8]);
PSPEC GET.CONS () / LOGICAL;
PSPEC GET.HOST () / LOGICAL;
PSPEC RESET ();
LABEL CANCEL.LINE;
MODULE (MONITOR, PUT.HEX.CONS, PRINTAP, PUT.HEX.CONSAP, GET.CONSAP, DISC.TRANAP)
;
@BOX 2.1
*CODE 1;
#SYS50/1
#SYS50/2
#SYS50/3
@BOX 3.1
*END
@END
@TITLE SYS50/1(1,10)
@COL 1S
@BOX 1.0
DECLARATIONS
@BOX 1.1
LITERAL / LOGICAL CONSOLE = 1, HOST = 2, RSET = 4;
LITERAL / LOGICAL8 BS = 8, LF = %A, CR = %D, SP = %20, XLIN = %18;
LITERAL / LOGICAL TX.READY = 4, RX.READY = 1;
LITERAL / LOGICAL8 CON=1, SEL=2, BSY=%10, BSY.CON=%11,
   H1S=1, H3S=4;
LITERAL / $LO8 SERROR=%80, MERROR=%40, SERROR.MERROR=%C0;
LITERAL / LOGICAL READ = 0, WRITE = 1;
PSPEC PUT.HEX.CONS(LOGICAL32,INTEGER);
*GLOBAL 5;
LOGICAL8 [%4000] D.BUFFER;
*GLOBAL 3;
ADDR MUSS.RAM.START, D.ADDR;
INTEGER GET.SW, GET.SIZE, NUM.DIG, I;
INTEGER DISC.TYPE;
INTEGER REG.NO, TEMP;
INTEGER LOAD.REPLY;
ADDR PUT.HEX.CONS PUT.HEX.CONSAP;
ADDR PRINT PRINTAP;
ADDR GET.CONS GETCONSAP;
ADDR DISC.TRAN DISC.TRANAP;
ADDR [LOGICAL8] V.ACT.STORE;
ADDR LOGICAL16 BPT;
LOGICAL16 B.INST;
*VTYPE LOGICAL8;
VSTORE V.EDC [32] %2801;
*VTYPE ADDR;
@END
@TITLE SYS50/2(1,10)
@COL 1S
@BOX 1.0
DATA VECTORS
@BOX 1.1
-> D.SKIP;
*CODE 2;
*GLOBAL 1;
DATAVEC WCH (LOGICAL8)
   4 6
END
DATAVEC COMM.NAME (LOGICAL8)
   "ABCDEGLMPRSUX" LF
END
DATAVEC HEX.DIG (LOGICAL8)
   "0123456789ABCDEF"
END
DATAVEC MON.ERR.MES (LOGICAL8)
   "< Error" LF
END
DATAVEC MENU.MESS (LOGICAL8)
   LF "0) Communicate to host"
   LF "1) MUSS V1"
   LF "2) MUSS V2"
   LF "3) Enter ROM MUSS."
   LF "4) Enter RAM MUSS."
   LF "5) Return to monitor."
   LF "6) Format disc"
   LF "7) Change disc type from "
END
DATAVEC EDC.E.MSG1 ($LO8)
  LF "ME: B"
END
DATAVEC EDC.E.MSG2 ($LO8)
  ", S"
END
LITERAL ROM.OPTIONS = 8;
*GLOBAL 3;
*CODE 1;
D.SKIP:
@END
@TITLE SYS50/3(1,10)
@COL 1S
@BOX 1.0
PROCEDURE DECLARATIONS
@BOX 1.1
PSPEC MONITOR (INTEGER);
PSPEC ENTER (ADDR);
PSPEC DISPLAY.REGS ();
PSPEC UPDATE.REG.VALUE (ADDR LOGICAL32);
PSPEC GET.HEX.CONS ()/LOGICAL32;
PSPEC TRANSMIT.CH (INTEGER)/INTEGER;
PSPEC GET.HEX ($IN)/LOGICAL32;
PSPEC GET.BLOCK (ADDR) / INTEGER;
PSPEC LOAD.STORE ();
PSPEC LOAD.DISC ();
PSPEC SET.DISC.TYPE ()/INTEGER;
#SYS50.2
#SYS50.3
#SYS50.4
#SYS50.5
#SYS50.7
#SYS50.9
#SYS50.13
#SYS50.14
#SYS50.15
#SYS50.16
#SYS50.17
#SYS50.18
@END
@TITLE SYS50.2(1,11)
@COL 12R
@COL 1S-10T-11R-2R-3R-4T-5T-6R-7N-9F
@COL 8R
@ROW 12-11
@ROW 5-8
@FLOW 1-10NO-11-2-3-4NEXT-5ALL DONE-6-7-2
@FLOW 10YES-12-2
@FLOW 4FOUND-8-7
@FLOW 5MORE-4
@BOX 1.0
MONITOR
@BOX 2.0
PUT PROMPT
@BOX 3.0
GET COMMAND NAME
@BOX 4.0
FOUND COMMAND IN LIST ?
@BOX 5.0
MORE NAMES IN LIST ?
@BOX 6.0
ERROR
@BOX 8.0
OBEY COMMAND
(A) CHANGE A REG
(B) SET BREAKPOINT
(C) SET PS
(D) CHANGE D REG
(E) EXAMINE STORE
(G) GO
(L) SELECT BOOT OPTIONS
(M) MODIFY STORE
(P) SET PC
(R) DISPLAY REGS
(V) SET USP
(X) CLEAR BREAKPOINT
@BOX 9.0
END
@BOX 10.0
RESET ENTRY
@BOX 11.0
CHECK FOR EDC INTERRUPT
PRINT TRAP.NO
@BOX 12.0
PRINT RESET
HEADING
@BOX 1.1
PROC MONITOR (TRAP.NO);
INTEGER COMMAND;
INTEGER NUM.COMMS;
SIZE (^COMM.NAME) => NUM.COMMS;
@BOX 2.1
XLIN.ENTRY:
XLIN.ENTRY => CANCEL.LINE;
IF LAST.CH /= LF THEN PUT.CONS (LF) FI
PUT.CONS ("-");
@BOX 3.1
GET.CONS () => COMMAND;
-1 => I;
@BOX 4.1
IF COMM.NAME [1 +> I] = COMMAND
@BOX 5.1
IF 1 + I < NUM.COMMS
@BOX 6.1
PRINT (^MON.ERR.MES);
@BOX 8.1
ALTERNATIVE I FROM
   #SYS50.2.1
   #SYS50.2.9
   #SYS50.2.4
   #SYS50.2.2
   #SYS50.2.6
   GO ();
   #SYS50.2.11
   #SYS50.2.7
   #SYS50.2.3
   DISPLAY.REGS ();
   #SYS50.2.8
   #SYS50.2.5
   #SYS50.2.10
   0;
END
@BOX 9.1
END
@BOX 10.1
IF TRAP.NO = 0
@BOX 11.1
INIT.IO.LINES (CONSOLE);
::#SYS50.2.12
PRINT (%"$LINTERRUPT ");
PUT.CONS (%30);
PUT.HEX.CONS (TRAP.NO, 8);
DISPLAY.REGS ();
@BOX 12.1
INIT.IO.LINES(RSET);
PRINT (%"$L MUSS Monitor [V7]");
INIT.DISC () => DISC.TYPE;
@END
@TITLE SYS50.2.1(1,10)
@COL 1S-3T-4R-6F
@COL 5R
@ROW 4-5
@FLOW 1-3VALID REG-4-6
@FLOW 3ILLEGAL-5-6
@BOX 1.0
CHANGE (SAVED) "A" REGISTER VALUES.
@BOX 3.0
IS REG.NO IN RANGE (0-7).
@BOX 4.0
ALTER ITS VALUE.
@BOX 5.0
ERROR
@BOX 6.0
END
@BOX 1.1
BEGIN :: CHANGE.A.REG;
@BOX 3.1
IF GET.CONS () - "0" => REG.NO < 0 OR REG.NO > 7
@BOX 4.1
UPDATE.REG.VALUE (^A.REG [REG.NO]);
@BOX 5.1
PRINT (^MON.ERR.MES);
@BOX 6.1
END
@END
@TITLE SYS50.2.2(1,10)
@COL 1S-3T-4R-6F
@COL 5R
@ROW 4-5
@FLOW 1-3VALID REG-4-6
@FLOW 3ILLEGAL-5-6
@BOX 1.0
CHANGE (SAVED) "D" REGISTER VALUE
@BOX 3.0
IS REG.NO IN RANGE (0-7).
@BOX 4.0
ALTER VALUE
@BOX 5.0
ERROR
@BOX 6.0
END
@BOX 1.1
BEGIN :: CHANGE.D.REG;
@BOX 3.1
IF GET.CONS () - "0" => REG.NO < 0 OR REG.NO > 7
@BOX 4.1
UPDATE.REG.VALUE (^D.REG [REG.NO]);
@BOX 5.1
PRINT (^MON.ERR.MES);
@BOX 6.1
END
@END
@TITLE SYS50.2.3(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
MODIFY VALUE OF (SAVED) PC
@BOX 2.0
UPDATE PC VALUE
@BOX 3.0
END
@BOX 1.1
BEGIN :: CHANGE.PC;
@BOX 2.1
PUT.CONS ("C");
UPDATE.REG.VALUE (^PC);
@BOX 3.1
END
@END
@TITLE SYS50.2.4(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
CHANGE STATUS REGISTER
@BOX 2.0
DISPLAY OLD CONTENTS
@BOX 3.0
END
@BOX 1.1
BEGIN :: CHANGE.STATUS;
@BOX 2.1
PRINT (%"$LStatus");
UPDATE.REG.VALUE (^STATUS);
@BOX 3.1
END
@END
@TITLE SYS50.2.5(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
CHANGE USER STACK POINTER (USP)
@BOX 2.0
DISPLAY OLD VALUE AND GET NEW VALUE.
@BOX 3.0
END
@BOX 1.1
BEGIN :: CHANGE.USP;
@BOX 2.1
PUT.CONS ("S"); PUT.CONS ("P");
UPDATE.REG.VALUE (^USP);
@BOX 3.1
END
@END
@TITLE SYS50.2.6(1,10)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
STORE EXAMINE
@BOX 2.0
GET, AND ADJUST, START AND END ADDRESSES
@BOX 3.0
PRINT STORE BY BYTES.
   SIXTEEN PER LINE, IN HEX AND CHAR FORM
@BOX 4.0
END
@BOX 1.1
BEGIN :: EXAMINE;
LOGICAL32 END.ADDR, BASE;
LOGICAL ST.ADDR;
@BOX 2.1
GET.HEX.CONS () => BASE;
IF LAST.CH = LF THEN
   1 => END.ADDR;
ELSE
   GET.HEX.CONS() - BASE => END.ADDR;
   PUT.CONS (LF);
FI
MAKE (LOGICAL8, 32768, BASE) => V.ACT.STORE;
0 => ST.ADDR;
@BOX 3.1
WHILE [ST.ADDR < END.ADDR] AND [V.CONS.STAT & RX.READY = 0] DO
   PUT.HEX.CONS (ST.ADDR + BASE, 32);
   FOR 16 DO
      PUT.HEX.CONS (V.ACT.STORE^ [ST.ADDR], 8);
      1 +> ST.ADDR;
      OD
   16 -> ST.ADDR;
   PUT.CONS (" ");
   FOR 16 DO
      V.ACT.STORE^ [ST.ADDR] & %7F => TEMP;
      1 +> ST.ADDR;
      IF TEMP < 32 OR TEMP = %7F THEN
         PUT.CONS (".")
      ELSE
         PUT.CONS (TEMP)
      FI
      OD
   PUT.CONS (LF);
   OD
@BOX 4.1
END
@END
@TITLE SYS50.2.7(1,10)
@COL 1S-2R-3R-4T-5R-6N-8T-7R
@COL 9F
@ROW 7-9
@FLOW 1-2-3-4NEW VALUE-5-6-8NEXT BYTE-7-3
@FLOW 4NO HEX VAL-6
@FLOW 8DONE-9
@BOX 1.0
MODIFY STORE
@BOX 2.0
GET START ADDRESS
@BOX 3.0
DISPLAY VALUE
@BOX 4.0
NEW VALUE GIVEN ?
@BOX 5.0
STORE NEW VALUE
@BOX 7.0
GO ON TO NEXT STORE LOCN.
@BOX 8.0
MODIFY DONE ?
(BY 'NEWLINE')
@BOX 9.0
END
@BOX 1.1
BEGIN :: MODIFY.STORE;
LOGICAL C.ADDR;
LOGICAL32 BASE;
@BOX 2.1
GET.HEX.CONS() => BASE;
MAKE (LOGICAL8, 32768, BASE) => V.ACT.STORE;
0 => C.ADDR;
@BOX 3.1
PUT.HEX.CONS (C.ADDR + BASE, 32);
PUT.HEX.CONS (V.ACT.STORE^ [C.ADDR], 8);
@BOX 4.1
GET.HEX.CONS() => TEMP;
IF NUM.DIG = 0
@BOX 5.1
TEMP => V.ACT.STORE^ [C.ADDR];
@BOX 7.1
PUT.CONS(LF);
1 +> C.ADDR;
@BOX 8.1
IF LAST.CH = LF
@BOX 9.1
END
@END
@TITLE SYS50.2.8(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
SINGLE STEP USER PROGRAM.
@BOX 2.0
SETSINGLE STEP MODE.
ENTER PROGRAM (COMES BACK THROUGH INT.ENTRY)
@BOX 3.0
END
@BOX 1.1
BEGIN :: STEP;
@BOX 2.1
%8000 !> STATUS;
GO ();
@BOX 3.1
END
@END
@TITLE SYS50.2.9(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
SET BREAKPOINT
@BOX 2.0
GET ADDRESS.
SAVE INSTRUCTION.
PLACE TRAP 15 INST
@BOX 3.0
END
@BOX 1.1
BEGIN :: SET.BREAKPOINT;
@BOX 2.1
MAKE (LOGICAL16, 0, GET.HEX.CONS () ) => BPT;
BPT^ => B.INST;
%4E4F => BPT^;
@BOX 3.1
END
@END
@TITLE SYS50.2.10(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
CLEAR BREAKPOINT
@BOX 2.0
REPLACE ORRIGINAL INSTRUCTION
@BOX 3.0
END
@BOX 1.1
BEGIN :: CLEAR.BREAKPOINT;
@BOX 2.1
B.INST => BPT^;
2 -> PC;
@BOX 3.1
END
@END
@TITLE SYS50.2.11(1,10)
@COL 1S-2N-6R-14T-10T-15R-12N-16F
@COL 9N-11R
@ROW 10-9
@FLOW 1-2-6-14NO-10DISC-15-12-2
@FLOW 14YES-9-11-12
@FLOW 10INVALID-2
@BOX 1.0
MENU SELECT
@BOX 6.0
OUTPUT MENU TABLES
@BOX 14.0
VALID ROM OPTIONS?
@BOX 10.0
VALID SUPPLEMENTARY OPTION?
@BOX 11.0
ENTER APROPRIATE MONITOR OPTION
0 - COMMUNICATE
1 - CALL V1
2 - CALL V2
3 - CALL ROM MUSS
4 - CALL RAM MUSS
5 - RECALL MONITOR
6 - FORMAT DISC
7 - SET DISC TYPE
@BOX 15.0
GET AND ENTER DISC OPTION
@BOX 16.0
END
@BOX 1.1
BEGIN :: MENU LOADER;
INTEGER CH, D.ADDR;
@BOX 6.1
PRINT (^MENU.MESS);
PRINT (DISC.TYPES [DISC.TYPE] );
PRINT (^SUPP.MENU);
@BOX 14.1
IF GET.CONS () - "0" => CH >= 0 < ROM.OPTIONS
@BOX 10.1
IF ROM.OPTIONS -> CH < 0 OR CH >= SUPP.OPTIONS
@BOX 11.1
ALTERNATIVE CH FROM
   #SYS50.2.11.1
   ENTER (READ.SYSTEM (1, DISC.TYPE));
   ENTER (READ.SYSTEM (2, DISC.TYPE));
   ENTER (MUSS.ROM.START);
   ENTER (MUSS.RAM.START);
   RESET();

   FORMAT (SET.DISC.TYPE ());
   SET.DISC.TYPE () => DISC.TYPE;
END
@BOX 15.1
OPTION.ADDRS [CH] => D.ADDR;
::SMS 32 +> D.ADDR;
DISC.TRAN (D.ADDR, OLAY.ADDR, DISC.TYPE, 16, READ);
^PRINT => PRINTAP;
^PUT.HEX.CONS => PUT.HEX.CONSAP;
^GET.CONS => GET.CONS.AP;
^DISC.TRAN => DISC.TRANAP;
SERVICE.ROUTINE ();
@BOX 16.1
OUT:
END
@END
@TITLE SYS50.2.11.1(1,10)
@COL 1S-4R-5T-6T-7T-8R-9R-10T-11T-12R-13T-14T-15R-16T-17T-20F
@COL 18R
@ROW 17-18
@FLOW 1-4-5Y-6Y-7Y-8-10Y-11Y-12-13Y-14Y-15-16OTHER TYPE-17INVALID-20
@FLOW 5N-10
@FLOW 6N-10
@FLOW 7-9-10
@FLOW 10N-5
@FLOW 11N-5
@FLOW 13N-5
@FLOW 14N-5
@FLOW 16FOUND-18-9
@FLOW 17MORE-16
@BOX 1.0
HOST
@BOX 4.0
CLEAR SWITCH
@BOX 5.0
ANY CONSOLE INPUT
@BOX 6.0
READY FOR HOST OUTPUT
@BOX 7.0
IS CH = $
@BOX 8.0
SET SWITCH
@BOX 9.0
TRANSMIT CH
@BOX 10.0
ANY HOST INPUT
@BOX 11.0
CONSOLE OUT READY ?
@BOX 12.0
CONS OUT CH
@BOX 13.0
IS THE CH = ^
@BOX 14.0
IS SWITCH SET
@BOX 15.0
GET LOAD TYPE
@BOX 16.0
THIS COMMAND ?
@BOX 17.0
MORE TYPES ?
@BOX 18.0
DO REQD LOAD.
@BOX 20.0
END
@BOX 1.1
BEGIN :: COMMS;
INTEGER I, CH, SW;
@BOX 4.1
INIT.IO.LINES (HOST);
0 => SW;
@BOX 5.1
IF V.CONS.STAT & RX.READY = 0
@BOX 6.1
IF V.HOST.STAT & TX.READY = 0
@BOX 7.1
IF V.CONS.RX.BUFF & %7F => CH /= "$$"
@BOX 8.1
1 +> SW;
@BOX 9.1
CH => V.HOST.TX.BUFF;
@BOX 10.1
IF V.HOST.STAT & RX.READY = 0
@BOX 11.1
IF V.CONS.STAT & TX.READY = 0
@BOX 12.1
V.HOST.RX.BUFF & %7F => CH => V.CONS.TX.BUFF;
@BOX 13.1
IF CH /= "^"
@BOX 14.1
IF SW = 0
@BOX 15.1
GET.HOST () => CH;
-1 => I;
@BOX 16.1
IF CH = WCH [1 +> I]
@BOX 17.1
IF I < SIZE (^WCH)
@BOX 18.1
WHILE GET.HOST () /= "^" DO OD
ALTERNATIVE I FROM
   LOAD.STORE ();
   LOAD.DISC ();
END
TRANSMIT.CH (LOAD.REPLY);
CR => CH;
@BOX 20.1
END
@END
@TITLE SYS50.2.12(1,10)
@COL 1S-2R-3F
@COL7C-4R-5T-6R
@FLOW 1-2-3
@FLOW 4-5NO-3
@FLOW 5YES-6
@ROW 2-4
@ROW 3-6
@BOX 1.0
CHECK FOR EDC INTERRUPT
@BOX 2.0
IF EDC ERROR ->
   "EDC.ERROR"
@BOX 3.0
END
@BOX 4.0
EDC.ERROR
PRINT ERROR
 MESSAGE
@BOX 5.0
MULTIPLE ERROR?
@BOX 6.0
CONTINUE SYSTEM
@BOX 1.1
BEGIN
  INTEGER I,J;
LOGICAL8 STAT;
@BOX 2.1
-1=>I;
WHILE 1+>I=<MAX.MEM.MODULES DO
  IF V.EDC [I*8 => J] =>STAT & SERROR.MERROR /= 0, ->EDC.ERROR;
OD;
@BOX 3.1
END
@BOX 4.1
EDC.ERROR:
  IF J=0 THEN EDC.STATUS=>STAT FI;
  0   => V.EDC [J];
  PRINT(^EDC.E.MSG1);
  PUT.CONS("0"+I);
  PRINT(^EDC.E.MSG2);
  PUT.HEX.CONS (STAT,8);
  PUT.CONS(LF);
  %C0 => V.EDC [J];
@BOX 5.1
IF STAT & MERROR /= 0
@BOX 6.1
GO();
@END
@TITLE SYS50.3(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
ENTER
@BOX 2.0
JUMP TO GIVEN ADDR
@BOX 3.0
END
@BOX 1.1
PROC ENTER (START);
@BOX 2.1
%2700 => STATUS;
%80400 => A.REG [7];
START => PC;
GO ();
@BOX 3.1
END
@END
@TITLE SYS50.4(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
PRINT (SAVED) REGISTERS.
@BOX 2.0
PRINT -
   'D' REGISTERS (1-8)
   'A' REGISTERS (1-8)
   PROGRAM COUNTER
   STACK POINTER
   STATUS REGISTER
@BOX 3.0
END
@BOX 1.1
PROC DISPLAY.REGS;
@BOX 2.1
PRINT (%"$LD-REG: ");
FOR I < 8 DO
   PUT.HEX.CONS (D.REG [I], 32);
   OD
PRINT (%"$LA-REG: ");
FOR I < 8 DO
   PUT.HEX.CONS (A.REG [I], 32);
   OD
PRINT (%"$LPC = "); PUT.HEX.CONS (PC, 32);
PRINT (%", USP = "); PUT.HEX.CONS (USP, 32);
PRINT (%", Status = "); PUT.HEX.CONS (STATUS, 16);
@BOX 3.1
END
@END
@TITLE SYS50.5(1,10)
@COL 1S-2R-3T-4R-5F
@FLOW 1-2-3NEW VAL-4-5
@FLOW 3LOOK ONLY-5
@BOX 1.0
ALTER ANY SAVED REGISTER VALUE
@BOX 2.0
PRINT OLD VALUE
@BOX 3.0
NEW VALUE GIVEN
@BOX 4.0
SAVE NEW VALUE
@BOX 5.0
ND
@BOX 1.1
PROC UPDATE.REG.VALUE (REG);
LOGICAL32 TEMP;
@BOX 2.1
PRINT (%" = ");
PUT.HEX.CONS (REG^, 32);
@BOX 3.1
GET.HEX.CONS () => TEMP;
IF NUM.DIG = 0
@BOX 4.1
TEMP => REG^;
@BOX 5.1
END
@END
@TITLE SYS50.7(1,10)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
PRINT VARIABLE SIZED HEX NUMBER TO CONSOLE
@BOX 2.0
LOOP, FROM MS 4 BITS O LS 4 BITS.
THEN PRINT SPACE
@BOX 3.0
END
@BOX 1.1
PROC PUT.HEX.CONS (VALUE, BIT.LEN);
INTEGER TEMP;
@BOX 2.1
WHILE 4 -> BIT.LEN >= 0 DO
   VALUE ->> BIT.LEN & %F => TEMP;
   PUT.CONS (HEX.DIG [TEMP]);
OD
PUT.CONS (" ");
@BOX 3.1
END
@END
@TITLE SYS50.9(1,10)
@COL 1S-2R-3T-9N-4R-5R
@COL 6T-7R
@COL 8F
@ROW 9-6
@ROW 4-7
@ROW 5-8
@FLOW 1-2-3ZERO TO NINE-9-4-5-3
@FLOW 3NOT DIGIT-6A TO F-7-5
@FLOW 6-8
@BOX 1.0
INPUT HEX VALUE
@BOX 2.0
CLEAR RUNNING TOTAL
@BOX 3.0
IS CHAR "0" TO "9"
@BOX 4.0
CALCULATE ACTUAL VALUE.
@BOX 5.0
ADD TO RUNNING TOTAL
@BOX 6.0
IS CHAR "A" TO "F"
@BOX 7.0
CALCULATE ACTUAL VALUE
@BOX 8.0
END
@BOX 1.1
PROC GET.HEX.CONS;
INTEGER CH;
@BOX 2.1
0 => NUM.DIG => GET.HEX.CONS;
@BOX 3.1
IF GET.CONS() => CH < "0" OR CH > "9"
@BOX 4.1
"0" -> CH;
@BOX 5.1
1 +> NUM.DIG;
GET.HEX.CONS <<- 4 + CH => GET.HEX.CONS;
@BOX 6.1
IF CH < "A" OR CH > "F"
@BOX 7.1
"A" - 10 -> CH;
@BOX 8.1
END
@END
@TITLE SYS50.13(1,10)

@COL 1S-3R-4R-5R-6R-7F
@FLOW 1-3-4-5-6-7
@BOX 1.0
TRANSMIT CH TO HOST MACHINE
@BOX 3.0
WAIT UNTIL READY TO TRANSMIT
@BOX 4.0
WRITE CH TO COMMS BUFFER
@BOX 5.0
WAIT UNTIL ECHO RECEIVED
@BOX 6.0
RETURN ECHOED CHARACTER
DELAY LOOP
@BOX 7.0
END
@BOX 1.1
PROC TRANSMIT.CH (CH);
@BOX 3.1
WHILE V.HOST.STAT & TX.READY = 0 DO OD
@BOX 4.1
CH => V.HOST.TX.BUFF;
@BOX 5.1
WHILE V.HOST.STAT & RX.READY = 0 DO OD
@BOX 6.1
V.HOST.RX.BUFF => TRANSMIT.CH;
FOR 500 DO OD
@BOX 7.1
END
@END
@TITLE SYS50.14(1,10)

@COL 1S-2R-3T-4T-5R-6R-8T-11F
@FLOW 1-2-3N-4Y-5
@FLOW 4N-3
@FLOW 3Y-6-8N-11
@FLOW 8Y-3
@BOX 1.0
GET HEX WORD
@BOX 2.0
SET COUNT
CLEAR RESULT
@BOX 3.0
IS THE NEXT CH A HEX CH
@BOX 4.0
IS IT "^"
@BOX 5.0
EXIT TWO LEVELS
@BOX 6.0
RESULT <<- 4 + NEWCH
@BOX 8.0
COUNT > 0?
@BOX 11.0
END
@BOX 1.1
PROC GET.HEX (N);
INTEGER COUNT, CH;
@BOX 2.1
N<<-3 => COUNT;
0 => GET.HEX;
@BOX 3.1
IF GET.HOST () => CH >= "A" =< "P"
@BOX 4.1
IF CH /= "^"
@BOX 5.1
1 => GET.SW;
EXIT;
@BOX 6.1
"A" -> CH;
GET.HEX <<- 4 + CH => GET.HEX;
@BOX 8.1
IF 4 -> COUNT > 0
@BOX 11.1
END
@END
@TITLE SYS50.15(1,11)
@COL 1S-2R-3R-7R-8T-9R-11R-12R-10F
@FLOW 1-2-3-7-8N-7
@FLOW 8Y-9-11-12-10
@BOX 1.0
GET BLOCK FROM HOST MACHINE
@BOX 2.0
SET PTR TO BUFFER
@BOX 3.0
ALLOCATE BUFFER
@BOX 7.0
GET HEX BYTE
@BOX 8.0
END OF BLOCK
@BOX 9.0
CALCULATE BLOCK SIZE
@BOX 10.0
END
@BOX 11.0
VALIDATE CHECKSUM
@BOX 12.0
FLAG IF CHECKSUM INVALID
@BOX 1.1
PROC GET.BLOCK (STORE.ADDR);
ADDR [LOGICAL8] BUFFER;
ADDR PTR, I;
LOGICAL32 LONGWORD, CHECKSUM, SUM;
0 => GET.SW => GET.BLOCK;
@BOX 2.1
-1 => PTR;
@BOX 3.1
MAKE (LOGICAL8, %4000, STORE.ADDR) => BUFFER;
@BOX 7.1
GET.HEX (1) => BUFFER^ [1 +> PTR];
@BOX 8.1
IF GET.SW = 0
@BOX 9.1
1 -> PTR + 256 / 256 => GET.SIZE;
@BOX 10.1
END
@BOX 11.1
GET.HEX (4) => CHECKSUM;
0 => SUM;
::GEM D.ADDR => SUM;
-1 => I;
WHILE 1 +> I =< PTR DO
   BUFFER^ [I] +> SUM;
OD
@BOX 12.1
IF CHECKSUM /= SUM THEN
   "A" => LOAD.REPLY;
   PRINT (%"$L*** Checksum fail ***$L");
   -1 => GET.BLOCK;
ELSE
   "@" => LOAD.REPLY;
FI
@END
@TITLE SYS50.16(1,10)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
LOAD BINARY TO STORE
@BOX 2.0
@BOX 3.0
GET ADDRESS AND
NOTE IN MUSS.RAM.START
LOAD DATA TO STORE
@BOX 4.0
END
@BOX 1.1
PROC LOAD.STORE;
@BOX 2.1
@BOX 3.1
GET.BLOCK (GET.HEX (4) => MUSS.RAM.START);
@BOX 4.1
END
@END
@TITLE SYS50.17(1,10)
@COL 1S-4R-2T-3R-9F
@FLOW 1-4-2YES-3-9
@FLOW 2NO-9
@BOX 1.0
LOAD BLOCK TO DISC (SPECIFIED SECTOR SIZE)
@BOX 2.0
GET BLOCK FROM HOST
SUCCESSFUL?
@BOX 3.0
DISC TRANSFER
@BOX 4.0
GET DISC ADDRESS
@BOX 9.0
END
@BOX 1.1
PROC LOAD.DISC;
ADDR C.ADDR;
@BOX 2.1
IF GET.BLOCK (C.ADDR) < 0
@BOX 3.1
WHILE GET.SIZE > 4 DO
   DISC.TRAN (D.ADDR, C.ADDR, DISC.TYPE, 4, WRITE);
   4 -> GET.SIZE;
   4 +> D.ADDR;
   1024 +> C.ADDR;
OD
IF GETSIZE /= 0 THEN
  DISC.TRAN (D.ADDR, C.ADDR, DISC.TYPE, GET.SIZE, WRITE);
FI
@BOX 4.1
GET.HEX (4) => D.ADDR;
BYTE (^D.BUFFER) => C.ADDR;
@BOX 9.1
END
@END
@TITLE SYS50.18(1,10)
@COL 1S-2N-3R-4T-5N
@COL 6F
@ROW 5-6
@FLOW 1-2-3-4ILLEGAL-5-2
@FLOW 4OK-6
@BOX 1.0
CHANGE DISC TYPE
@BOX 3.0
PRINT MENU
@BOX 4.0
IS NEW TYPE OK ?
@BOX 6.0
END
@BOX 1.1
PROC SET.DISC.TYPE;
@BOX 3.1
PRINT (%"$LDisc type$L");
FOR I < NUM.D.TYPES DO
   PUT.CONS (I + "0");
   PRINT (%" for ");
   PRINT (DISC.TYPES [I]);
OD
@BOX 4.1
IF GET.CONS () - "0" => SET.DISC.TYPE >= 0 < NUM.D.TYPES
@BOX 6.1
END
@END

