This is the standard RIM loader. It executes words from paper tape after waiting for the next word to be ready. Typically the format will be a series of DATAI followed by the word to be read into memory, but more creativity is possible.
20 710600 000060 CONO PTR,60 / init paper tape reader 21 710740 000010 A: CONSO PTR,10 / wait for next word 22 254000 000021 JRST .-1 23 710440 000026 DATAI PTR,B / read word to be executed into B 24 710740 000010 CONSO PTR,10 / wait again 25 254000 000024 JRST .-1 26 000000 000000 B: 0 / the instruction from tape, usually DATAI and a JRST at the end 27 254000 000021 JRST A / get next instruction
The DECtape is expected to have CONOs in the interblock words that move it to block 75 (octal). Block 75 then should contain a boot loader that loads blocks 76 and 77 (MACDMP) into memory and jump there. Such a tape can be generated by SYSENG; SYSTEM GEN.
The shadow loader looks like this, its job is to execute block 75:
00 255000 000000 JFCL / no-op, what for? 01 205000 255000 MOVSI (JFCL) / restore JFCL in 0 02 700200 635550 CONO 635550 / reset APR 03 700600 011577 CONO PI,11577 / reset PI 04 721200 223110 CONO UTC,223110 / 300ms delay, move forward, read all 05 720200 004010 CONO DC,4010 / input 06 720340 001000 LUP: CONSO DC,1000 / wait for word 07 254000 000006 JRST .-1 10 720040 000013 DATAI DC,A / read word 11 345540 000006 AOJGE A,LUP / add one, ignore positive words 12 602540 777777 TRNE A,-1 / execute if right half wasn't -1 13 000000 000013 A: . 14 254000 000006 JRST LUP
Since the read all operation is used, not only data but also block marks, reverse block marks and interblock words are read. Block marks are 0-1101 (octal), i.e. the left half is always zero, and the corresponding reverse block mark consequently has -1 in the right half. The AOJGE and TRNE check makes sure these types of words are not executed, which limits the kind of instructions that can be executed at all. SYSTEM GEN defines a macro to assemble words with two half word instructions and move them to some memory address with SETAM. It also sets up a JRST at 42 to the code put into memory and requests a PI on channel 1. Because it saves and restores the word at 42, it would have been easier to assemble a JRST at 15 and jump there with a skip (TRNA) at 13.
This means only interblock words and data words are (potentially executed). Since interblock words are not used by anything otherwise, they can contain CONOs to position the tape before block 75. They do this in read all mode, which means the following block will be skipped. The word before block 75 (reading forward) is a no-op (TRN), which means the UTC will not get another CONO and skip the next block but execute successive data words instead.
The code in block 75 is then executed directly word by word. An assembler macro is used to put a word FOO into memory with HRLI 17,(FOO); HRRI 17,FOO; SETAM 17,.. and advancing .. . (I'm ignoring the -1 here that's necessary because of the AOJGE in the loader. The code is the following:
SETM 17,42 / save word 42 SETAM 17,37176 / at 37176, first word in MACDMP / Placed into memory: 42 JRST 10,37177 / channel 1 PI: reset PI and jump to code below / Placed into memory: 37177 MOVE 17,.-1 / restore old word 42 37200 MOVEM 17,42 37201 MOVSI 17,-400 / transfer 400 words (blocks 76 and 77) 37201 CONO UTC,220310 / read data forward from DECtape #1 37202 CONSO DC,1000 / wait for word 37203 JRST .-1 37204 DATAI DC,37400(17) / put word into MACDMP's address range 37205 AOBJN 17,.-3 / loop through all words / initialize MACDMP 37206 MOVEI 1 / set DECtape unit number to 1 37207 MOVNI 12,1 / set WRITE to -1 (default) 37210 JRST MACLOD / jump into MACDMP to OPNTP to open tape 1 CONO PI,14300 / cause PI on channel 1, executing 42, jumping to 37177
This is a very clever way that they came up with at MIT to read a paper tape without having the RIM loader in memory already. It only needs two instructions. To use it, do this:
HRLZI 2,(JRST) HRLI 17,(CONO PTR,) HRRI 17,60 MOVEM 17,20 HRLI 17,(CONSO PTR,) HRRI 17,10 MOVEM 17,21 MOVEM 17,24 HRLI 17,(JRST) HRRI 17,21 MOVEM 17,22 MOVEM 17,27 HRRI 17,24 MOVEM 17,25 HRLI 17,(DATAI PTR,) HRRI 17,26 MOVEM 17,23 HRLI 17,(XCT) MOVEM 17,26 MOVEI 17,37176 MOVEM 17,37 HRLI 10,(CONO) HRRI 10,1000 HRLI 11,(JFCL) HRLI 12,(JFCL) HRLI 13,(JFCL) HRLI 14,(JFCL) HRLI 15,(CONSZ) HRRI 15,1000 HRLI 16,(JRST) HRRI 16,10 MOVSI 17,(SKIPA) JRST 10
The DATAI at 0 will read the first word from paper tape into 1 and execute it, which will place a JRST 0 in location 2. This completes the loop to execute consecutive words from paper tape. After everything has been executed, execution jumps to 10 and the memory contents will be this:
00 DATAI PTR,1 01 word read from paper tape 02 JRST 0 10 CONO 1000 / turn clock flag off 11 JFCL / waste some time 12 JFCL 13 JFCL 14 JFCL 15 CONSZ 1000 / skip if clock flag off 16 JRST 10 / clock on, so still on repeat 17 SKIPA / clock off, we're at full speed 20 CONO PTR,60 / this is the standard RIM loader 21 CONSO PTR,10 22 JRST 21 23 DATAI PTR,26 24 CONSO PTR,10 25 JRST 24 26 XCT 26 27 JRST 21 37 37176 / this seems to be MACDMP specific
The loop 10-16 waits until the clock flag is no longer set after four JFCLs. This will be the case when the code is no longer executed as repeated single stepping. It then proceeds to the normal RIM loader (and skips a CONO because the device is already reading) and the rest of the tape is loaded like normal.
SBLK is a simple format that consists of blocks made up of: a header word giving block length and address, n words of data, and a checksum word. SBLK files start with an SBLK loader ended by JRST 1 though the actual loader can be omitted. The end is signalled by any non-negative word. Usually JRST or JUMPA to the entry point.
MACDMP contains such a loader. It starts out by putting a RIM loader into memory, then contains some data in RIM format and some raw words in between. Then it puts the SBLK loader into memory and switches output to SBLK format. The SBLK loader in PDP-6 memory looks like this, execution is started at 1:
01 MOVE 1,15 / replace this instruction with CONO PTR,60 02 JSP 17,30 / wait for word from PTR 03 DATAI PTR,16 / read word 04 MOVE 15,16 / start checksum 05 JUMPG 16,16 / execute words > 0 (normally JRST or JUMPA) / begin a new block 06 JSP 17,30 / wait for word from PTR 07 DATAI PTR,(16) / read word into memory 10 ROT 15,1 / compute 11 ADD 15,(16) / checksum 12 AOBJN 16,6 / loop until block is done 13 MOVEI 17,33 / set return address to checksum check 14 JRST 30 / wait for next word 15 CONO PTR,60 / checksum / wait for word from paper tape 30 CONSO PTR,10 31 JRST 30 32 JRST (17) / return when ready / checksum check 33 DATAI PTR,16 / read word 34 CAMN 15,16 / should be equal to computed checksum 35 JRST 2 36 JRST 4,1 / halt if checksum wrong
The PDP-10 version is a bit simpler due to its hardware read in mode. There it is simply a read in block on paper tape started with -27,,0. Also the code starting at 30 starts at 20 because there is no paper tape RIM loader that has to be preserved.