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