First Commit of my working state
[simh.git] / H316 / h316_sys.c
1 /* h316_sys.c: Honeywell 316/516 simulator interface
2
3 Copyright (c) 1999-2005, Robert M Supnik
4
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:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
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.
21
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.
25
26 01-Dec-04 RMS Fixed fprint_opr calling sequence
27 24-Oct-03 RMS Added DMA/DMC support
28 17-Sep-01 RMS Removed multiconsole support
29 */
30
31 #include "h316_defs.h"
32 #include <ctype.h>
33
34 extern DEVICE cpu_dev;
35 extern UNIT cpu_unit;
36 extern DEVICE ptr_dev;
37 extern DEVICE ptp_dev;
38 extern DEVICE tty_dev;
39 extern DEVICE lpt_dev;
40 extern DEVICE clk_dev;
41 extern DEVICE dp_dev;
42 extern DEVICE fhd_dev;
43 extern DEVICE mt_dev;
44 extern REG cpu_reg[];
45 extern uint16 M[];
46 extern int32 sim_switches;
47
48 /* SCP data structures and interface routines
49
50 sim_name simulator name string
51 sim_PC pointer to saved PC register descriptor
52 sim_emax maximum number of words for examine/deposit
53 sim_devices array of pointers to simulated devices
54 sim_stop_messages array of pointers to stop messages
55 sim_load binary loader
56 */
57
58 char sim_name[] = "H316";
59
60 REG *sim_PC = &cpu_reg[0];
61
62 int32 sim_emax = 1;
63
64 DEVICE *sim_devices[] = {
65 &cpu_dev,
66 &ptr_dev,
67 &ptp_dev,
68 &tty_dev,
69 &lpt_dev,
70 &clk_dev,
71 &dp_dev,
72 &fhd_dev,
73 &mt_dev,
74 NULL
75 };
76
77 const char *sim_stop_messages[] = {
78 "Unknown error",
79 "Unimplemented instruction",
80 "Unimplemented I/O device",
81 "HALT instruction",
82 "Breakpoint",
83 "Indirect address loop",
84 "DMA error",
85 "MT write protected",
86 "DP write overrun, track destroyed",
87 "DP track format invalid"
88 };
89
90 /* Binary loader
91
92 Tbs.
93 */
94
95 t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
96 {
97 return SCPE_FMT;
98 }
99
100 /* Symbol tables */
101
102 #define I_V_FL 16 /* flag start */
103 #define I_M_FL 07 /* flag mask */
104 #define I_V_NPN 0 /* no operand */
105 #define I_V_MRF 1 /* mem ref */
106 #define I_V_MRX 2 /* mem ref, no idx */
107 #define I_V_IOT 3 /* I/O */
108 #define I_V_SHF 4 /* shift */
109 #define I_V_SK0 5 /* skip 0 */
110 #define I_V_SK1 6 /* skip 1 */
111 #define I_NPN (I_V_NPN << I_V_FL)
112 #define I_MRF (I_V_MRF << I_V_FL)
113 #define I_MRX (I_V_MRX << I_V_FL)
114 #define I_IOT (I_V_IOT << I_V_FL)
115 #define I_SHF (I_V_SHF << I_V_FL)
116 #define I_SK0 (I_V_SK0 << I_V_FL)
117 #define I_SK1 (I_V_SK1 << I_V_FL)
118
119 static const int32 masks[] = {
120 0177777, 0136000, 0176000, 0176000,
121 0177700, 0177000, 0177000
122 };
123
124 static const char *opcode[] = {
125 "HLT", "SGL", "DBL",
126 "DXA", "EXA", "RMP",
127 "SCA", "INK", "NRM",
128 "IAB", "ENB", "INH", "ERM",
129 "CHS", "CRA", "SSP",
130 "RCB", "CSA", "CMA",
131 "TCA", "SSM", "SCB",
132 "CAR", "CAL", "ICL",
133 "AOA", "ACA", "ICR", "ICA",
134 "NOP", "SKP", "SSR", "SSS",
135 "JMP", "JMP*",
136 "LDA", "LDA*", "ANA", "ANA*",
137 "STA", "STA*", "ERA", "ERA*",
138 "ADD", "ADD*", "SUB", "SUB*",
139 "JST", "JST*", "CAS", "CAS*",
140 "IRS", "IRS*", "IMA", "IMA*",
141 "MPY", "MPY*", "DIV", "DIV*",
142 "STX", "STX*", "LDX", "LDX*",
143 "LRL", "LRS", "LRR",
144 "LGR", "ARS", "ARR",
145 "LLL", "LLS", "LLR",
146 "LGL", "ALS", "ALR",
147 "OCP", "SKS", "INA", "OTA",
148 "SMK",
149 "SPL", "SPN", "SLZ", /* encode only */
150 "SZE", "SR1", "SR2",
151 "SR3", "SR4", "SRC",
152 "SMI", "SPS", "SLN",
153 "SNZ", "SS1", "SS2",
154 "SS3", "SS4", "SSC",
155 NULL, NULL, /* decode only */
156 NULL
157 };
158
159 static const int32 opc_val[] = {
160 0000000+I_NPN, 0000005+I_NPN, 0000007+I_NPN,
161 0000011+I_NPN, 0000013+I_NPN, 0000021+I_NPN,
162 0000041+I_NPN, 0000043+I_NPN, 0000101+I_NPN,
163 0000201+I_NPN, 0000401+I_NPN, 0001001+I_NPN, 0001401+I_NPN,
164 0140024+I_NPN, 0140040+I_NPN, 0140100+I_NPN,
165 0140200+I_NPN, 0140320+I_NPN, 0140401+I_NPN,
166 0140407+I_NPN, 0140500+I_NPN, 0140600+I_NPN,
167 0141044+I_NPN, 0141050+I_NPN, 0141140+I_NPN,
168 0141206+I_NPN, 0141216+I_NPN, 0141240+I_NPN, 0141340+I_NPN,
169 0101000+I_NPN, 0100000+I_NPN, 0100036+I_NPN, 0101036+I_NPN,
170 0002000+I_MRF, 0102000+I_MRF,
171 0004000+I_MRF, 0104000+I_MRF, 0006000+I_MRF, 0106000+I_MRF,
172 0010000+I_MRF, 0110000+I_MRF, 0012000+I_MRF, 0112000+I_MRF,
173 0014000+I_MRF, 0114000+I_MRF, 0016000+I_MRF, 0116000+I_MRF,
174 0020000+I_MRF, 0120000+I_MRF, 0022000+I_MRF, 0122000+I_MRF,
175 0024000+I_MRF, 0124000+I_MRF, 0026000+I_MRF, 0126000+I_MRF,
176 0034000+I_MRF, 0134000+I_MRF, 0036000+I_MRF, 0136000+I_MRF,
177 0032000+I_MRX, 0132000+I_MRX, 0072000+I_MRX, 0172000+I_MRX,
178 0040000+I_SHF, 0040100+I_SHF, 0040200+I_SHF,
179 0040400+I_SHF, 0040500+I_SHF, 0040600+I_SHF,
180 0041000+I_SHF, 0041100+I_SHF, 0041200+I_SHF,
181 0041400+I_SHF, 0041500+I_SHF, 0041600+I_SHF,
182 0030000+I_IOT, 0070000+I_IOT, 0130000+I_IOT, 0170000+I_IOT,
183 0170000+I_IOT,
184 0100400+I_SK0, 0100200+I_SK0, 0100100+I_SK0, /* encode only */
185 0100040+I_SK0, 0100020+I_SK0, 0100010+I_SK0,
186 0100004+I_SK0, 0100002+I_SK0, 0100001+I_SK0,
187 0101400+I_SK1, 0101200+I_SK1, 0101100+I_SK1,
188 0101040+I_SK1, 0101020+I_SK1, 0101010+I_SK1,
189 0101004+I_SK1, 0101002+I_SK1, 0101001+I_SK1,
190 0100000+I_SK0, 0101000+I_SK1, /* decode only */
191 -1
192 };
193
194 /* Operate decode
195
196 Inputs:
197 *of = output stream
198 inst = mask bits
199 class = instruction class code
200 sp = space needed?
201 Outputs:
202 status = space needed
203 */
204
205 void fprint_opr (FILE *of, int32 inst, int32 class)
206 {
207 int32 i, j, sp;
208
209 for (i = sp = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
210 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
211 if ((j == class) && (opc_val[i] & inst)) { /* same class? */
212 inst = inst & ~opc_val[i]; /* mask bit set? */
213 fprintf (of, (sp? " %s": "%s"), opcode[i]);
214 sp = 1;
215 }
216 }
217 return;
218 }
219
220 /* Symbolic decode
221
222 Inputs:
223 *of = output stream
224 addr = current PC
225 *val = pointer to data
226 *uptr = pointer to unit
227 sw = switches
228 Outputs:
229 return = status code
230 */
231
232 #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
233
234 t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
235 UNIT *uptr, int32 sw)
236 {
237 int32 cflag, i, j, inst, disp;
238
239 cflag = (uptr == NULL) || (uptr == &cpu_unit);
240 inst = val[0];
241 if (sw & SWMASK ('A')) { /* ASCII? */
242 if (inst > 0377) return SCPE_ARG;
243 fprintf (of, FMTASC (inst & 0177));
244 return SCPE_OK;
245 }
246 if (sw & SWMASK ('C')) { /* characters? */
247 fprintf (of, FMTASC ((inst >> 8) & 0177));
248 fprintf (of, FMTASC (inst & 0177));
249 return SCPE_OK;
250 }
251 if (!(sw & SWMASK ('M'))) return SCPE_ARG;
252
253 /* Instruction decode */
254
255 for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
256 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
257 if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */
258
259 switch (j) { /* case on class */
260
261 case I_V_NPN: /* no operands */
262 fprintf (of, "%s", opcode[i]); /* opcode */
263 break;
264
265 case I_V_MRF: case I_V_MRX: /* mem ref */
266 disp = inst & DISP; /* displacement */
267 fprintf (of, "%s ", opcode[i]); /* opcode */
268 if (inst & SC) { /* current sector? */
269 if (cflag) fprintf (of, "%-o", (addr & PAGENO) | disp);
270 else fprintf (of, "C %-o", disp);
271 }
272 else fprintf (of, "%-o", disp); /* sector zero */
273 if ((j == I_V_MRF) && (inst & IDX)) fprintf (of, ",1");
274 break;
275
276 case I_V_IOT: /* I/O */
277 disp = inst & 01777; /* pulse+dev */
278 fprintf (of, "%s %o", opcode[i], disp);
279 break;
280
281 case I_V_SHF: /* shift */
282 disp = -inst & SHFMASK; /* shift count */
283 fprintf (of, "%s %o", opcode[i], disp);
284 break;
285
286 case I_V_SK0: case I_V_SK1: /* skips */
287 fprint_opr (of, inst & 0777, j); /* print skips */
288 break;
289 } /* end case */
290
291 return SCPE_OK;
292 } /* end if */
293 } /* end for */
294 return SCPE_ARG;
295 }
296
297 /* Symbolic input
298
299 Inputs:
300 *cptr = pointer to input string
301 addr = current PC
302 *uptr = pointer to unit
303 *val = pointer to output values
304 sw = switches
305 Outputs:
306 status = error status
307 */
308
309 t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
310 {
311 int32 cflag, d, i, j, k;
312 t_stat r;
313 char gbuf[CBUFSIZE];
314
315 cflag = (uptr == NULL) || (uptr == &cpu_unit);
316 while (isspace (*cptr)) cptr++; /* absorb spaces */
317 if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
318 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
319 val[0] = (t_value) cptr[0] & 0177;
320 return SCPE_OK;
321 }
322 if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* char string? */
323 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
324 val[0] = (((t_value) cptr[0] & 0177) << 8) |
325 ((t_value) cptr[1] & 0177);
326 return SCPE_OK;
327 }
328
329 /* Instruction parse */
330
331 cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
332 for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
333 if (opcode[i] == NULL) return SCPE_ARG;
334 val[0] = opc_val[i] & DMASK; /* get value */
335 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
336
337 switch (j) { /* case on class */
338
339 case I_V_NPN: /* no operand */
340 break;
341
342 case I_V_IOT: /* IOT */
343 cptr = get_glyph (cptr, gbuf, 0); /* get pulse+dev */
344 d = get_uint (gbuf, 8, 01777, &r);
345 if (r != SCPE_OK) return SCPE_ARG;
346 val[0] = val[0] | d;
347 break;
348
349 case I_V_SHF: /* shift */
350 cptr = get_glyph (cptr, gbuf, 0); /* get shift count */
351 d = get_uint (gbuf, 8, SHFMASK, &r);
352 if (r != SCPE_OK) return SCPE_ARG;
353 val[0] = val[0] | (-d & SHFMASK); /* store 2's comp */
354 break;
355
356 case I_V_MRF: case I_V_MRX: /* mem ref */
357 cptr = get_glyph (cptr, gbuf, ','); /* get next field */
358 if (k = (strcmp (gbuf, "C") == 0)) { /* C specified? */
359 val[0] = val[0] | SC;
360 cptr = get_glyph (cptr, gbuf, 0);
361 }
362 else if (k = (strcmp (gbuf, "Z") == 0)) { /* Z specified? */
363 cptr = get_glyph (cptr, gbuf, ',');
364 }
365 d = get_uint (gbuf, 8, X_AMASK, &r); /* construe as addr */
366 if (r != SCPE_OK) return SCPE_ARG;
367 if (d <= DISP) val[0] = val[0] | d; /* fits? */
368 else if (cflag && !k && (((addr ^ d) & PAGENO) == 0))
369 val[0] = val[0] | (d & DISP) | SC;
370 else return SCPE_ARG;
371 if ((j == I_V_MRX) || (*cptr == 0)) break; /* indexed? */
372 cptr = get_glyph (cptr, gbuf, 0);
373 d = get_uint (gbuf, 8, 1, &r); /* get tag */
374 if (r != SCPE_OK) return SCPE_ARG;
375 if (d) val[0] = val[0] | IDX; /* or in index */
376 break;
377
378 case I_V_SK0: case I_V_SK1: /* skips */
379 for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
380 cptr = get_glyph (cptr, gbuf, 0)) {
381 for (i = 0; (opcode[i] != NULL) &&
382 (strcmp (opcode[i], gbuf) != 0) ; i++) ;
383 k = opc_val[i] & DMASK;
384 if ((opcode[i] == NULL) || (((k ^ val[0]) & 0177000) != 0))
385 return SCPE_ARG;
386 val[0] = val[0] | k;
387 }
388 break;
389 } /* end case */
390
391 if (*cptr != 0) return SCPE_ARG; /* junk at end? */
392 return SCPE_OK;
393 }