3 program asprint(prog,output);
15 escape1 = 254; { escape to secondary opcodes }
16 escape2 = 255; { escape to tertiary opcodes }
19 byte= 0..255; { memory is an array of bytes }
20 adr= {0..maxadr} long; { the range of addresses }
21 word= {0..maxuint} long;{ the range of unsigned integers }
22 size= 0..32766; { the range of sizes is the positive offsets }
23 sword= {-signbit..maxsint} long; { the range of signed integers }
24 full= {-maxuint..maxuint} long; { intermediate results need this range }
25 double={-maxdbl..maxdbl} long; { double precision range }
26 insclass=(prim,second,tert); { tells which opcode table is in use }
27 instype=(implic,explic); { does opcode have implicit or explicit operand }
28 iflags= (mini,short,sbit,wbit,zbit,ibit);
32 AAR, ADF, ADI, ADP, ADS, ADU,XAND, ASP, ASS, BEQ,
33 BGE, BGT, BLE, BLM, BLS, BLT, BNE, BRA, CAI, CAL,
34 CFF, CFI, CFU, CIF, CII, CIU, CMF, CMI, CMP, CMS,
35 CMU, COM, CSA, CSB, CUF, CUI, CUU, DCH, DEC, DEE,
36 DEL, DUP, DUS, DVF, DVI, DVU, EXG, FEF, FIF, FIL,
37 GTO, INC, INE, INL, INN, IOR, LAE, LAL, LAR, LDC,
38 LDE, LDF, LDL, LFR, LIL, LIM, LIN, LNI, LOC, LOE,
39 LOF, LOI, LOL, LOR, LOS, LPB, LPI, LXA, LXL, MLF,
40 MLI, MLU, MON, NGF, NGI, NOP, RCK, RET, RMI, RMU,
41 ROL, ROR, RTT, SAR, SBF, SBI, SBS, SBU, SDE, SDF,
42 SDL,XSET, SIG, SIL, SIM, SLI, SLU, SRI, SRU, STE,
43 STF, STI, STL, STR, STS, TEQ, TGE, TGT, TLE, TLT,
44 TNE, TRP, XOR, ZEQ, ZER, ZGE, ZGT, ZLE, ZLT, ZNE,
51 implic: (implicit:sword);
52 explic: (ilength:byte);
56 { variables indicating the size of words and addresses }
57 wsize: integer; { number of bytes in a word }
58 asize: integer; { number of bytes in an address }
59 pdsize: integer; { size of procedure descriptor in bytes = 2*asize }
61 pc,lb,sp,hp,pd: adr; { internal machine registers }
62 i: integer; { integer scratch variable }
63 s,t :word; { scratch variables }
64 sz:size; { scratch variables }
65 ss,st: sword; { scratch variables }
66 k :double; { scratch variables }
67 j:size; { scratch variable used as index }
68 a,b:adr; { scratch variable used for addresses }
69 dt,ds:double; { scratch variables for double precision }
70 found:boolean; { scratch }
73 dispat: array[insclass, byte] of dispatch ;
74 insr: mnem; { holds the instructionnumber }
75 header: array[1..8] of adr;
77 prog: file of byte; { program and initialized data }
79 procedure getit; { start the ball rolling }
95 function readb(n:integer):double;
99 begin writeln('Premature EOF on EM load file') ; halt end;
100 read(prog,b); if n>1 then readb:=readb(n-1)*256+b else readb:=b
103 function readbyte:byte;
104 begin readbyte:=readb(1) end;
108 begin dummy:=readb(1) end;
110 function readword:word;
111 begin readword:=readb(wsize) end;
113 function readadr:adr;
114 begin readadr:=readb(asize) end;
116 function ifind(ordinal:byte):mnem;
120 loopvar:=insr; found:=false;
122 if ordinal=ord(loopvar) then
123 begin found:=true; ifind:=loopvar end;
124 if loopvar<>ZRL then loopvar:=succ(loopvar) else loopvar:=NON;
125 until found or (loopvar=insr) ;
129 type hdrw=0..32767 ; { 16 bit header words }
136 0: if hdr<>3757 then { 07255 }
137 begin writeln('Not an em load file'); halt end;
138 1: writeln('Test flags: ',hdr);
140 begin writeln('Unsolved references: ',hdr) end;
142 begin writeln('Incorrect load file version') end;
144 5: begin asize:=hdr ; pdsize:= asize+asize end;
147 begin writeln('First header entry ',i,', is ',hdr) end;
150 writeln('word size',wsize,', pointer size',asize)
154 begin writeln('Illegal initialization'); halt end;
156 procedure readint(a:adr;s:size);
160 cont: array[1..mrange] of byte;
161 begin { construct integer out of byte sequence }
164 for i:=1 to s do cont[i]:=readbyte ;
165 if cont[s]>=128 then val:=cont[s]-256 else val:=cont[s];
166 for i:= s-1 downto 1 do val:= val*256 + cont[i];
167 writeln(', value ',val)
171 write(', bytes(little endian) ');
172 for i:=1 to s do write(readbyte:4) ;
177 procedure readuns(a:adr;s:size);
181 cont: array[1..mrange] of byte;
182 begin { construct unsigned integer out of byte sequence }
185 for i:=1 to s do cont[i]:=readbyte ;
187 for i:= s downto 1 do val:= val*256 + cont[i];
188 writeln(', value ',val)
192 write(', bytes(little endian) ');
193 for i:=1 to s do write(readbyte:4) ;
198 procedure readfloat(a:adr;s:size);
200 begin { construct float out of string}
202 repeat { eat the bytes, construct the value and intialize at a }
203 write(chr(readbyte)); i:=i+1;
210 { initialize tables }
211 for iclass:=prim to tert do
213 with dispat[iclass][i] do
214 begin instr:=NON; iflag:=[zbit] end;
216 { read instruction table file. see appendix B }
217 { The table read here is a simple transformation of the table on page xx }
218 { - instruction names were transformed to numbers }
219 { - the '-' flag was transformed to an 'i' flag for 'w' type instructions }
220 { - the 'S' flag was added for instructions having signed operands }
224 read(tables,insno) ; cset:=[]; f:=[];
226 if insr=NON then begin writeln('Incorrect table'); halt end;
227 repeat read(tables,c) until c<>' ' ;
232 if 'm' in cset then f:=f+[mini];
233 if 's' in cset then f:=f+[short];
234 if '-' in cset then f:=f+[zbit];
235 if 'i' in cset then f:=f+[ibit];
236 if 'S' in cset then f:=f+[sbit];
237 if 'w' in cset then f:=f+[wbit];
238 if (mini in f) or (short in f) then read(tables,nops) else nops:=1 ;
239 readln(tables,opcode);
240 if ('4' in cset) or ('8' in cset) then
241 begin iclass:=tert end
242 else if 'e' in cset then
243 begin iclass:=second end
245 for i:=0 to nops-1 do
247 with dispat[iclass,opcode+i] do
249 iflag:=f; instr:=insr;
250 if '2' in cset then ilength:=2
251 else if 'u' in cset then ilength:=2
252 else if '4' in cset then ilength:=4
253 else if '8' in cset then ilength:=8
254 else if (mini in f) or (short in f) then
256 if 'N' in cset then wtemp:=-1-i else wtemp:=i ;
257 if 'o' in cset then wtemp:=wtemp+1 ;
258 if short in f then wtemp:=wtemp*256 ;
266 { read in program text, data and procedure descriptors }
268 readhdr; { verify first header }
269 for i:=1 to 8 do header[i]:=readadr; { read second header }
270 writeln('textsize ',header[NTEXT],', datasize ',header[SZDATA]);
271 writeln('data descriptors: ',header[NDATA]);
272 writeln('procedure descriptors: ',header[NPROC]);
273 writeln('entry procedure: ',header[ENTRY]);
274 if header[7]<>0 then writeln('Second header entry 7 is ',header[7]);
275 if header[8]<>0 then writeln('Second header entry 8 is ',header[8]);
276 { read program text }
277 for i:=0 to header[NTEXT]-1 do skipbyte;
279 writeln; writeln('Data descriptors:');
281 for i:=1 to header[NDATA] do
287 elem:=readbyte; firsta:=nexta;
289 1: { uninitialized words }
291 writeln(elem,' uninitialised word(s)');
292 nexta:= nexta+ elem*wsize ;
294 2: { initialized bytes }
296 write(elem,' initialised byte(s)');
300 begin writeln ; write(nexta:6,':') end ;
301 write(readbyte:4); nexta:=nexta+1
305 3: { initialized words }
307 write(elem,' initialised word(s)');
311 begin writeln ; write(nexta:6,':') end ;
312 write(readword:9); nexta:=nexta+wsize
316 4,5: { instruction and data pointers }
319 write(elem,' initialised data pointers')
321 write(elem,' initialised instruction pointers');
325 begin writeln ; write(nexta:6,':') end ;
326 write(readadr:9); nexta:=nexta+asize
330 6: { signed integers }
332 write(elem,'-byte signed integer ');
333 readint(nexta,elem); nexta:=nexta+elem
335 7: { unsigned integers }
337 write(elem,'-byte unsigned integer ');
338 readuns(nexta,elem); nexta:=nexta+elem
340 8: { floating point numbers }
342 write(elem,'-byte floating point number ');
343 readfloat(nexta,elem); nexta:=nexta+elem
350 amount:=nexta-firsta;
351 writeln(repc,' copies of the data from ',firsta:2,' to ',nexta:2);
352 nexta:= nexta + repc*amount ;
355 if header[SZDATA]<>nexta then writeln('Data initialization error');
356 { read descriptor table }
358 for i:=1 to header[NPROC]*pdsize do skipbyte;
364 opcode := nextpc; { fetch the first byte of the instruction }
365 if opcode=escape1 then iclass:=second
366 else if opcode=escape2 then iclass:=tert
368 if iclass<>prim then opcode := nextpc;
369 with dispat[iclass][opcode] do
371 if not (zbit in iflag) then
372 if ibit in iflag then k:=pop else
374 if mini in iflag then k:=implicit else
376 if short in iflag then k:=implicit+nextpc else
378 if (sbit in iflag) and (k>=128) then k:=k-256;
379 for i:=2 to ilength do k:=256*k + nextpc
382 if wbit in iflag then k:=k*wsize;