First Commit of my working state
[simh.git] / PDP8 / pdp8_sys.c
CommitLineData
196ba1fc
PH
1/* pdp8_sys.c: PDP-8 simulator interface\r
2\r
3 Copyright (c) 1993-2008, 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 24-Jun-08 RMS Fixed bug in new rim loader (found by Don North)\r
27 24-May-08 RMS Fixed signed/unsigned declaration inconsistency\r
28 03-Sep-07 RMS Added FPP8 support\r
29 Rewrote rim and binary loaders\r
30 15-Dec-06 RMS Added TA8E support, IOT disambiguation\r
31 30-Oct-06 RMS Added infinite loop stop\r
32 18-Oct-06 RMS Re-ordered device list\r
33 17-Oct-03 RMS Added TSC8-75, TD8E support, DECtape off reel message\r
34 25-Apr-03 RMS Revised for extended file support\r
35 30-Dec-01 RMS Revised for new TTX\r
36 26-Nov-01 RMS Added RL8A support\r
37 17-Sep-01 RMS Removed multiconsole support\r
38 16-Sep-01 RMS Added TSS/8 packed char support, added KL8A support\r
39 27-May-01 RMS Added multiconsole support\r
40 18-Mar-01 RMS Added DF32 support\r
41 14-Mar-01 RMS Added extension detection of RIM binary tapes\r
42 15-Feb-01 RMS Added DECtape support\r
43 30-Oct-00 RMS Added support for examine to file\r
44 27-Oct-98 RMS V2.4 load interface\r
45 10-Apr-98 RMS Added RIM loader support\r
46 17-Feb-97 RMS Fixed bug in handling of bin loader fields\r
47*/\r
48\r
49#include "pdp8_defs.h"\r
50#include <ctype.h>\r
51\r
52extern DEVICE cpu_dev;\r
53extern UNIT cpu_unit;\r
54extern DEVICE tsc_dev;\r
55extern DEVICE ptr_dev, ptp_dev;\r
56extern DEVICE tti_dev, tto_dev;\r
57extern DEVICE clk_dev, lpt_dev;\r
58extern DEVICE rk_dev, rl_dev;\r
59extern DEVICE rx_dev;\r
60extern DEVICE df_dev, rf_dev;\r
61extern DEVICE dt_dev, td_dev;\r
62extern DEVICE mt_dev, ct_dev;\r
63extern DEVICE ttix_dev, ttox_dev;\r
64extern REG cpu_reg[];\r
65extern uint16 M[];\r
66extern int32 sim_switches;\r
67\r
68t_stat fprint_sym_fpp (FILE *of, t_value *val);\r
69t_stat parse_sym_fpp (char *cptr, t_value *val);\r
70char *parse_field (char *cptr, uint32 max, uint32 *val, uint32 c);\r
71char *parse_fpp_xr (char *cptr, uint32 *xr, t_bool inc);\r
72int32 test_fpp_addr (uint32 ad, uint32 max);\r
73\r
74/* SCP data structures and interface routines\r
75\r
76 sim_name simulator name string\r
77 sim_PC pointer to saved PC register descriptor\r
78 sim_emax maximum number of words for examine/deposit\r
79 sim_devices array of pointers to simulated devices\r
80 sim_consoles array of pointers to consoles (if more than one)\r
81 sim_stop_messages array of pointers to stop messages\r
82 sim_load binary loader\r
83*/\r
84\r
85char sim_name[] = "PDP-8";\r
86\r
87REG *sim_PC = &cpu_reg[0];\r
88\r
89int32 sim_emax = 4;\r
90\r
91DEVICE *sim_devices[] = {\r
92 &cpu_dev,\r
93 &tsc_dev,\r
94 &clk_dev,\r
95 &ptr_dev,\r
96 &ptp_dev,\r
97 &tti_dev,\r
98 &tto_dev,\r
99 &ttix_dev,\r
100 &ttox_dev,\r
101 &lpt_dev,\r
102 &rk_dev,\r
103 &rl_dev,\r
104 &rx_dev,\r
105 &df_dev,\r
106 &rf_dev,\r
107 &dt_dev,\r
108 &td_dev,\r
109 &mt_dev,\r
110 &ct_dev,\r
111 NULL\r
112 };\r
113\r
114const char *sim_stop_messages[] = {\r
115 "Unknown error",\r
116 "Unimplemented instruction",\r
117 "HALT instruction",\r
118 "Breakpoint",\r
119 "Non-standard device number",\r
120 "DECtape off reel",\r
121 "Infinite loop"\r
122 };\r
123\r
124/* Ambiguous device list - these devices have overlapped IOT codes */\r
125\r
126DEVICE *amb_dev[] = {\r
127 &rl_dev,\r
128 &ct_dev,\r
129 &td_dev,\r
130 NULL\r
131 };\r
132\r
133#define AMB_RL (1 << 12)\r
134#define AMB_CT (2 << 12)\r
135#define AMB_TD (3 << 12)\r
136\r
137/* RIM loader format consists of alternating pairs of addresses and 12-bit\r
138 words. It can only operate in field 0 and is not checksummed.\r
139*/\r
140\r
141t_stat sim_load_rim (FILE *fi)\r
142{\r
143int32 origin, hi, lo, wd;\r
144\r
145origin = 0200;\r
146do { /* skip leader */\r
147 if ((hi = getc (fi)) == EOF)\r
148 return SCPE_FMT;\r
149 } while ((hi == 0) || (hi >= 0200));\r
150do { /* data block */\r
151 if ((lo = getc (fi)) == EOF)\r
152 return SCPE_FMT;\r
153 wd = (hi << 6) | lo;\r
154 if (wd > 07777) origin = wd & 07777;\r
155 else M[origin++ & 07777] = wd;\r
156 if ((hi = getc (fi)) == EOF)\r
157 return SCPE_FMT;\r
158 } while (hi < 0200); /* until trailer */\r
159return SCPE_OK;\r
160}\r
161\r
162/* BIN loader format consists of a string of 12-bit words (made up from\r
163 7-bit characters) between leader and trailer (200). The last word on\r
164 tape is the checksum. A word with the "link" bit set is a new origin;\r
165 a character > 0200 indicates a change of field.\r
166*/\r
167\r
168int32 sim_bin_getc (FILE *fi, uint32 *newf)\r
169{\r
170int32 c, rubout;\r
171\r
172rubout = 0; /* clear toggle */\r
173while ((c = getc (fi)) != EOF) { /* read char */\r
174 if (rubout) /* toggle set? */\r
175 rubout = 0; /* clr, skip */\r
176 else if (c == 0377) /* rubout? */\r
177 rubout = 1; /* set, skip */\r
178 else if (c > 0200) /* channel 8 set? */\r
179 *newf = (c & 070) << 9; /* change field */\r
180 else return c; /* otherwise ok */\r
181 }\r
182return EOF;\r
183}\r
184\r
185t_stat sim_load_bin (FILE *fi)\r
186{\r
187int32 hi, lo, wd, csum, t;\r
188uint32 field, newf, origin;\r
189\r
190do { /* skip leader */\r
191 if ((hi = sim_bin_getc (fi, &newf)) == EOF)\r
192 return SCPE_FMT;\r
193 } while ((hi == 0) || (hi >= 0200));\r
194csum = origin = field = newf = 0; /* init */\r
195for (;;) { /* data blocks */\r
196 if ((lo = sim_bin_getc (fi, &newf)) == EOF) /* low char */\r
197 return SCPE_FMT;\r
198 wd = (hi << 6) | lo; /* form word */\r
199 t = hi; /* save for csum */\r
200 if ((hi = sim_bin_getc (fi, &newf)) == EOF) /* next char */\r
201 return SCPE_FMT;\r
202 if (hi == 0200) { /* end of tape? */\r
203 if ((csum - wd) & 07777) /* valid csum? */\r
204 return SCPE_CSUM;\r
205 return SCPE_OK;\r
206 }\r
207 csum = csum + t + lo; /* add to csum */\r
208 if (wd > 07777) /* chan 7 set? */\r
209 origin = wd & 07777; /* new origin */\r
210 else { /* no, data */\r
211 if ((field | origin) >= MEMSIZE) \r
212 return SCPE_NXM;\r
213 M[field | origin] = wd;\r
214 origin = (origin + 1) & 07777;\r
215 }\r
216 field = newf; /* update field */\r
217 }\r
218return SCPE_IERR;\r
219}\r
220\r
221/* Binary loader\r
222 Two loader formats are supported: RIM loader (-r) and BIN (-b) loader. */\r
223\r
224t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)\r
225{\r
226if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;\r
227if ((sim_switches & SWMASK ('R')) || /* RIM format? */\r
228 (match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B'))))\r
229 return sim_load_rim (fileref);\r
230else return sim_load_bin (fileref); /* no, BIN */\r
231}\r
232\r
233/* Symbol tables */\r
234\r
235#define I_V_FL 18 /* flag start */\r
236#define I_M_FL 07 /* flag mask */\r
237#define I_V_NPN 0 /* no operand */\r
238#define I_V_FLD 1 /* field change */\r
239#define I_V_MRF 2 /* mem ref */\r
240#define I_V_IOT 3 /* general IOT */\r
241#define I_V_OP1 4 /* operate 1 */\r
242#define I_V_OP2 5 /* operate 2 */\r
243#define I_V_OP3 6 /* operate 3 */\r
244#define I_V_IOA 7 /* ambiguous IOT */\r
245#define I_NPN (I_V_NPN << I_V_FL)\r
246#define I_FLD (I_V_FLD << I_V_FL)\r
247#define I_MRF (I_V_MRF << I_V_FL)\r
248#define I_IOT (I_V_IOT << I_V_FL)\r
249#define I_OP1 (I_V_OP1 << I_V_FL)\r
250#define I_OP2 (I_V_OP2 << I_V_FL)\r
251#define I_OP3 (I_V_OP3 << I_V_FL)\r
252#define I_IOA (I_V_IOA << I_V_FL)\r
253\r
254static const int32 masks[] = {\r
255 07777, 07707, 07000, 07000,\r
256 07416, 07571, 017457, 077777,\r
257 };\r
258\r
259/* Ambiguous device mnemonics must precede default mnemonics */\r
260\r
261static const char *opcode[] = {\r
262 "SKON", "ION", "IOF", "SRQ", /* std IOTs */\r
263 "GTF", "RTF", "SGT", "CAF",\r
264 "RPE", "RSF", "RRB", "RFC", "RFC RRB", /* reader/punch */\r
265 "PCE", "PSF", "PCF", "PPC", "PLS",\r
266 "KCF", "KSF", "KCC", "KRS", "KIE", "KRB", /* console */\r
267 "TLF", "TSF", "TCF", "TPC", "SPI", "TLS",\r
268 "SBE", "SPL", "CAL", /* power fail */\r
269 "CLEI", "CLDI", "CLSC", "CLLE", "CLCL", "CLSK", /* clock */\r
270 "CINT", "RDF", "RIF", "RIB", /* mem mmgt */\r
271 "RMF", "SINT", "CUF", "SUF",\r
272 "RLDC", "RLSD", "RLMA", "RLCA", /* RL - ambiguous */\r
273 "RLCB", "RLSA", "RLWC",\r
274 "RRER", "RRWC", "RRCA", "RRCB",\r
275 "RRSA", "RRSI", "RLSE",\r
276 "KCLR", "KSDR", "KSEN", "KSBF", /* CT - ambiguous */\r
277 "KLSA", "KSAF", "KGOA", "KRSB",\r
278 "SDSS", "SDST", "SDSQ", /* TD - ambiguous */\r
279 "SDLC", "SDLD", "SDRC", "SDRD",\r
280 "ADCL", "ADLM", "ADST", "ADRB", /* A/D */\r
281 "ADSK", "ADSE", "ADLE", "ADRS",\r
282 "DCMA", "DMAR", "DMAW", /* DF/RF */\r
283 "DCIM", "DSAC", "DIML", "DIMA",\r
284 "DCEA", "DEAL", "DEAC",\r
285 "DFSE", "DFSC", "DISK", "DMAC",\r
286 "DCXA", "DXAL", "DXAC",\r
287 "PSKF", "PCLF", "PSKE", /* LPT */\r
288 "PSTB", "PSIE", "PCLF PSTB", "PCIE",\r
289 "LWCR", "CWCR", "LCAR", /* MT */\r
290 "CCAR", "LCMR", "LFGR", "LDBR",\r
291 "RWCR", "CLT", "RCAR",\r
292 "RMSR", "RCMR", "RFSR", "RDBR",\r
293 "SKEF", "SKCB", "SKJD", "SKTR", "CLF",\r
294 "DSKP", "DCLR", "DLAG", /* RK */\r
295 "DLCA", "DRST", "DLDC", "DMAN",\r
296 "LCD", "XDR", "STR", /* RX */\r
297 "SER", "SDN", "INTR", "INIT",\r
298 "DTRA", "DTCA", "DTXA", "DTLA", /* DT */\r
299 "DTSF", "DTRB", "DTLB",\r
300 "ETDS", "ESKP", "ECTF", "ECDF", /* TSC75 */\r
301 "ERTB", "ESME", "ERIOT", "ETEN",\r
302 "FFST", "FPINT", "FPICL", "FPCOM", /* FPP8 */\r
303 "FPHLT", "FPST", "FPRST", "FPIST",\r
304 "FMODE", "FMRB",\r
305 "FMRP", "FMDO", "FPEP",\r
306\r
307 "CDF", "CIF", "CIF CDF",\r
308 "AND", "TAD", "ISZ", "DCA", "JMS", "JMP", "IOT",\r
309 "NOP", "NOP2", "NOP3", "SWAB", "SWBA",\r
310 "STL", "GLK", "STA", "LAS", "CIA",\r
311 "BSW", "RAL", "RTL", "RAR", "RTR", "RAL RAR", "RTL RTR",\r
312 "SKP", "SNL", "SZL",\r
313 "SZA", "SNA", "SZA SNL", "SNA SZL",\r
314 "SMA", "SPA", "SMA SNL", "SPA SZL",\r
315 "SMA SZA", "SPA SNA", "SMA SZA SNL", "SPA SNA SZL",\r
316 "SCL", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR",\r
317 "SCA", "SCA SCL", "SCA MUY", "SCA DVI",\r
318 "SCA NMI", "SCA SHL", "SCA ASR", "SCA LSR",\r
319 "ACS", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR",\r
320 "SCA", "DAD", "DST", "SWBA",\r
321 "DPSZ", "DPIC", "DCIM", "SAM",\r
322 "CLA", "CLL", "CMA", "CML", "IAC", /* encode only */\r
323 "CLA", "OAS", "HLT",\r
324 "CLA", "MQA", "MQL",\r
325 NULL, NULL, NULL, NULL, /* decode only */\r
326 NULL\r
327 };\r
328 \r
329static const int32 opc_val[] = {\r
330 06000+I_NPN, 06001+I_NPN, 06002+I_NPN, 06003+I_NPN,\r
331 06004+I_NPN, 06005+I_NPN, 06006+I_NPN, 06007+I_NPN,\r
332 06010+I_NPN, 06011+I_NPN, 06012+I_NPN, 06014+I_NPN, 06016+I_NPN,\r
333 06020+I_NPN, 06021+I_NPN, 06022+I_NPN, 06024+I_NPN, 06026+I_NPN,\r
334 06030+I_NPN, 06031+I_NPN, 06032+I_NPN, 06034+I_NPN, 06035+I_NPN, 06036+I_NPN,\r
335 06040+I_NPN, 06041+I_NPN, 06042+I_NPN, 06044+I_NPN, 06045+I_NPN, 06046+I_NPN,\r
336 06101+I_NPN, 06102+I_NPN, 06103+I_NPN,\r
337 06131+I_NPN, 06132+I_NPN, 06133+I_NPN, 06135+I_NPN, 06136+I_NPN, 06137+I_NPN,\r
338 06204+I_NPN, 06214+I_NPN, 06224+I_NPN, 06234+I_NPN,\r
339 06244+I_NPN, 06254+I_NPN, 06264+I_NPN, 06274+I_NPN,\r
340 06600+I_IOA+AMB_RL, 06601+I_IOA+AMB_RL, 06602+I_IOA+AMB_RL, 06603+I_IOA+AMB_RL,\r
341 06604+I_IOA+AMB_RL, 06605+I_IOA+AMB_RL, 06607+I_IOA+AMB_RL,\r
342 06610+I_IOA+AMB_RL, 06611+I_IOA+AMB_RL, 06612+I_IOA+AMB_RL, 06613+I_IOA+AMB_RL,\r
343 06614+I_IOA+AMB_RL, 06615+I_IOA+AMB_RL, 06617+I_IOA+AMB_RL,\r
344 06700+I_IOA+AMB_CT, 06701+I_IOA+AMB_CT, 06702+I_IOA+AMB_CT, 06703+I_IOA+AMB_CT,\r
345 06704+I_IOA+AMB_CT, 06705+I_IOA+AMB_CT, 06706+I_IOA+AMB_CT, 06707+I_IOA+AMB_CT,\r
346 06771+I_IOA+AMB_TD, 06772+I_IOA+AMB_TD, 06773+I_IOA+AMB_TD,\r
347 06774+I_IOA+AMB_TD, 06775+I_IOA+AMB_TD, 06776+I_IOA+AMB_TD, 06777+I_IOA+AMB_TD,\r
348 06530+I_NPN, 06531+I_NPN, 06532+I_NPN, 06533+I_NPN, /* AD */\r
349 06534+I_NPN, 06535+I_NPN, 06536+I_NPN, 06537+I_NPN,\r
350 06601+I_NPN, 06603+I_NPN, 06605+I_NPN, /* DF/RF */\r
351 06611+I_NPN, 06612+I_NPN, 06615+I_NPN, 06616+I_NPN,\r
352 06611+I_NPN, 06615+I_NPN, 06616+I_NPN,\r
353 06621+I_NPN, 06622+I_NPN, 06623+I_NPN, 06626+I_NPN,\r
354 06641+I_NPN, 06643+I_NPN, 06645+I_NPN,\r
355 06661+I_NPN, 06662+I_NPN, 06663+I_NPN, /* LPT */\r
356 06664+I_NPN, 06665+I_NPN, 06666+I_NPN, 06667+I_NPN,\r
357 06701+I_NPN, 06702+I_NPN, 06703+I_NPN, /* MT */\r
358 06704+I_NPN, 06705+I_NPN, 06706+I_NPN, 06707+I_NPN,\r
359 06711+I_NPN, 06712+I_NPN, 06713+I_NPN,\r
360 06714+I_NPN, 06715+I_NPN, 06716+I_NPN, 06717+I_NPN,\r
361 06721+I_NPN, 06722+I_NPN, 06723+I_NPN, 06724+I_NPN, 06725+I_NPN,\r
362 06741+I_NPN, 06742+I_NPN, 06743+I_NPN, /* RK */\r
363 06744+I_NPN, 06745+I_NPN, 06746+I_NPN, 06747+I_NPN,\r
364 06751+I_NPN, 06752+I_NPN, 06753+I_NPN, /* RX */\r
365 06754+I_NPN, 06755+I_NPN, 06756+I_NPN, 06757+I_NPN,\r
366 06761+I_NPN, 06762+I_NPN, 06764+I_NPN, 06766+I_NPN, /* DT */\r
367 06771+I_NPN, 06772+I_NPN, 06774+I_NPN,\r
368 06360+I_NPN, 06361+I_NPN, 06362+I_NPN, 06363+I_NPN, /* TSC */\r
369 06364+I_NPN, 06365+I_NPN, 06366+I_NPN, 06367+I_NPN,\r
370 06550+I_NPN, 06551+I_NPN, 06552+I_NPN, 06553+I_NPN, /* FPP8 */\r
371 06554+I_NPN, 06555+I_NPN, 06556+I_NPN, 06557+I_NPN,\r
372 06561+I_NPN, 06563+I_NPN,\r
373 06564+I_NPN, 06565+I_NPN, 06567+I_NPN,\r
374\r
375 06201+I_FLD, 06202+I_FLD, 06203+I_FLD,\r
376 00000+I_MRF, 01000+I_MRF, 02000+I_MRF, 03000+I_MRF,\r
377 04000+I_MRF, 05000+I_MRF, 06000+I_IOT,\r
378 07000+I_NPN, 07400+I_NPN, 07401+I_NPN, 07431+I_NPN, 07447+I_NPN,\r
379 07120+I_NPN, 07204+I_NPN, 07240+I_NPN, 07604+I_NPN, 07041+I_NPN,\r
380 07002+I_OP1, 07004+I_OP1, 07006+I_OP1,\r
381 07010+I_OP1, 07012+I_OP1, 07014+I_OP1, 07016+I_OP1,\r
382 07410+I_OP2, 07420+I_OP2, 07430+I_OP2,\r
383 07440+I_OP2, 07450+I_OP2, 07460+I_OP2, 07470+I_OP2,\r
384 07500+I_OP2, 07510+I_OP2, 07520+I_OP2, 07530+I_OP2,\r
385 07540+I_OP2, 07550+I_OP2, 07560+I_OP2, 07570+I_OP2,\r
386 07403+I_OP3, 07405+I_OP3, 07407+I_OP3,\r
387 07411+I_OP3, 07413+I_OP3, 07415+I_OP3, 07417+I_OP3,\r
388 07441+I_OP3, 07443+I_OP3, 07445+I_OP3, 07447+I_OP3,\r
389 07451+I_OP3, 07453+I_OP3, 07455+I_OP3, 07457+I_OP3,\r
390 017403+I_OP3, 017405+I_OP3, 0174017+I_OP3,\r
391 017411+I_OP3, 017413+I_OP3, 017415+I_OP3, 017417+I_OP3,\r
392 017441+I_OP3, 017443+I_OP3, 017445+I_OP3, 017447+I_OP3,\r
393 017451+I_OP3, 017453+I_OP3, 017455+I_OP3, 017457+I_OP3,\r
394 07200+I_OP1, 07100+I_OP1, 07040+I_OP1, 07020+I_OP1, 07001+I_OP1,\r
395 07600+I_OP2, 07404+I_OP2, 07402+I_OP2,\r
396 07601+I_OP3, 07501+I_OP3, 07421+I_OP3,\r
397 07000+I_OP1, 07400+I_OP2, 07401+I_OP3, 017401+I_OP3,\r
398 -1\r
399 };\r
400\r
401/* Symbol tables for FPP-8 */\r
402\r
403#define F_V_FL 18 /* flag start */\r
404#define F_M_FL 017 /* flag mask */\r
405#define F_V_NOP12 0 /* no opnd 12b */\r
406#define F_V_NOP9 1 /* no opnd 9b */\r
407#define F_V_AD15 2 /* 15b dir addr */\r
408#define F_V_AD15X 3 /* 15b dir addr indx */\r
409#define F_V_IMMX 4 /* 12b immm indx */\r
410#define F_V_X 5 /* index */\r
411#define F_V_MRI 6 /* mem ref ind */\r
412#define F_V_MR1D 7 /* mem ref dir 1 word */\r
413#define F_V_MR2D 8 /* mem ref dir 2 word */\r
414#define F_V_LEMU 9 /* LEA/IMUL */\r
415#define F_V_LEMUI 10 /* LEAI/IMULI */\r
416#define F_V_LTR 11 /* LTR */\r
417#define F_V_MRD 12 /* mem ref direct (enc) */\r
418#define F_NOP12 (F_V_NOP12 << F_V_FL)\r
419#define F_NOP9 (F_V_NOP9 << F_V_FL)\r
420#define F_AD15 (F_V_AD15 << F_V_FL)\r
421#define F_AD15X (F_V_AD15X << F_V_FL)\r
422#define F_IMMX (F_V_IMMX << F_V_FL)\r
423#define F_X (F_V_X << F_V_FL)\r
424#define F_MRI (F_V_MRI << F_V_FL)\r
425#define F_MR1D (F_V_MR1D << F_V_FL)\r
426#define F_MR2D (F_V_MR2D << F_V_FL)\r
427#define F_LEMU (F_V_LEMU << F_V_FL)\r
428#define F_LEMUI (F_V_LEMUI << F_V_FL)\r
429#define F_LTR (F_V_LTR << F_V_FL)\r
430#define F_MRD (F_V_MRD << F_V_FL)\r
431\r
432static const uint32 fmasks[] = {\r
433 07777, 07770, 07770, 07600,\r
434 07770, 07770, 07600, 07600,\r
435 07600, 017600, 017600, 07670,\r
436 07777\r
437 };\r
438\r
439/* Memory references are encode dir / decode 1D / decode 2D / indirect */\r
440\r
441static const char *fopcode[] = {\r
442 "FEXIT", "FPAUSE", "FCLA", "FNEG",\r
443 "FNORM", "STARTF", "STARTD", "JAC",\r
444 "ALN", "ATX", "XTA",\r
445 "FNOP", "STARTE",\r
446 "LDX", "ADDX",\r
447 "FLDA", "FLDA", "FLDA", "FLDAI",\r
448 "JEQ", "JGE", "JLE", "JA",\r
449 "JNE", "JLT", "JGT", "JAL",\r
450 "SETX", "SETB", "JSA", "JSR",\r
451 "FADD", "FADD", "FADD", "FADDI",\r
452 "JNX",\r
453 "FSUB", "FSUB", "FSUB", "FSUBI",\r
454 "TRAP3",\r
455 "FDIV", "FDIV", "FDIV", "FDIVI",\r
456 "TRAP4",\r
457 "FMUL", "FMUL", "FMUL", "FMULI",\r
458 "LTREQ", "LTRGE", "LTRLE", "LTRA",\r
459 "LTRNE", "LTRLT", "LTRGT", "LTRAL",\r
460 "FADDM", "FADDM", "FADDM", "FADDMI",\r
461 "IMUL", "LEA",\r
462 "FSTA", "FSTA", "FSTA", "FSTAI",\r
463 "IMULI", "LEAI",\r
464 "FMULM", "FMULM", "FMULM", "FMULMI",\r
465 NULL\r
466 };\r
467\r
468static const int32 fop_val[] = {\r
469 00000+F_NOP12, 00001+F_NOP12, 00002+F_NOP12, 00003+F_NOP12,\r
470 00004+F_NOP12, 00005+F_NOP12, 00006+F_NOP12, 00007+F_NOP12,\r
471 00010+F_X, 00020+F_X, 00030+F_X,\r
472 00040+F_NOP9, 00050+F_NOP9,\r
473 00100+F_IMMX, 00110+F_IMMX,\r
474 00000+F_MRD, 00200+F_MR1D, 00400+F_MR2D, 00600+F_MRI,\r
475 01000+F_AD15, 01010+F_AD15, 01020+F_AD15, 01030+F_AD15,\r
476 01040+F_AD15, 01050+F_AD15, 01060+F_AD15, 01070+F_AD15,\r
477 01100+F_AD15, 01110+F_AD15, 01120+F_AD15, 01130+F_AD15,\r
478 01000+F_MRD, 01200+F_MR1D, 01400+F_MR2D, 01600+F_MRI,\r
479 02000+F_AD15X,\r
480 02000+F_MRD, 02200+F_MR1D, 02400+F_MR2D, 02600+F_MRI,\r
481 03000+F_AD15,\r
482 03000+F_MRD, 03200+F_MR1D, 03400+F_MR2D, 03600+F_MRI,\r
483 04000+F_AD15,\r
484 04000+F_MRD, 04200+F_MR1D, 04400+F_MR2D, 04600+F_MRI,\r
485 05000+F_LTR, 05010+F_LTR, 05020+F_LTR, 05030+F_LTR,\r
486 05040+F_LTR, 05050+F_LTR, 05060+F_LTR, 05070+F_LTR,\r
487 05000+F_MRD, 05200+F_MR1D, 05400+F_MR2D, 05600+F_MRI,\r
488 016000+F_LEMU, 006000+F_LEMU,\r
489 06000+F_MRD, 06200+F_MR1D, 06400+F_MR2D, 06600+F_MRI,\r
490 017000+F_LEMUI, 007000+F_LEMUI,\r
491 07000+F_MRD, 07200+F_MR1D, 07400+F_MR2D, 07600+F_MRI,\r
492 -1\r
493 };\r
494\r
495/* Operate decode\r
496\r
497 Inputs:\r
498 *of = output stream\r
499 inst = mask bits\r
500 class = instruction class code\r
501 sp = space needed?\r
502 Outputs:\r
503 status = space needed\r
504*/\r
505\r
506int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp)\r
507{\r
508int32 i, j;\r
509\r
510for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r
511 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r
512 if ((j == class) && (opc_val[i] & inst)) { /* same class? */\r
513 inst = inst & ~opc_val[i]; /* mask bit set? */\r
514 fprintf (of, (sp? " %s": "%s"), opcode[i]);\r
515 sp = 1;\r
516 }\r
517 }\r
518return sp;\r
519}\r
520\r
521/* Symbolic decode\r
522\r
523 Inputs:\r
524 *of = output stream\r
525 addr = current PC\r
526 *val = pointer to data\r
527 *uptr = pointer to unit \r
528 sw = switches\r
529 Outputs:\r
530 return = status code\r
531*/\r
532\r
533#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)\r
534#define SIXTOASC(x) (((x) >= 040)? (x): (x) + 0100)\r
535#define TSSTOASC(x) ((x) + 040)\r
536\r
537t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,\r
538 UNIT *uptr, int32 sw)\r
539{\r
540int32 cflag, i, j, sp, inst, disp, opc;\r
541extern int32 emode;\r
542t_stat r;\r
543\r
544cflag = (uptr == NULL) || (uptr == &cpu_unit);\r
545inst = val[0];\r
546if (sw & SWMASK ('A')) { /* ASCII? */\r
547 if (inst > 0377) return SCPE_ARG;\r
548 fprintf (of, FMTASC (inst & 0177));\r
549 return SCPE_OK;\r
550 }\r
551if (sw & SWMASK ('C')) { /* characters? */\r
552 fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077));\r
553 fprintf (of, "%c", SIXTOASC (inst & 077));\r
554 return SCPE_OK;\r
555 }\r
556if (sw & SWMASK ('T')) { /* TSS8 packed? */\r
557 fprintf (of, "%c", TSSTOASC ((inst >> 6) & 077));\r
558 fprintf (of, "%c", TSSTOASC (inst & 077));\r
559 return SCPE_OK;\r
560 }\r
561if ((sw & SWMASK ('F')) && /* FPP8? */\r
562 ((r = fprint_sym_fpp (of, val)) != SCPE_ARG))\r
563 return r;\r
564if (!(sw & SWMASK ('M'))) return SCPE_ARG;\r
565\r
566/* Instruction decode */\r
567\r
568opc = (inst >> 9) & 07; /* get major opcode */\r
569if (opc == 07) /* operate? */\r
570 inst = inst | ((emode & 1) << 12); /* include EAE mode */\r
571if (opc == 06) { /* IOT? */\r
572 DEVICE *dptr;\r
573 DIB *dibp;\r
574 uint32 dno = (inst >> 3) & 077;\r
575 for (i = 0; (dptr = amb_dev[i]) != NULL; i++) { /* check amb devices */\r
576 if ((dptr->ctxt == NULL) || /* no DIB or */\r
577 (dptr->flags & DEV_DIS)) continue; /* disabled? skip */\r
578 dibp = (DIB *) dptr->ctxt; /* get DIB */\r
579 if ((dno >= dibp->dev) || /* IOT for this dev? */\r
580 (dno < (dibp->dev + dibp->num))) {\r
581 inst = inst | ((i + 1) << 12); /* disambiguate */\r
582 break; /* done */\r
583 }\r
584 }\r
585 }\r
586 \r
587for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r
588 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r
589 if ((opc_val[i] & 077777) == (inst & masks[j])) { /* match? */\r
590\r
591 switch (j) { /* case on class */\r
592\r
593 case I_V_NPN: case I_V_IOA: /* no operands */\r
594 fprintf (of, "%s", opcode[i]); /* opcode */\r
595 break;\r
596\r
597 case I_V_FLD: /* field change */\r
598 fprintf (of, "%s %-o", opcode[i], (inst >> 3) & 07);\r
599 break;\r
600\r
601 case I_V_MRF: /* mem ref */\r
602 disp = inst & 0177; /* displacement */\r
603 fprintf (of, "%s%s", opcode[i], ((inst & 00400)? " I ": " "));\r
604 if (inst & 0200) { /* current page? */\r
605 if (cflag) fprintf (of, "%-o", (addr & 07600) | disp);\r
606 else fprintf (of, "C %-o", disp);\r
607 }\r
608 else fprintf (of, "%-o", disp); /* page zero */\r
609 break;\r
610\r
611 case I_V_IOT: /* IOT */\r
612 fprintf (of, "%s %-o", opcode[i], inst & 0777);\r
613 break;\r
614\r
615 case I_V_OP1: /* operate group 1 */\r
616 sp = fprint_opr (of, inst & 0361, j, 0);\r
617 if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);\r
618 break;\r
619\r
620 case I_V_OP2: /* operate group 2 */\r
621 if (opcode[i]) fprintf (of, "%s", opcode[i]); /* skips */\r
622 fprint_opr (of, inst & 0206, j, opcode[i] != NULL);\r
623 break; \r
624\r
625 case I_V_OP3: /* operate group 3 */\r
626 sp = fprint_opr (of, inst & 0320, j, 0);\r
627 if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);\r
628 break;\r
629 } /* end case */\r
630\r
631 return SCPE_OK;\r
632 } /* end if */\r
633 } /* end for */\r
634return SCPE_ARG;\r
635}\r
636\r
637/* Symbolic input\r
638\r
639 Inputs:\r
640 *cptr = pointer to input string\r
641 addr = current PC\r
642 *uptr = pointer to unit\r
643 *val = pointer to output values\r
644 sw = switches\r
645 Outputs:\r
646 status = error status\r
647*/\r
648\r
649t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)\r
650{\r
651uint32 cflag, d, i, j, k;\r
652t_stat r;\r
653char gbuf[CBUFSIZE];\r
654\r
655cflag = (uptr == NULL) || (uptr == &cpu_unit);\r
656while (isspace (*cptr)) cptr++; /* absorb spaces */\r
657if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */\r
658 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r
659 val[0] = (t_value) cptr[0] | 0200;\r
660 return SCPE_OK;\r
661 }\r
662if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */\r
663 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r
664 val[0] = (((t_value) cptr[0] & 077) << 6) |\r
665 ((t_value) cptr[1] & 077);\r
666 return SCPE_OK;\r
667 }\r
668if ((sw & SWMASK ('T')) || ((*cptr == '"') && cptr++)) { /* TSS8 string? */\r
669 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r
670 val[0] = (((t_value) (cptr[0] - 040) & 077) << 6) |\r
671 ((t_value) (cptr[1] - 040) & 077);\r
672 return SCPE_OK;\r
673 }\r
674if ((r = parse_sym_fpp (cptr, val)) != SCPE_ARG) /* FPP8 inst? */\r
675 return r;\r
676\r
677/* Instruction parse */\r
678\r
679cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r
680for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r
681if (opcode[i] == NULL) return SCPE_ARG;\r
682val[0] = opc_val[i] & 07777; /* get value */\r
683j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r
684\r
685switch (j) { /* case on class */\r
686\r
687 case I_V_IOT: /* IOT */\r
688 if ((cptr = parse_field (cptr, 0777, &d, 0)) == NULL)\r
689 return SCPE_ARG; /* get dev+pulse */\r
690 val[0] = val[0] | d;\r
691 break;\r
692\r
693 case I_V_FLD: /* field */\r
694 for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;\r
695 cptr = get_glyph (cptr, gbuf, 0)) {\r
696 for (i = 0; (opcode[i] != NULL) &&\r
697 (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r
698 if (opcode[i] != NULL) {\r
699 k = (opc_val[i] >> I_V_FL) & I_M_FL;\r
700 if (k != j) return SCPE_ARG;\r
701 val[0] = val[0] | (opc_val[i] & 07777);\r
702 }\r
703 else {\r
704 d = get_uint (gbuf, 8, 07, &r);\r
705 if (r != SCPE_OK) return SCPE_ARG;\r
706 val[0] = val[0] | (d << 3);\r
707 break;\r
708 }\r
709 }\r
710 break;\r
711\r
712 case I_V_MRF: /* mem ref */\r
713 cptr = get_glyph (cptr, gbuf, 0); /* get next field */\r
714 if (strcmp (gbuf, "I") == 0) { /* indirect? */\r
715 val[0] = val[0] | 0400;\r
716 cptr = get_glyph (cptr, gbuf, 0);\r
717 }\r
718 if ((k = (strcmp (gbuf, "C") == 0)) || (strcmp (gbuf, "Z") == 0)) {\r
719 if ((cptr = parse_field (cptr, 0177, &d, 0)) == NULL)\r
720 return SCPE_ARG;\r
721 val[0] = val[0] | d | (k? 0200: 0);\r
722 }\r
723 else {\r
724 d = get_uint (gbuf, 8, 07777, &r);\r
725 if (r != SCPE_OK) return SCPE_ARG;\r
726 if (d <= 0177) val[0] = val[0] | d;\r
727 else if (cflag && (((addr ^ d) & 07600) == 0))\r
728 val[0] = val[0] | (d & 0177) | 0200;\r
729 else return SCPE_ARG;\r
730 }\r
731 break;\r
732\r
733 case I_V_OP1: case I_V_OP2: case I_V_OP3: /* operates */\r
734 case I_V_NPN: case I_V_IOA:\r
735 for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;\r
736 cptr = get_glyph (cptr, gbuf, 0)) {\r
737 for (i = 0; (opcode[i] != NULL) &&\r
738 (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r
739 k = opc_val[i] & 07777;\r
740 if ((opcode[i] == NULL) || (((k ^ val[0]) & 07000) != 0))\r
741 return SCPE_ARG;\r
742 val[0] = val[0] | k;\r
743 }\r
744 break;\r
745 } /* end case */\r
746\r
747if (*cptr != 0) return SCPE_ARG; /* junk at end? */\r
748return SCPE_OK;\r
749}\r
750\r
751/* FPP8 instruction decode */\r
752\r
753t_stat fprint_sym_fpp (FILE *of, t_value *val)\r
754{\r
755uint32 wd1, wd2, xr4b, xr3b, ad15;\r
756uint32 i, j;\r
757extern uint32 fpp_bra, fpp_cmd;\r
758\r
759wd1 = (uint32) val[0] | ((fpp_cmd & 04000) << 1);\r
760wd2 = (uint32) val[1];\r
761xr4b = (wd1 >> 3) & 017;\r
762xr3b = wd1 & 07;\r
763ad15 = (xr3b << 12) | wd2;\r
764\r
765for (i = 0; fop_val[i] >= 0; i++) { /* loop thru ops */\r
766 j = (fop_val[i] >> F_V_FL) & F_M_FL; /* get class */\r
767 if ((fop_val[i] & 017777) == (wd1 & fmasks[j])) { /* match? */\r
768\r
769 switch (j) { /* case on class */\r
770 case F_V_NOP12:\r
771 case F_V_NOP9:\r
772 case F_V_LTR: /* no operands */\r
773 fprintf (of, "%s", fopcode[i]);\r
774 break;\r
775\r
776 case F_V_X: /* index */\r
777 fprintf (of, "%s %o", fopcode[i], xr3b);\r
778 break;\r
779\r
780 case F_V_IMMX: /* index imm */\r
781 fprintf (of, "%s %-o,%o", fopcode[i], wd2, xr3b);\r
782 return -1; /* extra word */\r
783\r
784 case F_V_AD15: /* 15b address */\r
785 fprintf (of, "%s %-o", fopcode[i], ad15);\r
786 return -1; /* extra word */\r
787\r
788 case F_V_AD15X: /* 15b addr, indx */\r
789 fprintf (of, "%s %-o", fopcode[i], ad15);\r
790 if (xr4b >= 010)\r
791 fprintf (of, ",%o+", xr4b & 7);\r
792 else fprintf (of, ",%o", xr4b);\r
793 return -1; /* extra word */\r
794\r
795 case F_V_MR1D: /* 1 word direct */\r
796 ad15 = (fpp_bra + (3 * (wd1 & 0177))) & ADDRMASK;\r
797 fprintf (of, "%s %-o", fopcode[i], ad15);\r
798 break;\r
799\r
800 case F_V_LEMU:\r
801 case F_V_MR2D: /* 2 word direct */\r
802 fprintf (of, "%s %-o", fopcode[i], ad15);\r
803 if (xr4b >= 010)\r
804 fprintf (of, ",%o+", xr4b & 7);\r
805 else if (xr4b != 0)\r
806 fprintf (of, ",%o", xr4b);\r
807 return -1; /* extra word */\r
808\r
809 case F_V_LEMUI:\r
810 case F_V_MRI: /* indirect */\r
811 ad15 = (fpp_bra + (3 * xr3b)) & ADDRMASK;\r
812 fprintf (of, "%s %-o", fopcode[i], ad15);\r
813 if (xr4b >= 010)\r
814 fprintf (of, ",%o+", xr4b & 7);\r
815 else if (xr4b != 0)\r
816 fprintf (of, ",%o", xr4b);\r
817 break;\r
818\r
819 case F_V_MRD: /* encode only */\r
820 return SCPE_IERR;\r
821 }\r
822\r
823 return SCPE_OK;\r
824 } /* end if */\r
825 } /* end for */\r
826return SCPE_ARG;\r
827}\r
828\r
829/* FPP8 instruction parse */\r
830\r
831t_stat parse_sym_fpp (char *cptr, t_value *val)\r
832{\r
833uint32 i, j, ad, xr;\r
834int32 broff, nwd;\r
835char gbuf[CBUFSIZE];\r
836\r
837cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r
838for (i = 0; (fopcode[i] != NULL) && (strcmp (fopcode[i], gbuf) != 0) ; i++) ;\r
839if (fopcode[i] == NULL) return SCPE_ARG;\r
840val[0] = fop_val[i] & 07777; /* get value */\r
841j = (fop_val[i] >> F_V_FL) & F_M_FL; /* get class */\r
842xr = 0;\r
843nwd = 0;\r
844\r
845switch (j) { /* case on class */\r
846\r
847 case F_V_NOP12:\r
848 case F_V_NOP9:\r
849 case F_V_LTR: /* no operands */\r
850 break;\r
851\r
852 case F_V_X: /* 3b XR */\r
853 if ((cptr = parse_field (cptr, 07, &xr, 0)) == NULL)\r
854 return SCPE_ARG;\r
855 val[0] |= xr;\r
856 break;\r
857\r
858 case F_V_IMMX: /* 12b, XR */\r
859 if ((cptr = parse_field (cptr, 07777, &ad, ',')) == NULL)\r
860 return SCPE_ARG;\r
861 if ((*cptr == 0) ||\r
862 ((cptr = parse_fpp_xr (cptr, &xr, FALSE)) == NULL))\r
863 return SCPE_ARG;\r
864 val[0] |= xr;\r
865 val[++nwd] = ad;\r
866 break;\r
867\r
868 case F_V_AD15: /* 15b addr */\r
869 if ((cptr = parse_field (cptr, 077777, &ad, 0)) == NULL)\r
870 return SCPE_ARG;\r
871 val[0] |= (ad >> 12) & 07;\r
872 val[++nwd] = ad & 07777;\r
873 break;\r
874\r
875 case F_V_AD15X: /* 15b addr, idx */\r
876 if ((cptr = parse_field (cptr, 077777, &ad, ',')) == NULL)\r
877 return SCPE_ARG;\r
878 if ((*cptr == 0) ||\r
879 ((cptr = parse_fpp_xr (cptr, &xr, FALSE)) == NULL))\r
880 return SCPE_ARG;\r
881 val[0] |= ((xr << 3) | ((ad >> 12) & 07));\r
882 val[++nwd] = ad & 07777;\r
883 break;\r
884\r
885 case F_V_LEMUI:\r
886 case F_V_MRI: /* indirect */\r
887 if ((cptr = parse_field (cptr, 077777, &ad, ',')) == NULL)\r
888 return SCPE_ARG;\r
889 if ((*cptr != 0) &&\r
890 ((cptr = parse_fpp_xr (cptr, &xr, TRUE)) == NULL))\r
891 return SCPE_ARG;\r
892 if ((broff = test_fpp_addr (ad, 07)) < 0)\r
893 return SCPE_ARG;\r
894 val[0] |= ((xr << 3) | broff);\r
895 break;\r
896\r
897 case F_V_MRD: /* direct */\r
898 if ((cptr = parse_field (cptr, 077777, &ad, ',')) == NULL)\r
899 return SCPE_ARG;\r
900 if (((broff = test_fpp_addr (ad, 0177)) < 0) ||\r
901 (*cptr != 0)) {\r
902 if ((*cptr != 0) &&\r
903 ((cptr = parse_fpp_xr (cptr, &xr, TRUE)) == NULL))\r
904 return SCPE_ARG;\r
905 val[0] |= (00400 | (xr << 3) | ((ad >> 12) & 07));\r
906 val[++nwd] = ad & 07777;\r
907 }\r
908 else val[0] |= (00200 | broff);\r
909 break;\r
910\r
911 case F_V_LEMU:\r
912 if ((cptr = parse_field (cptr, 077777, &ad, ',')) == NULL)\r
913 return SCPE_ARG;\r
914 if ((*cptr != 0) &&\r
915 ((cptr = parse_fpp_xr (cptr, &xr, TRUE)) == NULL))\r
916 return SCPE_ARG;\r
917 val[0] |= ((xr << 3) | ((ad >> 12) & 07));\r
918 val[++nwd] = ad & 07777;\r
919 break;\r
920\r
921 case F_V_MR1D:\r
922 case F_V_MR2D:\r
923 return SCPE_IERR; \r
924 } /* end case */\r
925\r
926if (*cptr != 0) return SCPE_ARG; /* junk at end? */\r
927return -nwd;\r
928}\r
929\r
930/* Parse field */\r
931\r
932char *parse_field (char *cptr, uint32 max, uint32 *val, uint32 c)\r
933{\r
934char gbuf[CBUFSIZE];\r
935t_stat r;\r
936\r
937cptr = get_glyph (cptr, gbuf, c); /* get field */\r
938*val = get_uint (gbuf, 8, max, &r);\r
939if (r != SCPE_OK)\r
940 return NULL;\r
941return cptr;\r
942}\r
943\r
944/* Parse index register */\r
945\r
946char *parse_fpp_xr (char *cptr, uint32 *xr, t_bool inc)\r
947{\r
948char gbuf[CBUFSIZE];\r
949uint32 len;\r
950t_stat r;\r
951\r
952cptr = get_glyph (cptr, gbuf, 0); /* get field */\r
953len = strlen (gbuf);\r
954if (gbuf[len - 1] == '+') {\r
955 if (!inc)\r
956 return NULL;\r
957 gbuf[len - 1] = 0;\r
958 *xr = 010;\r
959 }\r
960else *xr = 0;\r
961*xr += get_uint (gbuf, 8, 7, &r);\r
962if (r != SCPE_OK)\r
963 return NULL;\r
964return cptr;\r
965}\r
966\r
967/* Test address in range of base register */\r
968\r
969int32 test_fpp_addr (uint32 ad, uint32 max)\r
970{\r
971uint32 off;\r
972extern uint32 fpp_bra;\r
973\r
974off = ad - fpp_bra;\r
975if (((off % 3) != 0) ||\r
976 (off > (max * 3)))\r
977 return -1;\r
978return ((int32) off / 3);\r
979}\r