.MCALL .MODULE .MODULE SIPP,VERSION=17,COMMENT=,AUDIT=YES ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. .SBTTL RT-11 SAVE IMAGE PATCH PROGRAM .ENABL LC,GBL .LIST MEB .SBTTL Macro definitions and invocations ;+ ; System macros ;- .MCALL .RCTRL, .GTIM, .SRESE .MCALL .CSISP, .DSTAT, .CSIGE .MCALL .GVAL, .SETTO, .GTLIN .MCALL .EXIT, .TTYOU, .PRINT .MCALL .READW, .WRITW, .CLOSE .MCALL .SCCA, .WAIT, .LOOKU .MCALL .PURGE, .SPFUN, .TTINR .MCALL .TTYIN, .SFDAT, .ENTER .MCALL .FETCH, .HERR, .SERR .MCALL .RENAM, .GFSTA .IIF NDF PASS,PASS=0 PASS=PASS+1 .IF EQ PASS-1 .LIBRARY "SRC:SYSTEM" .MCALL .OTBDF .OVRDF .SAVDF .MCALL .VTBDF .OTBDF .OVRDF .SAVDF .VTBDF .ENDC; EQ PASS-1 .LIBRARY "SRC:ULBMAC" .MCALL .ERR MSGLST ERRMSG MSGEND ;FOLLOWING lifted from ULBMAC until we fix it for compat with ;SYSTEM.MLB .MACRO .DSECT N=0,GLOBAL=NO ..TEMP = N ..GLBL = 0 .IIF IDN ,, ..GLBL = 1 .ENDM .DSECT .MCALL DS ;+ ; Calls the GETLIN routine which parses the string and ; dispatches if necessary. RET1 is the routine to return ; to if a CTRL/Z is typed in response to the prompt. RET2 ; is the routine to return to if a ;S, error, backslash, ; slash, or an un-intentional CTRL/C is typed. If every- ; thing is in order the normal return will be after RET2. ;- .MACRO STRING PRMPT,STOR,RET1,RET2,LOC MOV #PRMPT,R0 ;Point to prompt string MOV #STOR,R4 ;Point to store words CALL GETLIN ;Get the string .IF NB LOC: .WORD RET .IFF .WORD RET1 ;Return for CTRL/Z .ENDC ;NB .WORD RET2 ;Re-prompt .ENDM STRING .SBTTL Program symbolic definitions ;+ ; System communication area ;- STKPTR = 42 ;Location of the initial stack pointer JSW = 44 ;Location of the job status word HLIMIT = 50 ;Location of the program's high limit ERROR = 52 ;Location for error code USERRB = 53 ;User error byte SUCCS$ = 1 ;Success WARN$ = 2 ;Warning ERROR$ = 4 ;Error FATAL$ = 10 ;Fatal UNCON$ = 20 ;Unconditional ;+ ; General offsets and assignments ;- CHAN0 = 0 ;Output channel (log file) CHAN3 = 3 ;First input channel DSSIZ = 6 ;Offset to dstatus block for device size MAXCHN = 10 ;Number of channels IBSIZ = 24 ;Size of an information block in bytes SPACE = 40 ;Space (ASCII) PRCENT = 45 ;Percent sign (ASCII) DOT = 56 ;Dot (ASCII) USRLOC = 266 ;High limit of program BLREAD = 400 ;Block size for basic read OLREAD = 403 ;Block size plus 3 to read overlay info ;+ ; Offsets to the start of an information block. ;- AD0 = 2 ;Low order accumulated address AD1 = 4 ;High order accumulated address SEG = 6 ;Segment number LOBAS = 10 ;Low order base HGBAS = 12 ;High order base LOOFF = 14 ;Low order offset HGOFF = 16 ;High order offset OLDW = 20 ;Old contents NEWW = 22 ;New contents ;+ ; .DSTATUS bits ;- VERSIZ = 400 ;.DSTATUS multisized volume ;+ ; Offsets into window definition blocks (WDB). ;- W.NID = 0 ;Window ID W.NAPR = 1 ;Address page register (APR) W.NBAS = 2 ;Virtual base address W.NSIZ = 4 ;Size of the window (32. word) W.NRID = 6 ;Region ID W.NOFF = 10 ;Offset into region (32. word) W.NLEN = 12 ;Length of window to be mapped (32. word) W.NSTS = 14 ;Window status word W.NLGH = 16 ;Size of window definition block ;+ ; System and program status bits ; ; Bit definitions for valid switches. SWITWD ;- SLASHA = 1 ;Open non-file structure SLASHC = 2 ;Prompt for a checksum SLASHD = 4 ;Print the checksum SLASHL = 10 ;Create log. No modification ; Bits 4, 5, and 6 are reserved SLASHO = 200 ;File is overlaid ; Bits 8 to 15 are reserved ;+ ; Flag bits for FLGWRD: ;- SLASBK = 1 ;When set, slashs and backslashes are legal ODD = 2 ;Set when operation is on odd byte BYTE = 4 ;Byte operation if set, word if cleared ZERO = 10 ;When set character was typed in GTLIN routine UPARO = 20 ;Set open previous location without new header VIRT = 40 ;Set if current segment is virtual ; Bits 6, 7, and 8 are reserved ASCII = 1000 ;Ascii mode deposit ASC = 2000 ;Display in Ascii if set RAD50 = 4000 ;Rad50 mode display if set RAD = 10000 ;Display in Ascii if set ; Bits 13 and 14 are reserved DISP = 100000 ;Display bit for links ;+ ; The following are flag bits for FLGWD2. ;- EXTFIL = 1 ;Set file or root is extended EXTSEG = 2 ;Set segment is extended ABORT = 4 ;Set on hard error SEMIS = 10 ;Semi-colon S has been typed if set MOD = 20 ;Indicates SIPP in modify mode CHNG = 40 ;Set if there are changes for MODIFY routine TWOWRD = 100 ;If set convrt 2 octal wds to make 1 ASCII num SRCH = 200 ;Set when search is in progress WDB = 400 ;Set when modifying Window Definition BLock ;Bit 9 is reserved RDB = 2000 ;Set when modifying the regin definition block UOV = 4000 ;Set when extending the last /O overlay size RNDUP = 10000 ;Set rounds up virtual word count for tbl ent. LSOVLY = 20000 ;Set to check for new limit of ovly is bigger ; than previous larger limit HDR = 40000 ;Set to store header in buffer ;Bit 15 is reserved OVLBIT = 1000 ;Overlay file bit in JSW ;+ ; Flag bit for SIPP JSW ;- JS.NTG = 10 ;Non-terminating .GTLIN (print prompts ;when using CCL) ;+ ; RMON offset to test if we're using the correct version ;- S.VER = 276 ;Offset from RMON to monitor version number ; Directory entry definitions E.STAT =: 0 ;File status E.DATE =: 14 ;File creation date PROT =: 100000 ;Protected file .SBTTL PSECT definition ;+ ; This puts the psects in order ;- .PSECT IMPURE ;Program variables .PSECT MAIN ;Which brings us to the main body .PSECT MESS ;Messages .PSECT .LIBP. ;Following error PSECTS must be before PATCH .PSECT .LIBD. .PSECT .LIBC. .PSECT .LIBO. OVR .SBTTL START - Initialization .ASECT . = JSW .WORD 20020 ;Make SIPP re-enterable and turn off SL .PSECT MAIN ;Which brings us to the main body ;+ ; Command line buffer. ;- CMDBUF::.BLKB 100. ;Input command string buffer .EVEN ;+ ; SIPP starts here. This routine sets up the stack, and top of core. ;- BR START ;Re-enter point SIPP:: MOV SP,SVSP ;Save the stack pointer START:: MOV SVSP,SP ;Reset the stack .GVAL #EMTBLK,#S.VER ;Get the system version number CMPB R0,#5 ;Running on at least V5.x? BGE 10$ ;Yes... ;+ ;ERROR .ERR #ERAR,#EMX,LEVEL=F,RETURN=YES ;- CLR R0 ;Hard exit .EXIT ;Get out quick 10$: SWAB R0 ;R0 = version in <15:08> ; release in <07:00> MOV R0,RTVR ;Save version/release info CLR STATWD ;Make sure the CTRL/C status word is cleared MOV ,R0 ;Point to end of program MOV R0,R5 ;Save it .SETTOP CMP R5,R0 ;Was the return the same as high limit? BEQ 1$ ;Yes, no error ;+ ;ERROR .ERR #ERAR,#EMF,LEVEL=F,RETURN=YES ;Insufficient memory ;- .EXIT ;Exit from program ;+ ; The following disables CTRL/C inhibit, resets CTRL/O, gets date and time of ; day (to force date rollover. ;- 1$: .SCCA #EMTBLK,#0 ;Allow CTRL/C .RCTRLO ;Make sure the console can print .GTIM #EMTBLK,#EMTBLK+2 ;Do this to tweek time. Then throw away .SBTTL ASKFIL - Receive command string ;+ ; ASKFIL ; .CSISPC is used to get the command string. If the first byte of the command ; buffer is 0, the version is printed and a new command is requested (return ; to ASKFIL). The limit (LMT+2) is examined to see if the following operation ; is to a device or file. .DSTATUS is issued to see if a valid device was ; requested. The input and output filespecs are compared for illegal match. ;- .ENABL LSB ASKFIL::.SRESET ;Close files, and release handlers CLR R5 ;R5 = FLGWRD. Initialize. MOV #CMDBUF,R1 ;Now put the start of command buffer in R1 .CSISPC #BUFFER,#DEFLTX,#0,R1 ;Switch info will be on the stack from ;now on until stack is reset TSTB @R1 ;If zero, print version BNE 1$ ;Non - zero .PRINT #SIPPV ;Print version number BR ASKFIL ;and prompt for a filename 1$: MOV #BUFFER,R2 ;Get the start of file descriptor block MOV R2,R4 ;Save the start of output filespec ADD #36,R2 ;Point to input filespec TST @R2 ;Was an input specified - check for device BEQ 4$ ;No, error MOV #INFIL,R1 ;Point to start of stored input filespec MOV R1,R3 ;Save the start of the input filespec MOV (R2)+,(R1)+ ;Store input device name TST @R2 ;Was a filename specified? BNE 2$ ;Yes, go store the input filespec CLR 4(R2) ;No, clear the default extension 2$: MOV (R2)+,(R1)+ ;Store input filename name MOV (R2)+,(R1)+ ;Store input filename name MOV @R2,(R1)+ ;Store input extension MOV R4,R2 ;Assume patch file specified .REPT 4 ;Store name for possible error MOV (R2)+,(R1)+ .ENDR MOV #DSTA,R1 ;R1 --> 4 word status area for .DSTATUS .DSTAT R1,R3 ;Test for existence of input device BCS 5$ ;If set, device not in device table - error ; BCC ;Device in table TST @R1 ;Random-access device BPL 5$ ;No, sequential-access device 3$: CMP (R4)+,(R3)+ ;Are the filespecs the same? BNE SWTCHK ;No, set up switches CMP R3,#INFIL+10 ;Has the whole filespec been compared? BLO 3$ ;No, keep checking 4$: JMP ILCMD 5$: CLR 2(R3) ;Clear second word to only display device name ;+ ;ERROR .ERR #ERAR,#EMA,LEVEL=F,RETURN=NO,FILE=R3 ;Invalid device ;- .DSABL LSB .SBTTL SWTCHK - Get switches ;+ ; SWTCHK ; The stack is examined for any switches. If a valid switch is specified, the ; corresponding switch bit is set in R5 (SWITWD). See SWITCH (switch table in ; the IMPURE area. ; ;Input: R5 = SWITWD ; ;Output:R5 = SWITWD ;- .ENABL LSB SWTCHK::MOV (SP)+,R0 ;Are there any switches? BEQ PARSE ;If no, continue 1$: MOVB @SP,ERROPT ;Save option switch incase of error MOV (SP)+,R3 ;Get the switch BMI 4$ ;Minus means option with switch. Error MOV #SWITCH,R2 ;R2 points to beginning of switch table BIC #^C<177>,R3 ;Make ascii CMP R3,#141 ;Is switch lowercase? BLO 2$ ;No, find switch in table CMP R3,#172 ;Is switch lowercase? BHI 2$ ;No, find switch in table BIC #40,R3 ;Yes, make it uppercase ;DBF 2$: TST @R2 ;Zero is the end of table BEQ 4$ ;Zero is end of table. No switch. Error CMP R3,(R2)+ ;Is this the switch? BEQ 3$ ;Yes, set the bit and continue checking TST (R2)+ ;Point to next switch BR 2$ ;and compare it 3$: BIS (R2)+,R5 ;Set the appropriate flag DEC R0 ;One less switch to worry about BNE 1$ ;If not done check next switch BIT #,R5 ;Was /C specified? BEQ PARSE ;No, skip legal combination check BIT #,R5 ;Yes, was /D also specified? BEQ PARSE ;No, we're ok ;+ ;ERROR .ERR #ERAR,#EME,LEVEL=E,RETURN=NO ;Invalid option combination 4$: BICB #200,ERROPT ;Strip high bit .ERR #ERAR,#EMD,LEVEL=E,RETURN=NO,ASCII=#ERROPT ;Invalid option ;- .DSABL LSB .SBTTL PARSE - Parse command string ;+ ; PARSE ; .CSIGEN is issued to get the switches, fetch the handler, .LOOKUP and/or ; .ENTER specified files. After .CSIGEN is issued .SETTOP gets the highest ; available location for SIPP. All available space (from end of loaded ; handlers to the location returned by SETTOP) is set up for the link list ; buffer space. CTRL/C is inhibited, and invalid channels are checked to make ; sure they are not open (channels 0 and 3 are the only valid ones). ; ; Output: ; R5 = FLGWRD ; Stack contains switches ;- .ENABL LSB PARSE:: MOV R5,SWITWD ;Store SWITWD .PURGE #1 ;Make sure channel not in use .FETCH ,#INFIL ;Fetch handler for input file BCC 10$ ;If no error, branch ;+ ;ERROR .ERR #ERAR,#EMA,LEVEL=F,RETURN=NO,FILE=#INFIL ;- 10$: MOV R0,R4 ;R4 = Address of first free word ; above handler BIT #,SWITWD ;Was /L specified? BNE 40$ ;Yes, don't check protection .SERR ;Make monitor errors soft MOV #INFIL,R3 ;R3 -> Input file dblk TST 2(R3) ;Is it non-filestructured reference? BEQ 40$ ;Yep, so allow access CMP RTVR,#<5*400+5> ;Running under V5.5? BHIS 15$ ;Yep, use new programmed request MOV #RNAMBK,R1 ;R1 -> Rename dblk .REPT 4 MOV (R3)+,(R1)+ .ENDR MOV #INFIL,R3 ;R3 -> Input file dblk .REPT 4 MOV (R3)+,(R1)+ .ENDR MOV #INFIL,R3 ;R3 -> Input file spec MOV #14$,EMTBLK+10 ;Set routine address for USR call-back .RENAM #EMTBLK,#1,#RNAMBK+1 ;Try rename with USR call-back BCS 16$ ;Errors, check them out ; (they map the same as with .GFSTA) MOV DESTAT,R0 ;Get the directory entry status BR 30$ ; and check it ; USR Call-back code, returns to USR which ; returns to code following rename 14$: MOV E.STAT-E.DATE(R1),DESTAT ;Save directory entry status RETURN 15$: .GFSTA #EMTBLK,#1,R3 ;Get file status word 16$: ROL -(SP) ;Save the carry MOV R0,-(SP) ;*C* and R0 as well .HERR ;*C* Monitor handles errors again MOV (SP)+,R0 ;*C* Restore R0 ROR (SP)+ ; and the carry BCC 30$ ;Got the file status... TSTB @#ERROR ;Didn't get it, monitor error? BPL 20$ ;Nope, check for request error ;+ ;ERROR .ERR #ERAR,#EMY,LEVEL=F,RETURN=NO,FILE=R3 ;'Directory I/O error' 20$: .ERR #ERAR,#EM8,LEVEL=F,RETURN=NO,FILE=R3 ;'File not found' 30$: BIT #PROT,R0 ;Is file protected? BEQ 40$ ;Nope... .ERR #ERAR,#EM1,LEVEL=F,RETURN=NO,FILE=R3 ;'Protected file already exists' ;- 40$: MOV #CMDBUF,R1 ;Point to start of command buffer MOV #OUTFIL,R3 ;Point to file name in case protection error .CSIGEN R4,#DEFLTX,R1 BCS COMERR ;If set error occured. Find out what it was ;+ ; The next section of this routine sets up the start of the free core area ; (patch buffer) for information blocks. COUNT will contain the actual number ; of information blocks available for use. R0 is now pointing at the start of ; available space after the handler. ;- CLR @R0 ;Set to zero. End of list CLR BUFBEG ;Start of link list buffer MOV R0,BUFEND ;Save the start of free core ADD #3720,R0 ;100. modifications * 20. bytes / change MOV R0,-(SP) ;Put imaginary limit on stack .GVAL #EMTBLK,#USRLOC ;Get start address of USR TST -(R0) ;Point just below USR CMP R0,(SP)+ ;Should the USR swap? BHI 50$ ;No, set limit below USR MOV #-2,R0 ;Yes, grab all available core 50$: .SETTOP SUB BUFEND,R0 ;Calculate the actual free core space CLR R1 ;Clear high order for divide MOV #IBSIZ,R3 ;Divide by 24 bytes CALL DIV ;Divide for count MOV R0,COUNT ;Store the number of available info. blocks .SCCA #EMTBLK,#STATWD ;Inhibit CTRL/C ;+ ; Check for valid filespecs. The output [0] and input [3] channels are ; ignored. ;- CLR R0 ;Set R0 = 0 to check for open channels 60$: INC R0 ;Increment channel count CMP #CHAN3,R0 ;Is this channel 3? BEQ 60$ ;Yes, skip the check EMT 374 ;Is this channel open? (.WAIT) BCC ILCMD ;Yes, it shouldn't, error CMP R0,#MAXCHN ;Have all appropriate channels been checked? BLO 60$ ;No, check next channel .DSABL LSB .SBTTL GETBLK - Get block size ;+ ; GETBLK ; Get maximum block length of file if file-structured or maximum number of ; accessible blocks on a device if non file-structured (does not include ; manufactures or software bad block table). If a device, the /A switch will ; be set in SWITWD (at this time R5). ; ; Output: ; SWITWD ; Stack contains switches ;- .ENABL LSB GETBLK::.LOOKUP #EMTBLK,#1,#INFIL BCC 1$ ;No error TST @#ERROR ;What error was returned? BEQ ILCMD ;Channel already open - Invalid command BR 7$ ;Else file not found 1$: MOV #MAXADD,R3 ;Point to maximum address store words MOV R0,@R3 ;Set up to convert block number into an addr. BNE 4$ ;Opening up a file BIS #,SWITWD ;Set /A flag for non filestructure MOV #DSTA,R1 ;No, point to .DSTATUS block 2$: BIT #VERSIZ,@R1 ;Multisized volume? BEQ 3$ ;Branch if not multi-sized .SPFUN #EMTBLK,#1,#373,R3,#1,#0,#0 BCC 4$ ;SPFUN was successful ;+ ;ERROR .ERR #ERAR,#EMN,LEVEL=F,RETURN=NO ;Size function failed ;- ;+ ; At this point the block size is determined. Now use the block size to ; calculate the maximum address. This address is the first address outside ; of the program or device. ;- 3$: MOV DSSIZ(R1),@R3 ;Get the device size 4$: MOV (R3)+,MAXBLK ;Store the maximum block length CALL DPMULT ;Go convert .PURGE #1 BR READ0 COMERR: TSTB @#ERROR ;Is it an invalid command? BNE 5$ ;No ;+ ;ERROR ILCMD: .ERR #ERAR,#EM9,LEVEL=E,RETURN=NO ;Invalid command 5$: CMPB #2,@#ERROR ;Protected file? BNE 6$ ;No FPROT: .PURGE #1 ;Make sure channel is purged .ERR #ERAR,#EM1,LEVEL=F,RETURN=NO,FILE=R3 ;Protected file already exists 6$: CMPB #3,@#ERROR ;.ENTER failure? BNE 7$ ;No .ERR #ERAR,#EM4,LEVEL=F,RETURN=NO,FILE=#OUTFIL ;Device full 7$: .ERR #ERAR,#EM8,LEVEL=F,RETURN=NO,FILE=#INFIL ;File not found ;- .DSABL LSB .SBTTL READ0 - Get file characteristics ;+ ; READ0 ; This routine reads in block 0 of the file to determine if the file is ; overlaid or not. If it is overlaid, the overlay bit (/O) is set in SWITWD ; and the start of the overlay table is taken from location 64. SIPP then ; dispatches to query for a segment number. If non-overlaid, SIPP dispatches ; to query for a base address. ; ;Input: SWITWD ; ;Note: Upon returning from BLKZRO, R2 points to the start of BUFFER which ; contains block 0 of the file. ;- .ENABL LSB READ0:: MOV #PNUM1,R2 ;Point to first location to clear MOV #7,R4 ;Clear 7 words (count) 1$: CLR (R2)+ ;Initialize store word DEC R4 ;Decrement count BNE 1$ ;If not equal, not done MOV #SEGNUM,R2 ;Point to SEGNUM CLR (R2)+ ;Clear two ... CLR (R2)+ ;... words of SEGNUM CLR (R2)+ ;Clear two ... CLR (R2)+ ;... words of SEGLOW CLR ADRESS ;Initialize address CLR ADRES1 ;and carry word CLR FLGWRD ;Initialize flag word CLR FLGWD2 ;Initialize second flag word CALL BLKZRO ;Read in block 0 BIT #,SWITWD ;If set don't test for overlaid file BEQ 2$ ;Process overlayes BR ASKBAS ;and ask for base address 2$: BIT #OVLBIT,JSW(R2) ;Is the file overlaid? BEQ ASKBAS ;No go ask for base address BIS #,SWITWD ;Set bit for overlaid file MOV SV.SEG(R2),VTBL ;Save the start of the virtual overlay table MOV SV.OVR(R2),OVLTBL;Save the start of the overlay table BNE 3$ ;If equal, the file is not V04 format ;+ ;ERROR .ERR #ERAR,#EMI,LEVEL=E,RETURN=NO ;Not V4 overlaid file ;- 3$: CALL BLKZRO ;Reread block 0 + 3 words for overlaid file .DSABL LSB .SBTTL ASKSEG - Routine to request segment number ;+ ; ASKSEG ; This routine prompts for a segment number if the overlay bit in the JSW is ; set. If the first byte in the command buffer is 0 (type , or 0) ; SIPP assumes the operations to follow are to the root. User input is stored ; in SEGNUM. If a segment number is specified, the overlay table is read into ; BUFFER and SEGLOW and SEGENT are stored. If CTRL/Z (or uparrow Z) is typed ; SIPP modifies the file, and closes it. ; ; Output: ; SEGNUM = user specified segment number ; SEGLOW = starting address of specified segment ; SEGENT = start address of current segment in the overlay table ;- .ENABL LSB ASKSEG::BIC #,FLGWD2 ;Clear extension flag CLR SEGLOW ;Clear low order segment start address CLR SEGLOW+2 ;as well as the high order word CLR SVCA ;Initialize location for in core address BIC #,FLGWRD ;Make sure error is rtn if / or \ typed STRING SEGPMT,SEGNUM,CHECK,ASKSEG TST 2(R4) ;Test second segment store word BEQ 2$ ;If equal no error ;+ ;ERROR 1$: .ERR #ERAR,#EMG,LEVEL=E,RETURN=YES ;Invalid segment number ;- BR ASKSEG ;Prompt for new segment number 2$: MOV @R4,SNUM ;Was a segment number specified? BEQ ASKBAS ;No, SEGNUM is zero. Get base address CMP (R4)+,#2000 ;Legal segment number? BHIS 1$ ;No, error TST (R4)+ ;R4 --> the segment start word (SEGLOW) CALL SEGFND ;Look for valid segment BCS 1$ ;If c-bit set error MOV R0,SEGENT ;Store address of start of segments' entries MOV #SVCA,R4 ;Point to store word for incore address CALL VRTFND ;Get the in core address .DSABL LSB .SBTTL ASKBAS - Base address routine ;+ ; ASKBAS ; This routine prompts for the base address. If a CTRL/Z (or uparrow Z) is ; typed in response to the prompt, SIPP will return to the ASKSEG routine ; (if overlaid) or CHECK (if non-overlaid). If a segment was previously ; specified, the in core address of the start of the segment is stored in ; SVCA. ; ; Specifying an odd base or ('/', '\' characters) is illegal at this point. ;- .ENABL LSB ASKBAS::BIC #,FLGWRD ;Make sure error is returned if / or \ typed STRING BASPMT,BASADR,TSTZRT,ASKBAS BIT #1,@R4 ;Is the specified base odd? BEQ ASKOFF ;No, even ;+ ;ERROR .ERR #ERAR,#EMJ,LEVEL=E,RETURN=YES ;Odd base address ;- BR ASKBAS ;Prompt for new base .SBTTL ASKOFF - Offset routine ;+ ; ASKOFF ; This routine prompts for the offset to the previously specified base. If a ; CTRL/Z (or uparrow Z) is typed in response to the prompt, SIPP returns to ; the ASKBAS routine. If a number is typed, it will be converted and stored ; in OFFSET. SIPP then prints the appropriate header depending on the file ; being displayed. ; ; Specifying a odd base or ('/', '\' characters) is illegal at this point. ;- ASKOFF::BIS #,FLGWRD ;Make it legal to type / or \ BIC #,FLGWRD ;Clean up FLGWRD STRING OFFPMT,OFFSET,ASKBAS,ASKOFF HEADER::BIT #,FLGWRD ;Backing up? BNE PRIOUT ;Yes, don't print the header BIS #,FLGWD2 ;Set bit to incl header in nxt GTLIN pmt .SBTTL PRIOUT - Print out routine ;+ ; PRIOUT ; This routine adds SEGLOW, BASE, and OFFSET to create an accumulated address ; (stored in ADRESS). Pointers are set up to search the information block ; to determine if that location was previously modified. Information ; corresponding to the printed header are then displayed. If a link block ; exists for the specified location, the new contents is displayed as the old. ; If no information block exists, the old contents is displayed and a block ; created. Depending on the input from the GTLIN routine SIPP increments or ; decrements ADRESS and returns to the start of this routine. A value t ; at GTLIN is stored in the information block as the new contents. Execution ; continues to loop here until a legal control character is typed (ie-CTRL/Z ; returns to ASKOFF). ;- .ENABL LSB PRIOUT::MOV #ADRESS,R5 ;R5 --> Start of accumulated address CLR @R5 ;Initialize the lower order word of ADRE CLR 2(R5) ;Clear high address MOV #SEGLOW,R4 ;Point to stored address of start of segment 1$: CALL DPADD ;Add in stored value to accumulated address CMP (R4)+,(R4)+ ;Point to the next stored value CMP R4,#OFFSET ;Have all the values been added in? BLOS 1$ ;No, add in next TST SEGNUM ;Looking at a segment? BEQ 3$ ;No, skip addjustment for in core address SUB SVCA,@R5 ;Yes, subtract in core address from ADRESS SBC 2(R5) ;Subtract the carry from the high order word SUB #2,@R5 ;Count first word of segment for low boundary SBC 2(R5) ;Adjust high order if needed CMP 2(R5),SEGLOW+2 ;Cmp high order words for boundary viola BHI 2$ ;No violation continue operation BLO 11$ ;Error CMP @R5,SEGLOW ;Compare low order words BLO 11$ ;Error 2$: ADD #2,@R5 ;Add back to skip first word of segment ADC 2(R5) ;Add carry to high order word 3$: CMP 2(R5),MAXADD+2 ;Check high order for high limit of program BHI 12$ ;Error - end of file BLO 4$ ;Ok, go open that location and display CMP @R5,MAXADD ;Within maximum address bounds? BHIS 12$ ;No, error - end of file 4$: BIC #,FLGWRD ;Clear flag bits BIC #,FLGWD2 ;Clear flags in FLGWD BIT #1,@R5 ;Odd address? BEQ 5$ ;No, skip the round off BIS #,FLGWRD ;Set odd byte flags DEC @R5 ;Must open word 5$: MOV 2(R5),R1 ;R1 = high order accumulated address CMP #777,R1 ;Check for high order limit violation BHI 6$ ;High order falls into valid range BLO 14$ ;Beyond valid range - error CMP #177000,@R5 ;Equal - check for low order range BLOS 14$ ;Violation of limit - error 6$: MOV @R5,R0 ;R0 = low order accumulated address CALL FNDLOC ;Read in block and point to offset to bl BIS #,FLGWRD ;Set for display mode CALL LINK ;Search for link MOV #SEGNUM,R4 ;R4--> start of storage list MOV R2,-(SP) ;Save R2 for later LINK call CALL DSPLAY ;Print out information BIC #,FLGWD2 ;Make sure header gets printed once MOVB #SPACE,(R2)+ ;Must have space to center display MOVB #200,@R2 ;Put 200 in buffer to prevent MOV #ADRESS,R5 ;R5 --> accumulated address STRING CMDBUF,NWORD,ASKOFF,HEADER BIC #,FLGWRD ;Clear to modify BIT #,FLGWRD ;If 0, no modification BNE 7$ ;Go modify the location TST (SP)+ ;No modification, clean up stack BR 10$ ;Update the offset to get the next location 7$: BIT #,SWITWD ;Slash A? BNE 8$ ;Yes, skip limit check CALL LIMIT ;Extend the file or segment limit if nec BCS 15$ ;If set fatal error occured 8$: MOV (SP)+,R2 ;Restore register saved before DSPLAY routine CALL LINK ;Go create or modify the information block BCS 15$ ;If set no more buffer room ask for offset BIT #,FLGWRD ;Was a special character typed? BEQ 10$ ;No, bump the offset and address CALL SUBOP ;Yes, subtract the offset and address 9$: BR PRIOUT ;and return to the start of this routine 10$: MOV #OFFSET,R5 ;Set up pointer to OFFSET for increment MOV #DPADD,OPWRD ;Set up for add CALL WDBTOP ;Increment by word or byte BR 9$ ;and search for next link ;+ ;ERROR 11$: .ERR #ERAR,#EMK,LEVEL=E,RETURN=YES ;Below segment boundary BR 15$ ;Prompt for new offset 12$: BIT #,FLGWD2 ;Informational error? BNE 13$ ;Yes EOF: .ERR #ERAR,#EMR,LEVEL=E,RETURN=YES ;End of file BR 15$ ;Prompt for new offset 13$: .ERR #ERAR,#EMW,LEVEL=I,RETURN=YES ;End of file BR 15$ ;Go back to OFFSET prompt 14$: .ERR #ERAR,#EMP,LEVEL=E,RETURN=YES ;Invalid address ;- 15$: JMP ASKOFF ;Prompt for new offset .DSABL LSB .SBTTL CHECK - Checksum generation ;+ ; CHECK ; This routine generates a checksum for all previous changes. Two values are ; used to calculate the checksum. They are the accumulated address and the ; new contents of that address. It is possible to have an information block ; with the same new and old contents. This can happen if the user modifies ; the contents of a location (creating a information block), then modifying ; that location again to restore that location back to its original contents. ; In this case, this change is not figured into the checksum. After all ; changes have been figured into the checksum, FLGWRD is examined for a '/D' ; or '/C' switch. '/D' prints out the calculated checksum, '/C' prompts for ; a user entered checksum. In the case of the '/C' switch, the user's ; checksum is compared against the calculated checksum. If they differ an ; error message is returned and program control is returned to ASKSEG (if the ; file is overlaid) or ASKBAS (if the file is non-overlaid). ;- .ENABL LSB CHECK:: BIC #,FLGWRD MOV BUFBEG,R5 ;Get the start of information block area BEQ 6$ ;If zero, no modifications CLR R1 ;Clear for CRC checksum value 1$: CMP OLDW(R5),NEWW(R5) ;Any changes? BEQ 2$ ;No, skip checksum calculation and get nxt blk MOV AD0(R5),R0 ;Put low order accumulated address in R0 CALL CHKSM ;Update the checksum value MOV AD1(R5),R0 ;Put high order accumulated address in R0 CALL CHKSM ;Update the checksum value MOV NEWW(R5),R0 ;Put new contents of accumulated address in R0 CALL CHKSM ;Update the checksum value BIS #,FLGWD2 ;Set bit if there are actual modifications 2$: MOV @R5,R5 ;Get next information block (if 0 end of list) BNE 1$ ;and continue calculating the checksum BIT #,FLGWD2 ;If not set BEQ 6$ ;No modifications give msg and ret to START MOV R1,CHKNUM ;Save the checksum BIT #,SWITWD ;Print the checksum? BEQ 3$ ;No, check if checksum prompt is needed .PRINT #CHKRET ;Print "Checksum = " message MOV #CMDBUF,R2 ;Point to buffer for later output MOV R1,PNUM1 ;Set up to print the checksum CALL GETDGT ;Convert to ASCII and store for output CLRB @R2 ;Clear the end of buffer to print .PRINT #CMDBUF ;Print output from buffer. LOG on next check 3$: BIT #,SWITWD ;Prompt for a checksum? BEQ LOG ;No (also, if /D, branch) MOV #CMDBUF,R1 ;R1 points to beginning of command buffer MOV #JSW,R2 ;Get JSW BIS #JS.NTG,(R2) ;Set non-terminating .GTLIN bit .GTLIN R1,#CHKPMT ;Prompt for a checksum MOV #JSW,R2 ;Get JSW BIC #JS.NTG,(R2) ;Clear non-terminating .GTLIN bit MOV #CTCHAL,R4 ;Point to 2 words of catch all CALL ASCOCT ;Convert ascii input to octal number BCS 4$ ;Bad input give checksum error ; BCC ;Input ok TST 2(R4) ;High order should not be used BNE 4$ ;Give error if not equal CMP CHKNUM,@R4 ;Are the checksums the same? BEQ LOG ;Yes, checksum is correct ;+ ;ERROR 4$: .ERR #ERAR,#EM3,LEVEL=E,RETURN=YES ;Checksum error ;- TSTB SWITWD ;No, overlaid file? BMI 5$ ;Yes, print error and return to ASKSEG JMP ASKBAS ;Go back and ask for base 5$: JMP ASKSEG ;Go back and ask for segment 6$: BIT #,SWITWD ;See if /C was requested BEQ 7$ ;No, don't prompt for checksum .GTLIN #CMDBUF,#CHKPMT ;Get checksum, but ignore it ;+ ;ERROR 7$: .ERR #ERAR,#EMH,LEVEL=I,RETURN=NO ;I-No modifications made ;- .DSABL LSB .SBTTL LOG - Create a log file ;+ ; LOG ; If requested, this routine creates a log file. First, the "RUN SIPP" ; message and "filespec/C" are stored in BUFFER. /C is always stored in the ; log file. If /A was used to open the file it is also stored in the log ; file. The filespec is created by converting the stored RAD50 words ; (INFIL) to ASCII. ; ; All registers may be used upon entering this routine ;- .ENABL LSB LOG:: .WAIT #CHAN0 ;Should a log file be created? BCC 1$ ;Yes, create it JMP MODIFY ;No, MODIFY the file 1$: CLR BLKNUM ;Set relative block number to zero MOV #BUFFER,R2 ;R2 --> start of I/O buffer CLR R3 ;R3 = byte count MOV #RSIPP,R1 ;R1 --> RUN SIPP message MOV #UPZ,R4 ;R4 --> end of message CALL STORE ;Go store the message into BUFFER MOV #INFIL,R0 ;R0 -->RAD50 input filespec MOV #R50CVT,R1 ;R1 -->Start of ASCII text buffer MOV R1,R4 ;Save starting pointer for return from FNASC CALL $FNASC ;Convert RAD50 filespec to ASCII CLRB @R1 ;Make it look like the end 2$: MOVB (R4)+,(R2)+ ;Move the the ASCII filespec into BUFFER INC R3 ;Increment byte count TSTB @R4 ;End of ASCII filespec? BNE 2$ ;No - continue BIT #,SWITWD ;Does the patch involve /A? BEQ 3$ ;No, skip over installation of /A MOVB #'/,(R2)+ ;Move in /A to end filespec MOVB #'A,(R2)+ ; " " " ADD #2,R3 ;Increment count by 2 3$: MOVB #'/,(R2)+ ;Move a /C into buffer MOVB #'C,(R2)+ ; " " MOVB #15,(R2)+ ;Move in a carriage return MOVB #12,(R2)+ ;Move in a line feed ADD #4,R3 ;Increment count by 4 MOV BUFBEG,R5 ;R5 --> start of link list MOV R5,R4 ;R4 --> start of link list 4$: ADD #LOBAS,R4 ;R4 --> low base within current link block ;+ ; Move the segment number,base and offset into the BUFFER ;- TSTB SWITWD ;Overlaid file? BPL 5$ ;No, don't print segment SUB #2,R4 ;Point to segment number instead of base CALL MOVSEG ;Convert segment number and store in buffer 5$: CALL MOVBOF ;Move in 2 words of base 6$: CALL MOVBOF ;Move in 2 words of offset ;+ ; Test for double CTRL/C. If two CTRL/C's have been typed, restore the file ; back to its original state. Else, move the new contents of the address into ; BUFFER. ;- 7$: TST STATWD ;Are there any double CTRL/C's floating around BPL 8$ ;No,continue CALL CHKC ;Find out if typed intentionally? BCC 8$ ;Typed in error ; BCS ;CTRL/C was intentional .PURGE #0 ;Purge output file .EXIT 8$: MOV NEWW(R5),R1 ;R1 = New contents within link block CALL OCTASC ;Convert OCTAL to ASCII and store 9$: MOV R5,R0 ;Make current pointer previous pointer 10$: MOV @R5,R5 ;Get next block BEQ 14$ ;If 0 end of list - print ^Y CMP OLDW(R5),NEWW(R5) ;Are there any changes BEQ 10$ ;No, skip it MOV #ADRESS+2,R4 ;Point to second word of address storage MOV AD1(R0),@R4 ;Store the high order MOV AD0(R0),-(R4) ;and the low order words ADD #2,@R4 ;Make it next word location ADC 2(R4) ;and add the carry if any CMP AD0(R5),(R4)+ ;Low order address the same? BNE 11$ ;No, print ^Z and continue checking CMP AD1(R5),@R4 ;High order address the same? BEQ 7$ ;Yes, just store new contents ;+ ;This routine inserts ^Z ;- 11$: MOV R5,R4 ;R4 --> start of link list ADD #SEG,R4 ;R4 --> segment word within current link CALL BAKUP1 ;Print one CTRL/Z to strart with ADD #SEG,R0 ;Point to segment word of previous link block CMP @R4,(R0)+ ;Are the segments the same? BEQ 12$ ;Yes, check the base CALL BAKUP2 ;No, print two CTRL/Z's SUB #SEG,R4 ;Set up R4 for new segment insert BR 4$ ;and store segment 12$: ADD #2,R4 ;R4 -->low order base of current link block CMP @R4,(R0)+ ;Are previous and current words the same BNE 13$ ;No, print one CTRL/Z start storing new CMP 2(R4),(R0)+ ;Are the second words the same? BNE 13$ ;Go print ^Z and start with base ADD #4,R4 ;Point to new offset BR 6$ ;and store it 13$: CALL BAKUP1 ;Print a CTRL/Z BR 5$ ;and start storing from the current base ;+ ; This routine stores CTRL/Y, the checksum, then CTRL/C. After storing, the ; BUFFER is written out, channels are closed and SIPP returns to CSI mode. ;- 14$: MOV #UPY,R1 ;R1 -->^Y message MOV #UPC,R4 ;Set up end of message CALL STORE ;Go store into BUFFER MOV CHKNUM,R1 ;R1 = checksum CALL OCTASC ;Convert OCTAL to ASCII and store MOV #UPC,R1 ;R1 --> ^C message MOV #CRLF,R4 ;Set up end of message CALL STORE ;Go store into BUFFER CALL WRITIT ;Write it out to the log file ; BR MODIFY .DSABL LSB .SBTTL MODIFY - Modify the file ;+ ; MODIFY ; This routine inserts the changes specified in the information blocks. First, ; the ABORT bit is examined. If set, a read error had occured at some ; point in the previous change sessions. An error message is printed and the ; file is closed. No modifications are made. ; If the '/L' switch was typed, the files are not modified. During the ; changing phase, the CTRL/C flag is tested. If the user types double ; control C, the REVERS routine is called to reverse the modifications (insert ; the old contents into the locations instead of the new contents). When the ; modifications have been made the channels are closed and control returns to ; START. ;- .ENABL LSB MODIFY::BIT #,FLGWD2 ;Was a hard error previously encountered? BNE 4$ ;Yes, don't modify locations - error BIT #,SWITWD ;Was a /L specified? BNE CLOSE ;Yes, don't modify file. MOV BUFBEG,R5 ;Point to start of link list 1$: TST STATWD ;Are there any double CTRL/C's floating around BPL 2$ ;No, continue CALL CHKC ;Check for intentional CTRL/C BCC 2$ ;No, disregard the CTRL/C and continue ; BCS ;CTRL/C was intentional JMP REVERS ;Restore the old contents and exit 2$: MOV AD0(R5),R0 ;Get low order accumulated address MOV AD1(R5),R1 ;and high order accumulated address CALL FNDLOC ;Read in block and point to offset to blk BIS #,FLGWD2 ;Set modify flag BIT #,FLGWD2 ;Did a hard error occur? BNE 4$ ;Yes, give error and reverse changes MOV NEWW(R5),@R2 ;Put new contents into location in R2 MOV @R5,R5 ;Get next link block and modify BNE 1$ ;If zero, end of list else make changes ;+ ; Write the contents of the last BUFFER. All others are written out in the ; READ routine. ;- .WRITW #EMTBLK,#3,#BUFFER,#256.,BLKNUM BCC CLOSE ;Write was successful ;+ ;ERROR .ERR #ERAR,#EMO,LEVEL=F,RETURN=NO,FILE=#INFIL ;Output error ;- CLOSE: .CLOSE #CHAN3 ;Close the patch(ed) file BCS 4$ .CLOSE #CHAN0 ;Close log file BIT #,SWITWD ;Was a /L specified? BNE 3$ ;Yes, don't modify file date. .SFDAT #EMTBLK,#CHAN3,#INFIL ;Update the file date 3$: JMP START ;See if any other files need modification ;+ ;ERROR 4$: .ERR #ERAR,#EMQ,LEVEL=F,RETURN=YES ;Patch aborted, no modifications made ;- JMP REVERS ;Restore the old contents .DSABL LSB .SBTTL LINK - Link list routine ;+ ; LINK ; This routine is entered twice from the PRIOUT routine. The first time it's ; entered the DISP (display) flag is set. The list of information blocks are ; examined to see if the displayed location exists. If it does the new ; contents word is returned (for display) as the old contents. If not the ; actual old contents will be displayed. No modifications are made at this ; time. ; ; If the user specifies that a modification is necessary, this routine is ; entered a second time. This time the DISP bit in FLGWRD is cleared. The ; list is searched again for an existing information block. If one exists, ; the requested value is inserted as the new value. If the block does not ; exist a new block is created (12 octal words) at the start of available ; core. Each block is link to each other in ascending order by the accumlated ; address (segment number, base address, and offset). The following is the ; format of an information block (for each requested modification there is a ; created information block): ; ; +------------------------------+ ; + Pointer to next information + ; + block (last block in list if + ; + zero) + ; +------------------------------+ ; + Low order accumulated address+ ; +------------------------------+ ; +High order accumulated address+ ; +------------------------------+ ; + Segment number + ; +------------------------------+ ; + Low order base + ; +------------------------------+ ; + High order base + ; +------------------------------+ ; + Low order offset + ; +------------------------------+ ; + High order offset + ; +------------------------------+ ; + Old contents + ; +------------------------------+ ; + New contents + ; +------------------------------+ ; ;Input: R2--> Specified location in BLKBUF (block + offset in that block) ; R4--> New value for specified location (second pass) ; BUFBEG--> Start of link list ; BUFEND--> Next available memory space for link list ; FLGWRD - DISP bit set (first pass) ; DISP bit cleared (second pass) ; ; CALL LINK ;Link list routine ; ;Output:First pass - ; R0 = Value of new contents in information block ; ; Second pass - ; BUFBEG--> Start of link list (may have changed) ; BUFEND--> Next available memory space for link list (if a block was ; created. ; C=1 means failure on second pass ;- .ENABL LSB LINK:: MOV #BUFBEG,R3 ;R3 points to previous information block MOV @R3,CURENT ;Save the current pointer MOV @R3,R5 ;R5--> sliding pointer BEQ 4$ ;If equal, no information blocks in memory 1$: CMP ADRES1,AD1(R5) ;Compare computed address with stored address BHI 2$ ;Input > adjust pointers and check next block BLO 3$ ;Input < either display or construct new block CMP ADRESS,AD0(R5) ;Compare low computed adr. with stored adr. BHI 2$ ;Input > adjust pointers and check next block BLO 3$ ;Input < either display or construct new block TST FLGWRD ;Yes, are we in display mode? BPL 6$ ;No, we're modifying MOV NEWW(R5),R0 ;Yes, get previous new word for display BR 12$ ;and return 2$: MOV R5,R3 ;Make current pointer the previous pointer MOV @R5,R5 ;Point to next information block BEQ 4$ ;If equal go build a new block MOV R5,CURENT ;Make it current BR 1$ ;and continue link search 3$: TST FLGWRD ;Are we in display mode? BMI 11$ ;Yes, just display the contents of the buffer CALL ALLOC ;No, allocate space for modification BCS 14$ ;Branch if error occured ; BCC ;No error MOV CURENT,@R5 ;Put current ptr in link word of new block BR 5$ ;and create the rest of the new block 4$: TST FLGWRD ;Are we in display mode? BMI 11$ ;Yes, just display contents of the buffer CALL ALLOC ;Allocate space in free core BCS 14$ ;If set no more buffer room. Return 5$: BIS #,FLGWRD ;Set DISP flg - specify newly created info blk MOV R5,@R3 ;Put link to new block in loc. of previous ptr MOV ADRESS,AD0(R5) ;Move in low order accumulated address MOV ADRES1,AD1(R5) ;move in high order accumulated address 6$: MOV SEGNUM,SEG(R5) ;Relative block MOV #BASADR,R0 ;Set up to create a new information block MOV R5,R1 ;R1--> start of information block ADD #10,R1 ;Start with the low order base 7$: MOV (R0)+,(R1)+ ;Create block CMP R0,#NWORD ;Are we done? BLO 7$ ;No, move in next word MOV @R2,OLDW(R5) ;Old contents BIC #1,LOOFF(R5) ;Make sure stored as modified word TST FLGWRD ;Test for set.Display mode? BPL 8$ ;Modify exist info. blk don't force old contnt BIC #,FLGWRD ;Make sure bit cleared for next operation MOV @R2,NEWW(R5) ;Initially str old contents in new incase byte 8$: BIT #,FLGWRD ;Are we modifying a byte? BNE 9$ ;Yes, byte operation MOV @R4,NEWW(R5) ;New contents BR 14$ ;Link block complete - return 9$: BIT #,FLGWRD ;Is it the odd byte? BNE 10$ ;Yes MOVB @R4,NEWW(R5) ;Change the even byte BR 14$ ;and return 10$: SWAB NEWW(R5) ;Switch bytes incase block is already created MOVB @R4,NEWW(R5) ;Move the byte in SWAB NEWW(R5) ;and switch the bytes back BR 14$ ;Return 11$: MOV @R2,R0 ;Get old contents into R0 for display 12$: BIT #,FLGWRD ;Are we looking at an odd byte? BEQ 13$ ;No, check for even byte SWAB R0 ;Yes, swap the bytes for now 13$: BIT #,FLGWRD ;Even byte operation? BEQ 14$ ;No, just return BIC #177400,R0 ;Yes, byte in low order in either byte case 14$: RETURN .DSABL LSB .SBTTL GETLIN - Input retrieval and interpreter ;+ ; GETLIN ; Upon recieving input from the GTLIN EMT (R1 points to start of command ; string) certain characters (listed in CHART) are checked. If the first ; character matches the special character list execution is dispatched to the ; appropriate routine (DTABLE--> dispatch table). If there is no match, the ; routine tests for legal numerical characters. If input is legal, execution ; returns to the first instruction after the call. Illegal input produces an ; error message and execution is returned to the routine specified in the ; second argument in the call routine. Typing a carriage return or line feed ; (ZERO bit clear) immediately return execution back to the caller. ; ; This routine is called by a: ; ; CALL GETLIN ;GET THE STRING ; .WORD x ;RETURN FROM CTRL/Z ; .WORD y ;RE-PROMPT RETURN ADDRESS ; ; Note: the legal numerical input limit is: ; Highest number -- 177777400 ; ; Two words (double precision) -- 777 ;High order word ; 177000 ;Low order word ;- .ENABL LSB GETLIN::MOV R0,-(SP) ;Save R0 .RCTRLO ;Reset control O MOV (SP)+,R0 ;Restore R0 MOV #CMDBUF,R1 ;R1 points to the beg. of command buffer MOV #JSW,R2 ;Get JSW BIS #JS.NTG,(R2) ;Set non-terminating .GTLIN bit .GTLIN R1,R0 ;Get the string MOV #JSW,R2 ;Get JSW BIC #JS.NTG,(R2) ;Clear non-terminating .GTLIN bit GETCHR::BIC #,FLGWRD ;Clear inititially for no input TST STATWD ;Was double CTRL/C typed? BPL 1$ ;No, just return with C-bit clear CALL CHKC ;Yes, check if it was intentional BCS XIT ;If set, CTRL/C was intentional 1$: CALL ASCOCT ;Get input and convert it BCS 4$ ;Check for special character ; BCC ;No special characters - process number CMP R4,#NWORD ;Prompting for new contents? BNE 3$ ;No, check for address limit BIT #,FLGWRD ;Location opened in byte mode? BEQ 2$ ;No, check high order word - must be 1 word BIT #177400,@R4 ;Byte. Any strange char. making it a wor BNE 7$ ;Yes, illegal input 2$: TST 2(R4) ;If recieving new contents is high order BNE 7$ ;Yes, illegal input. If ok, fall through 3$: BIT #177000,2(R4) ;Was the number too large? BNE 7$ ;Yes, error NRMRET: ADD #4,(SP) ;Zero, end of string. Return to the RETURN 4$: CLR R0 ;Initialize R4 5$: CMPB R3,CHART(R0) ;Is the character a special character? BNE 6$ ;No ASL R0 ;Yes, make word offset JMP @DTABLE(R0) ;and go to that routine 6$: INC R0 ;Point to the next special char. in char CMP #ENDCRT-CHART,R0;Have we reached the end of the chart? BHIS 5$ ;No, keep processing ;+ ;ERROR 7$: .ERR #ERAR,#EMB,LEVEL=E,RETURN=YES ;Invalid input ;- BR RTURN ;Return to second argument .DSABL LSB ;+ ; Table of special input characters ;- CHART: .BYTE 3 ;Control-C .BYTE 31 ;Control-Y .BYTE 32 ;Control-Z .BYTE 57 ;Slash (word) .BYTE 72 ;Colon .BYTE 73 ;Semi-colon .BYTE 134 ;Back-slash (byte) ENDCRT: .BYTE 136 ;Uparrow .EVEN .SBTTL Control or uparrow dispatch routines ;+ ; We are dispatched to one of these routines if a special character is a ; control or uparrow character. The actual dispatching is done through DTABLE ; ; If a CTRL/C or uparrow C is typed, program control is dispatched to the ; following routine. This routine makes sure that these characters were ; typed intentionally. If not, control is returned to whatever the prompt ; was when the character was typed. If so, control is returned to the monitor ; and no modifications are made. ;- .ENABL LSB CTRLC:: CALL CHKC ;Check for intentional CTRL/C BCC RTURN ;Unintentional CTRL/C. Continue XIT: MOVB #,@#USERRB ;Set error fatal to abort indirect file .EXIT ;This will terminate the program ;+ ; If CTRL/Y or uparrow is typed, we exit from the query routines and ; control goes directly to the modification and close routines. ;- CTRLY:: TST (SP)+ ;We won't be returning 2$: JMP CHECK ;Just modify file and exit ;+ ; This routine is entered when a circumflex has been typed. The routine ; checks for valid combinations and dispatches to the appropriate routine. ;- UPAROW::BIT #,FLGWRD ;Was a number typed? BNE 3$ ;Yes see if n^ construction TSTB @R1 ;Anything following circumflex? BEQ 3$ ;No, must be ^ TSTB 1(R1) ;Was something typed after supposed CTRL/char BNE 5$ ;Yes, error CMPB #'Z,@R1 ;^Z? BEQ CTRLZ ;Yes CMPB #'z,@R1 ;^Z (lower case)? BEQ CTRLZ ;Yes CMPB #'Y,@R1 ;^Y? BEQ CTRLY ;Yes CMPB #'y,@R1 ;^Y (lower case)? BEQ CTRLY ;Yes CMPB #'C,@R1 ;^C? BEQ CTRLC ;Yes CMPB #'c,@R1 ;^C (lower case)? BEQ CTRLC ;Yes BR 5$ ;If got this far error 3$: TST FLGWRD ;Can only use nnn^ when modifying.Display on? BPL 5$ ;No, error TSTB @R1 ;Anything typed after circumflex? BNE 5$ ;Yes, error CMP #NWORD,R4 ;Was circumflex typed in response to new cont. BNE 5$ ;No, error BIS #,FLGWRD ;Set bit to show we want previous location BIT #,FLGWRD ;Was a number typed? BNE NRMRET ;and make a normal return to modify 4$: CALL SUBOP ;Double precision decrement OFFSET and ADRESS RTURN: ADD #2,@SP ;Rtn to the specified routine in sec. arg. CTRLZ:: MOV @(SP),@SP ;Return to RETURN ;+ ; This routine determines what should be done when a control or uparrow Z is ; typed in response to the BASE prompt. If the file is overlaid control ; returns to ASKSEG to prompt for a new segment number. If non-overlaid SIPP ; begins modifying the file. ;- TSTZRT::TSTB SWITWD ;Is the file overlaid? BPL 2$ ;Close the file JMP ASKSEG ;Prompt for new segment number 5$: JMP ILCOM ;Illegal command error .DSABL LSB .SBTTL Function routines ;+ ; SEMIC ; This routine is dispatched from DTABLE if first byte of CMDBUF contains a ; semi-colon. A semi-colon denotes that the next character is a function ; character. ;- .ENABL LSB SEMIC:: TSTB FLGWD2 ;Are we already in search mode? BMI 9$ ;Yes, error CLR R3 ;Set up index into command table TSTB @R1 ;Looking for a 0 ? BEQ 9$ ;Yes, branch to error 1$: CMPB @R1,SEMIT(R3) ;Is this the command? BNE 2$ ;No ASL R3 ;Make it a word offset JMP @SCRTN(R3) ;Go to appropriate routine 2$: TSTB SEMIT(R3) ;End of list? BEQ 9$ ;Common branch to avoid addressing error INC R3 ;Point to next BR 1$ ;Compare next ;+ ; The following routine makes certain that the command was issued from ; either the "Search for" or "New" contents prompt. Any other is invalid ; and generates an error. On return R1 points beyond thecommand character. ;- VALID: CMP #NWORD,R4 ;Coming from new contents prompt? BEQ 3$ ;Yes, go ahead CMP #SRCHWD,R4 ;No, how about the search for prompt BNE 4$ ;Error 3$: TSTB (R1)+ ;Point to next character SEZ ;Set z-bit for success 4$: RETURN ;Return to caller ;+ ; Semi-colon A ;- A$: CALL VALID ;Is it legal for this command to be issued? BNE 9$ ;No, error MOVB (R1)+,@R4 ;Move character into store area BNE 6$ ;Store an ASCII byte 5$: CMP #SRCHWD,R4 ;Semi-colon A coming from search? BEQ 9$ ;Yes, illegal at this point BIC #,FLGWRD ;Make sure no RAD50 mode BIS #,FLGWRD ;Set bits to display as ASCII char. (BYTE) TST (SP)+ ;Clear GETLIN return off stack JMP PRIOUT ;Go display the contents as ASCII ;+ ; Semi-colon Ay (where y is a ASCII character to store in the file) ;- 6$: TSTB @R1 ;Other characters? Can specify one at a time BNE 9$ ;Yes, then illegal command BIC #,FLGWRD ;Make sure no RAD50 mode BIS #,FLGWRD ;Insert character set bits 7$: JMP NRMRET ;Skip bit set of FLGWRD ;+ ; Semi-colon O ;- O$: BIC #,FLGWRD ;Clear ASCII & RAD50 func. flag JMP SEMIO ;Go back to word mode and display the contents ;+ ; Semi-colon R ;- R$: CALL VALID ;Is it legal for this command to be issued? BNE 9$ ;No, error TSTB @R1 ;Convert to octal and store in the file? BNE 8$ ;Yes, set up to do so CMP #SRCHWD,R4 ;Semi-colon A coming from search? BEQ 9$ ;Yes, illegal at this point BIC #1,OFFSET ;Yes, make it an even boundary BIS #,FLGWRD ;Set bit to display in RAD50 BIC #,FLGWRD ;Must be in word mode. No ASCII TST (SP)+ ;Clean up stack JMP PRIOUT ;Go display the RAD50 characters ;+ ; Semi-colon Ry (where y is a RAD50 word to store in the file) ;- 8$: BIT #1,OFFSET ;Is current location the high byte of loc.? BNE 9$ ;Yes, give error must be on low byte CALL ASCR50 ;Convert 3 ASCII characters to word of RAD50 BCS 9$ ;If c-bit set on return, illegal RAD50 char. TSTB @R1 ;Was there any other characters left BNE 9$ ;Yes, then illegal input CMP #SRCHWD,R4 ;No, specified for search? BEQ 7$ ;Skip bit set of FLGWRD BIS #,FLGWRD ;Insert char. set bits BIC #,FLGWRD ;Word mode and cancel RAD50 BR 7$ ;Continue at point of interuption ;+ ; Semi-colon S ;- S$: BIT #,FLGWD2 ;Has semi-colon S been typed in this sequence? BNE 9$ ;Yes, give error and return to search prompt ADD #2,@SP ;Yes set up stack MOV @(SP),@SP ;for future return BIS #,FLGWD2 ;Set bit to signify ;S has been typed CALL SEARCH ;Go fish RETURN ;+ ; Semi-colon V ;- V$: ADD #2,@SP ;Yes set up stack MOV @(SP),(SP) ;for future return JMP VERIFY ;and verify input 9$: JMP ILCOM ;Common jump to illegal command message .DSABL LSB .SBTTL Utility dispatched routines ;+ ; COLON ; R4 contains the segment number of either the start or end of the search ; parameters. If R4 is equal to SRCHST the segment came from the "Start" ; search prompt, if not it came from the "End" search prompt. SSEG1 is the ; storage location of the start segment number and SSEG2 for the end segment ; number. R1 is examined to determine if a number follows. If zero, execution ; returns with an offset of zero. If not equal, execution returns to get more ; input (GETCHR). ;- .ENABL LSB COLON:: TSTB FLGWD2 ;Was this routine entered in search mode? BPL ILCOM ;No, illegal command TSTB SWITWD ;Is the file overlaid? BPL ILCOM ;No, illegal command TST (R4)+ ;Was a segment number specified? BEQ ILCOM ;No, illegal command - return to search prompt TST @R4 ;Did the seg number overflow to the next loc? BNE ILCOM ;Yes, the number is too high - error CMP -(R4),#2000 ;Is the segment number within the legal limit? BHIS ILCOM ;No, print error and return to search prompt CMP #SRCHST,R4 ;If equal, the colon came from 'Start' prompt BNE 1$ ;Colon was typed from 'End' prompt MOV @R4,SSEG1 ;Store the segment number in 'Start' sv word BR 2$ ;and go do common code 1$: MOV @R4,SSEG2 ;Store the segment number in 'End' save word 2$: CLR @R4 ;Prepare R4 for recieving offset into segment TSTB @R1 ;Was an offset specified? BEQ 7$ ;No, just return to the search routine JMP GETCHR ;Yes, get the offset ;+ ; SLASH ; Typing a slash forces displays to be in word mode. Initially all ; operations are in words. This routine resets backslash (byte mode) ;- SLASH:: BIT #,FLGWRD ;Was numbers typed? BNE ILCOM ;Yes,error 3$: TSTB @R1 ;Anything following? BNE ILCOM ;Yes, error BIT #,FLGWRD ;Are we in ASCII or RAD50 mode? BNE ILCOM ;Yes - error BIT #,FLGWRD ;Is slash legal? BEQ ILCOM ;No, error SEMIO: BIT #,FLGWRD ;Was the last address odd? BEQ 4$ ;No,just clear byte flag and return CALL SUBOP ;Double precision decrement OFFSET and ADRESS 4$: BIC #,FLGWRD ;Force word operation JMP RTURN ;and return ;+ ; BACKSL ; Typing a backslash forces displays and searches to be in byte mode. ;- BACKSL::CMP #SRCHWD,R4 ;Coming from Search for prompt? BEQ 5$ ;Yes, skip check BIT #,FLGWRD ;Was numbers typed? BNE ILCOM ;Yes,error 5$: TSTB @R1 ;Anything following? BNE ILCOM ;Yes, error BIT #,FLGWRD ;Are we in ASCII or RAD50 mode? BNE ILCOM ;Yes - error TSTB FLGWD2 ;Are we in search mode BMI ILCOM ;Yes, give error CMP R4,#SRCHWD ;Legal at this point BEQ 6$ ;Backslash legal at this point in search mode BIT #,FLGWRD ;Is backslash legal? BEQ ILCOM ;No, error BIS #,FLGWRD ;Yes, make byte operation TST (SP)+ ;Get rid of the return JMP HEADER ;Go print the header and open the location 6$: TSTB @R1 ;Was anything typed after the backslash? BNE ILCOM ;Yes, error BIS #,FLGWRD ;Search for byte 7$: JMP NRMRET ;Normal return ILCOM: TSTB FLGWD2 ;Did the error occur in search mode? BPL 8$ ;No, print "Illegal command" ;+ ;ERROR .ERR #ERAR,#EMC,LEVEL=E,RETURN=YES ;Invalid search command BR 9$ ;Go jump to where we came from 8$: .ERR #ERAR,#EMB,LEVEL=E,RETURN=YES ;Invalid input ;- 9$: ADD #2,@SP ;Return to whatever is in the second argument MOV @(SP),@SP ;Return to 10$: RETURN ;appropriate address .DSABL LSB .SBTTL SEARCH - Numerical search routine ;+ ; SEARCH ; This routine searches a given set of locations for a given content. First ; the user is asked a series of questions to determine what to search and ; where to look for it. SIPP compares the number to be searched with the ; modified location if that location lies between the specified boundaries. ; When the specified search number is found, SIPP prints the message: ; ; Found at nnnnnn ; or ; Found at s:mmmm,oooo ; ; where: ; ; nnnnnn is the location of the specified contents ; s: is the segment in an overlaid file ; mmmm is the incore address of the segment ; oooo is the offset into the segment (s:) ; ; If /A was used on an overlaid file, the first message is generated. No ; segments are shown. When the search operation is completed, SIPP returns to ; the operation which was interupted by the ";S" command. ; ; All registers as well as the current block number are saved upon entering ; and restored upon exiting this routine. ;- .ENABL LSB SEARCH::CALL $SAVAL ;Save all registers MOV BLKNUM,-(SP) ;Save the current block number MOV FLGWRD,-(SP) ;Save the current FLGWRD SRCHRT: BIC #,FLGWRD ;Clear bits BIC #,FLGWD2 ;Clear search mode flag bit CALL BLKZRO ;Read in block 0 STRING SRCPMT,SRCHWD,RETTMP,SRCHRT ;Get search word TST 2(R4) ;Is the search word in double precission? BNE 8$ ;Yes, give error STRLOC::BIC #,FLGWRD ;Clear flag initially BIS #,FLGWD2 ;Set flag for search mode CLR SSEG1 ;Clear 'Start' segment storage word CLR SSEG2 ;Clear 'End' segment storage word STRING STRPMT,SRCHST,SRCHRT,SRCHRT BIT #1,@R4 ;Odd address? BEQ 1$ ;No, don't set byte bit BIS #,FLGWRD ;Yes, set byte search flag 1$: CLR CORADD ;Save 2 words for storing the in core address CLR CORADD+2 ;of the current segment (if there is one) TSTB SWITWD ;Overlaid file? BMI 2$ ;Yes, check overlay boundaries BIT #,SWITWD ;No, Non-file structured? BNE 6$ ;Yes, check if within maximum address boundary MOV #SCHCAL,R4 ;No, Point to area for calculation MOV #HLIMIT,R0 ;Get location 50 CLR R1 ;No high order word CALL CHKLOC ;Get the most recent contents of location 50 BR 4$ ;Check if specified start is beyond boundary 2$: MOV SSEG1,SNUM ;Was a segment number specified? BNE 3$ ;Yes, calculate the high limit of the segment MOV #SEGEND,R4 ;Point to store area for high limit of root MOV OVLTBL,R0 ;Get address of start of overlay table SUB #<-OVR.ER>,R0 ;Make it address of high root limit CLR R1 ;No high order CALL CHKLOC ;Get the most current contents of high limit BR 4$ ;Make sure start location is not beyond limit 3$: CALL BNDRY ;Set up segment boundies to search BCS INVSEG ;If c-bit set, error MOV #SEGEND,R4 ;Set up for following test 4$: MOV R4,R5 ;R5 -> calculated limit MOV #SRCHST,R4 ;Set up to compare the input from file size CMP 2(R4),2(R5) ;High order within limit BHI INVBND ;No give boundary error BLO 6$ ;Yes, check for maximum address TSTB SWITWD ;Overlaid file BPL 5$ ;No, use BHIS CMP @R4,@R5 ;Low order within limit BHIS INVBND ;No, give boundary error BR 6$ ;Yes, check maximum address limit 5$: CMP @R4,@R5 ;Low order within boundary? BHI INVBND ;No, error 6$: MOV #MAXADD+2,R5 ;Get the files maximum size CMP 2(R4),@R5 ;Compare the high orders BHI INVBND ;Input higher than maximum size - error BLO ENDLOC ;Input lower, limit ok. Get the end location CMP @R4,-(R5) ;Check the low order words BLO ENDLOC ;OK, get end limit ;+ ;ERROR INVBND: .ERR #ERAR,#EMV,LEVEL=E,RETURN=YES ;Invalid boundary size 7$: BR SRCHRT ;Yes, start search prompts again INVSEG: .ERR #ERAR,#EMG,LEVEL=E,RETURN=YES ;Invalid segment ;- BR 7$ ;Ask for starting location of search 8$: JMP ILSRCH ;Give illegal search error .DSABL LSB .SBTTL ENDLOC - Calculate the end location for search ;+ ; ENDLOC ; This routine is entered after the word to search and the starting search ; location is recieved. If the input to the "End?" prompt is SIPP ; creates the ending location depending on the file being searched. If the ; file of device was opened with /A the end location is maximum address ; (MAXADD). If the file is non-overlayed, the end location is what is in ; location 50. If the file is overlayed, the end location is calculated from ; the last segment in the overlay table. ; ; If input was made to the "End? prompt and the file is non-overlayed or open ; non-file structured the input is compared with the last address of the file. ; If the file is overlayed, it is determined if the search is within the root ; if no segmnet is specified. If a segment is specified, the actual address ; is calculated. If the calculated end location is within bounds control is ; dispatch to SCHCMP to search for the specified contents. ;- .ENABL LSB ENDLOC::BIC #,FLGWRD ;Make sure virtual bit is cleared STRING ENDPMT,SRCHED,SRCHRT,SRCHRT BIT #1,@R4 ;Odd address? BEQ 1$ ;No, don't set byte bit BIS #,FLGWRD ;Yes, set byte search flag 1$: TSTB CMDBUF ;Was anything typed other than BNE 4$ ;Yes, what is in SRCHED is treated as end TSTB SWITWD ;Searching an overlaid file? BMI 3$ ;Yes, do overlay set up BIT #,SWITWD ;Non-file structured search? BEQ 2$ ;No, get high limit from location 50 MOV MAXADD,(R4)+ ;Yes, the search limit Should be the maximum MOV MAXADD+2,@R4 ;Can be two words (high order word) BR 9$ ;Check high and low address for search ;+ ; Searching a non-overlayed file and no input was typed for the ending search ; location ( only). No /A (non-file structured). ;- 2$: MOV #HLIMIT,R0 ;Get location 50 in low order word CLR R1 ;No high order word CALL CHKLOC ;Get the most current contents of location 50 ADD #2,(R4)+ ;Add 2 to point 1 word beyond end ADC @R4 ;Add carry if any BR 7$ ;Check with maximum address ;+ ; Searching an overlayed file and no input was typed for the ending search ; location ( only). Effectively search the overlay table for a non- ; existant segment entry. When the end of the table is reached SNUM contains ; 2000 minus the amount of segments in the file. The word count of the last ; segment (contents of the last location in the overlay table) is converted ; to the offset to that last segment (SRCHED) and the segment is stored in ; SSEG2. These calculations are now set up as if the user used the seg:nnn ; construction. ;- 3$: MOV #2000,SSEG2 ;Store 1 seg number higher than legal number MOV SSEG2,SNUM ;Store it in SNUM for call to SEGFND CALL SEGFND ;Look for segment entry in overlay table BCC INVSEG ;If returns with no c-bit set something wrong SUB SNUM,SSEG2 ;The difference is act. number of seg in file MOV R4,R3 ;R3 -> area to calculate (SRCHED) MOV BLKNUM,(R3)+ ;Move the block number into the area CALL DPMULT ;Convert the block number to an address ADD R2,@R3 ;Add the buffer location SUB #BUFFER+2,@R3 ;Contains the address of last location of ;overlay table. The last segments' word count MOV @R3,R0 ;Move that address into R0 CLR R1 ;Clear high order CALL CHKLOC ;Get most current word count of the last seg DEC @R4 ;One less, to adjust for first word of segment ASL @R4 ;Make it a byte count CLR 2(R4) ;No high order word ;+ ; Something was typed. Find out what type of file is being searched. ;- 4$: BIT #,SWITWD ;Non-file structured? BNE 7$ ;Yes, ignore location 50 MOV #SCHCAL,R4 ;Point to area for calculation TSTB SWITWD ;Overlayed file? BMI 5$ ;Yes, check overlay boundaries MOV #HLIMIT,R0 ;Get location 50 to get end of file CLR R1 ;No high order word CALL CHKLOC ;Get the most current contents of location 50 MOV R4,R5 ;Make R5 point to the contents of location 50 ADD #2,(R5)+ ;Add two to point beyond ADC @R5 ;Add carry,all other boundaries are +2 BR 8$ ;Check for valid boundary ;+ ; Search in overlay file. The search ends with the specified segment ; (in SSEG2). The offset into the start is in SRCHED. If no segment is ; specified the end location is in the root. ;- 5$: MOV SSEG2,SNUM ;Set up to search for seg entry in ovly tbl BNE 6$ ;Yes, don't test if within root boundary ;+ ; Search within the root. See if the ending location falls within the high ; boundary limit of the root. ;- MOV OVLTBL,R0 ;Get address of start of overlay table SUB #<-OVR.ER>,R0 ;Make it address of high root limit CLR R1 ;No high order CALL CHKLOC ;Get the most current contents of high limit MOV R4,R5 ;Get the high limit of the root MOV #SRCHED+2,R4 ;Point to the user input (high order word) TST @R4 ;Was a high order word specified? BNE 11$ ;Yes, invalid boundary was specified CMP -(R4),@R5 ;Was the specified address within the root BHI 11$ ;Outside the root - error MOV (R4)+,SEGEND ;Store in SEGEND Since this bondry chked first BR 9$ ;OK, compare the users two limits ;+ ; End search is in the form of segment:nnn where nnn is the offset from the ; start of the specified segment. ;- 6$: CALL SEGFND ;Search the ovl tbl for segment entry BCS INVSEG ;If c-bit set, segment not found - error MOV #SRCHED,R5 ;R5 -> ending offset ADD #2,@R5 ;Skip the first word of the segment ADC 2(R5) ;Add in the carry CALL DPADD ;Get the actual address of the search end CMP SSEG1,SSEG2 ;Are the start and segments the same? BNE 7$ ;No, check boundaries MOV #SEGEND,R4 ;Yes, set up to make SEGEND equal SRCHED MOV (R5)+,(R4)+ ;Move in the low order word MOV @R5,@R4 ;Move in the high order word ;+ ; Check if the specified (or calculated) ending address is within the maximum ; address of the file. ;- 7$: MOV #MAXADD+2,R5 ;Point to maximum address for compare 8$: MOV #SRCHED+2,R4 ;Point to ending location CMP @R4,@R5 ;Compare the high order words BHI 11$ ;Input too high - error BLO 9$ ;Limit ok, skip rest of check CMP -(R4),-(R5) ;Compare the low order words BHI 11$ ;Too high - error TST (R4)+ ;Point to second word of end location ;+ ; Check if specified (or calculated) ending search location is higher than the ; specified (or calculated) starting search location. If the two locations ; are the same the search routine is exited. ;- 9$: BIT #,FLGWRD ;Byte mode? BEQ 10$ ;No, don't check for byte input BIT #177400,SRCHWD ;Was word specified for byte? BNE ILSRCH ;More than byte is entered 10$: MOV #SRCHST+2,R3 ;R3 -> second word of start location CMP @R3,@R4 ;Are the high order words the same? BHI ILSRCH ;The start is higher than the end - error BLO SCHCMP ;The end is higher than start - OK go search CMP -(R3),-(R4) ;Are the low order addresses the same? BLO SCHCMP ;The boundaries are OK - go search BEQ RETTMP ;Equal, no locations to check ;+ ;ERROR ILSRCH: .ERR #ERAR,#EMC,LEVEL=E,RETURN=YES ;Invalid search command ;- JMP SRCHRT ;Yes, start all over again 11$: JMP INVBND ;Go print invalid boundry error message .DSABL LSB .SBTTL SCHCMP - Search compare routine ;+ ; SCHCMP ; This routine compares the contents of either the modified location or the ; contents of the program with the specified search value. If the contents ; does not match, the location in SRCHST is incremented by 1 (byte mode) or ; 2 (word mode). If there is a match, the location is displayed and then ; search's starting location is incremented upon return. When the start ; address is greater than the ending address or a "read beyond END OF FILE" is ; returned, the old block number, BUFFER, and registers are restored. Program ; control is returned to where ever the ';S' command was issued. ; ; All registers are saved when entered. ;- .ENABL LSB SCHCMP::TST STATWD ;Are there any CTRL/C's floating around BPL 1$ ;No, continue CALL CHKC ;Check for intentional CTRL/C BCC 1$ ;No, disregard the CTRL/C and continue ; BCS ;CTRL/C was intentional .EXIT 1$: MOV SRCHST,R0 ;R1--> Search start location MOV SRCHST+2,R1 ;High order BIT #1,R0 ;Is the address odd? BEQ 2$ ;No - branch BIS #,FLGWRD ;Set flag to search odd byte BIC #1,R0 ;Make search address even 2$: MOV #CTCHAL+2,R4 ;Point to 2 words for return from CHKLOC CLR @R4 ;Initially clear CLR -(R4) ;both words CALL CHKLOC ;Get the most current contents of location BIT #,FLGWRD ;Byte search? BEQ 4$ ;No, word search BIT #,FLGWRD ;Search odd byte? BEQ 3$ ;No, even byte or word search SWAB @R4 ;Yes, swap the bytes 3$: BIC #177400,@R4 ;Strip off the high byte 4$: CMP @R4,SRCHWD ;Are the contents the same? BNE 5$ ;If N bit set upon return -- no match CALL MATCH ;Go print our findings ;+ ; The following bumps search's start address. If the address is greater than ; the end address the search is complete. If the end address is zero, search ; continues until an attempt to read beyond the end of file occurs. This ; condition causes the search to end. ;- 5$: MOV #SRCHST,R0 ;Get starting location BIT #,FLGWRD ;Byte search? BEQ 6$ ;No, increment the address twice (words) BIC #,FLGWRD ;Make sure the byte flag is clear BR 7$ ;Branch around to increment by 1 6$: CLC ;Make sure C bit cleared ADD #1,@R0 ;Add one to the low order address ADC 2(R0) ;Add any carry 7$: CLC ;Make sure C bit cleared ADD #1,(R0)+ ;Add one to the low order address ADC @R0 ;Add any carry TSTB SWITWD ;Overlaid? BPL 9$ ;No,make boundary limit MOV #SEGEND+2,R3 ;Get the last location in segment or root CMP @R0,@R3 ;Compare the high limits BLO SCHCMP ;Actual is lower than limit, check for match BHI 8$ ;End of segment or root. Get next CMP -(R0),-(R3) ;Do the low orders match? BLO SCHCMP ;If equal or lower keep checking 8$: CLR (R0)+ ;Reset starting location for search CLR @R0 ;Two words INC SSEG1 ;Increment starting segment number MOV SSEG1,SNUM ;Get new segment to set up new boundaries CALL BNDRY ;Set up segment boundies to search BCS RETTMP ;If c-bit set, error MOV #SRCHST+2,R0 ;Point to the start location for search 9$: MOV #SRCHED+2,R3 ;Point to user's ending address CMP @R0,@R3 ;Are the high limits the same? BLO SCHCMP ;Haven't reached the end. Check for match BHI RETTMP ;End, leave search routine CMP -(R0),-(R3) ;The same. Are the low orders the same? BLO SCHCMP ;Haven't reached the end. Check for match RETTMP: MOV (SP)+,FLGWRD ;Restore the old FLGWRD MOV (SP)+,BLKNUM ;Restore the old block number CLR R2 ;After read R2 points to start of BUFFER CALL READ ;Read block into BUFFER BIC #,FLGWD2 ;Make sure srch bits clear CLR SSEG1 ;Initialize SSEG1 CLR SSEG2 ;Initialize SSEG2 .RCTRLO ;Make sure CTRL/O is reset RETURN .DSABL LSB .SBTTL BNDRY - Set up top of segment ;+ ; BNDRY ; This routine sets up the top of the segment as a boundary for search. ; First, it gets the location of the start of the segment (in the file). Then ; it gets the segment word count, makes it a byte count,and adds it to the ; start of the segment. This is the high end of the segment. It then gets ; the incore address of the segment, and updates it by two for future ; calculations. The start of the search is then calculated to be start of ; segment plus the users specified offset. ; ;Input: SNUM = Segment currently being searched ; ; CALL BNDRY ;Set up segment boundaries to search ; ;Output:SEGLST = Start of segment boundary in file (2 words) ; SEGEND = Last location of the segment in file (2 words) ; CORADD = Incore address of segment being searched ; SRCHST = Starting address to search from ; C-bit set if error ;- .ENABL LSB BNDRY:: MOV #SEGLST+2,R4 ;Point to storage for segment boundary CLR @R4 ;Initialize both words (high order) CLR -(R4) ;low order CALL SEGFND ;Get the starting address of the segment BCS 1$ ;Segment was not found - last segment MOV R0,-(SP) ;Save the start of segment entry ADD #,R0 ;Point to word count CLR R1 ;No high order word MOV #SEGEND,R4 ;Points to 2 words segment word count CALL CHKLOC ;Has the location been modified? ASL @R4 ;Make it a byte count MOV R4,R5 ;Set up SEGEND for addition MOV #SEGLST,R4 ;Point to the calculated start of that segment CALL DPADD ;Double presission add MOV #CORADD,R4 ;Now point to the store words for in core addr MOV (SP)+,R0 ;Get address of incore address in overlay tbl CALL VRTFND ;Get the in core address MOV #SEGLST,R4 ;Point to stored starting address of segment MOV #SRCHST,R5 ;Point to stored offset into the segment start ADD #2,@R4 ;Make sure to skip the first word of the seg ADC 2(R4) ;Add any carry to the high byte ADD #2,CORADD ;Bump core address by 2 ADC CORADD+2 ;Add carry CALL DPADD ;Perform double precision add CLC 1$: RETURN .DSABL LSB .SBTTL MATCH - Print location of match ;+ ; MATCH ; This routine is entered if the specified search word matches the contents ; of the opened location (SRCHST). ;- .ENABL LSB MATCH:: .PRINT #FNDAT ;Print 'Found at ' message MOV #SRCHST,R1 ;Point to the search location MOV #CMDBUF,R2 ;Point to the buffer to store the output MOV SSEG1,PNUM1 ;Move in the segment number BEQ 1$ ;If equal, no segment. Branch over to print CLR PNUM2 ;Set up to store seg. number in print buffer MOV R1,-(SP) ;Save the pointer to the matching address CALL GETDGT ;Convert seg num to ASCII and store for output MOVB #72,(R2)+ ;Colon to divide segment offset into segment MOV CORADD,PNUM1 ;Point to stored in core address CLR PNUM2 ;No high order word to deal with CALL GETDGT ;Store the in core address MOVB #54,(R2)+ ;Comma to seperate incore address and offset MOV #CTCHAL,R5 ;Point to area for calculations MOV (SP)+,R1 ;Restore pointer to matching address MOV (R1)+,@R5 ;Get low order MOV @R1,2(R5) ;And high order for matching address MOV #SEGLST,R4 ;Point to the start address of segment CALL DPSUB ;Double precision subtract to get offset MOV R5,R1 ;Set up R1 for common routine for offset print 1$: MOV (R1)+,PNUM1 ;Set up low word to print MOV @R1,PNUM2 ;Set up the high order word to print CALL GETDGT ;Convert to ASCII and store for output CLRB @R2 ;Clear the last byte of string for .PRINT #CMDBUF ;Print the string RETURN .DSABL LSB .SBTTL SEGFND - Find the segment entry in the overlay table ;+ ; SEGFND ; This routine reads the block containing the start of the overlay table into ; BUFFER. Then it looks for the specified segment and extracts the block ; number to get the actual address of the start of the segment. ; ;Input: R4 -> Two words for storage set up by the caller ; SNUM = segment number ; OVLTBL = starting address of overlay table ; ; CALL SEGFND ;Find the entry for the specified segment ; ;Output:R0 = Actual address of segment in core address entry ; R2 -> Location within BUFFER (segments in core address) ; R3 -> Actual address of start of overlay ; R4 -> Same as R3 ; BLKNUM = Current block number of contents of BUFFER ; C-bit set if segment entry is not found ;- .ENABL LSB SEGFND::MOV OVLTBL,R0 ;Get the relative location of overlay table CLR R1 ;No high order CALL FNDLOC ;Read in block and point to offset to blk 1$: BITB #1,@R2 ;If odd end of table. Didn't reach segment BNE 7$ ;Odd, error DEC SNUM ;Decrement the temporary segment count BLE 3$ ;If segment count zero we have the right one CMP R2,#BEND ;Past the end of the buffer? BMI 2$ ;No, bump the pointer CALL UPBLK ;Yes, read in another block 2$: ADD #6,R2 ;Point to next entry BR 1$ ;See if end of table ;+ ; At this point the coresponding segment entry has been found. ;- 3$: MOV #CTCHAL,R3 ;Set up to check for modification MOV BLKNUM,(R3)+ ;Move in the block number CALL DPMULT ;Multiply by 1000 ADD R2,@R3 ;Add in the location in the buffer SUB #BUFFER-2,@R3 ;And subtract the start of BUFFER to get add. MOV VTBL,R0 ;Get start of /V table BEQ 4$ ;If equal, No need to get address TST (R0)+ ;R0 is start of /V table + 2 CMP @R3,R0 ;Is the segment virtual? BLO 4$ ;No, don't set bit BIS #,FLGWRD ;Yes, set the bit for virtual 4$: MOV (R3)+,R0 ;Get the low order word for compare MOV @R3,R1 ;Get the high order word for compare CALL CMPARE ;Check for modification MOV R4,R3 ;R3 -> store words set up by caller BCC 5$ ;C-bit clear: use actual contents of program ; BCS ;C-bit set: location was modified MOV NEWW(R5),(R3)+ ;Get new contents (starting block) BR 6$ ;Go do common code 5$: MOV 2(R2),(R3)+ ;Move in contents of unmodified location 6$: CALL DPMULT ;Make the starting block into a starting addr. TST -(R0) ;R0 contains the first entry of the segment TST (PC)+ ;Skip over the next instruction. C-bit clear 7$: SEC ;Set the c-bit for error RETURN .DSABL LSB .SBTTL VRTFND - Get incore address ;+ ; VRTFND ; This routine retrieves the incore address from the overlay table. It first ; gets the address from the first word of the segment entry (overlay table). ; If the segment is not virtual we return with the incore address. If it is ; virtual, the address in the overlay table is used to point to the correct ; window definition block where the PAR is extracted and the incore address is ; calculated from there. ; ;Input: R0 = Address of second word of segment entry in overlay table ; R4 -> Word to store the incore address ; ; CALL VRTFND ;Get the in core address ; ;Output:R4 -> Incore address ; All other registers may be destroyed upon leaving this routine ;- .ENABL LSB VRTFND::CLR R1 ;No high order CALL CHKLOC ;Has it been modified? BIT #,FLGWRD ;Virtual overlay? BEQ 2$ ;No, just exit. Incore address in @R4 MOV @R4,R0 ;Yes, set up to get addr. from WDB. R1 cleared CLR R1 ;Make sure only one word CALL CHKLOC ;Has it been modified? CLRB @R4 ;Clear out ID MOV #5,R3 ;Set up shift count 1$: ASL @R4 ;Shift PAR DEC R3 ;Decrement count BNE 1$ ;If not done, shift again 2$: RETURN .DSABL LSB .SBTTL CMPARE - Check if location has been modified ;+ ; CMPARE ; This routine checks if the specified has been previously modified. If it ; has there is a information block constructed in memory for that accumulated ; address. Therefore this routine compares the accumulated address of each ; information block with the accumulated address entered with. If there is a ; match, the C-bit is set on exit. ; ;Input: R0 = Low order word of accumulated address to compare ; R1 = High order word of accumulated address to compare ; ; CALL CMPARE ;See if the location has been modified ; ;Output:C-bit is set if an information block exists for the accumulated ; address ; C-bit cleared if no information block exists for the accumulated ; address ; If the C-bit is set R5 points to the start (the link word) of the ; matching information block ; If the C-bit is cleared R5 is destroyed ;- .ENABL LSB CMPARE::MOV BUFBEG,R5 ;Point to start of information block BEQ 3$ ;Branch out if no modifications 1$: CMP AD1(R5),R1 ;High order the same? BHI 3$ ;Beyond the location. Exit with C-bit clear BLO 2$ ;Low, get next information block CMP AD0(R5),R0 ;Low order the same? BHI 3$ ;Beyond the location. Exit with C-bit clear BEQ 4$ ;The location was modified. Set C-bit 2$: MOV @R5,R5 ;Get next information block BNE 1$ ;and compare next block if not the end 3$: TST (PC)+ ;Clear C-bit 4$: SEC ;Set C-bit RETURN .DSABL LSB .SBTTL VERIFY - Verify modified locations ;+ ; VERIFY ; This subroutine displays all previously modified locations, and thier old ; and new contents. It is called whenever the user types ;V in response to ; any of SIPP's prompts. If no location is modified when the ;V command is ; issued the user is notified and program control returns to whatever prompt ; the verify command was issued from. If locations have been modified the ; appropriate header is printed (overlaid or non-overlaid file) and modified ; locations are displayed in ascending order. Locations are taken from the ; stored information blocks (link list created by the LINK routine). Upon ; completion program control returns to whatever prompt the verify command was ; issued from. ; ; Previous operations and registers are not destroyed by this subroutine. ;- .ENABL LSB VERIFY::JSR R5,SAVREG ;Save all registers MOV FLGWRD,-(SP) ;Save current FLGWRD BIC #,FLGWRD ;Make sure whole word is displayed MOV BUFBEG,R5 ;Point to the start of the link list BNE 1$ ;Print the appropriate header ;+ ;ERROR .ERR #ERAR,#EMH,LEVEL=I,RETURN=YES ;No modifications made ;- BR VEREND ;Leave this routine 1$: BIS #,FLGWD2 ;Set bit to store header 2$: MOV R5,R4 ;R4 -> start of information block ADD #6,R4 ;Point to segment number within block MOV OLDW(R5),R0 ;R0 contains old contents when DSPLAY entered CALL DSPLAY ;Display contents BIC #,FLGWD2 ;Disable header store MOVB #SPACE,(R2)+ ;Space before new content MOV NEWW(R5),PNUM1 ;Get the new word to store CLR PNUM2 ;Clr for single number (not double precision) CALL GETDGT ;Convert to ASCII and store for output CLRB @R2 ;Make sure output ends with .PRINT #CMDBUF ;Print the output MOV @R5,R5 ;Get the next link block BNE 2$ ;More to display - continue VEREND: MOV (SP)+,FLGWRD ;Restore FLGWRD .RCTRLO ;Make sure the console can print RETURN .DSABL LSB .SBTTL FNDLOC - Read/Write routine ;+ ; The following subroutine has two entry points (FNDLOC & READ). ; ; FNDLOC ; When entered, the double precision divide routine is called to change the ; accumulated address (R0 & R1) into a block number and offset into that ; block. R2 returns with the remainder which is the offset into the ; calculated block. Whatever is in BUFFER, at the time this routine is called ; by MODIFY, is writen out to patched file. After the write, a new block is ; read into BUFFER. The contents of R2 is then changed to be the pointer into ; BUFFER. ; ;Input: R0 = Low order accumulated address ; R1 = High order accumulated address ; BLKNUM = Current block of file in BUFFER ; ; CALL FNDLOC ;Read in block and point to offset to blk ; ;Output:R2 Points to the offset into the block in BUFFER ; BLKNUM = New block of file in BUFFER ; ;Changed registers: R0,R1,R2,R3 ; ;***************************************************************************** ; ; READ ; This routine is typically entered to read in block 0 of the file or a ; specific block. The block number is modified before entering this routine. ; ;Input: R2 = Number to the offset into the specified block ; BLKNUM = Block of file to read into BUFFER ; ;Output:R2 Points to the offset into the block in BUFFER ; ;Changed registers: R0,R2 ;- .ENABL LSB FNDLOC::MOV #1000,R3 ;Divide by 1000 CALL DIV ;Divide CMP R0,BLKNUM ;Is the block currently in the buffer? BEQ 3$ ;Yes, no need to read it in again BIT #,FLGWD2 ;Are we modifying? BEQ 1$ ;No, just read in a new block MOV R0,-(SP) ;Yes, save R0 before WRITE .WRITW #EMTBLK,#3,#BUFFER,#256.,BLKNUM BCS 4$ ;Branch if error MOV (SP)+,R0 ;Restore R0 1$: MOV R0,BLKNUM ;No, store number READ: MOV #BLREAD,R3 ;R3 -> number of words to read in buffer BIT #,SWITWD ;Is file overlaid? BEQ 2$ ;No, branch to read BIT #,SWITWD ;Is /A specified? BNE 2$ ;Yes, branch to read MOV #OLREAD,R3 ;Read extra words with block for ovrly info 2$: .READW #EMTBLK,#3,#BUFFER,R3,BLKNUM BCS 5$ ;No, error 3$: ADD #BUFFER,R2 ;Point to the beginning of read buffer RETURN ;+ ;ERROR 4$: .ERR #ERAR,#EMO,LEVEL=F,RETURN=NO,FILE=#INFIL ;Output error ;- ;+ ; If a read error occurs, BYTE 52 is examined for and end of file error. ; If a hard error occurs, an input error is printed, the abort flag is set, ; and program control returns (normal return). Execution continues but with ; the abort bit set no modifications occur. If a hard error occurs during the ; modification phase the old contents is re-instated. ;- 5$: TSTB @#ERROR ;End of file? BNE 7$ ;No, hard error 6$: JMP EOF ;Give end of file message ;+ ;ERROR 7$: .ERR #ERAR,#EMS,LEVEL=F,RETURN=YES,FILE=#INFIL ;Input error ;- BIS #,FLGWD2 ;Set the abort bit RETURN ;and return .DSABL LSB .SBTTL BAKUP1 and BAKUP2 - Insert CTRL/Z in log file ;+ ; BAKUP1 and BAKUP2 ; This routine sets up to print either one or two CTRL/Z(s). If entered at ; BAKUP2 two CTRL/Z's will be printed. ; ;Input: R0-->location in previous link block ; R2-->next storage word in BUFFER ; R3 = byte count for BUFFER write ; R4-->location in current link block ; R5 = Start of current link block ; ; R4 will be saved on the stack for future return ;- BAKUP2: CALL BAKUP1 ;Call BAKUP1 (to print two CTRL/Z's) BAKUP1: MOV R4,-(SP) ;Save R4 MOV #UPZ,R1 ;Point to "^Z" message MOV #UPY,R4 ;Point to end of message CALL STORE ;Go store it MOV (SP)+,R4 ;Restore R4 RETURN MOVBOF: BIS #,FLGWD2 ;Set to convert and store next two words MOVSEG: MOV (R4)+,R1 ;R1 = low order base within link block CALL OCTASC ;Convert OCTAL to ASCII and store RETURN .SBTTL Block boundary and block 0 read routines ;+ ; UPBLK ; This routine updates the BUFFER to reflect the next block. ; ;Input: R2 is the pointer into BUFFER ;- UPBLK:: SUB #BEND,R2 ;Make R2 an offset to next entry INC BLKNUM ;Update the block number CALL READ ;Get the next part of the overlay table RETURN ;+ ; BLKSTR ; Reads block 0 of file or device into BUFFER. Points at start of BUFFER. ; ; Call: CALL BLKSTR ; ;Output:R2 --> Start of BUFFER (block 0) ;- BLKZRO: CLR BLKNUM ;Clear to read blk zero of the file to BUFFER BLKSTR: CLR R2 ;Clear to return with R2 = start of BUFFER CALL READ ;Read the block into BUFFER RETURN .SBTTL CHKSM - CRC-16 checksum routine ;+ ; CHKSM ; This routine generates the checksum. ; ;Input: R0= Word to check ; R1= CRC storage register ; ; CALL CHKSM ;Update the checksum value ; ;Output:R1= New or updated CRC register ; R0,R2,R3,R4 are destroyed ;- CHKSM:: MOV R0,-(SP) ;Save the value on the stack for further oper. CALL CRC16 ;Do checksum MOV R4,R1 ;New CRC SWAB @SP ;Swap bytes MOV (SP)+,R0 ;Prepare to CALL CRC16 ;Do checksum MOV R4,R1 ;New CRC RETURN CRC16:: BIC #177400,R0 ;Clear the high byte MOV R1,R3 ;Set up for XOR MOV R0,R4 ;Set up for XOR, results return in R4 CALL XOR ;EXCLUSIVE OR byte with old CRC MOV R4,R0 ;Put results in R0 MOV R0,R2 ;Save a copy of result BIC #177760,R0 ;Extract low 4 bits ASL R0 ;Byte address, word index ADD PC,R0 ;Set up PIC address MOV CTABLA-.(R0),R0 ;Get first modifier word BIC #177417,R2 ;Now extract high 4 bits ASR R2 ;Set up to enter second half ASR R2 ;Again byte address to ASR R2 ;word index ADD PC,R2 ;Set up pic address MOV CTABLE-.(R2),R2 ;Get second modifier word MOV R2,R3 ;Set up for XOR MOV R0,R4 ;Set up for XOR, results return in R4 CALL XOR ;EXCLUSIVE OR modifier values CLRB R1 ;Clear low byte or old CRC SWAB R1 ;Now work on upper byte MOV R4,R3 ;Set up previous return from XOR oper. for XOR MOV R1,R4 ;Set up for XOR, results return in R4 XOR: MOV R3,-(SP) ;Set for bit clear BIC R4,R3 ;Clear all set bits BIC (SP)+,R4 ;Clear set bits BIS R3,R4 ;Now combine all bits RETURN .SBTTL OCTASC - Convert OCTAL to ASCII ;+ ; OCTASC ; This routine converts octal words to ASCII characters and stores them in ; the log output buffer. If the buffer fills the buffer is written out. ; ;Input: R1 = Location containing the octal word ; R2 -> The next byte location in BUFFER ; R3 = Byte count ; R5 -> Start of current information block ; If TWOWRD bit is set in FLGWRD: ; R4 -> the high order word to convert else, ; R4 is not used ; ; CALL OCTASC ;Convert OCTAL to ASCII and store ; ;Output:R2 -> Updated byte location in BUFFER ; R3 = Updated byte count ; R1 and R5 are unchanged ;- .ENABL LSB OCTASC::CLR -(SP) ;Mark end of string 1$: MOV R1,-(SP) ;Copy word onto stack BIC #-10,@SP ;Isolate next digit ADD #'0,@SP ;"ASCII'ize" the digit ROR R1 ;Effectively ASR R1 ;divide by ASR R1 ;10(8) BNE 1$ ;Repeat until done BIT #,FLGWD2 ;Have both words been processed? BEQ 2$ ;Yes - go store words in BUFFER BIC #,FLGWD2 ;Clear to do second word MOV (R4)+,R1 ;Get second word BNE 1$ ;If NE - process. If 0 fall through to store 2$: MOVB (SP)+,(R2)+ ;Move into BUFFER BEQ 3$ ;If equal the end INC R3 ;Increment the count CMP R3,#1000 ;End of BUFFER? BNE 2$ ;No, keep filling CALL WRITIT ;Write it out to the log file BR 2$ ;Get some more 3$: TSTB -(R2) ;Last character was 0. Point to previous loc MOV R4,-(SP) ;Save incase storing base or offset values MOV #CRLF,R1 ;Set up to store MOV #MSEND,R4 ;Set up end of message CALL STORE ;Store message into BUFFER MOV (SP)+,R4 ;Restore R4 before returning RETURN .DSABL LSB .SBTTL WRITIT - Write BUFFER to log file ;+ ; WRITIT ; If the BUFFER is full this routine writes it to the created log file. It is ; also called to write out the last block of the log file. ; ; CALL WRITIT ;Write it out to the log file ; ;- .ENABL LSB WRITIT::MOV R0,-(SP) ;Save R0 BIT #1,R3 BEQ 1$ CLRB @R2 1$: INC R3 ASR R3 ;Make word count for EMT .WRITW #EMTBLK,#0,#BUFFER,R3,BLKNUM BCS 4$ ;Output error MOV #BUFFER,R2 ;Reset buffer pointer INC BLKNUM ;Increment block number CLR R3 ;Initialize byte count for storing MOV (SP)+,R0 ;Restore R0 2$: RETURN STORE:: MOVB (R1)+,(R2)+ ;Move the "R SIPP" message into the buffer INC R3 ;Increment byte count CMP R3,#1000 ;End of BUFFER? BNE 3$ ;No, branch CALL WRITIT ;Write it out to the log file 3$: CMP R1,R4 ;End of message? BLO STORE ;No, continue CMP R1,#MSEND ;Yes, was the message ? BEQ 2$ ;Completed storing return MOV #CRLF,R1 ;No, point to message to store MOV #MSEND,R4 ;Point to end of message BR STORE ;Store the message ;+ ;ERROR 4$: .ERR #ERAR,#EMO,LEVEL=F,RETURN=NO,FILE=#OUTFIL ;Output error ;- .DSABL LSB .SBTTL ASCOCT - ASCII to OCTAL conversion routine ;+ ; ASCOCT ; This routine converts a string of ASCII numbers to a double precision ; number. The routine is entered from the GTLIN routine. If a valid ; numerical value was typed the ZERO bit is set in FLGWRD. If is ; typed with no other input the bit is not set. This bit is checked upon ; returning from this routine. ; ;Input: R1 ->the command string from GTLIN ; R4 ->two word area to store the converted result ; ZERO bit is cleared in FLGWRD ; ; CALL ASCOCT ;Convert the input to an octal value ; ;Output:R1 ->one byte beyond the user input ; @R4 contains the converted value ; R2,R3 are destroyed ; C-bit set if illegal character was detected ; C-bit cleared if legal input or ; If only ZERO bit is cleared in FLGWRD ; If numerical input ZERO bit is set in FLGWRD ;- .ENABL LSB ASCOCT::CLR @R4 ;Initialize R4 for number CLR 2(R4) ;and carry word 1$: MOV #3,R0 ;Set count of three for shifting three bits MOVB (R1)+,R3 ;Move character into R3 BEQ 3$ ;If zero end of command line CMPB R3,#'0 ;Is character less than 0? BLO 4$ ;Yes, check for special character CMPB R3,#'7 ;No, is it greater than 7? BHI 4$ ;Yes, check for special character BIS #,FLGWRD ;Set to show we recieved a character BICB #370,R3 ;Make it octal 2$: ASL @R4 ;Multiply by 10(8) ROL 2(R4) ;Shift high order word and add in carry DEC R0 ;Decrement count BNE 2$ ;If not equal, not done shifting ADD R3,@R4 ;Add in the new digit BR 1$ ;and get the next character 3$: TST (PC)+ ;Clear carry for normal return 4$: SEC ;Set carry for char out of numerical range RETURN .DSABL LSB .SBTTL GETDGT - Routine to store ASCII characters for output ;+ ; GETDGT ; This routine converts an octal digit (from byte or word) into ASCII ; characters and stores it for future output. All leading zeros are also ; stored. If the number is two words in length (double precision) only the ; first three digits of the high order word is printed (this includes leading ; zeros). ; ;Input: PNUM1 = Low order word of number to print ; PNUM2 = High order word of number to print ; R2 -> Buffer to store ASCII characters ; ; CALL GETDGT ;Convert to ASCII and store for output ; ;Output:PNUM1 = 0 ; PNUM2 = 0 ; R0 = 0 ; R1 is destroyed ; R2 -> One byte beyond the last stored ASCII character ;- .ENABL LSB GETDGT::CLR R1 ;Initialize word bit count MOV PNUM1,-(SP) ;Put low order word on the stack TSTB FLGWD2 ;Search mode? BMI 3$ ;Yes, only print words. No bytes. BIT #,FLGWRD ;Byte mode? BEQ 3$ ;No, word mode ;+ ; Routine to output bytes with leading zeros. ; ; 246 --- firts digit is the guard bit ; second digit is the count ; third digit is ASCII number ;- MOV #246,R0 ;<<'0+400>/4+400>/2 1$: ASLB R0 ;Set C bit = 1 if first time 2$: ROLB @SP ;Shift number and add carry BEQ 11$ ;If carry clear - done ROLB R0 ;Shift bit and add to digit BCC 2$ ;If clear get next bit else MOVB R0,(R2)+ ;Store the character in the print buffer MOV #23,R0 ;<<'0+400/10+0>/2> BR 1$ ;Convert next 3 bits for ASCII digit ;+ ; Routine to output words with leading zeros. ; ; Print high order word. ;- 3$: MOV PNUM2,R0 ;Get the high order word BEQ 7$ ;If equal one word number MOV #3,R1 ;Skip the first three digits ASL @SP ;Shift out bit 15 of the low order word ROL R0 ;and shift it into the high order word MOV R0,@SP ;Get high order word MOV #30,R0 ;'0/2 - for bit 15 SEC ;Set guard bit to flag finish 4$: ROL @SP ;Get next bit from output word ROLB R0 ;Shift it into ASCII byte DEC R1 ;Decrement the count BGT 5$ ;Greater - don't print the character MOVB R0,(R2)+ ;Store the character in the print buffer 5$: MOV #206,R0 ;'0/10+200 6$: ASL @SP ;Get next bit BEQ 7$ ;If equal, done. Go print out low order word ROLB R0 ;Shift C-bit into ASCII byte BCS 6$ ;If set, get the second bit BR 4$ ;Else get third bit and print it ;+ ; Print low order word. ;- 7$: MOV PNUM1,@SP ;Get the low order word MOV #30,R0 ;'0/2 - for bit 15 SEC ;Set guard bit to flag finish 8$: ROL @SP ;get next bit from output word ROLB R0 ;Shift into ASCII byte TST PNUM2 ;Two word output BNE 9$ ;Yes, skip the first bit MOVB R0,(R2)+ ;Store the character in the print buffer 9$: CLR PNUM2 ;Get this far clear word two to print rest MOV #206,R0 ;'0/10+100 10$: ASL @SP ;Get next bit BEQ 11$ ;Equal - done ROLB R0 ;Shift bit into ASCII byte BCS 10$ ;Branch to get second bit BR 8$ ;Branch to get third bit and print 11$: CLR R0 ;Initialize R0 CLR PNUM1 ;Initialize for future use CLR PNUM2 ;Initialize for future use TST (SP)+ ;Clean up stack RETURN .DSABL LSB .SBTTL DSPLAY - Display routine ;+ ; DSPLAY ; This routine is called to set up a display string of the users input as well ; as the old contents of the opened location. FLGWRD is saved on the stack ; and the ODD and BYTE bits are cleared to force the segment, base, and offset ; to be displayed in word mode. After these values have been stored in the ; diplay buffer the saved FLGWRD is restored for the old value. If in byte ; mode the old contents is stored as a 3 digit value. If in word mode the old ; contents is stored as a 7 digit value. Leading zeros are included in both ; cases. The total display string is stored in CMDBUF. When the display ; string is completed control returns to the caller for printing (.PRINT). ; ;Input: R0 = the old contents of the opened location ; R2 ->the start of the display buffer ; R4 ->the start of the users stored location attributes (SEGNUM) ; ; CALL DSPLAY ;Store location attributes and old contents to display ; ;Output:R0,R1,R4 destroyed ; R2 ->One byte beyond stored display string (after old contents and ; spaces ;- .ENABL LSB DSPLAY::MOV #CMDBUF,R2 ;Point to buffer space to store print string BIT #,FLGWD2 ;Is the header part of the prompt? BEQ 99$ ;No, stuff buffer w/o header for prompt CALL PRHEAD ;Yes, put header in buffer 99$: MOVB #15,(R2)+ ; must be at start of buffer MOV R0,-(SP) ;R0 contains the old contents. Save it. MOV FLGWRD,-(SP) ;Save FLGWRD on stack BIC #,FLGWRD ;Force word mode for display MOV (R4)+,PNUM1 ;Get segment number for print out CMP #SEGNUM+2,R4 ;Are we getting the numbers from storage? BNE 1$ ;No, don't skip next two words CMP (R4)+,(R4)+ ;Point to stored base address TST (R4)+ 1$: TSTB SWITWD ;Is the file overlaid? BPL 2$ ;No, skip segment CALL GETDGT ;Convert to ASCII and store for output CALL SPACE2 ;Print two space 2$: CALL DBSOFF ;Display the base and offset MOV (SP)+,FLGWRD ;Restore FLGWRD BIT #,FLGWRD ;Byte mode? BEQ 4$ ;No, use normal spacing CALL SPACE2 ;Yes, add 2 extra spaces MOVB #SPACE,(R2)+ ;Store a space in the print buffer BIT #,FLGWRD ;Ascii mode? BEQ 4$ ;No, do normal conversion MOVB #74,(R2)+ ;Yes, store a "<" character in the buffer MOV (SP)+,R0 ;Save old contents on stack BICB #200,R0 ;Clear off any extra bytes BITB #140,R0 ;Control character BNE 3$ ;No, skip uparrow stuff TSTB -(R2) ;Point to the < character in the buffer MOVB @R2,-(R2) ;Shift it over a space to line up display TSTB (R2)+ ;Point to next location to store MOVB #'^,(R2)+ ;Yes, store an uparrow ADD #100,R0 ;Make equivalant character 3$: MOVB R0,(R2)+ ;Store the character BR 7$ ;Store > and space and exit 4$: BIT #,FLGWRD ;RAD50 mode? BEQ 8$ ;No, skip RAD50 conversion MOV (SP)+,R0 ;Get the contents to display MOVB #SPACE,(R2)+ ;Print a space to position correctly MOVB #74,(R2)+ ;Print a "<" to start the RAD50 display MOV R2,R1 ;Set up to go to the conversion routine CALL $R50ASC ;Convert a word into RAD50 characters 5$: CMPB (R2)+,#PRCENT ;Is this character %? BNE 6$ ;No, get next character MOVB #DOT,-1(R2) ;Yes, make it a dot (.) instead 6$: CMP R1,R2 ;Are the pointers equal? BNE 5$ ;No, check next character 7$: MOVB #76,(R2)+ ;Print a ">" to close the RAD50 display BR 9$ ;Store a space and exit 8$: MOV (SP)+,PNUM1 ;Get old contents for print out CALL GETDGT ;Convert to ASCII and store for output BR 9$ ;Print one space SPACE2: CALL 9$ ;Execute this routine twice 9$: MOVB #SPACE,(R2)+ ;Store a space in the print buffer RETURN ;Return to caller .DSABL LSB .SBTTL DBSOFF - Display base and offset ;+ ; DBSOFF ; This routine sets up the base and offset to display on the console. ; ;Input: R2 ->Next byte of display buffer to store base and offset values ; R4 ->Low order base in impure area (BASADR) ; ;Output:R2 ->Next available byte in display buffer ; R4 ->NWORD (in impure area) ;- .ENABL LSB DBSOFF::CALL 1$ ;We execute this routine twice 1$: MOV (R4)+,PNUM1 ;Get low order base or offset for print out MOV (R4)+,PNUM2 ;Get high order base or offset for print out BNE 2$ ;If NE don't print extra spaces CALL SPACE2 ;Else, print two spaces MOVB #SPACE,(R2)+ ;Store a space in the print buffer 2$: CALL GETDGT ;Convert to ASCII and store for output CALL SPACE2 ;Else, print two spaces RETURN ;Return to caller .DSABL LSB ;+ ; REVERS ; This routine reverses the modification process. This means if SIPP has ; already installed new contents into a location, REVERS changes it back to ; its original state. SIPP goes through the linked list of information blocks ; and installs the old contents into the file and closes it. ;- REVERS::CALL BLKZRO ;Read in block 0 MOV BUFBEG,R5 ;Point to start of link list BEQ 2$ ;No link blocks - exit 1$: MOV AD0(R5),R0 ;Get low order address of link block MOV AD1(R5),R1 ;Get high order address of link block CALL FNDLOC ;Read in block and point to offset to blk MOV OLDW(R5),@R2 ;Restore old contents of opened location MOV @R5,R5 ;Point to next location BNE 1$ ;Process next link block 2$: .PURGE #0 ;Purge log file if any .CLOSE #3 ;Close input file .EXIT .SBTTL ALLOC - Allocate routine ;+ ; ALLOC ; When this routine has been entered it has been determined that an ; information block must be created to store the attributes of the location ; being modified. This routine to allocates free buffer space for the new ; information blocks. If we are within 5 (information blocks) from the end of ; available core the user is informed of the fact. If the available space is ; full, an the C-bit is set on return. ; ;Input: COUNT = Number of available information blocks ; BUFEND = End of last physical information block in core ; ; CALL ALLOC ;Room for creating info block? ; ;Output:R5 = First available address in core to store attributes (link word) ; COUNT = Number of available information blocks left ; BUFEND =New end of last physical information block ;- .ENABL LSB ALLOC:: TST COUNT ;Is there any space for information blocks? BNE 1$ ;Yes, allocate the space for input ;+ ;ERROR .ERR #ERAR,#EMM,LEVEL=E,RETURN=YES ;Patch buffer full ;- BR 3$ ;Exit this routine 1$: CMP #5,COUNT ;Is the buffer almost full? BLO 2$ ;No, no need to give a warning ;+ ;ERROR .ERR #ERAR,#EML,LEVEL=W,RETURN=YES ;Patch buffer approaching limit ;- 2$: MOV BUFEND,R5 ;Point to next available space for input ADD #24,BUFEND ;Get next location for further input CLR @BUFEND ;Clear contents for end DEC COUNT ;Decrement information block count TST (PC)+ ;Don't set carry (normal return) 3$: SEC ;Error, set carry RETURN ;and return .DSABL LSB ;+ ; PRHEAD ; This routine is called to determine (via the overlay bit in FLGWRD) what ; header to print. The appropriate header is then printed and program control ; returns to the caller. ;- PRHEAD::TSTB SWITWD ;Is it a overlaid file? BMI 1$ ;Yes MOV #HEADR1,R1 ;Point to non-overlaid header BR 2$ ;And get command 1$: MOV #HEADR2,R1 ;Point to overlaid header 2$: MOVB @R1,(R2)+ ;Move header character into the buffer CMPB (R1)+,#'? ;End of header string? BNE 2$ ;No, store next character MOVB #12,(R2)+ ;Store a line feed into the buffer RETURN .SBTTL LIMIT - Boundary check routine ;+ ; LIMIT ; This routine is called by PRIOUT. It checks if a boundary is exceeded or ; must be extended. If the file is non-overlaid, the accumulated address is ; compared against the contents of location 50. If the accumulated address is ; larger, MAXADD (maximum address of file) is compared. If the accumulated ; address exceeds this address an error occurs. If less, location 50 is ; modified to extend the limit to the new address, then execution is returned ; to PRIOUT where the original address is modified. ; ; If overlaid, the accumulated address is examined to determine if the ; modification is to the root. If so, modifying the root of a /O file ; is illegal and an error message is given. If /V overlay only the root ; can be extended to the block boundary. If this is the case, location 50, ; the high limit of the root in the handler and the high limit of the root ; plus /O overlays in the handler are all updated accordingly. If the address ; to modify is in a segment, program control goes to SEGLIM. ; ;Input: store words in impure area. From ADRESS to NWORD. ; ; CALL LIMIT ;Extend the file or segment limit if necessary ; ;Output:Same as when entering routine. ; The c-bit is clear upon leaving this routine unless there is an error. ; Then the c-bit is set ;- .ENABL LSB LIMIT:: JSR R5,SAVREG ;Save all registers MOV BLKNUM,-(SP) ;Save the current block number MOV FLGWRD,-(SP) ;Save current FLGWRD MOV SP,RET ;Save stack for return from error BIC #,FLGWRD ;Make sure FLGWRD shows word operation MOV #HLIMIT,R0 ;Set up for checking modified location 50 TSTB SWITWD ;Overlaid file? BPL 1$ ;No, location 50 is the high limit of program TST SEGNUM ;Is the modification to the root? BNE 3$ ;No, to the segment MOV OVLTBL,R0 ;Get first word of overlay table SUB #<-OVR.ER>,R0 ;Point to high limit in the handler 1$: CLR R1 ;No high order word MOV #CTCHAL+2,R4 ;Set up for return from following call CLR @R4 ;No high order word TST -(R4) ;Point to the low order word CALL CHKLOC ;Has the location been modified? TSTB SWITWD ;Overlaid? BPL 2$ ;No, don,t adjust SUB #2,@R4 ;Contents - 2 is current high limit ;+ ; At this point, CTCHAL [@R4] is the actual limit of the program (root). ;- 2$: MOV #ADRESS,R3 ;Point to the accumulated address TST 2(R3) ;Anything in the high order word of address BNE 7$ ;Yes, automatically too high CMP @R3,@R4 ;Are we beyond the high limit? BLOS RETFIT ;No need to change location 50 et al ;+ ; If the file is non-overlaid at this point the next compare causes execution ; to fall through since both VTBL and OVLTBL are zero. ;- CMP VTBL,OVLTBL ;Only virtual (or no) overlays involved? BNE 8$ ;No, error TSTB SWITWD ;Overlayed? BPL 4$ ;No, use locaion 50 BIT #777,@R4 ;Already a block boundary? BEQ 8$ ;Yes, error can't extend boundary ADD #1000,@R4 ;Bring to next block boundary ADC 2(R4) ;Add carry if any BIC #777,@R4 ;Highest possible limit BR 5$ ;Check if ADRESS has exceeded it 3$: BR SEGLIM ;Need this to avoid addressing err. from MACRO 4$: MOV MAXADD,@R4 ;Set up for common check 5$: CMP 2(R3),2(R4) ;Check for high order of limits BHI 7$ ;Over give error BLO 6$ ;If lower, no need for further check CMP @R3,@R4 ;Check the low order limit BHIS 7$ ;Error - over limit 6$: BIT #,FLGWD2 ;Has the file been extended? BNE UPROOT ;Yes, don't give message BIS #,FLGWD2 ;Set flag to show file extending mes. printed ;+ ;ERROR .ERR #ERAR,#EM7,LEVEL=I,RETURN=YES ;Extending high limit ;- ;+ ; Update the root limit ;- UPROOT::MOV (R3)+,@R4 ;Move in low limit address MOV @R3,2(R4) ;Move in high order address MOV #SEGHGH+2,R3 ;Point to area for scratch CLR @R3 ;No high order word MOV #HLIMIT,-(R3) ;To update location 50 CALL UPDATE ;Go update location 50 TSTB SWITWD ;Overlaid file? BPL RETFIT ;No, restore and return MOV #SEGHGH+2,R3 ;Yes, point to scratch area CLR @R3 ;No high order word MOV OVLTBL,-(R3) ;Get the starting address of the overlay table SUB #-OVR.ER,@R3 ;Make it address to get the root's high limit ADD #2,@R4 ;Must point 1 past the last location MOV @R3,-(SP) ;Save the limit on the stack MOV @SP,R0 ;Set up high limit for CALC CLR R1 ;Set up high order word CALL CALC ;Get most recent contents MOV #SEGHGH,R3 ;Restore R3 (clobbered by CALC) CALL UPDATE ;Set up information block to modify that loc. MOV @SP,R0 ;R0 -> high limit of the root in the handler SUB XYZ,@R4 ;Get difference between old and new root limit TST (R0)+ ;Point to address of high limit of /O's ovly CLR R1 ;Clear high order CALL CALC ;Get current content of location ADD XYZ,@R4 ;Add current contents to the difference MOV #SEGHGH,R3 ;Point to area for calculation MOV (SP)+,@R3 ;Point to overlay segment table ADD #<-OVR.ER+OVR.EO>,@R3 ;Point to the high limit of the /O ovly CALL UPDATE ;Go update it RETFIT: MOV (SP)+,FLGWRD ;Restore old FLGWRD MOV (SP)+,BLKNUM ;Restore old block number CALL BLKSTR ;Read that block back into BUFFER RETURN ;Restore registers and return to caller ;+ ;ERROR 7$: .ERR #ERAR,#EM2,LEVEL=E,RETURN=YES ;Exceeds program limit BR 9$ ;Leave this routine 8$: .ERR #ERAR,#EMT,LEVEL=E,RETURN=YES ;Illegal extension of root seg. ;- 9$: JMP RETF ;Leave this routine .DSABL LSB .SBTTL SEGLIM - Check segment limit routine ;+ ; SEGLIM ; This routine checks if the current location (ADRESS) exceeds the segment ; limit. If so, it checks if it a legal extension and updates the appropriate ; locations if necessary. If it is an illegal extension an error message is ; printed. This routine is called by LIMIT via a BRANCH. ; ;Input: SEGENT = Start of segment table entries for specified segment ; ; BR SEGLIM ;Check segment limits ; ;Output:Same as when entering LIMIT routine. ; The c-bit is clear upon leaving this routine unless there is an error. ; Then the c-bit is set ;- .ENABL LSB SEGLIM::MOV SEGENT,R0 ;Get address of entry of the current seg CLR R1 ;No high order word CALL CALC ;Get current content of location MOV XYZ,-(SP) ;Save the incore address on the stack MOV SEGENT,R0 ;Get address starting entry of segment again CLR R1 ;No high order word ADD #OTB.SZ,R0 ;Make it the address of the segment word count CALL CALC ;Get the most current word count MOV XYZ,R4 ;R4 = segment word size MOV R4,ST ;Save it for later BIT #,FLGWRD ;Is the segment virtual? BEQ 1$ ;No, srch table for biggest seg in this region TST (SP)+ ;Yes, clean up the stack BR 9$ ;and do common stuff 1$: MOV OVLTBL,R0 ;Get the start of the overlay table CLR R1 ;No high order word MOV R0,STD ;Store the low order word CALL CALC ;Read blk into buffer, check for modified loc MOV (SP)+,R3 ;Get the incore address and clean up stack ;+ ; Correct block should already be in BUFFER. No need to read it again. ;- 2$: CALL CALC1 ;Get incore addr of first entry in table CMP R3,XYZ ;In the same region? BEQ 4$ ;Yes CMP R2,#BEND ;Past end of buffer? BMI 3$ ;If mi no CALL UPBLK ;Go get the next block in BUFFER 3$: ADD #OTB.ES,STD ;Point to next entry in file ADD #OTB.ES,R2 ;Point to next entry in buffer BR 2$ ;Process next entry 4$: ADD #OTB.SZ,STD ;Point to size word in file CMP (R2)+,(R2)+ ;Point in BUFFER too CALL CALC1 ;Get the current contents CMP XYZ,R4 ;Is this segment larger than previous one? BMI 5$ ;No MOV XYZ,R4 ;Update the largest word count in this region 5$: CMP R2,#BEND ;Need a new block? BMI 6$ ;If MI no CALL UPBLK ;Go get the next block 6$: ADD #,STD ;Point to next entry in file TST (R2)+ ;Next one in BUFFER CALL CALC1 ;Get the current contents BIT #1,XYZ ;End of table? BEQ 10$ ;If EQ no 7$: MOV R4,CORADD ;Save the size of biggest overlay CMP R4,ST ;Is the overlay we are extending the largest? BEQ 8$ ;Yes, just set update bit BIS #,FLGWD2 ;No, set for last overlay region check BR 9$ ;and skip UOV bit setting 8$: BIS #,FLGWD2 ;Set update size in handler and loc 50 bit 9$: ADD #377,R4 ;Round up to block boundary BIC #377,R4 ;Make it a block boundary BR 11$ ;Done with table 10$: CMP R3,XYZ ;Done? BEQ 4$ ;If EQ no CMP VTBL,STD ;Is this the last /O region BEQ 7$ ;Yes, extend to block boundary is legal 11$: MOV SEGENT,R0 ;Point back to the original entry CLR R1 ;No high order ADD #OTB.SZ,R0 ;Point to segment word count CALL CALC ;Get current contents MOV XYZ,R3 ;R3= current size in words CLR R0 ;No high order ASL R3 ;Make word count into byte count ROL R0 ;Shift in carry ADD SEGLOW,R3 ;Add in segment start ADC R0 ;Add carry to high order ADD SEGLOW+2,R0 ;Add in high order MOV #ADRESS+2,R1 ;Point to high order word of accum address CMP @R1,R0 ;Compare high order words BHI 13$ ;If high, need boundary check BLO 12$ ;If low no boundary condition just return CMP -2(R1),R3 ;Compare the low order word of accum address BHIS 13$ ;If high or same, need boundary check 12$: JMP RETFIT ;+ ; Check if the attempted extension is legal. ;- 13$: CLR R0 ;Initialize R0 for high order byte conversion ASL R4 ;Convert word size to bytes ROL R0 ;Shift carry into high order ADD SEGLOW,R4 ;Highest possible address ADC R0 ;Add carry into high order ADD SEGLOW+2,R0 ;Double precision add BIT #777,-(R1) ;Already at boundary? BEQ 18$ ;Yes, give segment boundary error MOV (R1)+,R2 ;Restore to point to the original accum addr MOV @R1,R1 ;Get high limit ADD #1000,R2 ;Point to end of block ADC R1 ;Add in carry BIC #777,R2 ;Make block boundary by clearing garbage bits CMP R0,R1 ;Which is smaller, to block boundary or until ;size of biggest segment in region? BHI 15$ ;If HI use R2,R1 (block boundary) BLO 14$ ;If LO use R4,R0 (biggest segment in region) CMP R4,R2 ;Compare the low order BHIS 15$ ;If HIS use R2,R1 (block boundary) 14$: MOV R4,R2 ;Else use biggest segment in region (R4,R0) MOV R0,R1 ;High order 15$: CMP ADRESS+2,R1 ;Legal extension? BHI 18$ ;If HI no BLO 16$ ;If low, it's ok. Don't check low order CMP ADRESS,R2 ;Check low order word BHIS 18$ ;If HIS illegal 16$: BIT #,FLGWD2 ;Has this segment been extended? BNE 17$ ;Yes, don't give message BIS #,FLGWD2 ;Set flag to show segment extention ;+ ;ERROR .ERR #ERAR,#EM6,LEVEL=I,RETURN=YES ;Extending overlay segment ;- 17$: MOV R2,R0 ;Get the low order maximum extension SUB ADRESS,R0 ;Subtract current position SBC R1 ;Subtract carry SUB ADRESS+2,R1 ;Subtract high order BNE UPS ;If high order non-zero, not near boundary CMP R0,#10. ;Near 5 words of boundary? BHI UPS ;No, skip message ;+ ;ERROR .ERR #ERAR,#EM0,LEVEL=I,RETURN=YES ;Approaching segment boundary BR UPS ;Update the segment limit 18$: .ERR #ERAR,#EM5,LEVEL=E,RETURN=YES ;Exceeds segment boundary ;- RETF: MOV RET,SP ;Point stack to necessary stack information MOV (SP)+,FLGWRD ;Restore old FLGWRD MOV (SP)+,BLKNUM ;Restore old block number CALL BLKSTR ;Read that block back into BUFFER SEC ;Set C-bit for error RETURN ;Restore registers and return to caller .DSABL LSB .SBTTL UPS - Update segment limit routines ;+ ; UPS ; This routine is the driver for updating the overlay table, handler, WDB's, ; and region definition block. ; ;Output:R0,R1 are destroyed ; all others are restored ;- .ENABL LSB UPS:: MOV FLGWD2,-(SP) ;Save flag word 2 BIC #,FLGWD2 ;Clear this regardless for this pass BIT #,FLGWRD ;Is it a virtual word count? BEQ 1$ ;No, /O word count BIS #,FLGWD2 ;Yes, set round up bit (32. word round up) 1$: CALL UPSEG ;Go update the limit in overlay table MOV (SP)+,FLGWD2 ;Restore the flag word BIT #,FLGWRD ;Is it a virtual one? BEQ 5$ ;If EQ no MOV SEGENT,R0 ;Point to table entry CLR R1 ;No high order CALL CALC ;Get the pointer to the WDB MOV SEGENT,-(SP) ;Save SEGENT MOV XYZ,SEGENT ;Point to WDB BIS #,FLGWD2 ;Say its a WDB size(WDB SIZE=BYTES/32.) CALL UPSEG ;Go get the WDB and update it TST ST ;Did we change the size in WDB? BLE 4$ ;No, clean up and leave this routine ADD #,SEGENT ;Update length to map CALL UPSEG ;Update it MOV #CORADD,R4 ;Point to store area for new offset in region MOV OVLTBL,R0 ;Get start of overlay table CLR R1 ;Clear for high order calculations SUB #-OVR.EW,R0 ;Point to the end of WDB's in handler CALL CALC ;Read blk into buffer, check for modified loc MOV XYZ,STD ;Store pointer to end of the WDB's in handler MOV @SP,R0 ;Get the start of the current segment entry CALL CALC ;Read blk into buffer, check for modified loc MOV XYZ,R0 ;R0 -> WDB ADD #W.NOFF,R0 ;Now point to the offset into the region CALL CALC ;Read blk into buffer, check for modified loc MOV XYZ,SEGLST ;Store the offset into the region 2$: ADD #W.NLGH,R0 ;Point to offset into the region of next WDB CMP R0,STD ;End of WDB table? BHI 3$ ;Yes, blow this garage CALL CALC ;Read blk into buffer, check for modified loc CMP XYZ,SEGLST ;Does this WDB need updating? BEQ 2$ ;No, get next WDB MOV XYZ,@R4 ;Get most recent offset into region of WDB ADD SEGEND,@R4 ;Calculate new value (SEGEND is difference) MOV #CTCHAL,R3 ;Point to area for in file address MOV R0,@R3 ;Set up in file address for UPDATE CLR 2(R3) ;No high order word CALL UPDATE ;Update the location MOV @R3,R0 ;Restore the low CLR R1 ;and high order words BR 2$ ;Go get next WDB 3$: MOV OVLTBL,SEGENT ;Point to overlay table SUB #<-OVR.RS>,SEGENT ;Point to region size in handler MOV SEGENT,R0 ;Set up for CALC CLR R1 ;No high order CALL CALC ;Get the current contents MOV XYZ,@R4 ;Initialize new contents SUB #4,SEGENT ;Set up for common code in update BIS #,FLGWD2 ;Say its a RDB CALL UPSEG ;Update it 4$: MOV (SP)+,SEGENT ;Restore BIC #,FLGWD2 ;Clear the divide by 32. flag 5$: BIT #,FLGWD2 ;Update the handler? BEQ 6$ ;If EQ no CALL UPSEG ;Update the handler words 6$: BIC #,FLGWD2 ;Reset bit JMP RETFIT ;Split .DSABL LSB .SBTTL UPSEG - Set up parameters for UPDATE ;+ ; UPSEG ; This routine will set up the appropriate parameters for UPDATE. ; All registers are used ; ;Input: R4 -> new contents ; R3 -> address to modify ;- .ENABL LSB UPSEG:: MOV #CTCHAL,R5 ;Point to area for calculations BIT #,FLGWD2 ;Updating a region definition block? BNE 4$ ;Yes, process RDB MOV #ADRESS,R4 ;No, point to the accumulated address MOV (R4)+,(R5)+ ;Move in the low order high limit of segment MOV @R4,@R5 ;and the high order ADD #2,-(R5) ;Update the high limit ADC 2(R5) ;add carry to high order MOV #SEGLOW,R4 ;Point to stored segment start address CALL DPSUB ;Get the offset (in bytes) MOV R5,R4 ;Set up R4 for further calculations ASR 2(R4) ;Now divide byte offset by 2 ROR @R4 ;to give word offset BIT #,FLGWD2 ;Was this in the biggest overlay region BEQ 2$ ;No, skip check CMP CORADD,@R4 ;Is the new size bigger than the old size? BHIS 1$ ;No, don't update program limits BIS #,2(SP) ;Set to update program limit 1$: BIC #,2(SP) ;Clear the check bit 2$: BIT #,FLGWD2 ;Is this a WDB? BEQ 5$ ;No WDB ;+ ; Divide by 32. ;- ADD #37,@R4 ;Round up to 32. word boundary BIC #37,@R4 ;Round up to 32. word boundary MOV #5,R0 ;Set up count for divide 3$: ASR 2(R4) ;Now divide byte offset by 2 ROR @R4 ;to give word offset DEC R0 ;Decrement the count BNE 3$ ;Continue loop until count is 0 MOV @R4,SEGEND ;Get new contents of window size SUB XYZ,SEGEND ;Subtract MOST RECENT to get difference BR 5$ ;Finish WDB update 4$: BIC #,FLGWD2 ;Clear the WDB flag ADD SEGEND,@R4 ;Add the difference in size to word count ADC 2(R4) ;Add in carry CMP #6000,@R4 ;Overflowed 96K? BHIS 5$ ;No, error message not needed ;+ ;ERROR .ERR #ERAR,#EMU,LEVEL=E,RETURN=YES ;Region size exceeds 96K ;- 5$: BIT #,FLGWD2 ;Round up virtual word count? BEQ 6$ ;No, don't round up ADD #<37>,@R4 ;Round up to 32 word boundary BIC #<37>,@R4 ;Clear low bits 6$: MOV #SEGHGH+2,R3 ;Point to area for calculation CLR @R3 ;No high order MOV SEGENT,-(R3) ;Get start of entries for specified segment ADD #OTB.SZ,@R3 ;Make it the address of the segment word count ADC 2(R3) ;High order too BIT #,FLGWD2 ;Extending the last overlay size? BEQ 7$ ;No, just update the word count MOV OVLTBL,@R3 ;Yes, get the start of the overlay table CLR 2(R3) ;No high order word SUB #-OVR.EO,@R3 ;Make it the address for the size word in hndl SBC 2(R3) ;High order MOV #CTCHAL,R5 ;Point to area for calculations MOV (R4)+,@R5 ;R5 -> New largest segment in the region CLR 2(R5) ;Clear high order SUB CORADD,@R5 ;Subtract previous largest seg. size in region ASL @R5 ;Convert words to bytes MOV R5,R4 ;R4 must contain accumulated address to update 7$: CALL UPDATE ;Update the location with new contents RETURN .DSABL LSB .SBTTL UPDATE - Update locations to extend limits ;+ ; UPDATE ; If this routine is entered a limit has been exceeded and other locations ; must be modified to reflect the new limits (whether it is location 50, ; overlay table, handler, or WDB. This routine may be entered many times for ; one user change. ; First, the contents of the current modification block are saved on tne stack ; and the storage locations are cleared. ; ;Input: R3 -> 2 words of double precisioned accumulated address ; R4 -> New contents to store in the accumulated address (from R3) ; ; CALL UPDATE ;Update the location with new contents ; ;Destroys R0,R1,R2,R4,R5 ;- .ENABL LSB UPDATE::MOV #ADRESS,R5 ;Point to start of variable list MOV @R5,-(SP) ;Save the low order address MOV (R3)+,(R5)+ ;Move in new low order address MOV @R5,-(SP) ;Save the high order address MOV @R3,(R5)+ ;Move in new high order address TST -(R3) ;Point to start of stored new address 1$: MOV @R5,-(SP) ;Save the rest of the variables CLR (R5)+ ;and clear that location CMP #NWORD+4,R5 ;End of list? BHI 1$ ;No,continue saving ;+ ; The accumulated address has already been stored. Now store the new offset ; (same as accumulated address), and new value. ;- MOV #OFFSET,R5 ;Point to OFFSET to store MOV (R3)+,(R5)+ ;Move in new low order address into OFFSET MOV (R3)+,(R5)+ ;Move in new high order address into OFFSET+2 MOV @R4,@R5 ;Move the new contents in next locations MOV -(R3),R1 ;Get the high limit MOV -(R3),R0 ;Get location to modify (low order) CALL CALC ;Read blk into buffer, check for modified loc BIT #,FLGWD2 ;Changing contents in a window definition blk? BEQ 2$ ;No, check if modifying handler word CMP @R4,XYZ ;Yes, is size change needed? BLOS 5$ ;No, just restore contents leave this routine 2$: BIT #,FLGWD2 ;Updating the handler word? BEQ 3$ ;No, just enter stored info into link list ADD XYZ,@R4 ;Calculate the new contents of size word CALL LINK ;Store high address of /O in handler BCS 4$ ;Error returned, don't install change SUB #2,@R4 ;Calculate new value for location 50 MOV #HLIMIT,R0 ;Get location 50 to get current contents CLR R1 ;No high order CALL CALC ;Read blk into buffer, check for modified loc MOV R0,ADRESS ;Set up to store in LINK MOV R0,OFFSET ;Set up to store in LINK BIC #,FLGWD2 ;Clear flag 3$: CALL LINK ;Create or update the information block BCC 5$ ;No error 4$: JMP RETF ;Error, exit for lack of space 5$: MOV @R4,ST ;Get the size SUB XYZ,ST ;Calculate the difference MOV #NWORD+4,R5 ;Set up to restore old contents in store area 6$: MOV (SP)+,-(R5) ;Restore location CMP #ADRESS,R5 ;Done yet? BLO 6$ ;No, branch for more RETURN .DSABL LSB .SBTTL CALC and CALC1 - Get current contents ;+ ; CALC1 ; Get the most recent contents of the location specified in STD and STD1 ; (double precision). Return the contents in XYZ. This routine assumes the ; the correct block has already been read into the buffer, and the address to ; check is within that block (contents of R2). ; ;Input: STD = actual location in question (low order word) ; R2 -> Location in BUFFER coresponding to contents in STD and STD2 ; ; CALL CALC1 ;Get most recent contents of location ; ;Output:XYZ = most recent contents of location ; Destroyes R0,R1 and R5 ;***************************************************************************** ; CALC ; This routine forces a read of one block into the buffer. The block ; corresponds to the address in R0 and R1. XYZ contains the most recent ; contents of the location. ; ;Input: R0 = actual location in question (low order word) ; R1 = actual location in question (high order word) ; ; CALL CALC ;Read blk into buffer, check for modified loc ; ;Output:XYZ = most recent contents of location ; Destroyes R0,R1 and R5 ;- .ENABL LSB CALC1:: MOV STD,R0 ;R0 points to the low order word CLR R1 ;No high order word BR 1$ ;Just compare. Don't read in new block CALC:: MOV R0,-(SP) ;Save the low order on the stack MOV R1,-(SP) ;Save the high order word on the stack CALL FNDLOC ;Read in block and point to offset to blk MOV (SP)+,R1 ;Restore high order word MOV (SP)+,R0 ;Restore the low order word 1$: MOV @R2,XYZ ;Get the original contents into XYZ CALL CMPARE ;See if the location has been modified BCC 2$ ;If c-bit clear, no. Contents from file MOV NEWW(R5),XYZ ;Location been modified, get new content 2$: RETURN .DSABL LSB .SBTTL CHKLOC - Check for previous location modification ;+ ; CHKLOC ; This routine searches the linked information blocks to make sure the ; location passed in R0 and R1 has not been modified. If it has, the new ; contents is moved into @R4. If it hasn't, the block containing the location ; in question is read into BUFFER and the contents is moved into @R4. ; ;Input: R0 = Low order word of location to examine ; R1 = High order word of location to examine ; R4 -> Two store words for returned contents ; ; CALL CHKLOC ;Has the location been modified? ; ;Output:R4 -> contents of location entered in R0 and R1 ; R0,R1,R2,R5 are corrupted if the location was not previously modified. ;- .ENABL LSB CHKLOC::CALL CMPARE ;See if modified BCC 1$ ;Not modified. Get addr from file ; BCS ;Location is modified. Get addr.from link blk MOV NEWW(R5),@R4 ;Take the modified contents for compare BR 2$ ;Go compare for limit extension 1$: CALL FNDLOC ;Read the block into the buffer MOV @R2,@R4 ;Make it equivalent to new contents 2$: CLR 2(R4) ;Clear high order word since there isn't any RETURN .DSABL LSB .SBTTL Double precision operations ;+ ; The following routines are double precision arithmetic operations. ; ; WDBTOP ; The following routine increments (adds or subtracts) the contents of R5 by ; one (byte) or two (word). ;- .ENABL LSB WDBTOP::MOV #INCDEC,R4 ;Increment the contents by one byte or word BIT #,FLGWRD ;Is this a byte or word increment? BNE 1$ ;Byte CALL 1$ ;Word 1$: CALL @OPWRD ;Do double precision add or subtract RETURN ;+ ; DPADD ; Double precision add. Upon return R5 points to the new stored value (low ; order word). R4 remains unchanged. ;- DPADD:: ADD @R4,@R5 ;Add low order ADC 2(R5) ;Add the carry ADD 2(R4),2(R5) ;Add high order BR 4$ ;and return ;+ ; DPSUB ; Double precision subtract. Upon return R5 points to the new stored value ; (low order word). R4 remains unchanged. ;- DPSUB:: SUB @R4,@R5 ;Subtract low order SBC 2(R5) ;Subtract the carry SUB 2(R4),2(R5) ;Subtract high order BR 4$ ;and return ;+ ; DIV ; Double precision divide routine. ; ;Input: R0 = low order word to divide ; R1 = high order word ; R3 = Divisor ; ; CALL DIV ;Perform double precision divide ; ;Output:R0 = Result ; R2 = remainder ; R1 is destroyed ;- DIV:: MOV #40,-(SP) ;Set up loop - double precision count (bits) CLR R2 ;Clear for remainder 2$: ASL R0 ;Double precision left shift ROL R1 ROL R2 CMP R2,R3 ;Subtract out divisor BLO 3$ ;Low, don't subtract SUB R3,R2 ;Subtract it INC R0 ;Add in low bit 3$: DEC @SP ;Decrement the loop count BGT 2$ ;If greater there's more to go TST (SP)+ ;Clean up stack 4$: RETURN ;Return .DSABL LSB ;+ ; DPMULT ; Double precision multiply subroutine to convert a block number into an ; address. The high byte of low order word (block number) is moved into the ; low byte of the high order word. The low order word shifts left and the ; c-bit is shifted into the high order word. This effectively shifts the block ; number 9 times (multiplies by 1000). ; ;Input: First word contains block number [-2(R3)] ; R3 -> Second word (high order) of two store words to multiply by 1000 ; ; CALL DPMULT ; ;Output:R3 -> Store locations. Now contains the address. ;- DPMULT::CLR @R3 ;Nothing in the high word TSTB -(R3) ;Point to high byte of low word MOVB (R3)+,(R3)+ ;Move it into the low byte of the high word TSTB (R3)+ ;Point beyond high word CMP -(R3),-(R3) ;Point to the beginning of the low word SWAB @R3 ;Move the low byte to the high byte of word CLRB @R3 ;Clear the low order before shift ASL @R3 ;Shift the low order word ROL 2(R3) ;and shift the C-bit into the high order word RETURN ;+ ; SUBOP ; Set up for double precision subtract of the offset. Subtract one for byte ; and 2 for word. ;- SUBOP: MOV #OFFSET,R5 ;Set up pointer to OFFSET for decrement MOV #DPSUB,OPWRD ;Do a subtract CALL WDBTOP ;Decrement by word or byte RETURN .SBTTL ASCR50 - ASCII to RAD50 conversion routine ;+ ; ASCR50 ; The ACSII to RAD50 routine converts three ASCII characters pointed to ; to one RAD50 word contained in R4. Imbedded spaces are kept intact. S ; are filled in if less than 3 ascii characters are passed. The following ; a list of all the legal RAD50 characters: ; ;*********************************************************************** ; CHARACTER ASCII OCTAL RADIX-50 ; EQUIVALENT EQUIVALENT ;*********************************************************************** ; space 40 0 ; $ 44 33 ; % 45 34 ;This charater is converted ; ;to a RAD50 dot ; * 52 35 ; . 56 34 ; 0-9 60-71 36-47 ; A-Z 101-132 1-32 ;*********************************************************************** ; ;Input: R1 -> The area containing the ASCII characters ; R4 -> Storage area for RAD50 word ; ; CALL ASCR50 ;Convert 3 ASCII characters to a RAD50 word ; ;Output:R1 -> One byte past the three ASCII characters ; R4 -> The RAD50 converted word (stored) ; C-bit Clear if the input contained legal RAD50 characters ; Set if input contained an illegal character ;- .ENABL LSB ASCR50::MOV #3,R3 ;Number of characters to convert 1$: CLR R0 ;Clear accumulator TSTB @R1 ;End of output? BNE 2$ ;No, don't fill with spaces MOVB #SPACE,@R1 ;Yes, fill with a blank (space) CLRB 1(R1) ;Set up a dummy end of line 2$: MOVB (R1)+,R0 ;Get a character SUB #40,R0 ;Subtract 40 from the character BEQ 7$ ;The character is a space. Include it SUB #4,R0 ;Subtract 4 from what is left BEQ 5$ ;ASCII $, convert to 33 (RAD50) DEC R0 ;Check for % character BEQ 4$ ;ASCII % Treat as ASCII dot cvrt to 34 (.) SUB #5,R0 ;Subtract 5 from whatever is left BEQ 3$ ;ASCII *, convert to 35 (RAD50) SUB #4,R0 ;Subtract 4 from whatever is left BEQ 4$ ;ASCII dot (.), convert to 34 (RAD50) SUB #2,R0 ;Subtract 2 from whatever is left BLO 8$ ;If lower the character is illegal CMP #11,R0 ;Is the character numerical? BLO 6$ ;No, check for upper case alpha character INC R0 ;Numerical increment by 1 (36-47) 3$: INC R0 ;RAD50 asterisk (35) 4$: INC R0 ;RAD50 dot (34) 5$: ADD #33,R0 ;RAD50 dollar (33) BR 7$ ;Include it into the RAD50 word 6$: SUB #20,R0 ;Subtract 17 from whatever is left BLOS 8$ ;If lower or same the character is illegel CMP #32,R0 ;Is it an upper case alpha character? BLO 8$ ;No, must be an illegal RAD50 character 7$: ASL @R4 ;Multiply by 2 ASL @R4 ;Multiply by 4 ASL @R4 ;Multiply by 10 MOV @R4,-(SP) ;Save it ASL @R4 ;Multiply by 20 ASL @R4 ;Multiply by 40 ADD (SP)+,@R4 ;Multiply by 50 ADD R0,@R4 ;Add in the next character DEC R3 ;Done? BNE 1$ ;No, continue conversion TST (PC)+ ;Skip next instruction and clear c-bit 8$: SEC ;Set c-bit for error RETURN ;Yes, exit this routine .DSABL LSB .SBTTL CHKC - Check for intentional CTRL/C ;+ ; CHKC ; This routine is entered if two control C's are typed. First, the input ; buffer is purged (first .TTINR). The 'Are you sure' message is sent to ; the terminal and a .TTYIN request is used to get the first character of the ; response. TTINR is used to purge the buffer of all other input. The ; response is then examined to see if it is a CTRL/C. If it is the prompt is ; re-printed and another response is required. If not CTRL/C, R0 (the ; character) is examined for a Y (yes) response. If it is, the C-bit is ; set and control returns to the caller. Any other response causes the c-bit ; to be cleared upon return. ; ; CALL CHKC ;See if CTRL/c was intentional ; ;Output:C-bit is set if the response is yes ; C-bit clear if response is other than yes (except CTRL/C) ; R0 is destroyed ;- .ENABL LSB CHKC:: BIS #100,@#JSW ;Set special mode bit for .TTINR .TTINR ;Keep getting char. until nothing left BCC CHKC ;Recieved a character, go get another ; BCS ;No more characters 1$: CLR R0 ;Set up R0 to .PRINT ;print .PRINT #RUSURE ;Print the prompt 2$: .TTYIN ;Get characters until non-CTRL/C MOV R0,-(SP) ;Save non-CTRL/C character 3$: .TTINR ;Get rid of all characters for buffer BCC 3$ ;More characters MOV (SP)+,R0 ;Get the character CMPB #3,R0 ;Was CTRL/C in the buffer? BEQ 1$ ;Yes do another TTYIN to get character CLR STATWD ;Clear SCCA status word BIC #100,@#JSW ;No more special mode CMPB R0,#'Y ;Was reponse yes BEQ 4$ ;No, disregard CTRL/C and continue TST (PC)+ ;Skip next instruction and clear C-bit 4$: SEC ;Set C-bit if yes RETURN .DSABL LSB .SBTTL Save and restore registers subroutine ;+ ; SAVREG ; Called by a JSR R5,SAVREG instruction. ; Saves registers 2 - 5 on the stack, and restores them when the next RTS PC ; instruction is executed. ;- SAVREG::MOV R4,-(SP) MOV R3,-(SP) MOV R2,-(SP) MOV R5,-(SP) CALL @(SP)+ RESTOR::MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 MOV (SP)+,R5 RETURN .SBTTL Messages .PSECT MESS .NLIST MEB .NLIST BEX SIPPV: .NLCSI PATLEV=:.-2 ;+ ;ERROR MSGLST MSGTAB ERRMSG EM0 ;Level I ERRMSG EM1 ;Level F ERRMSG EM2 ;Level E ERRMSG EM3 ;Level E ERRMSG EM4 ;Level F ERRMSG EM5 ;Level E ERRMSG EM6 ;Level I ERRMSG EM7 ;Level I ERRMSG EM8 ;Level F ERRMSG EM9 ;Level E ERRMSG EMA ;Level F ERRMSG EMB ;Level E ERRMSG EMC ;Level E ERRMSG EMD ;Level E ERRMSG EME ;Level E ERRMSG EMF ;Level F ERRMSG EMG ;Level E ERRMSG EMH ;Level I ERRMSG EMI ;Level E ERRMSG EMJ ;Level E ERRMSG EMK ;Level E ERRMSG EML ;Level W ERRMSG EMM ;Level E ERRMSG EMN ;Level F ERRMSG EMO ;Level F ERRMSG EMP ;Level E ERRMSG EMQ ;Level F ERRMSG EMR ;Level E ERRMSG EMS ;Level F ERRMSG EMT ;Level E ERRMSG EMU ;Level E ERRMSG EMV ;Level E ERRMSG EMW ;Level I ERRMSG EMX ;Level F ERRMSG EMY ;Level F .EVEN MSGEND ;- SPP:: .ASCII \?SIPP-\ ;Prefix string LEV:: .ASCII \X-\<200> ;Level string ERROPT: .ASCII \ \<200> ;Switch value for error purposes .EVEN ERAR:: .BYTE 0 ;Error code number .BYTE 0 ;Ascii char level.High bit set if ;taking abort .WORD SPP ;Pointer to prefix string .WORD LEV ;Pointer to level byte .WORD MSGTAB ;Pointer to start of error messages .WORD 0 ;Pointer to file name. Filenames in ;messages are not needed .WORD START ;Pointer to abort return CHKPMT: .ASCIZ <15><12>/Checksum? /<200> CHKRET: .ASCIZ <15><12>/Checksum = /<200> BASPMT: .ASCIZ /Base? /<200> SEGPMT: .ASCIZ /Segment? /<200> OFFPMT: .ASCIZ /Offset? /<200> HEADR1: .ASCIZ <15><12>/ Base Offset Old New?/ HEADR2: .ASCIZ <15><12>/Segment Base Offset Old New?/ RUSURE: .ASCIZ /SIPP - Are you sure? /<200> SRCPMT: .ASCIZ /Search for? /<200> STRPMT: .ASCIZ /Start? /<200> ENDPMT: .ASCIZ /End? /<200> FNDAT: .ASCIZ /Found at /<200> RSIPP: .ASCII /R SIPP/ UPZ: .ASCII /^Z/ UPY: .ASCII /^Y/ UPC: .ASCII /^C/ CRLF: .ASCII <15><12> MSEND: .BYTE 0 .EVEN .LIST BEX .SBTTL Tables for SIPP operations .PSECT IMPURE ;+ ; Table of valid switches ;- SWITCH::'A,SLASHA ;Non-file structured 'C,SLASHC ;Checksum? 'D,SLASHD ;Checksum= 'L,SLASHL ;Create log file only .WORD 0 ;End of table DTABLE: .WORD CTRLC ;Control-C .WORD CTRLY ;Control-Y .WORD CTRLZ ;Control-Z .WORD SLASH ;Slash (word) .WORD COLON ;Colon .WORD SEMIC ;Semi-colon .WORD BACKSL ;Back-slash (byte) .WORD UPAROW ;Uparrow ;+ ; Table of valid commands which are preceeded by a semi-colon. The ordering ; are directly related to SCRTN. Any modification of this table must also be ; made in SCRTN. ;- SEMIT:: .BYTE 'A,'O,'R,'S,'V .BYTE 0 ;End of table .EVEN ;+ ; Table of entry points to routines called from a command preceeded by ; a semi-colon. This table is directly related to SEMIT and any modification ; of this table must also be reflected in SEMIT. ;- SCRTN:: .WORD A$ ;Display or insert ASCII .WORD O$ ;Display or insert OCTAL (default) .WORD R$ ;Display or insert RAD50 .WORD S$ ;Request for search mode .WORD V$ ;Display all modified locations and contents ;+ ; Local data - Modifier table for CRC-16 checksum ;- CTABLA: .WORD 0 ;First half of table .WORD 140301 .WORD 140601 .WORD 500 .WORD 141401 .WORD 1700 .WORD 1200 .WORD 141101 .WORD 143001 .WORD 3300 .WORD 3600 .WORD 143501 .WORD 2400 .WORD 142701 .WORD 142201 .WORD 2100 CTABLE: .WORD 0 ;Second half of table .WORD 146001 .WORD 154001 .WORD 12000 .WORD 170001 .WORD 36000 .WORD 24000 .WORD 162001 .WORD 120001 .WORD 66000 .WORD 74000 .WORD 132001 .WORD 50000 .WORD 116001 .WORD 104001 .WORD 42000 .SBTTL Program storage allocations ;+ ; The next fourteen words must be kept together and in this sequence ;- ADRESS::.WORD 0 ;Contains low order accum. address to modify ADRES1::.WORD 0 ;Contains high order accum. address to modify SEGNUM::.BLKW 2 ;User specified overlay segment number SEGLOW::.BLKW 2 ;Low limit of overlay segment BASADR::.BLKW 2 ;Base address (double precision) OFFSET::.BLKW 2 ;Offset (double precision) NWORD:: .BLKW 2 ;User specified new word for accum addr INCDEC: .WORD 1 ;Increment or decrement by one .WORD 0 ;Must be zero to avoid carry ;+ ; The next block of words is set up for Rad50 to ASCII conversion. It is also ; used for the status area for .DSTATUS (first 4 words) and a temporary area ; for calculations in SEARCH (first 2 words). ;- SCHCAL:: ;Uses first 2 words DSTA:: ;Uses first 4 words R50CVT::.BLKW 10 ;Storage for RAD50 to ASCII conversion(all 10) ;+ ; PNUM1 to VTBL must stay together. These next 7 words are cleared in a loop ; in the READ0 routine. ;- PNUM1:: .WORD 0 ;Low order word to convert to ASCII PNUM2:: .WORD 0 ;High order word to convert to ASCII SEGENT::.WORD 0 ;Starting location of enties for specified seg SEGHGH::.BLKW 2 ;Scratch area for LIMIT OVLTBL::.WORD 0 ;Contains start of program overlay table VTBL:: .WORD 0 ;Contains start of virtual overlay table ;+ ; End of critical stuff ;- SVSP:: .WORD 0 ;Store area for start of stack ST:: .WORD 0 ;Storage for RDB update difference STD:: .WORD 0 ;Storage for INFILE addr when searching OVTBL XYZ:: .WORD 0 ;Most recent content of a given loc.(see CALC) SVCA:: .BLKW 2 ;Saved incore address of the current segment SNUM:: .WORD 0 ;Temporary segment count CURENT::.WORD 0 ;Current pointer to link block OPWRD: .WORD 0 ;Location for double precision add or subtract CHKNUM::.WORD 0 ;Checksum RET: .WORD 0 ;Save stack pointer when entering LIMIT MAXBLK::.WORD 0 ;Maximum block size of device or file MAXADD::.BLKW 2 ;Maximum address of device or file BLKNUM::.WORD 0 ;Block number coresponding to what's in BUFFER SWITWD::.WORD 0 ;Flag word for valid switches FLGWRD::.WORD 0 ;Status word for SIPP FLGWD2::.WORD 0 ;An extention to the status word for SIPP SRCHWD::.WORD 0 ;Word to search for SRCHST::.BLKW 2 ;Start loc. for search (dbl prec.) inclusive SRCHED::.BLKW 2 ;End loc. for search (dbl prec.) exclusive CORADD::.BLKW 2 ;Incore address of segment in search ;also used in SEGLIM SSEG1:: .WORD 0 ;Specified starting segment number in search SSEG2:: .WORD 0 ;Specified ending segment number in search SEGLST::.BLKW 2 ;Start of segment boundary if file (SEARCH) ;also used in SEGLIM SEGEND::.BLKW 2 ;Last location in current seg being searched ;also used in SEGLIM CTCHAL::.BLKW 2 ;Two word area for calculations COUNT:: .WORD 0 ;Total information blocks available BUFBEG::.WORD 0 ;This word will be the beginning location of ;storage buffer (1st location after handler) BUFEND::.WORD 0 ;The actual end of storage buffer STATWD::.WORD 0 ;Terminal status word for CTRL/C DEFLTX: .RAD50 'SAV' ;Default file extension for CSIGEN .RAD50 'COM' INFIL:: .BLKW 4 ;Name of file to patch OUTFIL::.BLKW 4 ;Patch file name EMTBLK: .BLKW 10 ;Block for EMT's BUFFER::.BLKW 256. ;Buffer space BEND: .BLKW 6 ;Extra buffer space to examine ovly tbl easily RTVR: .BLKW ;RT version/release info RNAMBK: .BLKW 2*4 ;Rename dblk for protection check DESTAT: .BLKW ;Directory entry status from rename LMT:: .LIMIT ;First word is low limit; second high limit ;If more patch space is needed, more than 128. ;you can update the second word up to the end ;of the block .END SIPP