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