Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /* pdp1_sys.c: PDP-1 simulator interface\r |
2 | \r | |
3 | Copyright (c) 1993-2007, 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 | 03-Jan-07 RMS Fixed bugs in block loader, char input\r | |
27 | 21-Dec-06 RMS Added 16-channel sequence break support, PDP-1D support\r | |
28 | 06-Apr-04 RMS Fixed bug in binary loader (found by Mark Crispin)\r | |
29 | 08-Feb-04 PLB Merged display support\r | |
30 | 08-Dec-03 RMS Added parallel drum support, drum mnemonics\r | |
31 | 18-Oct-03 RMS Added DECtape off reel message\r | |
32 | 01-Sep-03 RMS Added support for loading in multiple fields\r | |
33 | 22-Jul-03 RMS Updated for "hardware" RIM loader\r | |
34 | 05-Dec-02 RMS Added drum support\r | |
35 | 21-Nov-02 RMS Changed typewriter to half duplex\r | |
36 | 20-Aug-02 RMS Added DECtape support\r | |
37 | 17-Sep-01 RMS Removed multiconsole support\r | |
38 | 13-Jul-01 RMS Fixed RIM loader format\r | |
39 | 27-May-01 RMS Added multiconsole support\r | |
40 | 14-Mar-01 RMS Revised load/dump interface (again)\r | |
41 | 30-Oct-00 RMS Added support for examine to file\r | |
42 | 27-Oct-98 RMS V2.4 load interface\r | |
43 | 20-Oct-97 RMS Fixed endian-dependence in RIM loader\r | |
44 | (found by Michael Somos)\r | |
45 | */\r | |
46 | \r | |
47 | #include "pdp1_defs.h"\r | |
48 | #include <ctype.h>\r | |
49 | \r | |
50 | extern DEVICE cpu_dev;\r | |
51 | extern DEVICE clk_dev;\r | |
52 | extern DEVICE ptr_dev;\r | |
53 | extern DEVICE ptp_dev;\r | |
54 | extern DEVICE tti_dev;\r | |
55 | extern DEVICE tto_dev;\r | |
56 | extern DEVICE lpt_dev;\r | |
57 | extern DEVICE dt_dev;\r | |
58 | extern DEVICE drm_dev;\r | |
59 | extern DEVICE drp_dev;\r | |
60 | extern DEVICE dcs_dev, dcsl_dev;\r | |
61 | extern DEVICE dpy_dev;\r | |
62 | extern UNIT cpu_unit;\r | |
63 | extern REG cpu_reg[];\r | |
64 | extern int32 M[];\r | |
65 | extern int32 PC;\r | |
66 | extern int32 ascii_to_fiodec[], fiodec_to_ascii[];\r | |
67 | extern int32 sc_map[];\r | |
68 | extern int32 sim_switches;\r | |
69 | \r | |
70 | /* SCP data structures and interface routines\r | |
71 | \r | |
72 | sim_name simulator name string\r | |
73 | sim_PC pointer to saved PC register descriptor\r | |
74 | sim_emax number of words for examine\r | |
75 | sim_devices array of pointers to simulated devices\r | |
76 | sim_stop_messages array of pointers to stop messages\r | |
77 | sim_load binary loader\r | |
78 | */\r | |
79 | \r | |
80 | char sim_name[] = "PDP-1";\r | |
81 | \r | |
82 | REG *sim_PC = &cpu_reg[0];\r | |
83 | \r | |
84 | int32 sim_emax = 1;\r | |
85 | \r | |
86 | DEVICE *sim_devices[] = {\r | |
87 | &cpu_dev,\r | |
88 | &clk_dev,\r | |
89 | &ptr_dev,\r | |
90 | &ptp_dev,\r | |
91 | &tti_dev,\r | |
92 | &tto_dev,\r | |
93 | &lpt_dev,\r | |
94 | &dt_dev,\r | |
95 | &drm_dev,\r | |
96 | &drp_dev,\r | |
97 | &dcs_dev,\r | |
98 | &dcsl_dev,\r | |
99 | /* &dpy_dev, */\r | |
100 | NULL\r | |
101 | };\r | |
102 | \r | |
103 | const char *sim_stop_messages[] = {\r | |
104 | "Unknown error",\r | |
105 | "Undefined instruction",\r | |
106 | "HALT instruction",\r | |
107 | "Breakpoint",\r | |
108 | "Nested XCT's",\r | |
109 | "Nested indirect addresses",\r | |
110 | "Infinite I/O wait state",\r | |
111 | "DECtape off reel"\r | |
112 | };\r | |
113 | \r | |
114 | /* Binary loader - supports both RIM format and Macro block format */\r | |
115 | \r | |
116 | int32 pdp1_getw (FILE *inf)\r | |
117 | {\r | |
118 | int32 i, tmp, word;\r | |
119 | \r | |
120 | word = 0;\r | |
121 | for (i = 0; i < 3;) {\r | |
122 | if ((tmp = getc (inf)) == EOF) return -1;\r | |
123 | if (tmp & 0200) {\r | |
124 | word = (word << 6) | (tmp & 077);\r | |
125 | i++;\r | |
126 | }\r | |
127 | }\r | |
128 | return word;\r | |
129 | }\r | |
130 | \r | |
131 | t_stat rim_load (FILE *inf, int32 fld)\r | |
132 | {\r | |
133 | int32 origin, val;\r | |
134 | \r | |
135 | for (;;) {\r | |
136 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r | |
137 | if (((val & 0760000) == OP_DIO) || /* DIO? */\r | |
138 | ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */\r | |
139 | origin = val & DAMASK;\r | |
140 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r | |
141 | M[fld | origin] = val;\r | |
142 | }\r | |
143 | else if ((val & 0760000) == OP_JMP) { /* JMP? */\r | |
144 | PC = fld | (val & DAMASK);\r | |
145 | break;\r | |
146 | }\r | |
147 | else return SCPE_FMT; /* bad instr */\r | |
148 | }\r | |
149 | return SCPE_OK; /* done */\r | |
150 | }\r | |
151 | \r | |
152 | t_stat blk_load (FILE *inf, int32 fld)\r | |
153 | {\r | |
154 | int32 val, start, count, csum;\r | |
155 | \r | |
156 | for (;;) {\r | |
157 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; /* get word, EOF? */\r | |
158 | if ((val & 0760000) == OP_DIO) { /* DIO? */\r | |
159 | csum = val; /* init checksum */\r | |
160 | start = val & DAMASK; /* starting addr */\r | |
161 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r | |
162 | if ((val & 0760000) != OP_DIO) return SCPE_FMT;\r | |
163 | csum = csum + val;\r | |
164 | if (csum > DMASK) csum = (csum + 1) & DMASK;\r | |
165 | count = (val & DAMASK) - start; /* block count */\r | |
166 | if (count <= 0) return SCPE_FMT;\r | |
167 | while (count--) { /* loop on data */\r | |
168 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r | |
169 | csum = csum + val;\r | |
170 | if (csum > DMASK) csum = (csum + 1) & DMASK;\r | |
171 | M[fld | start] = val;\r | |
172 | start = (start + 1) & DAMASK;\r | |
173 | }\r | |
174 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r | |
175 | if (val != csum) return SCPE_CSUM;\r | |
176 | }\r | |
177 | else if ((val & 0760000) == OP_JMP) { /* JMP? */\r | |
178 | PC = fld | (val & DAMASK);\r | |
179 | break;\r | |
180 | }\r | |
181 | else return SCPE_FMT; /* bad instr */\r | |
182 | }\r | |
183 | return SCPE_OK; /* done */\r | |
184 | }\r | |
185 | \r | |
186 | t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)\r | |
187 | {\r | |
188 | t_stat sta;\r | |
189 | int32 fld;\r | |
190 | \r | |
191 | if (flag != 0) return SCPE_ARG;\r | |
192 | if (cptr && (*cptr != 0)) {\r | |
193 | fld = get_uint (cptr, 8, AMASK, &sta);\r | |
194 | if (sta != SCPE_OK) return sta;\r | |
195 | fld = fld & EPCMASK;\r | |
196 | }\r | |
197 | else fld = 0;\r | |
198 | sta = rim_load (fileref, fld);\r | |
199 | if (sta != SCPE_OK) return sta;\r | |
200 | if ((sim_switches & SWMASK ('B')) || match_ext (fnam, "BIN"))\r | |
201 | return blk_load (fileref, fld);\r | |
202 | return SCPE_OK;\r | |
203 | }\r | |
204 | \r | |
205 | /* Symbol tables */\r | |
206 | \r | |
207 | #define I_V_FL 18 /* inst class */\r | |
208 | #define I_M_FL 017 /* class mask */\r | |
209 | #define I_V_NPN 0 /* no operand */\r | |
210 | #define I_V_IOT 1 /* IOT */\r | |
211 | #define I_V_LAW 2 /* LAW */\r | |
212 | #define I_V_MRF 3 /* memory reference */\r | |
213 | #define I_V_MRI 4 /* mem ref no ind */\r | |
214 | #define I_V_OPR 5 /* OPR */\r | |
215 | #define I_V_SKP 6 /* skip */\r | |
216 | #define I_V_SHF 7 /* shift */\r | |
217 | #define I_V_SPC 8 /* special */\r | |
218 | #define I_NPN (I_V_NPN << I_V_FL) /* no operand */\r | |
219 | #define I_IOT (I_V_IOT << I_V_FL) /* IOT */\r | |
220 | #define I_LAW (I_V_LAW << I_V_FL) /* LAW */\r | |
221 | #define I_MRF (I_V_MRF << I_V_FL) /* memory reference */\r | |
222 | #define I_MRI (I_V_MRI << I_V_FL) /* mem ref no ind */\r | |
223 | #define I_OPR (I_V_OPR << I_V_FL) /* OPR */\r | |
224 | #define I_SKP (I_V_SKP << I_V_FL) /* skip */\r | |
225 | #define I_SHF (I_V_SHF << I_V_FL) /* shift */\r | |
226 | #define I_SPC (I_V_SPC << I_V_FL)\r | |
227 | \r | |
228 | static const int32 masks[] = {\r | |
229 | 0777777, 0760077, 0760000, 0760000,\r | |
230 | 0770000, 0760017, 0760077, 0777000,\r | |
231 | 0760003\r | |
232 | };\r | |
233 | \r | |
234 | static const char *opcode[] = {\r | |
235 | "AND", "IOR", "XOR", "XCT", /* mem refs */\r | |
236 | "LAC", "LIO", "DAC", "DAP",\r | |
237 | "DIP", "DIO", "DZM", "ADD",\r | |
238 | "SUB", "IDX", "ISP", "SAD",\r | |
239 | "SAS", "MUL", "DIV", "JMP",\r | |
240 | "JSP", "LCH", "DCH", "TAD",\r | |
241 | \r | |
242 | "CAL", "JDA", /* mem ref no ind */\r | |
243 | \r | |
244 | "LAW",\r | |
245 | \r | |
246 | "IOH", "RPA", "RPB", "RRB", /* I/O instructions */\r | |
247 | "PPA", "PPB", "TYO", "TYI",\r | |
248 | "DPY",\r | |
249 | "DSC", "ASC", "ISC", "CAC",\r | |
250 | "LSM", "ESM", "CBS",\r | |
251 | "LEM", "EEM", "CKS",\r | |
252 | "MSE", "MLC", "MRD", "MWR", "MRS",\r | |
253 | "DIA", "DBA", "DWC", "DRA", "DCL",\r | |
254 | "DRD", "DWR", "DBL", "DCN",\r | |
255 | "DTD", "DSE", "DSP",\r | |
256 | "LRG", "ERG", "LRM", "ERM",\r | |
257 | "RNM", "RSM", "RCK", "CTB",\r | |
258 | "RCH", "RCC", "TCC", "TCB",\r | |
259 | "RRC", "SSB", "RSC",\r | |
260 | \r | |
261 | "SKP", "SKP I", "CLO", /* base as NPNs */\r | |
262 | "SFT", "SPC", "OPR",\r | |
263 | \r | |
264 | "RAL", "RIL", "RCL", /* shifts */\r | |
265 | "SAL", "SIL", "SCL",\r | |
266 | "RAR", "RIR", "RCR",\r | |
267 | "SAR", "SIR", "SCR",\r | |
268 | \r | |
269 | "SZF1", "SZF2", "SZF3", /* skips */\r | |
270 | "SZF4", "SZF5", "SZF6", "SZF7",\r | |
271 | "SZS1", "SZS1 SZF1", "SZS1 SZF2", "SZS1 SZ3",\r | |
272 | "SZS1 SZF4", "SZS1 SZF5", "SZS1 SZF6", "SZS1 SZF7",\r | |
273 | "SZS2", "SZS2 SZF1", "SZS2 SZF2", "SZS2 SZ3",\r | |
274 | "SZS2 SZF4", "SZS2 SZF5", "SZS2 SZF6", "SZS2 SZF7",\r | |
275 | "SZS3", "SZS3 SZF1", "SZS3 SZF2", "SZS3 SZ3",\r | |
276 | "SZS3 SZF4", "SZS3 SZF5", "SZS3 SZF6", "SZS3 SZF7",\r | |
277 | "SZS4", "SZS4 SZF1", "SZS4 SZF2", "SZS4 SZ3",\r | |
278 | "SZS4 SZF4", "SZS4 SZF5", "SZS4 SZF6", "SZS4 SZF7",\r | |
279 | "SZS5", "SZS5 SZF1", "SZS5 SZF2", "SZS5 SZ3",\r | |
280 | "SZS5 SZF4", "SZS5 SZF5", "SZS5 SZF6", "SZS5 SZF7",\r | |
281 | "SZS6", "SZS6 SZF1", "SZS6 SZF2", "SZS6 SZ3",\r | |
282 | "SZS6 SZF4", "SZS6 SZF5", "SZS6 SZF6", "SZS6 SZF7",\r | |
283 | "SZS7", "SZS7 SZF1", "SZS7 SZF2", "SZS7 SZ3",\r | |
284 | "SZS7 SZF4", "SZS7 SZF5", "SZS7 SZF6", "SZS7 SZF7",\r | |
285 | \r | |
286 | "CLF1", "CLF2", "CLF3", /* operates */\r | |
287 | "CLF4", "CLF5", "CLF6", "CLF7",\r | |
288 | "STF1", "STF2", "STF3",\r | |
289 | "STF4", "STF5", "STF6", "STF7",\r | |
290 | \r | |
291 | "FF1", "FF2", "FF3", /* specials */\r | |
292 | \r | |
293 | "SZA", "SPA", "SMA", /* uprog skips */\r | |
294 | "SZO", "SPI", "SNI",\r | |
295 | "I", /* encode only */\r | |
296 | \r | |
297 | "LIA", "LAI", "SWP", /* uprog opers */\r | |
298 | "LAP", "CLA", "HLT",\r | |
299 | "CMA", "LAT", "CLI",\r | |
300 | "CMI",\r | |
301 | \r | |
302 | "CML", "CLL", "SZL", /* uprog specials */\r | |
303 | "SCF", "SCI", "SCM",\r | |
304 | "IDA", "IDC", "IFI",\r | |
305 | "IIF",\r | |
306 | \r | |
307 | NULL, NULL, NULL, /* decode only */\r | |
308 | NULL,\r | |
309 | };\r | |
310 | \r | |
311 | static const int32 opc_val[] = {\r | |
312 | 0020000+I_MRF, 0040000+I_MRF, 0060000+I_MRF, 0100000+I_MRF,\r | |
313 | 0200000+I_MRF, 0220000+I_MRF, 0240000+I_MRF, 0260000+I_MRF,\r | |
314 | 0300000+I_MRF, 0320000+I_MRF, 0340000+I_MRF, 0400000+I_MRF,\r | |
315 | 0420000+I_MRF, 0440000+I_MRF, 0460000+I_MRF, 0500000+I_MRF,\r | |
316 | 0520000+I_MRF, 0540000+I_MRF, 0560000+I_MRF, 0600000+I_MRF,\r | |
317 | 0620000+I_MRF, 0120000+I_MRF, 0140000+I_MRF, 0360000+I_MRF,\r | |
318 | \r | |
319 | 0160000+I_MRI, 0170000+I_MRI,\r | |
320 | \r | |
321 | 0700000+I_LAW,\r | |
322 | \r | |
323 | 0730000+I_NPN, 0720001+I_IOT, 0720002+I_IOT, 0720030+I_IOT,\r | |
324 | 0720005+I_IOT, 0720006+I_IOT, 0720003+I_IOT, 0720004+I_IOT,\r | |
325 | 0720007+I_IOT,\r | |
326 | 0720050+I_IOT, 0720051+I_IOT, 0720052+I_IOT, 0720053+I_NPN,\r | |
327 | 0720054+I_NPN, 0720055+I_NPN, 0720056+I_NPN,\r | |
328 | 0720074+I_NPN, 0724074+I_NPN, 0720033+I_NPN,\r | |
329 | 0720301+I_NPN, 0720401+I_NPN, 0720501+I_NPN, 0720601+I_NPN, 0720701+I_NPN, \r | |
330 | 0720061+I_NPN, 0722061+I_NPN, 0720062+I_NPN, 0722062+I_NPN, 0720063+I_NPN,\r | |
331 | 0720161+I_NPN, 0721161+I_NPN, 0720162+I_NPN, 0721162+I_NPN,\r | |
332 | 0720163+I_NPN, 0720164+I_NPN, 0721164+I_NPN,\r | |
333 | 0720010+I_NPN, 0720011+I_NPN, 0720064+I_NPN, 0720065+I_NPN,\r | |
334 | 0720066+I_IOT, 0720067+I_NPN, 0720032+I_NPN, 0720035+I_NPN,\r | |
335 | 0720022+I_NPN, 0721022+I_NPN, 0725022+I_NPN, 0724022+I_NPN,\r | |
336 | 0720122+I_NPN, 0724122+I_NPN, 0721122+I_NPN,\r | |
337 | \r | |
338 | 0640000+I_NPN, 0650000+I_NPN, 0651600+I_NPN,\r | |
339 | 0660000+I_NPN, 0740000+I_NPN, 0760000+I_NPN,\r | |
340 | \r | |
341 | 0661000+I_SHF, 0662000+I_SHF, 0663000+I_SHF,\r | |
342 | 0665000+I_SHF, 0666000+I_SHF, 0667000+I_SHF,\r | |
343 | 0671000+I_SHF, 0672000+I_SHF, 0673000+I_SHF,\r | |
344 | 0675000+I_SHF, 0676000+I_SHF, 0677000+I_SHF,\r | |
345 | \r | |
346 | 0640001+I_SKP, 0640002+I_SKP, 0640003+I_SKP,\r | |
347 | 0640004+I_SKP, 0640005+I_SKP, 0640006+I_SKP, 0640007+I_SKP,\r | |
348 | 0640010+I_SKP, 0640011+I_SKP, 0640012+I_SKP, 0640013+I_SKP,\r | |
349 | 0640014+I_SKP, 0640015+I_SKP, 0640016+I_SKP, 0640017+I_SKP,\r | |
350 | 0640020+I_SKP, 0640021+I_SKP, 0640022+I_SKP, 0640023+I_SKP,\r | |
351 | 0640024+I_SKP, 0640025+I_SKP, 0640026+I_SKP, 0640027+I_SKP,\r | |
352 | 0640030+I_SKP, 0640031+I_SKP, 0640032+I_SKP, 0640033+I_SKP,\r | |
353 | 0640034+I_SKP, 0640035+I_SKP, 0640036+I_SKP, 0640037+I_SKP,\r | |
354 | 0640040+I_SKP, 0640041+I_SKP, 0640042+I_SKP, 0640043+I_SKP,\r | |
355 | 0640044+I_SKP, 0640045+I_SKP, 0640046+I_SKP, 0640047+I_SKP,\r | |
356 | 0640050+I_SKP, 0640051+I_SKP, 0640052+I_SKP, 0640053+I_SKP,\r | |
357 | 0640054+I_SKP, 0640055+I_SKP, 0640056+I_SKP, 0640057+I_SKP,\r | |
358 | 0640060+I_SKP, 0640061+I_SKP, 0640062+I_SKP, 0640063+I_SKP,\r | |
359 | 0640064+I_SKP, 0640065+I_SKP, 0640066+I_SKP, 0640067+I_SKP,\r | |
360 | 0640070+I_SKP, 0640071+I_SKP, 0640072+I_SKP, 0640073+I_SKP,\r | |
361 | 0640074+I_SKP, 0640075+I_SKP, 0640076+I_SKP, 0640077+I_SKP,\r | |
362 | \r | |
363 | 0760001+I_OPR, 0760002+I_OPR, 0760003+I_OPR,\r | |
364 | 0760004+I_OPR, 0760005+I_OPR, 0760006+I_OPR, 0760007+I_OPR,\r | |
365 | 0760011+I_OPR, 0760012+I_OPR, 0760013+I_OPR,\r | |
366 | 0760014+I_OPR, 0760015+I_OPR, 0760016+I_OPR, 0760017+I_OPR,\r | |
367 | \r | |
368 | 0740001+I_SPC, 0740002+I_SPC, 0740003+I_OPR,\r | |
369 | \r | |
370 | 0640100+I_SKP, 0640200+I_SKP, 0640400+I_SKP,\r | |
371 | 0641000+I_SKP, 0642000+I_SKP, 0644000+I_SKP,\r | |
372 | 0010000+I_SKP, /* encode only */\r | |
373 | \r | |
374 | 0760020+I_OPR, 0760040+I_OPR, 0760060+I_NPN,\r | |
375 | 0760100+I_OPR, 0760200+I_OPR, 0760400+I_OPR,\r | |
376 | 0761000+I_OPR, 0762000+I_OPR, 0764000+I_OPR,\r | |
377 | 0770000+I_OPR,\r | |
378 | \r | |
379 | 0740004+I_SPC, 0740010+I_SPC, 0740020+I_SPC,\r | |
380 | 0740040+I_SPC, 0740100+I_SPC, 0740200+I_SPC,\r | |
381 | 0740400+I_SPC, 0741000+I_SPC, 0742000+I_SPC,\r | |
382 | 0744000+I_SPC,\r | |
383 | \r | |
384 | 0640000+I_SKP, 0740000+I_SPC, 0760000+I_OPR, /* decode only */\r | |
385 | -1\r | |
386 | };\r | |
387 | \r | |
388 | /* Operate or skip decode\r | |
389 | \r | |
390 | Inputs:\r | |
391 | *of = output stream\r | |
392 | inst = mask bits\r | |
393 | class = instruction class code\r | |
394 | sp = space needed?\r | |
395 | Outputs:\r | |
396 | status = space needed?\r | |
397 | */\r | |
398 | \r | |
399 | int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp)\r | |
400 | {\r | |
401 | int32 i, j;\r | |
402 | \r | |
403 | for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r | |
404 | j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r | |
405 | if ((j == class) && (opc_val[i] & inst)) { /* same class? */\r | |
406 | inst = inst & ~opc_val[i]; /* mask bit set? */\r | |
407 | fprintf (of, (sp? " %s": "%s"), opcode[i]);\r | |
408 | sp = 1;\r | |
409 | }\r | |
410 | }\r | |
411 | return sp;\r | |
412 | }\r | |
413 | \r | |
414 | /* Symbolic decode\r | |
415 | \r | |
416 | Inputs:\r | |
417 | *of = output stream\r | |
418 | addr = current PC\r | |
419 | *val = pointer to values\r | |
420 | *uptr = pointer to unit\r | |
421 | sw = switches\r | |
422 | Outputs:\r | |
423 | return = status code\r | |
424 | */\r | |
425 | \r | |
426 | #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)\r | |
427 | #define SIXTOASC(x) fiodec_to_ascii[x]\r | |
428 | #define ASCTOSIX(x) (ascii_to_fiodec[x] & 077)\r | |
429 | \r | |
430 | t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,\r | |
431 | UNIT *uptr, int32 sw)\r | |
432 | {\r | |
433 | int32 cflag, i, j, sp, inst, disp, ma;\r | |
434 | \r | |
435 | inst = val[0];\r | |
436 | cflag = (uptr == NULL) || (uptr == &cpu_unit);\r | |
437 | if (sw & SWMASK ('A')) { /* ASCII? */\r | |
438 | if (inst > 0377) return SCPE_ARG;\r | |
439 | fprintf (of, FMTASC (inst & 0177));\r | |
440 | return SCPE_OK;\r | |
441 | }\r | |
442 | if (sw & SWMASK ('F')) {\r | |
443 | fputc (fiodec_to_ascii[inst & 077], of);\r | |
444 | return SCPE_OK;\r | |
445 | }\r | |
446 | if (sw & SWMASK ('C')) { /* character? */\r | |
447 | fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077));\r | |
448 | fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077));\r | |
449 | fprintf (of, "%c", SIXTOASC (inst & 077));\r | |
450 | return SCPE_OK;\r | |
451 | }\r | |
452 | if (!(sw & SWMASK ('M'))) return SCPE_ARG;\r | |
453 | \r | |
454 | /* Instruction decode */\r | |
455 | \r | |
456 | disp = inst & 007777;\r | |
457 | ma = (addr & EPCMASK) | disp;\r | |
458 | for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r | |
459 | j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r | |
460 | if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */\r | |
461 | \r | |
462 | switch (j) { /* case on class */\r | |
463 | \r | |
464 | case I_V_NPN: /* no operands */\r | |
465 | fprintf (of, "%s", opcode[i]); /* opcode */\r | |
466 | break;\r | |
467 | \r | |
468 | case I_V_IOT: /* IOT */\r | |
469 | disp = (inst - opc_val[i]) & 017777;\r | |
470 | if (disp == IA) fprintf (of, "%s I", opcode[i]);\r | |
471 | else if (disp) fprintf (of, "%s %-o", opcode[i], disp);\r | |
472 | else fprintf (of, "%s", opcode[i]);\r | |
473 | break;\r | |
474 | \r | |
475 | case I_V_LAW: /* LAW */\r | |
476 | cflag = 0; /* fall thru to MRF */\r | |
477 | case I_V_MRF: /* mem ref */\r | |
478 | fprintf (of, "%s%s%-o", opcode[i],\r | |
479 | ((inst & IA)? " I ": " "), (cflag? ma: disp));\r | |
480 | break;\r | |
481 | \r | |
482 | case I_V_MRI: /* mem ref no ind */\r | |
483 | fprintf (of, "%s %-o", opcode[i], (cflag? ma: disp));\r | |
484 | break;\r | |
485 | \r | |
486 | case I_V_OPR: /* operates */\r | |
487 | sp = fprint_opr (of, inst & 017760, j, 0);\r | |
488 | if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);\r | |
489 | break;\r | |
490 | \r | |
491 | case I_V_SKP: /* skips */\r | |
492 | sp = fprint_opr (of, inst & 007700, j, 0);\r | |
493 | if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]);\r | |
494 | if (inst & IA) fprintf (of, sp? " I": "I");\r | |
495 | break;\r | |
496 | \r | |
497 | case I_V_SPC: /* specials */\r | |
498 | sp = fprint_opr (of, inst & 007774, j, 0);\r | |
499 | if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]);\r | |
500 | if (inst & IA) fprintf (of, sp? " I": "I");\r | |
501 | break;\r | |
502 | \r | |
503 | case I_V_SHF: /* shifts */\r | |
504 | fprintf (of, "%s %-d", opcode[i], sc_map[inst & 0777]);\r | |
505 | break;\r | |
506 | } /* end case */\r | |
507 | \r | |
508 | return SCPE_OK;\r | |
509 | } /* end if */\r | |
510 | } /* end for */\r | |
511 | return SCPE_ARG;\r | |
512 | }\r | |
513 | \r | |
514 | /* Get 18b signed number\r | |
515 | \r | |
516 | Inputs:\r | |
517 | *cptr = pointer to input string\r | |
518 | *sign = pointer to sign\r | |
519 | *status = pointer to error status\r | |
520 | Outputs:\r | |
521 | val = output value\r | |
522 | */\r | |
523 | \r | |
524 | t_value get_sint (char *cptr, int32 *sign, t_stat *status)\r | |
525 | {\r | |
526 | *sign = 1;\r | |
527 | if (*cptr == '+') {\r | |
528 | *sign = 0;\r | |
529 | cptr++;\r | |
530 | }\r | |
531 | else if (*cptr == '-') {\r | |
532 | *sign = -1;\r | |
533 | cptr++;\r | |
534 | }\r | |
535 | return get_uint (cptr, 8, DMASK, status);\r | |
536 | }\r | |
537 | \r | |
538 | /* Symbolic input\r | |
539 | \r | |
540 | Inputs:\r | |
541 | *cptr = pointer to input string\r | |
542 | addr = current PC\r | |
543 | uptr = pointer to unit\r | |
544 | *val = pointer to output values\r | |
545 | sw = switches\r | |
546 | Outputs:\r | |
547 | status = error status\r | |
548 | */\r | |
549 | \r | |
550 | t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)\r | |
551 | {\r | |
552 | int32 cflag, d, i, j, k, sign;\r | |
553 | t_stat r;\r | |
554 | static int32 sc_enc[10] = { 0, 01, 03, 07, 017, 037, 077, 0177, 0377, 0777 };\r | |
555 | char gbuf[CBUFSIZE];\r | |
556 | \r | |
557 | cflag = (uptr == NULL) || (uptr == &cpu_unit);\r | |
558 | while (isspace (*cptr)) cptr++;\r | |
559 | for (i = 1; (i < 3) && (cptr[i] != 0); i++)\r | |
560 | if (cptr[i] == 0) for (j = i + 1; j <= 3; j++) cptr[j] = 0;\r | |
561 | if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */\r | |
562 | if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r | |
563 | val[0] = (t_value) cptr[0];\r | |
564 | return SCPE_OK;\r | |
565 | }\r | |
566 | if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */\r | |
567 | if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r | |
568 | val[0] = ((ASCTOSIX (cptr[0]) & 077) << 12) |\r | |
569 | ((ASCTOSIX (cptr[1]) & 077) << 6) |\r | |
570 | (ASCTOSIX (cptr[2]) & 077);\r | |
571 | return SCPE_OK;\r | |
572 | }\r | |
573 | \r | |
574 | cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r | |
575 | for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r | |
576 | if (opcode[i] == NULL) return SCPE_ARG;\r | |
577 | val[0] = opc_val[i] & DMASK; /* get value */\r | |
578 | j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r | |
579 | \r | |
580 | switch (j) { /* case on class */\r | |
581 | \r | |
582 | case I_V_LAW: /* LAW */\r | |
583 | cflag = 0; /* fall through */\r | |
584 | case I_V_MRF: case I_V_MRI: /* mem ref */\r | |
585 | cptr = get_glyph (cptr, gbuf, 0); /* get next field */\r | |
586 | if ((j != I_V_MRI) && strcmp (gbuf, "I") == 0) { /* indirect? */\r | |
587 | val[0] = val[0] | IA;\r | |
588 | cptr = get_glyph (cptr, gbuf, 0);\r | |
589 | }\r | |
590 | d = get_uint (gbuf, 8, AMASK, &r);\r | |
591 | if (r != SCPE_OK) return SCPE_ARG;\r | |
592 | if (d <= DAMASK) val[0] = val[0] | d;\r | |
593 | else if (cflag && (((addr ^ d) & EPCMASK) == 0))\r | |
594 | val[0] = val[0] | (d & DAMASK);\r | |
595 | else return SCPE_ARG;\r | |
596 | break;\r | |
597 | \r | |
598 | case I_V_SHF: /* shift */\r | |
599 | cptr = get_glyph (cptr, gbuf, 0);\r | |
600 | d = get_uint (gbuf, 10, 9, &r);\r | |
601 | if (r != SCPE_OK) return SCPE_ARG;\r | |
602 | val[0] = val[0] | sc_enc[d];\r | |
603 | break;\r | |
604 | \r | |
605 | case I_V_NPN: case I_V_IOT:\r | |
606 | case I_V_OPR: case I_V_SKP: case I_V_SPC:\r | |
607 | for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;\r | |
608 | cptr = get_glyph (cptr, gbuf, 0)) {\r | |
609 | for (i = 0; (opcode[i] != NULL) &&\r | |
610 | (strcmp (opcode[i], gbuf) != 0); i++) ;\r | |
611 | if (opcode[i] != NULL) {\r | |
612 | k = opc_val[i] & DMASK;\r | |
613 | if ((k != IA) && (((k ^ val[0]) & 0760000) != 0))\r | |
614 | return SCPE_ARG;\r | |
615 | val[0] = val[0] | k;\r | |
616 | }\r | |
617 | else {\r | |
618 | d = get_sint (gbuf, &sign, &r);\r | |
619 | if (r != SCPE_OK) return SCPE_ARG;\r | |
620 | if (sign == 0) val[0] = val[0] + d; \r | |
621 | else if (sign < 0) val[0] = val[0] - d;\r | |
622 | else val[0] = val[0] | d;\r | |
623 | }\r | |
624 | }\r | |
625 | break;\r | |
626 | } /* end case */\r | |
627 | if (*cptr != 0) return SCPE_ARG; /* junk at end? */\r | |
628 | return SCPE_OK;\r | |
629 | }\r |