Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /* sds_sys.c: SDS 940 simulator interface\r |
2 | \r | |
3 | Copyright (c) 2001-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 | \r | |
27 | #include "sds_defs.h"\r | |
28 | #include <ctype.h>\r | |
29 | #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)\r | |
30 | \r | |
31 | extern DEVICE cpu_dev;\r | |
32 | extern DEVICE chan_dev;\r | |
33 | extern DEVICE ptr_dev;\r | |
34 | extern DEVICE ptp_dev;\r | |
35 | extern DEVICE tti_dev;\r | |
36 | extern DEVICE tto_dev;\r | |
37 | extern DEVICE lpt_dev;\r | |
38 | extern DEVICE rtc_dev;\r | |
39 | extern DEVICE drm_dev;\r | |
40 | extern DEVICE rad_dev;\r | |
41 | extern DEVICE dsk_dev;\r | |
42 | extern DEVICE mt_dev;\r | |
43 | extern DEVICE mux_dev, muxl_dev;\r | |
44 | extern UNIT cpu_unit;\r | |
45 | extern REG cpu_reg[];\r | |
46 | extern uint32 M[MAXMEMSIZE];\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 number of words for examine\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 | |
58 | char sim_name[] = "SDS 940";\r | |
59 | \r | |
60 | REG *sim_PC = &cpu_reg[0];\r | |
61 | \r | |
62 | int32 sim_emax = 1;\r | |
63 | \r | |
64 | DEVICE *sim_devices[] = {\r | |
65 | &cpu_dev,\r | |
66 | &chan_dev,\r | |
67 | &ptr_dev,\r | |
68 | &ptp_dev,\r | |
69 | &tti_dev,\r | |
70 | &tto_dev,\r | |
71 | &lpt_dev,\r | |
72 | &rtc_dev,\r | |
73 | &drm_dev,\r | |
74 | &rad_dev,\r | |
75 | &dsk_dev,\r | |
76 | &mt_dev,\r | |
77 | &mux_dev,\r | |
78 | &muxl_dev,\r | |
79 | NULL\r | |
80 | };\r | |
81 | \r | |
82 | const char *sim_stop_messages[] = {\r | |
83 | "Unknown error",\r | |
84 | "IO device not ready",\r | |
85 | "HALT instruction",\r | |
86 | "Breakpoint",\r | |
87 | "Invalid IO device",\r | |
88 | "Invalid instruction",\r | |
89 | "Invalid I/O operation",\r | |
90 | "Nested indirects exceed limit",\r | |
91 | "Nested EXU's exceed limit",\r | |
92 | "Memory management trap during interrupt",\r | |
93 | "Memory management trap during trap",\r | |
94 | "Trap instruction not BRM",\r | |
95 | "RTC instruction not MIN or SKR",\r | |
96 | "Interrupt vector zero",\r | |
97 | "Runaway carriage control tape"\r | |
98 | };\r | |
99 | \r | |
100 | /* Character conversion tables */\r | |
101 | \r | |
102 | const char sds_to_ascii[64] = {\r | |
103 | '0', '1', '2', '3', '4', '5', '6', '7',\r | |
104 | '8', '9', ' ', '=', '\'', ':', '>', '%', /* 17 = check mark */\r | |
105 | '+', 'A', 'B', 'C', 'D', 'E', 'F', 'G',\r | |
106 | 'H', 'I', '?', '.', ')', '[', '<', '@', /* 37 = stop code */\r | |
107 | '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',\r | |
108 | 'Q', 'R', '!', '$', '*', ']', ';', '^', /* 57 = triangle */\r | |
109 | '_', '/', 'S', 'T', 'U', 'V', 'W', 'X',\r | |
110 | 'Y', 'Z', '?', ',', '(', '~', '\\', '#' /* 72 = rec mark */\r | |
111 | }; /* 75 = squiggle, 77 = del */\r | |
112 | \r | |
113 | const char ascii_to_sds[128] = {\r | |
114 | -1, -1, -1, -1, -1, -1, -1, -1, /* 0 - 37 */\r | |
115 | 032, 072, -1, -1, -1, 052, -1, -1,\r | |
116 | -1, -1, -1, -1, -1, -1, -1, -1,\r | |
117 | -1, -1, -1, -1, -1, -1, -1, -1,\r | |
118 | 012, 052, -1, 077, 053, 017, -1, 014, /* 40 - 77 */\r | |
119 | 074, 034, 054, 020, 073, 040, 033, 061,\r | |
120 | 000, 001, 002, 003, 004, 005, 006, 007,\r | |
121 | 010, 011, 015, 056, 036, 013, 016, 072,\r | |
122 | 037, 021, 022, 023, 024, 025, 026, 027, /* 100 - 137 */\r | |
123 | 030, 031, 041, 042, 043, 044, 045, 046,\r | |
124 | 047, 050, 051, 062, 063, 064, 065, 066,\r | |
125 | 067, 070, 071, 035, 076, 055, 057, 060,\r | |
126 | 000, 021, 022, 023, 024, 025, 026, 027, /* 140 - 177 */\r | |
127 | 030, 031, 041, 042, 043, 044, 045, 046,\r | |
128 | 047, 050, 051, 062, 063, 064, 065, 066,\r | |
129 | 067, 070, 071, -1, -1, -1, -1, -1\r | |
130 | };\r | |
131 | \r | |
132 | const char odd_par[64] = {\r | |
133 | 0100, 0001, 0002, 0103, 0004, 0105, 0106, 0007,\r | |
134 | 0010, 0111, 0112, 0013, 0114, 0015, 0016, 0117,\r | |
135 | 0020, 0121, 0122, 0023, 0124, 0025, 0026, 0127,\r | |
136 | 0130, 0031, 0032, 0133, 0034, 0135, 0136, 0037,\r | |
137 | 0040, 0141, 0142, 0043, 0144, 0045, 0046, 0147,\r | |
138 | 0150, 0051, 0052, 0153, 0054, 0155, 0156, 0057,\r | |
139 | 0160, 0061, 0062, 0163, 0064, 0165, 0166, 0067,\r | |
140 | 0070, 0171, 0172, 0073, 0174, 0075, 0076, 0177\r | |
141 | };\r | |
142 | \r | |
143 | /* Load carriage control tape\r | |
144 | \r | |
145 | A carriage control tape consists of entries of the form\r | |
146 | \r | |
147 | (repeat count) column number,column number,column number,...\r | |
148 | \r | |
149 | The CCT entries are stored in lpt_cct[0:lnt-1], lpt_ccl contains the\r | |
150 | number of entries\r | |
151 | */\r | |
152 | \r | |
153 | t_stat sim_load_cct (FILE *fileref)\r | |
154 | {\r | |
155 | int32 col, rpt, ptr, mask, cctbuf[CCT_LNT];\r | |
156 | t_stat r;\r | |
157 | extern int32 lpt_ccl, lpt_ccp, lpt_cct[CCT_LNT];\r | |
158 | char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE];\r | |
159 | \r | |
160 | ptr = 0;\r | |
161 | for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */\r | |
162 | mask = 0;\r | |
163 | if (*cptr == '(') { /* repeat count? */\r | |
164 | cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */\r | |
165 | rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */\r | |
166 | if (r != SCPE_OK) return SCPE_FMT;\r | |
167 | }\r | |
168 | else rpt = 1;\r | |
169 | while (*cptr != 0) { /* get col no's */\r | |
170 | cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r | |
171 | col = get_uint (gbuf, 10, 7, &r); /* column number */\r | |
172 | if (r != SCPE_OK) return SCPE_FMT;\r | |
173 | mask = mask | (1 << col); /* set bit */\r | |
174 | }\r | |
175 | for ( ; rpt > 0; rpt--) { /* store vals */\r | |
176 | if (ptr >= CCT_LNT) return SCPE_FMT;\r | |
177 | cctbuf[ptr++] = mask;\r | |
178 | }\r | |
179 | }\r | |
180 | if (ptr == 0) return SCPE_FMT;\r | |
181 | lpt_ccl = ptr;\r | |
182 | lpt_ccp = 0;\r | |
183 | for (rpt = 0; rpt < lpt_ccl; rpt++) lpt_cct[rpt] = cctbuf[rpt];\r | |
184 | return SCPE_OK;\r | |
185 | }\r | |
186 | \r | |
187 | /* Load command. -l means load a line printer tape. Otherwise, load\r | |
188 | a bootstrap paper tape.\r | |
189 | */\r | |
190 | \r | |
191 | int32 get_word (FILE *fileref, int32 *ldr)\r | |
192 | {\r | |
193 | int32 i, c, wd;\r | |
194 | \r | |
195 | for (i = wd = 0; i < 4; ) {\r | |
196 | if ((c = fgetc (fileref)) == EOF) return -1;\r | |
197 | if ((c == 0) && (*ldr == 0)) return -1;\r | |
198 | if (c == 0) continue;\r | |
199 | *ldr = 0;\r | |
200 | wd = (wd << 6) | (c & 077);\r | |
201 | i++;\r | |
202 | }\r | |
203 | return wd;\r | |
204 | }\r | |
205 | \r | |
206 | t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)\r | |
207 | {\r | |
208 | int32 i, wd, buf[8];\r | |
209 | int32 ldr = 1;\r | |
210 | extern int32 sim_switches;\r | |
211 | extern uint32 P;\r | |
212 | \r | |
213 | if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;\r | |
214 | if (sim_switches & SWMASK ('L')) return sim_load_cct (fileref);\r | |
215 | for (i = 0; i < 8; i++) { /* read boot */\r | |
216 | if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_FMT;\r | |
217 | buf[i] = wd;\r | |
218 | }\r | |
219 | if ((buf[0] != 023200012) || /* 2 = WIM 12,2 */\r | |
220 | (buf[1] != 004100002) || /* 3 = BRX 2 */\r | |
221 | (buf[2] != 007100011) || /* 4 = LDX 11 */\r | |
222 | (buf[3] != 023200000) || /* 5 = WIM 0,2 */\r | |
223 | (buf[4] != 004021000) || /* 6 = SKS 21000 */\r | |
224 | (buf[5] != 004100005)) return SCPE_FMT; /* 7 = BRX 5 */\r | |
225 | for (i = 0; i < 8; i++) M[i + 2] = buf[i]; /* copy boot */\r | |
226 | if (I_GETOP (buf[6]) == BRU) P = buf[6] & VA_MASK;\r | |
227 | for (i = buf[7] & VA_MASK; i <= VA_MASK; i++) { /* load data */\r | |
228 | if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_OK;\r | |
229 | M[i] = wd;\r | |
230 | }\r | |
231 | return SCPE_NXM;\r | |
232 | }\r | |
233 | \r | |
234 | /* Symbol tables */\r | |
235 | \r | |
236 | #define I_V_FL 24 /* inst class */\r | |
237 | #define I_M_FL 017 /* class mask */\r | |
238 | #define I_V_NPN 000 /* no operand */\r | |
239 | #define I_V_PPO 001 /* POP */\r | |
240 | #define I_V_IOI 002 /* IO */\r | |
241 | #define I_V_MRF 003 /* memory reference */\r | |
242 | #define I_V_REG 004 /* register change */\r | |
243 | #define I_V_SHF 005 /* shift */\r | |
244 | #define I_V_OPO 006 /* opcode only */\r | |
245 | #define I_V_CHC 007 /* chan cmd */\r | |
246 | #define I_V_CHT 010 /* chan test */\r | |
247 | #define I_NPN (I_V_NPN << I_V_FL) \r | |
248 | #define I_PPO (I_V_PPO << I_V_FL) \r | |
249 | #define I_IOI (I_V_IOI << I_V_FL) \r | |
250 | #define I_MRF (I_V_MRF << I_V_FL) \r | |
251 | #define I_REG (I_V_REG << I_V_FL) \r | |
252 | #define I_SHF (I_V_SHF << I_V_FL) \r | |
253 | #define I_OPO (I_V_OPO << I_V_FL)\r | |
254 | #define I_CHC (I_V_CHC << I_V_FL)\r | |
255 | #define I_CHT (I_V_CHT << I_V_FL) \r | |
256 | \r | |
257 | static const int32 masks[] = {\r | |
258 | 037777777, 010000000, 017700000,\r | |
259 | 017740000, 017700000, 017774000,\r | |
260 | 017700000, 017377677, 027737677\r | |
261 | };\r | |
262 | \r | |
263 | static const char *opcode[] = {\r | |
264 | "POP", "EIR", "DIR",\r | |
265 | "ROV", "REO", "OTO", "OVT",\r | |
266 | "IDT", "IET",\r | |
267 | "BPT4", "BPT3", "BPT2", "BPT1",\r | |
268 | "CLAB", "ABC", "BAC", "XAB",\r | |
269 | "XXB", "STE", "LDE", "XEE",\r | |
270 | "CLEAR",\r | |
271 | \r | |
272 | "HLT", "BRU", "EOM", "EOD",\r | |
273 | "MIY", "BRI", "MIW", "POT",\r | |
274 | "ETR", "MRG", "EOR",\r | |
275 | "NOP", "EXU",\r | |
276 | "YIM", "WIM", "PIN",\r | |
277 | "STA", "STB", "STX",\r | |
278 | "SKS", "BRX", "BRM",\r | |
279 | "SKE", "BRR", "SKB", "SKN",\r | |
280 | "SUB", "ADD", "SUC", "ADC",\r | |
281 | "SKR", "MIN", "XMA", "ADM",\r | |
282 | "MUL", "DIV",\r | |
283 | "SKM", "LDX", "SKA", "SKG",\r | |
284 | "SKD", "LDB", "LDA", "EAX",\r | |
285 | \r | |
286 | "BRU*", \r | |
287 | "MIY*", "BRI*", "MIW*", "POT*",\r | |
288 | "ETR*", "MRG*", "EOR*",\r | |
289 | "EXU*",\r | |
290 | "YIM*", "WIM*", "PIN*",\r | |
291 | "STA*", "STB*", "STX*",\r | |
292 | "BRX*", "BRM*",\r | |
293 | "SKE*", "BRR*", "SKB*", "SKN*",\r | |
294 | "SUB*", "ADD*", "SUC*", "ADC*",\r | |
295 | "SKR*", "MIN*", "XMA*", "ADM*",\r | |
296 | "MUL*", "DIV*",\r | |
297 | "SKM*", "LDX*", "SKA*", "SKG*",\r | |
298 | "SKD*", "LDB*", "LDA*", "EAX*",\r | |
299 | \r | |
300 | "RSH", "RCY", "LRSH",\r | |
301 | "LSH", "NOD", "LCY",\r | |
302 | "RSH*", "LSH*",\r | |
303 | \r | |
304 | "ALC", "DSC", "ASC", "TOP",\r | |
305 | "CAT", "CET", "CZT", "CIT",\r | |
306 | \r | |
307 | "CLA", "CLB", "CAB", /* encode only */\r | |
308 | "CBA", "CBX", "CXB",\r | |
309 | "XPO", "CXA", "CAX",\r | |
310 | "CNA", "CLX", NULL,\r | |
311 | NULL\r | |
312 | };\r | |
313 | \r | |
314 | static const int32 opc_val[] = {\r | |
315 | 010000000+I_PPO, 000220002+I_NPN, 000220004+I_NPN,\r | |
316 | 002200001+I_NPN, 002200010+I_NPN, 002200100+I_NPN, 002200101+I_NPN,\r | |
317 | 004020002+I_NPN, 004020004+I_NPN,\r | |
318 | 004020040+I_NPN, 004020100+I_NPN, 004020200+I_NPN, 004020400+I_NPN,\r | |
319 | 004600003+I_NPN, 004600005+I_NPN, 004600012+I_NPN, 004600014+I_NPN,\r | |
320 | 004600060+I_NPN, 004600122+I_NPN, 004600140+I_NPN, 004600160+I_NPN,\r | |
321 | 024600003+I_NPN,\r | |
322 | \r | |
323 | 000000000+I_NPN, 000100000+I_MRF, 000200000+I_IOI, 000600000+I_IOI,\r | |
324 | 001000000+I_MRF, 001100000+I_MRF, 001200000+I_MRF, 001300000+I_MRF,\r | |
325 | 001400000+I_MRF, 001600000+I_MRF, 001700000+I_MRF,\r | |
326 | 002000000+I_OPO, 002300000+I_MRF,\r | |
327 | 003000000+I_MRF, 003200000+I_MRF, 003300000+I_MRF,\r | |
328 | 003500000+I_MRF, 003600000+I_MRF, 003700000+I_MRF,\r | |
329 | 004000000+I_IOI, 004100000+I_MRF, 004300000+I_MRF,\r | |
330 | 005000000+I_MRF, 005100000+I_MRF, 005200000+I_MRF, 005300000+I_MRF,\r | |
331 | 005400000+I_MRF, 005500000+I_MRF, 005600000+I_MRF, 005700000+I_MRF,\r | |
332 | 006000000+I_MRF, 006100000+I_MRF, 006200000+I_MRF, 006300000+I_MRF,\r | |
333 | 006400000+I_MRF, 006500000+I_MRF,\r | |
334 | 007000000+I_MRF, 007100000+I_MRF, 007200000+I_MRF, 007300000+I_MRF,\r | |
335 | 007400000+I_MRF, 007500000+I_MRF, 007600000+I_MRF, 007700000+I_MRF,\r | |
336 | \r | |
337 | 000140000+I_MRF,\r | |
338 | 001040000+I_MRF, 001140000+I_MRF, 001240000+I_MRF, 001340000+I_MRF,\r | |
339 | 001440000+I_MRF, 001640000+I_MRF, 001740000+I_MRF,\r | |
340 | 002340000+I_MRF,\r | |
341 | 003040000+I_MRF, 003240000+I_MRF, 003340000+I_MRF,\r | |
342 | 003540000+I_MRF, 003640000+I_MRF, 003740000+I_MRF,\r | |
343 | 004140000+I_MRF, 004340000+I_MRF,\r | |
344 | 005040000+I_MRF, 005140000+I_MRF, 005240000+I_MRF, 005340000+I_MRF,\r | |
345 | 005440000+I_MRF, 005540000+I_MRF, 005640000+I_MRF, 005740000+I_MRF,\r | |
346 | 006040000+I_MRF, 006140000+I_MRF, 006240000+I_MRF, 006340000+I_MRF,\r | |
347 | 006440000+I_MRF, 006540000+I_MRF,\r | |
348 | 007040000+I_MRF, 007140000+I_MRF, 007240000+I_MRF, 007340000+I_MRF,\r | |
349 | 007440000+I_MRF, 007540000+I_MRF, 007640000+I_MRF, 007740000+I_MRF,\r | |
350 | \r | |
351 | 006600000+I_SHF, 006620000+I_SHF, 006624000+I_SHF,\r | |
352 | 006700000+I_SHF, 006710000+I_SHF, 006720000+I_SHF,\r | |
353 | 006640000+I_MRF, 006740000+I_MRF,\r | |
354 | \r | |
355 | 000250000+I_CHC, 000200000+I_CHC, 000212000+I_CHC, 000214000+I_CHC,\r | |
356 | 004014000+I_CHT, 004011000+I_CHT, 004012000+I_CHT, 004010400+I_CHT,\r | |
357 | \r | |
358 | 004600001+I_REG, 004600002+I_REG, 004600004+I_REG,\r | |
359 | 004600010+I_REG, 004600020+I_REG, 004600040+I_REG,\r | |
360 | 004600100+I_REG, 004600200+I_REG, 004600400+I_REG,\r | |
361 | 004601000+I_REG, 024600000+I_REG, 004600000+I_REG,\r | |
362 | -1\r | |
363 | };\r | |
364 | \r | |
365 | static const char *chname[] = {\r | |
366 | "W", "Y", "C", "D", "E", "F", "G", "H", NULL\r | |
367 | };\r | |
368 | \r | |
369 | /* Register change decode\r | |
370 | \r | |
371 | Inputs:\r | |
372 | *of = output stream\r | |
373 | inst = mask bits\r | |
374 | */\r | |
375 | \r | |
376 | void fprint_reg (FILE *of, int32 inst)\r | |
377 | {\r | |
378 | int32 i, j, sp;\r | |
379 | \r | |
380 | inst = inst & ~(I_M_OP << I_V_OP); /* clear opcode */\r | |
381 | for (i = sp = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r | |
382 | j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r | |
383 | if ((j == I_V_REG) && (opc_val[i] & inst)) { /* reg class? */\r | |
384 | inst = inst & ~opc_val[i]; /* mask bit set? */\r | |
385 | fprintf (of, (sp? " %s": "%s"), opcode[i]);\r | |
386 | sp = 1;\r | |
387 | }\r | |
388 | }\r | |
389 | return;\r | |
390 | }\r | |
391 | \r | |
392 | /* Symbolic decode\r | |
393 | \r | |
394 | Inputs:\r | |
395 | *of = output stream\r | |
396 | addr = current PC\r | |
397 | *val = pointer to values\r | |
398 | *uptr = pointer to unit\r | |
399 | sw = switches\r | |
400 | Outputs:\r | |
401 | return = status code\r | |
402 | */\r | |
403 | \r | |
404 | t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,\r | |
405 | UNIT *uptr, int32 sw)\r | |
406 | {\r | |
407 | int32 i, j, ch;\r | |
408 | int32 inst, op, tag, va, shf, nonop;\r | |
409 | \r | |
410 | inst = val[0]; /* get inst */\r | |
411 | op = I_GETOP (inst); /* get fields */\r | |
412 | tag = (inst >> 21) & 06;\r | |
413 | va = inst & VA_MASK;\r | |
414 | shf = inst & I_SHFMSK;\r | |
415 | nonop = inst & 077777;\r | |
416 | \r | |
417 | if (sw & SWMASK ('A')) { /* ASCII? */\r | |
418 | if (inst > 0377) return SCPE_ARG;\r | |
419 | fprintf (of, FMTASC (inst & 0177));\r | |
420 | return SCPE_OK;\r | |
421 | }\r | |
422 | if (sw & SWMASK ('C')) { /* character? */\r | |
423 | fprintf (of, "%c", sds_to_ascii[(inst >> 18) & 077]);\r | |
424 | fprintf (of, "%c", sds_to_ascii[(inst >> 12) & 077]);\r | |
425 | fprintf (of, "%c", sds_to_ascii[(inst >> 6) & 077]);\r | |
426 | fprintf (of, "%c", sds_to_ascii[inst & 077]);\r | |
427 | return SCPE_OK;\r | |
428 | }\r | |
429 | if (!(sw & SWMASK ('M'))) return SCPE_ARG;\r | |
430 | \r | |
431 | /* Instruction decode */\r | |
432 | \r | |
433 | for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r | |
434 | j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r | |
435 | if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */\r | |
436 | \r | |
437 | switch (j) { /* case on class */\r | |
438 | \r | |
439 | case I_V_NPN: /* no operands */\r | |
440 | case I_V_OPO: /* opcode only */\r | |
441 | fprintf (of, "%s", opcode[i]); /* opcode */\r | |
442 | break;\r | |
443 | \r | |
444 | case I_V_SHF: /* shift */\r | |
445 | fprintf (of, "%s %-o", opcode[i], shf);\r | |
446 | if (tag) fprintf (of, ",%-o", tag);\r | |
447 | break;\r | |
448 | \r | |
449 | case I_V_PPO: /* pop */\r | |
450 | fprintf (of, "POP %-o,%-o", op, nonop);\r | |
451 | if (tag) fprintf (of, ",%-o", tag);\r | |
452 | break;\r | |
453 | \r | |
454 | case I_V_IOI: /* I/O */\r | |
455 | fprintf (of, "%s %-o", opcode[i], nonop);\r | |
456 | if (tag) fprintf (of, ",%-o", tag);\r | |
457 | break;\r | |
458 | \r | |
459 | case I_V_MRF: /* mem ref */\r | |
460 | fprintf (of, "%s %-o", opcode[i], va);\r | |
461 | if (tag) fprintf (of, ",%-o", tag);\r | |
462 | break;\r | |
463 | \r | |
464 | case I_V_REG: /* reg change */\r | |
465 | fprint_reg (of, inst); /* decode */\r | |
466 | break;\r | |
467 | \r | |
468 | case I_V_CHC: /* chan cmd */\r | |
469 | ch = I_GETEOCH (inst); /* get chan */\r | |
470 | fprintf (of, "%s %s", opcode[i], chname[ch]);\r | |
471 | break;\r | |
472 | \r | |
473 | case I_V_CHT: /* chan test */\r | |
474 | ch = I_GETSKCH (inst); /* get chan */\r | |
475 | fprintf (of, "%s %s", opcode[i], chname[ch]);\r | |
476 | break;\r | |
477 | } /* end case */\r | |
478 | \r | |
479 | return SCPE_OK;\r | |
480 | } /* end if */\r | |
481 | } /* end for */\r | |
482 | return SCPE_ARG;\r | |
483 | }\r | |
484 | \r | |
485 | /* Get (optional) tag\r | |
486 | \r | |
487 | Inputs:\r | |
488 | *cptr = pointer to input string\r | |
489 | *tag = pointer to tag\r | |
490 | Outputs:\r | |
491 | cptr = updated pointer to input string\r | |
492 | */\r | |
493 | \r | |
494 | char *get_tag (char *cptr, t_value *tag)\r | |
495 | {\r | |
496 | char *tptr, gbuf[CBUFSIZE];\r | |
497 | t_stat r;\r | |
498 | \r | |
499 | tptr = get_glyph (cptr, gbuf, 0); /* get next field */\r | |
500 | *tag = get_uint (gbuf, 8, 07, &r) << I_V_TAG; /* parse */\r | |
501 | if (r == SCPE_OK) return tptr; /* ok? advance */\r | |
502 | *tag = 0;\r | |
503 | return cptr; /* no change */\r | |
504 | }\r | |
505 | \r | |
506 | /* Symbolic input\r | |
507 | \r | |
508 | Inputs:\r | |
509 | *cptr = pointer to input string\r | |
510 | addr = current PC\r | |
511 | uptr = pointer to unit\r | |
512 | *val = pointer to output values\r | |
513 | sw = switches\r | |
514 | Outputs:\r | |
515 | status = error status\r | |
516 | */\r | |
517 | \r | |
518 | t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)\r | |
519 | {\r | |
520 | int32 i, j, k;\r | |
521 | t_value d, tag;\r | |
522 | t_stat r;\r | |
523 | char gbuf[CBUFSIZE];\r | |
524 | \r | |
525 | while (isspace (*cptr)) cptr++;\r | |
526 | for (i = 1; (i < 4) && (cptr[i] != 0); i++)\r | |
527 | if (cptr[i] == 0) for (j = i + 1; j <= 4; j++) cptr[j] = 0;\r | |
528 | if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */\r | |
529 | if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r | |
530 | val[0] = (t_value) cptr[0] | 0200;\r | |
531 | return SCPE_OK;\r | |
532 | }\r | |
533 | if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* string? */\r | |
534 | if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r | |
535 | for (i = j = 0, val[0] = 0; i < 4; i++) {\r | |
536 | if (cptr[i] == 0) j = 1; /* latch str end */\r | |
537 | k = ascii_to_sds[cptr[i] & 0177]; /* cvt char */\r | |
538 | if (j || (k < 0)) k = 0; /* bad, end? spc */\r | |
539 | val[0] = (val[0] << 6) | k;\r | |
540 | }\r | |
541 | return SCPE_OK;\r | |
542 | }\r | |
543 | \r | |
544 | cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r | |
545 | for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r | |
546 | if (opcode[i] == NULL) return SCPE_ARG;\r | |
547 | val[0] = opc_val[i] & DMASK; /* get value */\r | |
548 | j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r | |
549 | \r | |
550 | switch (j) { /* case on class */\r | |
551 | \r | |
552 | case I_V_NPN: case I_V_OPO: /* opcode only */\r | |
553 | break;\r | |
554 | \r | |
555 | case I_V_SHF: /* shift */\r | |
556 | cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r | |
557 | d = get_uint (gbuf, 8, I_SHFMSK, &r); /* shift count */\r | |
558 | if (r != SCPE_OK) return SCPE_ARG;\r | |
559 | cptr = get_tag (cptr, &tag); /* get opt tag */\r | |
560 | val[0] = val[0] | d | tag;\r | |
561 | break;\r | |
562 | \r | |
563 | case I_V_PPO: /* pop */\r | |
564 | cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r | |
565 | d = get_uint (gbuf, 8, 077, &r); /* opcode */\r | |
566 | if (r != SCPE_OK) return SCPE_ARG;\r | |
567 | val[0] = val[0] | d; /* fall thru */\r | |
568 | \r | |
569 | case I_V_IOI: /* I/O */\r | |
570 | cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r | |
571 | d = get_uint (gbuf, 8, 077777, &r); /* 15b address */\r | |
572 | if (r != SCPE_OK) return SCPE_ARG;\r | |
573 | cptr = get_tag (cptr, &tag); /* get opt tag */\r | |
574 | val[0] = val[0] | d | tag;\r | |
575 | break;\r | |
576 | \r | |
577 | case I_V_MRF: /* mem ref */\r | |
578 | cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r | |
579 | d = get_uint (gbuf, 8, VA_MASK, &r); /* virt address */\r | |
580 | if (r != SCPE_OK) return SCPE_ARG;\r | |
581 | cptr = get_tag (cptr, &tag); /* get opt tag */\r | |
582 | val[0] = val[0] | d | tag;\r | |
583 | break;\r | |
584 | \r | |
585 | case I_V_REG: /* register */\r | |
586 | for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;\r | |
587 | cptr = get_glyph (cptr, gbuf, 0)) {\r | |
588 | for (i = 0; (opcode[i] != NULL) &&\r | |
589 | (strcmp (opcode[i], gbuf) != 0); i++) ;\r | |
590 | if (opcode[i] != NULL) {\r | |
591 | k = opc_val[i] & DMASK;;\r | |
592 | if (I_GETOP (k) != RCH) return SCPE_ARG;\r | |
593 | val[0] = val[0] | k;\r | |
594 | }\r | |
595 | else {\r | |
596 | d = get_uint (gbuf, 8, 077777, &r);\r | |
597 | if (r != SCPE_OK) return SCPE_ARG;\r | |
598 | else val[0] = val[0] | d;\r | |
599 | }\r | |
600 | }\r | |
601 | break;\r | |
602 | \r | |
603 | case I_V_CHC: case I_V_CHT: /* channel */\r | |
604 | cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r | |
605 | for (i = 0; (chname[i] != NULL) && (strcmp (chname[i], gbuf) != 0);\r | |
606 | i++);\r | |
607 | if (chname[i] != NULL) d = i; /* named chan */\r | |
608 | else {\r | |
609 | d = get_uint (gbuf, 8, NUM_CHAN - 1, &r);\r | |
610 | if (r != SCPE_OK) return SCPE_ARG; /* numbered chan */\r | |
611 | }\r | |
612 | val[0] = val[0] | ((j == I_V_CHC)? I_SETEOCH (d): I_SETSKCH (d));\r | |
613 | break;\r | |
614 | } /* end case */\r | |
615 | \r | |
616 | if (*cptr != 0) return SCPE_ARG; /* junk at end? */\r | |
617 | return SCPE_OK;\r | |
618 | }\r |