1 /* pdp8_sys.c: PDP-8 simulator interface
3 Copyright (c) 1993-2008, Robert M Supnik
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
26 24-Jun-08 RMS Fixed bug in new rim loader (found by Don North)
27 24-May-08 RMS Fixed signed/unsigned declaration inconsistency
28 03-Sep-07 RMS Added FPP8 support
29 Rewrote rim and binary loaders
30 15-Dec-06 RMS Added TA8E support, IOT disambiguation
31 30-Oct-06 RMS Added infinite loop stop
32 18-Oct-06 RMS Re-ordered device list
33 17-Oct-03 RMS Added TSC8-75, TD8E support, DECtape off reel message
34 25-Apr-03 RMS Revised for extended file support
35 30-Dec-01 RMS Revised for new TTX
36 26-Nov-01 RMS Added RL8A support
37 17-Sep-01 RMS Removed multiconsole support
38 16-Sep-01 RMS Added TSS/8 packed char support, added KL8A support
39 27-May-01 RMS Added multiconsole support
40 18-Mar-01 RMS Added DF32 support
41 14-Mar-01 RMS Added extension detection of RIM binary tapes
42 15-Feb-01 RMS Added DECtape support
43 30-Oct-00 RMS Added support for examine to file
44 27-Oct-98 RMS V2.4 load interface
45 10-Apr-98 RMS Added RIM loader support
46 17-Feb-97 RMS Fixed bug in handling of bin loader fields
49 #include "pdp8_defs.h"
52 extern DEVICE cpu_dev
;
54 extern DEVICE tsc_dev
;
55 extern DEVICE ptr_dev
, ptp_dev
;
56 extern DEVICE tti_dev
, tto_dev
;
57 extern DEVICE clk_dev
, lpt_dev
;
58 extern DEVICE rk_dev
, rl_dev
;
60 extern DEVICE df_dev
, rf_dev
;
61 extern DEVICE dt_dev
, td_dev
;
62 extern DEVICE mt_dev
, ct_dev
;
63 extern DEVICE ttix_dev
, ttox_dev
;
66 extern int32 sim_switches
;
68 t_stat
fprint_sym_fpp (FILE *of
, t_value
*val
);
69 t_stat
parse_sym_fpp (char *cptr
, t_value
*val
);
70 char *parse_field (char *cptr
, uint32 max
, uint32
*val
, uint32 c
);
71 char *parse_fpp_xr (char *cptr
, uint32
*xr
, t_bool inc
);
72 int32
test_fpp_addr (uint32 ad
, uint32 max
);
74 /* SCP data structures and interface routines
76 sim_name simulator name string
77 sim_PC pointer to saved PC register descriptor
78 sim_emax maximum number of words for examine/deposit
79 sim_devices array of pointers to simulated devices
80 sim_consoles array of pointers to consoles (if more than one)
81 sim_stop_messages array of pointers to stop messages
82 sim_load binary loader
85 char sim_name
[] = "PDP-8";
87 REG
*sim_PC
= &cpu_reg
[0];
91 DEVICE
*sim_devices
[] = {
114 const char *sim_stop_messages
[] = {
116 "Unimplemented instruction",
119 "Non-standard device number",
124 /* Ambiguous device list - these devices have overlapped IOT codes */
126 DEVICE
*amb_dev
[] = {
133 #define AMB_RL (1 << 12)
134 #define AMB_CT (2 << 12)
135 #define AMB_TD (3 << 12)
137 /* RIM loader format consists of alternating pairs of addresses and 12-bit
138 words. It can only operate in field 0 and is not checksummed.
141 t_stat
sim_load_rim (FILE *fi
)
143 int32 origin
, hi
, lo
, wd
;
146 do { /* skip leader */
147 if ((hi
= getc (fi
)) == EOF
)
149 } while ((hi
== 0) || (hi
>= 0200));
150 do { /* data block */
151 if ((lo
= getc (fi
)) == EOF
)
154 if (wd
> 07777) origin
= wd
& 07777;
155 else M
[origin
++ & 07777] = wd
;
156 if ((hi
= getc (fi
)) == EOF
)
158 } while (hi
< 0200); /* until trailer */
162 /* BIN loader format consists of a string of 12-bit words (made up from
163 7-bit characters) between leader and trailer (200). The last word on
164 tape is the checksum. A word with the "link" bit set is a new origin;
165 a character > 0200 indicates a change of field.
168 int32
sim_bin_getc (FILE *fi
, uint32
*newf
)
172 rubout
= 0; /* clear toggle */
173 while ((c
= getc (fi
)) != EOF
) { /* read char */
174 if (rubout
) /* toggle set? */
175 rubout
= 0; /* clr, skip */
176 else if (c
== 0377) /* rubout? */
177 rubout
= 1; /* set, skip */
178 else if (c
> 0200) /* channel 8 set? */
179 *newf
= (c
& 070) << 9; /* change field */
180 else return c
; /* otherwise ok */
185 t_stat
sim_load_bin (FILE *fi
)
187 int32 hi
, lo
, wd
, csum
, t
;
188 uint32 field
, newf
, origin
;
190 do { /* skip leader */
191 if ((hi
= sim_bin_getc (fi
, &newf
)) == EOF
)
193 } while ((hi
== 0) || (hi
>= 0200));
194 csum
= origin
= field
= newf
= 0; /* init */
195 for (;;) { /* data blocks */
196 if ((lo
= sim_bin_getc (fi
, &newf
)) == EOF
) /* low char */
198 wd
= (hi
<< 6) | lo
; /* form word */
199 t
= hi
; /* save for csum */
200 if ((hi
= sim_bin_getc (fi
, &newf
)) == EOF
) /* next char */
202 if (hi
== 0200) { /* end of tape? */
203 if ((csum
- wd
) & 07777) /* valid csum? */
207 csum
= csum
+ t
+ lo
; /* add to csum */
208 if (wd
> 07777) /* chan 7 set? */
209 origin
= wd
& 07777; /* new origin */
210 else { /* no, data */
211 if ((field
| origin
) >= MEMSIZE
)
213 M
[field
| origin
] = wd
;
214 origin
= (origin
+ 1) & 07777;
216 field
= newf
; /* update field */
222 Two loader formats are supported: RIM loader (-r) and BIN (-b) loader. */
224 t_stat
sim_load (FILE *fileref
, char *cptr
, char *fnam
, int flag
)
226 if ((*cptr
!= 0) || (flag
!= 0)) return SCPE_ARG
;
227 if ((sim_switches
& SWMASK ('R')) || /* RIM format? */
228 (match_ext (fnam
, "RIM") && !(sim_switches
& SWMASK ('B'))))
229 return sim_load_rim (fileref
);
230 else return sim_load_bin (fileref
); /* no, BIN */
235 #define I_V_FL 18 /* flag start */
236 #define I_M_FL 07 /* flag mask */
237 #define I_V_NPN 0 /* no operand */
238 #define I_V_FLD 1 /* field change */
239 #define I_V_MRF 2 /* mem ref */
240 #define I_V_IOT 3 /* general IOT */
241 #define I_V_OP1 4 /* operate 1 */
242 #define I_V_OP2 5 /* operate 2 */
243 #define I_V_OP3 6 /* operate 3 */
244 #define I_V_IOA 7 /* ambiguous IOT */
245 #define I_NPN (I_V_NPN << I_V_FL)
246 #define I_FLD (I_V_FLD << I_V_FL)
247 #define I_MRF (I_V_MRF << I_V_FL)
248 #define I_IOT (I_V_IOT << I_V_FL)
249 #define I_OP1 (I_V_OP1 << I_V_FL)
250 #define I_OP2 (I_V_OP2 << I_V_FL)
251 #define I_OP3 (I_V_OP3 << I_V_FL)
252 #define I_IOA (I_V_IOA << I_V_FL)
254 static const int32 masks
[] = {
255 07777, 07707, 07000, 07000,
256 07416, 07571, 017457, 077777,
259 /* Ambiguous device mnemonics must precede default mnemonics */
261 static const char *opcode
[] = {
262 "SKON", "ION", "IOF", "SRQ", /* std IOTs */
263 "GTF", "RTF", "SGT", "CAF",
264 "RPE", "RSF", "RRB", "RFC", "RFC RRB", /* reader/punch */
265 "PCE", "PSF", "PCF", "PPC", "PLS",
266 "KCF", "KSF", "KCC", "KRS", "KIE", "KRB", /* console */
267 "TLF", "TSF", "TCF", "TPC", "SPI", "TLS",
268 "SBE", "SPL", "CAL", /* power fail */
269 "CLEI", "CLDI", "CLSC", "CLLE", "CLCL", "CLSK", /* clock */
270 "CINT", "RDF", "RIF", "RIB", /* mem mmgt */
271 "RMF", "SINT", "CUF", "SUF",
272 "RLDC", "RLSD", "RLMA", "RLCA", /* RL - ambiguous */
273 "RLCB", "RLSA", "RLWC",
274 "RRER", "RRWC", "RRCA", "RRCB",
275 "RRSA", "RRSI", "RLSE",
276 "KCLR", "KSDR", "KSEN", "KSBF", /* CT - ambiguous */
277 "KLSA", "KSAF", "KGOA", "KRSB",
278 "SDSS", "SDST", "SDSQ", /* TD - ambiguous */
279 "SDLC", "SDLD", "SDRC", "SDRD",
280 "ADCL", "ADLM", "ADST", "ADRB", /* A/D */
281 "ADSK", "ADSE", "ADLE", "ADRS",
282 "DCMA", "DMAR", "DMAW", /* DF/RF */
283 "DCIM", "DSAC", "DIML", "DIMA",
284 "DCEA", "DEAL", "DEAC",
285 "DFSE", "DFSC", "DISK", "DMAC",
286 "DCXA", "DXAL", "DXAC",
287 "PSKF", "PCLF", "PSKE", /* LPT */
288 "PSTB", "PSIE", "PCLF PSTB", "PCIE",
289 "LWCR", "CWCR", "LCAR", /* MT */
290 "CCAR", "LCMR", "LFGR", "LDBR",
291 "RWCR", "CLT", "RCAR",
292 "RMSR", "RCMR", "RFSR", "RDBR",
293 "SKEF", "SKCB", "SKJD", "SKTR", "CLF",
294 "DSKP", "DCLR", "DLAG", /* RK */
295 "DLCA", "DRST", "DLDC", "DMAN",
296 "LCD", "XDR", "STR", /* RX */
297 "SER", "SDN", "INTR", "INIT",
298 "DTRA", "DTCA", "DTXA", "DTLA", /* DT */
299 "DTSF", "DTRB", "DTLB",
300 "ETDS", "ESKP", "ECTF", "ECDF", /* TSC75 */
301 "ERTB", "ESME", "ERIOT", "ETEN",
302 "FFST", "FPINT", "FPICL", "FPCOM", /* FPP8 */
303 "FPHLT", "FPST", "FPRST", "FPIST",
305 "FMRP", "FMDO", "FPEP",
307 "CDF", "CIF", "CIF CDF",
308 "AND", "TAD", "ISZ", "DCA", "JMS", "JMP", "IOT",
309 "NOP", "NOP2", "NOP3", "SWAB", "SWBA",
310 "STL", "GLK", "STA", "LAS", "CIA",
311 "BSW", "RAL", "RTL", "RAR", "RTR", "RAL RAR", "RTL RTR",
313 "SZA", "SNA", "SZA SNL", "SNA SZL",
314 "SMA", "SPA", "SMA SNL", "SPA SZL",
315 "SMA SZA", "SPA SNA", "SMA SZA SNL", "SPA SNA SZL",
316 "SCL", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR",
317 "SCA", "SCA SCL", "SCA MUY", "SCA DVI",
318 "SCA NMI", "SCA SHL", "SCA ASR", "SCA LSR",
319 "ACS", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR",
320 "SCA", "DAD", "DST", "SWBA",
321 "DPSZ", "DPIC", "DCIM", "SAM",
322 "CLA", "CLL", "CMA", "CML", "IAC", /* encode only */
325 NULL
, NULL
, NULL
, NULL
, /* decode only */
329 static const int32 opc_val
[] = {
330 06000+I_NPN
, 06001+I_NPN
, 06002+I_NPN
, 06003+I_NPN
,
331 06004+I_NPN
, 06005+I_NPN
, 06006+I_NPN
, 06007+I_NPN
,
332 06010+I_NPN
, 06011+I_NPN
, 06012+I_NPN
, 06014+I_NPN
, 06016+I_NPN
,
333 06020+I_NPN
, 06021+I_NPN
, 06022+I_NPN
, 06024+I_NPN
, 06026+I_NPN
,
334 06030+I_NPN
, 06031+I_NPN
, 06032+I_NPN
, 06034+I_NPN
, 06035+I_NPN
, 06036+I_NPN
,
335 06040+I_NPN
, 06041+I_NPN
, 06042+I_NPN
, 06044+I_NPN
, 06045+I_NPN
, 06046+I_NPN
,
336 06101+I_NPN
, 06102+I_NPN
, 06103+I_NPN
,
337 06131+I_NPN
, 06132+I_NPN
, 06133+I_NPN
, 06135+I_NPN
, 06136+I_NPN
, 06137+I_NPN
,
338 06204+I_NPN
, 06214+I_NPN
, 06224+I_NPN
, 06234+I_NPN
,
339 06244+I_NPN
, 06254+I_NPN
, 06264+I_NPN
, 06274+I_NPN
,
340 06600+I_IOA
+AMB_RL
, 06601+I_IOA
+AMB_RL
, 06602+I_IOA
+AMB_RL
, 06603+I_IOA
+AMB_RL
,
341 06604+I_IOA
+AMB_RL
, 06605+I_IOA
+AMB_RL
, 06607+I_IOA
+AMB_RL
,
342 06610+I_IOA
+AMB_RL
, 06611+I_IOA
+AMB_RL
, 06612+I_IOA
+AMB_RL
, 06613+I_IOA
+AMB_RL
,
343 06614+I_IOA
+AMB_RL
, 06615+I_IOA
+AMB_RL
, 06617+I_IOA
+AMB_RL
,
344 06700+I_IOA
+AMB_CT
, 06701+I_IOA
+AMB_CT
, 06702+I_IOA
+AMB_CT
, 06703+I_IOA
+AMB_CT
,
345 06704+I_IOA
+AMB_CT
, 06705+I_IOA
+AMB_CT
, 06706+I_IOA
+AMB_CT
, 06707+I_IOA
+AMB_CT
,
346 06771+I_IOA
+AMB_TD
, 06772+I_IOA
+AMB_TD
, 06773+I_IOA
+AMB_TD
,
347 06774+I_IOA
+AMB_TD
, 06775+I_IOA
+AMB_TD
, 06776+I_IOA
+AMB_TD
, 06777+I_IOA
+AMB_TD
,
348 06530+I_NPN
, 06531+I_NPN
, 06532+I_NPN
, 06533+I_NPN
, /* AD */
349 06534+I_NPN
, 06535+I_NPN
, 06536+I_NPN
, 06537+I_NPN
,
350 06601+I_NPN
, 06603+I_NPN
, 06605+I_NPN
, /* DF/RF */
351 06611+I_NPN
, 06612+I_NPN
, 06615+I_NPN
, 06616+I_NPN
,
352 06611+I_NPN
, 06615+I_NPN
, 06616+I_NPN
,
353 06621+I_NPN
, 06622+I_NPN
, 06623+I_NPN
, 06626+I_NPN
,
354 06641+I_NPN
, 06643+I_NPN
, 06645+I_NPN
,
355 06661+I_NPN
, 06662+I_NPN
, 06663+I_NPN
, /* LPT */
356 06664+I_NPN
, 06665+I_NPN
, 06666+I_NPN
, 06667+I_NPN
,
357 06701+I_NPN
, 06702+I_NPN
, 06703+I_NPN
, /* MT */
358 06704+I_NPN
, 06705+I_NPN
, 06706+I_NPN
, 06707+I_NPN
,
359 06711+I_NPN
, 06712+I_NPN
, 06713+I_NPN
,
360 06714+I_NPN
, 06715+I_NPN
, 06716+I_NPN
, 06717+I_NPN
,
361 06721+I_NPN
, 06722+I_NPN
, 06723+I_NPN
, 06724+I_NPN
, 06725+I_NPN
,
362 06741+I_NPN
, 06742+I_NPN
, 06743+I_NPN
, /* RK */
363 06744+I_NPN
, 06745+I_NPN
, 06746+I_NPN
, 06747+I_NPN
,
364 06751+I_NPN
, 06752+I_NPN
, 06753+I_NPN
, /* RX */
365 06754+I_NPN
, 06755+I_NPN
, 06756+I_NPN
, 06757+I_NPN
,
366 06761+I_NPN
, 06762+I_NPN
, 06764+I_NPN
, 06766+I_NPN
, /* DT */
367 06771+I_NPN
, 06772+I_NPN
, 06774+I_NPN
,
368 06360+I_NPN
, 06361+I_NPN
, 06362+I_NPN
, 06363+I_NPN
, /* TSC */
369 06364+I_NPN
, 06365+I_NPN
, 06366+I_NPN
, 06367+I_NPN
,
370 06550+I_NPN
, 06551+I_NPN
, 06552+I_NPN
, 06553+I_NPN
, /* FPP8 */
371 06554+I_NPN
, 06555+I_NPN
, 06556+I_NPN
, 06557+I_NPN
,
372 06561+I_NPN
, 06563+I_NPN
,
373 06564+I_NPN
, 06565+I_NPN
, 06567+I_NPN
,
375 06201+I_FLD
, 06202+I_FLD
, 06203+I_FLD
,
376 00000+I_MRF
, 01000+I_MRF
, 02000+I_MRF
, 03000+I_MRF
,
377 04000+I_MRF
, 05000+I_MRF
, 06000+I_IOT
,
378 07000+I_NPN
, 07400+I_NPN
, 07401+I_NPN
, 07431+I_NPN
, 07447+I_NPN
,
379 07120+I_NPN
, 07204+I_NPN
, 07240+I_NPN
, 07604+I_NPN
, 07041+I_NPN
,
380 07002+I_OP1
, 07004+I_OP1
, 07006+I_OP1
,
381 07010+I_OP1
, 07012+I_OP1
, 07014+I_OP1
, 07016+I_OP1
,
382 07410+I_OP2
, 07420+I_OP2
, 07430+I_OP2
,
383 07440+I_OP2
, 07450+I_OP2
, 07460+I_OP2
, 07470+I_OP2
,
384 07500+I_OP2
, 07510+I_OP2
, 07520+I_OP2
, 07530+I_OP2
,
385 07540+I_OP2
, 07550+I_OP2
, 07560+I_OP2
, 07570+I_OP2
,
386 07403+I_OP3
, 07405+I_OP3
, 07407+I_OP3
,
387 07411+I_OP3
, 07413+I_OP3
, 07415+I_OP3
, 07417+I_OP3
,
388 07441+I_OP3
, 07443+I_OP3
, 07445+I_OP3
, 07447+I_OP3
,
389 07451+I_OP3
, 07453+I_OP3
, 07455+I_OP3
, 07457+I_OP3
,
390 017403+I_OP3
, 017405+I_OP3
, 0174017+I_OP3
,
391 017411+I_OP3
, 017413+I_OP3
, 017415+I_OP3
, 017417+I_OP3
,
392 017441+I_OP3
, 017443+I_OP3
, 017445+I_OP3
, 017447+I_OP3
,
393 017451+I_OP3
, 017453+I_OP3
, 017455+I_OP3
, 017457+I_OP3
,
394 07200+I_OP1
, 07100+I_OP1
, 07040+I_OP1
, 07020+I_OP1
, 07001+I_OP1
,
395 07600+I_OP2
, 07404+I_OP2
, 07402+I_OP2
,
396 07601+I_OP3
, 07501+I_OP3
, 07421+I_OP3
,
397 07000+I_OP1
, 07400+I_OP2
, 07401+I_OP3
, 017401+I_OP3
,
401 /* Symbol tables for FPP-8 */
403 #define F_V_FL 18 /* flag start */
404 #define F_M_FL 017 /* flag mask */
405 #define F_V_NOP12 0 /* no opnd 12b */
406 #define F_V_NOP9 1 /* no opnd 9b */
407 #define F_V_AD15 2 /* 15b dir addr */
408 #define F_V_AD15X 3 /* 15b dir addr indx */
409 #define F_V_IMMX 4 /* 12b immm indx */
410 #define F_V_X 5 /* index */
411 #define F_V_MRI 6 /* mem ref ind */
412 #define F_V_MR1D 7 /* mem ref dir 1 word */
413 #define F_V_MR2D 8 /* mem ref dir 2 word */
414 #define F_V_LEMU 9 /* LEA/IMUL */
415 #define F_V_LEMUI 10 /* LEAI/IMULI */
416 #define F_V_LTR 11 /* LTR */
417 #define F_V_MRD 12 /* mem ref direct (enc) */
418 #define F_NOP12 (F_V_NOP12 << F_V_FL)
419 #define F_NOP9 (F_V_NOP9 << F_V_FL)
420 #define F_AD15 (F_V_AD15 << F_V_FL)
421 #define F_AD15X (F_V_AD15X << F_V_FL)
422 #define F_IMMX (F_V_IMMX << F_V_FL)
423 #define F_X (F_V_X << F_V_FL)
424 #define F_MRI (F_V_MRI << F_V_FL)
425 #define F_MR1D (F_V_MR1D << F_V_FL)
426 #define F_MR2D (F_V_MR2D << F_V_FL)
427 #define F_LEMU (F_V_LEMU << F_V_FL)
428 #define F_LEMUI (F_V_LEMUI << F_V_FL)
429 #define F_LTR (F_V_LTR << F_V_FL)
430 #define F_MRD (F_V_MRD << F_V_FL)
432 static const uint32 fmasks
[] = {
433 07777, 07770, 07770, 07600,
434 07770, 07770, 07600, 07600,
435 07600, 017600, 017600, 07670,
439 /* Memory references are encode dir / decode 1D / decode 2D / indirect */
441 static const char *fopcode
[] = {
442 "FEXIT", "FPAUSE", "FCLA", "FNEG",
443 "FNORM", "STARTF", "STARTD", "JAC",
447 "FLDA", "FLDA", "FLDA", "FLDAI",
448 "JEQ", "JGE", "JLE", "JA",
449 "JNE", "JLT", "JGT", "JAL",
450 "SETX", "SETB", "JSA", "JSR",
451 "FADD", "FADD", "FADD", "FADDI",
453 "FSUB", "FSUB", "FSUB", "FSUBI",
455 "FDIV", "FDIV", "FDIV", "FDIVI",
457 "FMUL", "FMUL", "FMUL", "FMULI",
458 "LTREQ", "LTRGE", "LTRLE", "LTRA",
459 "LTRNE", "LTRLT", "LTRGT", "LTRAL",
460 "FADDM", "FADDM", "FADDM", "FADDMI",
462 "FSTA", "FSTA", "FSTA", "FSTAI",
464 "FMULM", "FMULM", "FMULM", "FMULMI",
468 static const int32 fop_val
[] = {
469 00000+F_NOP12
, 00001+F_NOP12
, 00002+F_NOP12
, 00003+F_NOP12
,
470 00004+F_NOP12
, 00005+F_NOP12
, 00006+F_NOP12
, 00007+F_NOP12
,
471 00010+F_X
, 00020+F_X
, 00030+F_X
,
472 00040+F_NOP9
, 00050+F_NOP9
,
473 00100+F_IMMX
, 00110+F_IMMX
,
474 00000+F_MRD
, 00200+F_MR1D
, 00400+F_MR2D
, 00600+F_MRI
,
475 01000+F_AD15
, 01010+F_AD15
, 01020+F_AD15
, 01030+F_AD15
,
476 01040+F_AD15
, 01050+F_AD15
, 01060+F_AD15
, 01070+F_AD15
,
477 01100+F_AD15
, 01110+F_AD15
, 01120+F_AD15
, 01130+F_AD15
,
478 01000+F_MRD
, 01200+F_MR1D
, 01400+F_MR2D
, 01600+F_MRI
,
480 02000+F_MRD
, 02200+F_MR1D
, 02400+F_MR2D
, 02600+F_MRI
,
482 03000+F_MRD
, 03200+F_MR1D
, 03400+F_MR2D
, 03600+F_MRI
,
484 04000+F_MRD
, 04200+F_MR1D
, 04400+F_MR2D
, 04600+F_MRI
,
485 05000+F_LTR
, 05010+F_LTR
, 05020+F_LTR
, 05030+F_LTR
,
486 05040+F_LTR
, 05050+F_LTR
, 05060+F_LTR
, 05070+F_LTR
,
487 05000+F_MRD
, 05200+F_MR1D
, 05400+F_MR2D
, 05600+F_MRI
,
488 016000+F_LEMU
, 006000+F_LEMU
,
489 06000+F_MRD
, 06200+F_MR1D
, 06400+F_MR2D
, 06600+F_MRI
,
490 017000+F_LEMUI
, 007000+F_LEMUI
,
491 07000+F_MRD
, 07200+F_MR1D
, 07400+F_MR2D
, 07600+F_MRI
,
500 class = instruction class code
503 status = space needed
506 int32
fprint_opr (FILE *of
, int32 inst
, int32
class, int32 sp
)
510 for (i
= 0; opc_val
[i
] >= 0; i
++) { /* loop thru ops */
511 j
= (opc_val
[i
] >> I_V_FL
) & I_M_FL
; /* get class */
512 if ((j
== class) && (opc_val
[i
] & inst
)) { /* same class? */
513 inst
= inst
& ~opc_val
[i
]; /* mask bit set? */
514 fprintf (of
, (sp
? " %s": "%s"), opcode
[i
]);
526 *val = pointer to data
527 *uptr = pointer to unit
533 #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
534 #define SIXTOASC(x) (((x) >= 040)? (x): (x) + 0100)
535 #define TSSTOASC(x) ((x) + 040)
537 t_stat
fprint_sym (FILE *of
, t_addr addr
, t_value
*val
,
538 UNIT
*uptr
, int32 sw
)
540 int32 cflag
, i
, j
, sp
, inst
, disp
, opc
;
544 cflag
= (uptr
== NULL
) || (uptr
== &cpu_unit
);
546 if (sw
& SWMASK ('A')) { /* ASCII? */
547 if (inst
> 0377) return SCPE_ARG
;
548 fprintf (of
, FMTASC (inst
& 0177));
551 if (sw
& SWMASK ('C')) { /* characters? */
552 fprintf (of
, "%c", SIXTOASC ((inst
>> 6) & 077));
553 fprintf (of
, "%c", SIXTOASC (inst
& 077));
556 if (sw
& SWMASK ('T')) { /* TSS8 packed? */
557 fprintf (of
, "%c", TSSTOASC ((inst
>> 6) & 077));
558 fprintf (of
, "%c", TSSTOASC (inst
& 077));
561 if ((sw
& SWMASK ('F')) && /* FPP8? */
562 ((r
= fprint_sym_fpp (of
, val
)) != SCPE_ARG
))
564 if (!(sw
& SWMASK ('M'))) return SCPE_ARG
;
566 /* Instruction decode */
568 opc
= (inst
>> 9) & 07; /* get major opcode */
569 if (opc
== 07) /* operate? */
570 inst
= inst
| ((emode
& 1) << 12); /* include EAE mode */
571 if (opc
== 06) { /* IOT? */
574 uint32 dno
= (inst
>> 3) & 077;
575 for (i
= 0; (dptr
= amb_dev
[i
]) != NULL
; i
++) { /* check amb devices */
576 if ((dptr
->ctxt
== NULL
) || /* no DIB or */
577 (dptr
->flags
& DEV_DIS
)) continue; /* disabled? skip */
578 dibp
= (DIB
*) dptr
->ctxt
; /* get DIB */
579 if ((dno
>= dibp
->dev
) || /* IOT for this dev? */
580 (dno
< (dibp
->dev
+ dibp
->num
))) {
581 inst
= inst
| ((i
+ 1) << 12); /* disambiguate */
587 for (i
= 0; opc_val
[i
] >= 0; i
++) { /* loop thru ops */
588 j
= (opc_val
[i
] >> I_V_FL
) & I_M_FL
; /* get class */
589 if ((opc_val
[i
] & 077777) == (inst
& masks
[j
])) { /* match? */
591 switch (j
) { /* case on class */
593 case I_V_NPN
: case I_V_IOA
: /* no operands */
594 fprintf (of
, "%s", opcode
[i
]); /* opcode */
597 case I_V_FLD
: /* field change */
598 fprintf (of
, "%s %-o", opcode
[i
], (inst
>> 3) & 07);
601 case I_V_MRF
: /* mem ref */
602 disp
= inst
& 0177; /* displacement */
603 fprintf (of
, "%s%s", opcode
[i
], ((inst
& 00400)? " I ": " "));
604 if (inst
& 0200) { /* current page? */
605 if (cflag
) fprintf (of
, "%-o", (addr
& 07600) | disp
);
606 else fprintf (of
, "C %-o", disp
);
608 else fprintf (of
, "%-o", disp
); /* page zero */
611 case I_V_IOT
: /* IOT */
612 fprintf (of
, "%s %-o", opcode
[i
], inst
& 0777);
615 case I_V_OP1
: /* operate group 1 */
616 sp
= fprint_opr (of
, inst
& 0361, j
, 0);
617 if (opcode
[i
]) fprintf (of
, (sp
? " %s": "%s"), opcode
[i
]);
620 case I_V_OP2
: /* operate group 2 */
621 if (opcode
[i
]) fprintf (of
, "%s", opcode
[i
]); /* skips */
622 fprint_opr (of
, inst
& 0206, j
, opcode
[i
] != NULL
);
625 case I_V_OP3
: /* operate group 3 */
626 sp
= fprint_opr (of
, inst
& 0320, j
, 0);
627 if (opcode
[i
]) fprintf (of
, (sp
? " %s": "%s"), opcode
[i
]);
640 *cptr = pointer to input string
642 *uptr = pointer to unit
643 *val = pointer to output values
646 status = error status
649 t_stat
parse_sym (char *cptr
, t_addr addr
, UNIT
*uptr
, t_value
*val
, int32 sw
)
651 uint32 cflag
, d
, i
, j
, k
;
655 cflag
= (uptr
== NULL
) || (uptr
== &cpu_unit
);
656 while (isspace (*cptr
)) cptr
++; /* absorb spaces */
657 if ((sw
& SWMASK ('A')) || ((*cptr
== '\'') && cptr
++)) { /* ASCII char? */
658 if (cptr
[0] == 0) return SCPE_ARG
; /* must have 1 char */
659 val
[0] = (t_value
) cptr
[0] | 0200;
662 if ((sw
& SWMASK ('C')) || ((*cptr
== '"') && cptr
++)) { /* sixbit string? */
663 if (cptr
[0] == 0) return SCPE_ARG
; /* must have 1 char */
664 val
[0] = (((t_value
) cptr
[0] & 077) << 6) |
665 ((t_value
) cptr
[1] & 077);
668 if ((sw
& SWMASK ('T')) || ((*cptr
== '"') && cptr
++)) { /* TSS8 string? */
669 if (cptr
[0] == 0) return SCPE_ARG
; /* must have 1 char */
670 val
[0] = (((t_value
) (cptr
[0] - 040) & 077) << 6) |
671 ((t_value
) (cptr
[1] - 040) & 077);
674 if ((r
= parse_sym_fpp (cptr
, val
)) != SCPE_ARG
) /* FPP8 inst? */
677 /* Instruction parse */
679 cptr
= get_glyph (cptr
, gbuf
, 0); /* get opcode */
680 for (i
= 0; (opcode
[i
] != NULL
) && (strcmp (opcode
[i
], gbuf
) != 0) ; i
++) ;
681 if (opcode
[i
] == NULL
) return SCPE_ARG
;
682 val
[0] = opc_val
[i
] & 07777; /* get value */
683 j
= (opc_val
[i
] >> I_V_FL
) & I_M_FL
; /* get class */
685 switch (j
) { /* case on class */
687 case I_V_IOT
: /* IOT */
688 if ((cptr
= parse_field (cptr
, 0777, &d
, 0)) == NULL
)
689 return SCPE_ARG
; /* get dev+pulse */
693 case I_V_FLD
: /* field */
694 for (cptr
= get_glyph (cptr
, gbuf
, 0); gbuf
[0] != 0;
695 cptr
= get_glyph (cptr
, gbuf
, 0)) {
696 for (i
= 0; (opcode
[i
] != NULL
) &&
697 (strcmp (opcode
[i
], gbuf
) != 0) ; i
++) ;
698 if (opcode
[i
] != NULL
) {
699 k
= (opc_val
[i
] >> I_V_FL
) & I_M_FL
;
700 if (k
!= j
) return SCPE_ARG
;
701 val
[0] = val
[0] | (opc_val
[i
] & 07777);
704 d
= get_uint (gbuf
, 8, 07, &r
);
705 if (r
!= SCPE_OK
) return SCPE_ARG
;
706 val
[0] = val
[0] | (d
<< 3);
712 case I_V_MRF
: /* mem ref */
713 cptr
= get_glyph (cptr
, gbuf
, 0); /* get next field */
714 if (strcmp (gbuf
, "I") == 0) { /* indirect? */
715 val
[0] = val
[0] | 0400;
716 cptr
= get_glyph (cptr
, gbuf
, 0);
718 if ((k
= (strcmp (gbuf
, "C") == 0)) || (strcmp (gbuf
, "Z") == 0)) {
719 if ((cptr
= parse_field (cptr
, 0177, &d
, 0)) == NULL
)
721 val
[0] = val
[0] | d
| (k
? 0200: 0);
724 d
= get_uint (gbuf
, 8, 07777, &r
);
725 if (r
!= SCPE_OK
) return SCPE_ARG
;
726 if (d
<= 0177) val
[0] = val
[0] | d
;
727 else if (cflag
&& (((addr
^ d
) & 07600) == 0))
728 val
[0] = val
[0] | (d
& 0177) | 0200;
729 else return SCPE_ARG
;
733 case I_V_OP1
: case I_V_OP2
: case I_V_OP3
: /* operates */
734 case I_V_NPN
: case I_V_IOA
:
735 for (cptr
= get_glyph (cptr
, gbuf
, 0); gbuf
[0] != 0;
736 cptr
= get_glyph (cptr
, gbuf
, 0)) {
737 for (i
= 0; (opcode
[i
] != NULL
) &&
738 (strcmp (opcode
[i
], gbuf
) != 0) ; i
++) ;
739 k
= opc_val
[i
] & 07777;
740 if ((opcode
[i
] == NULL
) || (((k
^ val
[0]) & 07000) != 0))
747 if (*cptr
!= 0) return SCPE_ARG
; /* junk at end? */
751 /* FPP8 instruction decode */
753 t_stat
fprint_sym_fpp (FILE *of
, t_value
*val
)
755 uint32 wd1
, wd2
, xr4b
, xr3b
, ad15
;
757 extern uint32 fpp_bra
, fpp_cmd
;
759 wd1
= (uint32
) val
[0] | ((fpp_cmd
& 04000) << 1);
760 wd2
= (uint32
) val
[1];
761 xr4b
= (wd1
>> 3) & 017;
763 ad15
= (xr3b
<< 12) | wd2
;
765 for (i
= 0; fop_val
[i
] >= 0; i
++) { /* loop thru ops */
766 j
= (fop_val
[i
] >> F_V_FL
) & F_M_FL
; /* get class */
767 if ((fop_val
[i
] & 017777) == (wd1
& fmasks
[j
])) { /* match? */
769 switch (j
) { /* case on class */
772 case F_V_LTR
: /* no operands */
773 fprintf (of
, "%s", fopcode
[i
]);
776 case F_V_X
: /* index */
777 fprintf (of
, "%s %o", fopcode
[i
], xr3b
);
780 case F_V_IMMX
: /* index imm */
781 fprintf (of
, "%s %-o,%o", fopcode
[i
], wd2
, xr3b
);
782 return -1; /* extra word */
784 case F_V_AD15
: /* 15b address */
785 fprintf (of
, "%s %-o", fopcode
[i
], ad15
);
786 return -1; /* extra word */
788 case F_V_AD15X
: /* 15b addr, indx */
789 fprintf (of
, "%s %-o", fopcode
[i
], ad15
);
791 fprintf (of
, ",%o+", xr4b
& 7);
792 else fprintf (of
, ",%o", xr4b
);
793 return -1; /* extra word */
795 case F_V_MR1D
: /* 1 word direct */
796 ad15
= (fpp_bra
+ (3 * (wd1
& 0177))) & ADDRMASK
;
797 fprintf (of
, "%s %-o", fopcode
[i
], ad15
);
801 case F_V_MR2D
: /* 2 word direct */
802 fprintf (of
, "%s %-o", fopcode
[i
], ad15
);
804 fprintf (of
, ",%o+", xr4b
& 7);
806 fprintf (of
, ",%o", xr4b
);
807 return -1; /* extra word */
810 case F_V_MRI
: /* indirect */
811 ad15
= (fpp_bra
+ (3 * xr3b
)) & ADDRMASK
;
812 fprintf (of
, "%s %-o", fopcode
[i
], ad15
);
814 fprintf (of
, ",%o+", xr4b
& 7);
816 fprintf (of
, ",%o", xr4b
);
819 case F_V_MRD
: /* encode only */
829 /* FPP8 instruction parse */
831 t_stat
parse_sym_fpp (char *cptr
, t_value
*val
)
837 cptr
= get_glyph (cptr
, gbuf
, 0); /* get opcode */
838 for (i
= 0; (fopcode
[i
] != NULL
) && (strcmp (fopcode
[i
], gbuf
) != 0) ; i
++) ;
839 if (fopcode
[i
] == NULL
) return SCPE_ARG
;
840 val
[0] = fop_val
[i
] & 07777; /* get value */
841 j
= (fop_val
[i
] >> F_V_FL
) & F_M_FL
; /* get class */
845 switch (j
) { /* case on class */
849 case F_V_LTR
: /* no operands */
852 case F_V_X
: /* 3b XR */
853 if ((cptr
= parse_field (cptr
, 07, &xr
, 0)) == NULL
)
858 case F_V_IMMX
: /* 12b, XR */
859 if ((cptr
= parse_field (cptr
, 07777, &ad
, ',')) == NULL
)
862 ((cptr
= parse_fpp_xr (cptr
, &xr
, FALSE
)) == NULL
))
868 case F_V_AD15
: /* 15b addr */
869 if ((cptr
= parse_field (cptr
, 077777, &ad
, 0)) == NULL
)
871 val
[0] |= (ad
>> 12) & 07;
872 val
[++nwd
] = ad
& 07777;
875 case F_V_AD15X
: /* 15b addr, idx */
876 if ((cptr
= parse_field (cptr
, 077777, &ad
, ',')) == NULL
)
879 ((cptr
= parse_fpp_xr (cptr
, &xr
, FALSE
)) == NULL
))
881 val
[0] |= ((xr
<< 3) | ((ad
>> 12) & 07));
882 val
[++nwd
] = ad
& 07777;
886 case F_V_MRI
: /* indirect */
887 if ((cptr
= parse_field (cptr
, 077777, &ad
, ',')) == NULL
)
890 ((cptr
= parse_fpp_xr (cptr
, &xr
, TRUE
)) == NULL
))
892 if ((broff
= test_fpp_addr (ad
, 07)) < 0)
894 val
[0] |= ((xr
<< 3) | broff
);
897 case F_V_MRD
: /* direct */
898 if ((cptr
= parse_field (cptr
, 077777, &ad
, ',')) == NULL
)
900 if (((broff
= test_fpp_addr (ad
, 0177)) < 0) ||
903 ((cptr
= parse_fpp_xr (cptr
, &xr
, TRUE
)) == NULL
))
905 val
[0] |= (00400 | (xr
<< 3) | ((ad
>> 12) & 07));
906 val
[++nwd
] = ad
& 07777;
908 else val
[0] |= (00200 | broff
);
912 if ((cptr
= parse_field (cptr
, 077777, &ad
, ',')) == NULL
)
915 ((cptr
= parse_fpp_xr (cptr
, &xr
, TRUE
)) == NULL
))
917 val
[0] |= ((xr
<< 3) | ((ad
>> 12) & 07));
918 val
[++nwd
] = ad
& 07777;
926 if (*cptr
!= 0) return SCPE_ARG
; /* junk at end? */
932 char *parse_field (char *cptr
, uint32 max
, uint32
*val
, uint32 c
)
937 cptr
= get_glyph (cptr
, gbuf
, c
); /* get field */
938 *val
= get_uint (gbuf
, 8, max
, &r
);
944 /* Parse index register */
946 char *parse_fpp_xr (char *cptr
, uint32
*xr
, t_bool inc
)
952 cptr
= get_glyph (cptr
, gbuf
, 0); /* get field */
954 if (gbuf
[len
- 1] == '+') {
961 *xr
+= get_uint (gbuf
, 8, 7, &r
);
967 /* Test address in range of base register */
969 int32
test_fpp_addr (uint32 ad
, uint32 max
)
972 extern uint32 fpp_bra
;
975 if (((off
% 3) != 0) ||
978 return ((int32
) off
/ 3);