BPUN File Format

From NDWiki
Jump to navigation Jump to search

The :BPUN file format

Preamble Start Boot ! Address Count Data Checksum Action
Preamble May contain any characters except "!" (41 octal, 0x21). Its original use was a bootstrap loader for stand-alone CPUs. This is no longer used. But various tools still generate the bootstrap loader, including the BPUN command in NRL.
Start A field containing an ASCII encoded octal start address for the program. It is terminated by a carriage return (15 octal) and optionally a line feed (12 octal).
Boot A field containing an ASCII encoded octal value giving the start address of the bootstrap loader (see Pre-amble) and terminated by the "!" character (i.e. the next field, below). No longer used, but still created by tools that generate the bootstrap loader.
"!" Exclamation mark: Start-of-data signal.
Address Address where the binary load of the data will start. Two-byte word in big endian format.
Count Number of 16-bit words in the following Data field. Two-byte word in big endian format.
Data A field containing <Count> 16-bit words. Big endian format.
Checksum Arithmetic sum of all the words in the Data field, modulo 216. Two-byte word in big endian format.
Action Two-byte field. If the action field is zero, execution will start at the address specified in the Start field. If not zero, the CPU will remain in OPCOM mode. The P register will contain the value read from the Start field.

Everything before the "!" mark is in 7-bit ASCII with even parity, except that there may be a string of binary zeroes before the actual preamble starts. The preamble itself (the bootstrap) is code encoded as octal values of the instructions, with carriage return and line feed between each instruction. CR/LF also use parity, so CR is encoded as 0x8D.

The preamble (boostrap loader) starts with a command that instructs the hardware loader about where in memory to load the following code. The command is an address followed by the "/" character. Example of preamble below (hexdump with parity stripped off in the ascii section at the right):

000000: 8D 0A B1 B7 B7 B4 30 30 AF B1 B4 36 B1 30 B1 8D    ..177400/146101.
000010: 0A B1 33 B4 30 B2 B1 8D 0A B1 B4 36 B1 35 B7 8D    .134021..146157.
000020: 0A B1 33 B4 30 B1 B7 8D 0A B1 B4 36 B1 35 36 8D    .134017..146156.
000030: 0A B1 33 B4 30 B1 35 8D 0A 30 30 36 30 30 30 8D    .134015..006000.
000040: 0A B1 B4 36 30 35 B1 8D 0A B1 B4 36 B2 30 36 8D    .146051..146206.
000050: 0A B1 B4 B2 30 30 36 8D 0A B1 B2 B4 30 30 33 8D    .142006..124003.
000060: 0A B1 B7 33 B4 30 B1 8D 0A B1 B2 B4 33 B7 B1 8D    .173401..124371.
000070: 0A B1 33 B4 30 30 35 8D 0A B1 B4 36 36 B1 35 8D    .134005..146615.
000080: 0A B1 33 B1 30 B2 33 8D 0A B1 35 B1 30 B7 B7 8D    .131023..151077.
000090: 0A 30 36 35 35 30 B4 8D 0A B1 B4 36 B1 B4 35 8D    .065504..146145.
0000a0: 0A 30 30 B4 30 B1 36 8D 0A B1 33 B4 30 30 36 8D    .004016..134006.
0000b0: 0A B1 35 35 35 B7 30 8D 0A 30 30 B4 33 B7 33 8D    .155570..004373.
0000c0: 0A B1 33 B4 30 30 33 8D 0A 30 36 30 33 B7 B1 8D    .134003..060371.
0000d0: 0A B1 B2 35 30 B1 30 8D 0A B1 B7 30 B4 30 B4 8D    .125010..170404.
0000e0: 0A B1 36 B4 B4 30 33 8D 0A B1 36 B4 B4 30 B2 8D    .164403..164402.
0000f0: 0A B1 B7 35 B2 33 35 8D 0A B1 B2 B4 33 B7 36 8D    .175235..124376.
000100: 0A B1 36 B4 B4 30 30 8D 0A B1 B4 36 B1 B4 B2 8D    .164400..146142.
000110: 0A 30 30 30 30 30 30 8D 0A B1 B2 35 30 30 B1 8D    .000000..125001.
000120: 0A 30 30 30 30 30 30 8D 0A B1 B7 B7 B4 30 30 21    .000000..177400!

The last line shows the 'Start' and 'Boot' fields, with the value 000000 for the start address of the program, and 177400 as the address of the bootstrap. It matches the bootstrap load address seen in the first line. A '!' character indicates that the program part follows, and that part is in binary unlike the section before the exclamation mark. The actual bootstrap loader is position independent code, so the bootstrap load address may vary between :BPUN files (the 177400 value in the example above, i.e. first and last numbers), but the actual bootstrap code appears to always be the same. The load address of the bootstrap code will be after the end of the actual program code which the bootstrap is loading, so not to overwrite the bootstrap code itself. But :BPUN files do not always follow this rule, and can thus not be loaded by this mechanism. For these files the preamble section is a vestigal non-functioning section. But tools like DITAP will produce :BPUN files from :PROG files with correctly adjusted boostrap load address. The above hexdump is from such a file, PED-ENG-J:BPUN as generated bu DITAP from PED-ENG-J:PROG. PED loads from 0 to 177377, and the boostrap loader is placed at 177400 by the hardware loader. PED can therefore be safely loaded without overwriting the bootstrap loader itself.

Some :BPUN files have no preamble, they start with just the 'Start' and 'Boot' fields, followed by the exclamation mark and the rest. These files obviously can't run stand-alone.

The bootstrap loader used for :BPUN files is as follows. 'ORG' would be 177400 for the example in the hexdump above.

%
% Paper Tape Reader Bootstrap Loader
% The paper tape is a character (byte) storage.
% 'ORG' is a 16-bit word, in octal.
% The rest of the bootstrap loader is also in octal,
% all written as ASCII with parity, each octal value
% terminated with CR or CR/LF.
% Loading of the Boostrap Loader stops when an exclamation
% mark (!) is found on the tape.
%
       ORG/		% Tell hardware loader where to write the following.
ORG,   COPY 0 DD	% 0 =: D % Init checksum register
% Read Address word:
       JPL * 21		% Call GetW
       COPY SA DX	% A =: X % Store address in X
% Read Count word:
       JPL * 17		% Call GetW
       COPY SA DT	% A =: T % Store count in T

% Read Data (program), word by word, decrement T until T is zero:
next,  JPL * 15		% Call GetW
       STA ,X 0		% A =: (X) % Store word in (X) (i.e. at address)
       RADD SA DD	% A+D =: D % Add up checksum
       RADD CM1 0 DT	% T-1 =: T % Decrement T
       SKP IF DT UEQ 0	% IF T != 0 goto cont % Done?
       JMP * 3		% Otherwise goto done (i.e. T has become zero)
cont,  AAX 1		% X+1 =: X % Increment X (which points to address)
       JMP * - 7	% goto next

% Read Checksum word:
done,  JPL * 5		% Call GetW
       RSUB SD DA	% A-D =: D % Check if A = D           % Checksum OK?
       JAZ * 23		% Goto Run		              % Yes
       WAIT 77		% Stop,[1]  show 77 in operator panel % No

tmp,			% Holding space for upper byte of a word

% Function to get a 16-bit word from paper tape reader:
GetW,  COPY SL DA	% L =: A
       STA * 16		% A =: L-reg   % Store L in memory
       JPL * 6		% Call rdbyt   % Get higher byte
       SHA ROT - 10	% A << 8       % (shift 8 bits arithmetic left)
       STA * - 5	% A =: tmp     % Store upper byte of word
       JPL * 3		% Call rdbyt   % Get lower byte
       ADD * - 7	% A + tmp =: A % A now contains 16-bit word
       JMP I * 10	% Goto (L-reg) % Return

rdbyt, SAA 4		% 4 =: A       % Set bit 2: function "Activate"
       IOX 403		% Write control register paper tape reader (activate)
wait,  IOX 402		% STATUS =: A  % Read status register
       BSKP ONE 30 DA	% If bit 3 goto getbyt % Test bit 3: Data ready
       JMP * - 2	% goto wait    % Data not available yet
getbyt,IOX 400		% DATA =: A    % Read data register (8 bits for PTR[2])
       COPY SL DP	% L =: P       % Return (COPY SL DP: Also called EXIT)

L-reg,	    		% L-reg temporary storage

Run    JMP I * 1	% Goto (start)
start  000000		% Start address (hardcoded, may be != 000000)
btldr  177400		% Boot loader address (hardcoded)

[1] WAIT stops CPU if interrupt system is off
[2] PTR: Paper Tape Reader

Note that the bootstrap loader completely ignores the Action field. If the Checksum is correct then the loaded program will start.