1 /* h316_sys.c: Honeywell 316/516 simulator interface
3 Copyright (c) 1999-2005, 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 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
31 #include "h316_defs.h"
34 extern DEVICE cpu_dev
;
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
;
42 extern DEVICE fhd_dev
;
46 extern int32 sim_switches
;
48 /* SCP data structures and interface routines
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
58 char sim_name
[] = "H316";
60 REG
*sim_PC
= &cpu_reg
[0];
64 DEVICE
*sim_devices
[] = {
77 const char *sim_stop_messages
[] = {
79 "Unimplemented instruction",
80 "Unimplemented I/O device",
83 "Indirect address loop",
86 "DP write overrun, track destroyed",
87 "DP track format invalid"
95 t_stat
sim_load (FILE *fileref
, char *cptr
, char *fnam
, int flag
)
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)
119 static const int32 masks
[] = {
120 0177777, 0136000, 0176000, 0176000,
121 0177700, 0177000, 0177000
124 static const char *opcode
[] = {
128 "IAB", "ENB", "INH", "ERM",
133 "AOA", "ACA", "ICR", "ICA",
134 "NOP", "SKP", "SSR", "SSS",
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*",
147 "OCP", "SKS", "INA", "OTA",
149 "SPL", "SPN", "SLZ", /* encode only */
155 NULL
, NULL
, /* decode only */
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
,
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 */
199 class = instruction class code
202 status = space needed
205 void fprint_opr (FILE *of
, int32 inst
, int32
class)
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
]);
225 *val = pointer to data
226 *uptr = pointer to unit
232 #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
234 t_stat
fprint_sym (FILE *of
, t_addr addr
, t_value
*val
,
235 UNIT
*uptr
, int32 sw
)
237 int32 cflag
, i
, j
, inst
, disp
;
239 cflag
= (uptr
== NULL
) || (uptr
== &cpu_unit
);
241 if (sw
& SWMASK ('A')) { /* ASCII? */
242 if (inst
> 0377) return SCPE_ARG
;
243 fprintf (of
, FMTASC (inst
& 0177));
246 if (sw
& SWMASK ('C')) { /* characters? */
247 fprintf (of
, FMTASC ((inst
>> 8) & 0177));
248 fprintf (of
, FMTASC (inst
& 0177));
251 if (!(sw
& SWMASK ('M'))) return SCPE_ARG
;
253 /* Instruction decode */
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? */
259 switch (j
) { /* case on class */
261 case I_V_NPN
: /* no operands */
262 fprintf (of
, "%s", opcode
[i
]); /* opcode */
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
);
272 else fprintf (of
, "%-o", disp
); /* sector zero */
273 if ((j
== I_V_MRF
) && (inst
& IDX
)) fprintf (of
, ",1");
276 case I_V_IOT
: /* I/O */
277 disp
= inst
& 01777; /* pulse+dev */
278 fprintf (of
, "%s %o", opcode
[i
], disp
);
281 case I_V_SHF
: /* shift */
282 disp
= -inst
& SHFMASK
; /* shift count */
283 fprintf (of
, "%s %o", opcode
[i
], disp
);
286 case I_V_SK0
: case I_V_SK1
: /* skips */
287 fprint_opr (of
, inst
& 0777, j
); /* print skips */
300 *cptr = pointer to input string
302 *uptr = pointer to unit
303 *val = pointer to output values
306 status = error status
309 t_stat
parse_sym (char *cptr
, t_addr addr
, UNIT
*uptr
, t_value
*val
, int32 sw
)
311 int32 cflag
, d
, i
, j
, k
;
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;
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);
329 /* Instruction parse */
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 */
337 switch (j
) { /* case on class */
339 case I_V_NPN
: /* no operand */
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
;
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 */
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);
362 else if (k
= (strcmp (gbuf
, "Z") == 0)) { /* Z specified? */
363 cptr
= get_glyph (cptr
, gbuf
, ',');
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 */
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))
391 if (*cptr
!= 0) return SCPE_ARG
; /* junk at end? */