First Commit of my working state
[simh.git] / PDP11 / pdp11_sys.c
CommitLineData
196ba1fc
PH
1/* pdp11_sys.c: PDP-11 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 15-May-08 RMS Added KE11-A, DC11 support\r
27 Renamed DL11\r
28 04-Feb-08 RMS Modified to allow -A, -B use with 8b devices\r
29 25-Jan-08 RMS Added RC11, KG11A support from John Dundas\r
30 10-Sep-07 RMS Cleaned up binary loader\r
31 20-Dec-06 RMS Added TA11 support\r
32 12-Nov-06 RMS Fixed operand order in EIS instructions (found by W.F.J. Mueller)\r
33 14-Jul-06 RMS Reordered device list\r
34 06-Jul-06 RMS Added multiple KL11/DL11 support\r
35 26-Jun-06 RMS Added RF11 support\r
36 17-May-06 RMS Added CR11/CD11 support (from John Dundas)\r
37 16-Aug-05 RMS Fixed C++ declaration and cast problems\r
38 22-Jul-05 RMS Fixed missing , in initializer (from Doug Gwyn)\r
39 22-Dec-03 RMS Added second DEUNA/DELUA support\r
40 18-Oct-03 RMS Added DECtape off reel message\r
41 06-May-03 RMS Added support for second DEQNA/DELQA\r
42 09-Jan-03 RMS Added DELUA/DEUNA support\r
43 17-Oct-02 RMS Fixed bugs in branch, SOB address parsing\r
44 09-Oct-02 RMS Added DELQA support\r
45 12-Sep-02 RMS Added TMSCP, KW11P, RX211 support, RAD50 examine\r
46 29-Nov-01 RMS Added read only unit support\r
47 17-Sep-01 RMS Removed multiconsole support\r
48 26-Aug-01 RMS Added DZ11\r
49 20-Aug-01 RMS Updated bad block inquiry\r
50 17-Jul-01 RMS Fixed warning from VC++ 6.0\r
51 27-May-01 RMS Added multiconsole support\r
52 05-Apr-01 RMS Added support for TS11/TSV05\r
53 14-Mar-01 RMS Revised load/dump interface (again)\r
54 11-Feb-01 RMS Added DECtape support\r
55 30-Oct-00 RMS Added support for examine to file\r
56 14-Apr-99 RMS Changed t_addr to unsigned\r
57 09-Nov-98 RMS Fixed assignments of ROR/ROL (John Wilson)\r
58 27-Oct-98 RMS V2.4 load interface\r
59 08-Oct-98 RMS Fixed bug in bad block routine\r
60 30-Mar-98 RMS Fixed bug in floating point display\r
61 12-Nov-97 RMS Added bad block table routine\r
62*/\r
63\r
64#include "pdp11_defs.h"\r
65#include <ctype.h>\r
66\r
67extern DEVICE cpu_dev;\r
68extern DEVICE sys_dev;\r
69extern DEVICE ptr_dev;\r
70extern DEVICE ptp_dev;\r
71extern DEVICE tti_dev;\r
72extern DEVICE tto_dev;\r
73extern DEVICE lpt_dev;\r
74extern DEVICE cr_dev;\r
75extern DEVICE clk_dev;\r
76extern DEVICE pclk_dev;\r
77extern DEVICE dli_dev;\r
78extern DEVICE dlo_dev;\r
79extern DEVICE dci_dev;\r
80extern DEVICE dco_dev;\r
81extern DEVICE dz_dev;\r
82extern DEVICE vh_dev;\r
83extern DEVICE dt_dev;\r
84extern DEVICE rc_dev;\r
85extern DEVICE rf_dev;\r
86extern DEVICE rk_dev;\r
87extern DEVICE rl_dev;\r
88extern DEVICE hk_dev;\r
89extern DEVICE rx_dev;\r
90extern DEVICE ry_dev;\r
91extern DEVICE mba_dev[];\r
92extern DEVICE rp_dev;\r
93extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;\r
94extern DEVICE tm_dev;\r
95extern DEVICE tq_dev;\r
96extern DEVICE ts_dev;\r
97extern DEVICE tu_dev;\r
98extern DEVICE ta_dev;\r
99extern DEVICE xq_dev, xqb_dev;\r
100extern DEVICE xu_dev, xub_dev;\r
101extern DEVICE ke_dev;\r
102extern DEVICE kg_dev;\r
103extern UNIT cpu_unit;\r
104extern REG cpu_reg[];\r
105extern uint16 *M;\r
106extern int32 saved_PC;\r
107\r
108/* SCP data structures and interface routines\r
109\r
110 sim_name simulator name string\r
111 sim_PC pointer to saved PC register descriptor\r
112 sim_emax number of words for examine\r
113 sim_devices array of pointers to simulated devices\r
114 sim_stop_messages array of pointers to stop messages\r
115 sim_load binary loader\r
116*/\r
117\r
118char sim_name[] = "PDP-11";\r
119\r
120REG *sim_PC = &cpu_reg[0];\r
121\r
122int32 sim_emax = 4;\r
123\r
124DEVICE *sim_devices[] = {\r
125 &cpu_dev,\r
126 &sys_dev,\r
127 &mba_dev[0],\r
128 &mba_dev[1],\r
129 &clk_dev,\r
130 &pclk_dev,\r
131 &ptr_dev,\r
132 &ptp_dev,\r
133 &tti_dev,\r
134 &tto_dev,\r
135 &cr_dev,\r
136 &lpt_dev,\r
137 &dli_dev,\r
138 &dlo_dev,\r
139 &dci_dev,\r
140 &dco_dev,\r
141 &dz_dev,\r
142 &vh_dev,\r
143 &rc_dev,\r
144 &rf_dev,\r
145 &rk_dev,\r
146 &rl_dev,\r
147 &hk_dev,\r
148 &rx_dev,\r
149 &ry_dev,\r
150 &rp_dev,\r
151 &rq_dev,\r
152 &rqb_dev,\r
153 &rqc_dev,\r
154 &rqd_dev,\r
155 &dt_dev,\r
156 &tm_dev,\r
157 &ts_dev,\r
158 &tq_dev,\r
159 &tu_dev,\r
160 &ta_dev,\r
161 &xq_dev,\r
162 &xqb_dev,\r
163 &xu_dev,\r
164 &xub_dev,\r
165 &ke_dev,\r
166 &kg_dev,\r
167 NULL\r
168 };\r
169\r
170const char *sim_stop_messages[] = {\r
171 "Unknown error",\r
172 "Red stack trap",\r
173 "Odd address trap",\r
174 "Memory management trap",\r
175 "Non-existent memory trap",\r
176 "Parity error trap",\r
177 "Privilege trap",\r
178 "Illegal instruction trap",\r
179 "BPT trap",\r
180 "IOT trap",\r
181 "EMT trap",\r
182 "TRAP trap",\r
183 "Trace trap",\r
184 "Yellow stack trap",\r
185 "Powerfail trap",\r
186 "Floating point exception",\r
187 "HALT instruction",\r
188 "Breakpoint",\r
189 "Wait state",\r
190 "Trap vector fetch abort",\r
191 "Trap stack push abort",\r
192 "RQDX3 consistency error",\r
193 "Sanity timer expired",\r
194 "DECtape off reel"\r
195 };\r
196\r
197/* Binary loader.\r
198\r
199 Loader format consists of blocks, optionally preceded, separated, and\r
200 followed by zeroes. Each block consists of:\r
201\r
202 001 ---\r
203 xxx |\r
204 lo_count |\r
205 hi_count |\r
206 lo_origin > count bytes\r
207 hi_origin |\r
208 data byte |\r
209 : |\r
210 data byte ---\r
211 checksum\r
212\r
213 If the byte count is exactly six, the block is the last on the tape, and\r
214 there is no checksum. If the origin is not 000001, then the origin is\r
215 the PC at which to start the program.\r
216*/\r
217\r
218t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)\r
219{\r
220int32 c[6], d, i, cnt, csum;\r
221uint32 org;\r
222\r
223if ((*cptr != 0) || (flag != 0))\r
224 return SCPE_ARG;\r
225do { /* block loop */\r
226 csum = 0; /* init checksum */\r
227 for (i = 0; i < 6; ) { /* 6 char header */\r
228 if ((c[i] = getc (fileref)) == EOF)\r
229 return SCPE_FMT;\r
230 if ((i != 0) || (c[i] == 1)) /* 1st must be 1 */\r
231 csum = csum + c[i++]; /* add into csum */\r
232 }\r
233 cnt = (c[3] << 8) | c[2]; /* count */\r
234 org = (c[5] << 8) | c[4]; /* origin */\r
235 if (cnt < 6) /* invalid? */\r
236 return SCPE_FMT;\r
237 if (cnt == 6) { /* end block? */\r
238 if (org != 1) /* set PC? */\r
239 saved_PC = org & 0177776;\r
240 return SCPE_OK;\r
241 }\r
242 for (i = 6; i < cnt; i++) { /* exclude hdr */\r
243 if ((d = getc (fileref)) == EOF) /* data char */\r
244 return SCPE_FMT;\r
245 csum = csum + d; /* add into csum */\r
246 if (org >= MEMSIZE) /* invalid addr? */\r
247 return SCPE_NXM;\r
248 M[org >> 1] = (org & 1)? /* store data */\r
249 (M[org >> 1] & 0377) | (d << 8):\r
250 (M[org >> 1] & 0177400) | d;\r
251 org = (org + 1) & 0177777; /* inc origin */\r
252 }\r
253 if ((d = getc (fileref)) == EOF) /* get csum */\r
254 return SCPE_FMT;\r
255 csum = csum + d; /* add in */\r
256 } while ((csum & 0377) == 0); /* result mbz */\r
257return SCPE_CSUM;\r
258}\r
259\r
260/* Factory bad block table creation routine\r
261\r
262 This routine writes a DEC standard 044 compliant bad block table on the\r
263 last track of the specified unit. The bad block table consists of 10\r
264 repetitions of the same table, formatted as follows:\r
265\r
266 words 0-1 pack id number\r
267 words 2-3 cylinder/sector/surface specifications\r
268 :\r
269 words n-n+1 end of table (-1,-1)\r
270\r
271 Inputs:\r
272 uptr = pointer to unit\r
273 sec = number of sectors per surface\r
274 wds = number of words per sector\r
275 Outputs:\r
276 sta = status code\r
277*/\r
278\r
279t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds)\r
280{\r
281int32 i, da;\r
282uint16 *buf;\r
283\r
284if ((sec < 2) || (wds < 16))\r
285 return SCPE_ARG;\r
286if ((uptr->flags & UNIT_ATT) == 0)\r
287 return SCPE_UNATT;\r
288if (uptr->flags & UNIT_RO)\r
289 return SCPE_RO;\r
290if (!get_yn ("Create bad block table on last track? [N]", FALSE))\r
291 return SCPE_OK;\r
292da = (uptr->capac - (sec * wds)) * sizeof (uint16);\r
293if (fseek (uptr->fileref, da, SEEK_SET))\r
294 return SCPE_IOERR;\r
295if ((buf = (uint16 *) malloc (wds * sizeof (uint16))) == NULL)\r
296 return SCPE_MEM;\r
297buf[0] = buf[1] = 012345u;\r
298buf[2] = buf[3] = 0;\r
299for (i = 4; i < wds; i++) buf[i] = 0177777u;\r
300for (i = 0; (i < sec) && (i < 10); i++)\r
301 fxwrite (buf, sizeof (uint16), wds, uptr->fileref);\r
302free (buf);\r
303if (ferror (uptr->fileref))\r
304 return SCPE_IOERR;\r
305return SCPE_OK;\r
306}\r
307\r
308/* Symbol tables */\r
309\r
310#define I_V_L 16 /* long mode */\r
311#define I_V_D 17 /* double mode */\r
312#define I_L (1 << I_V_L)\r
313#define I_D (1 << I_V_D)\r
314\r
315/* Warning: for literals, the class number MUST equal the field width!! */\r
316\r
317#define I_V_CL 18 /* class bits */\r
318#define I_M_CL 037 /* class mask */\r
319#define I_V_NPN 0 /* no operands */\r
320#define I_V_REG 1 /* reg */\r
321#define I_V_SOP 2 /* operand */\r
322#define I_V_3B 3 /* 3b literal */\r
323#define I_V_FOP 4 /* flt operand */\r
324#define I_V_AFOP 5 /* fac, flt operand */\r
325#define I_V_6B 6 /* 6b literal */\r
326#define I_V_BR 7 /* cond branch */\r
327#define I_V_8B 8 /* 8b literal */\r
328#define I_V_SOB 9 /* reg, disp */\r
329#define I_V_RSOP 10 /* reg, operand */\r
330#define I_V_ASOP 11 /* fac, operand */\r
331#define I_V_ASMD 12 /* fac, moded int op */\r
332#define I_V_DOP 13 /* double operand */\r
333#define I_V_CCC 14 /* CC clear */\r
334#define I_V_CCS 15 /* CC set */\r
335#define I_V_SOPR 16 /* operand, reg */\r
336#define I_NPN (I_V_NPN << I_V_CL)\r
337#define I_REG (I_V_REG << I_V_CL)\r
338#define I_3B (I_V_3B << I_V_CL)\r
339#define I_SOP (I_V_SOP << I_V_CL)\r
340#define I_FOP (I_V_FOP << I_V_CL)\r
341#define I_6B (I_V_6B << I_V_CL)\r
342#define I_BR (I_V_BR << I_V_CL)\r
343#define I_8B (I_V_8B << I_V_CL)\r
344#define I_AFOP (I_V_AFOP << I_V_CL)\r
345#define I_ASOP (I_V_ASOP << I_V_CL)\r
346#define I_RSOP (I_V_RSOP << I_V_CL)\r
347#define I_SOB (I_V_SOB << I_V_CL)\r
348#define I_ASMD (I_V_ASMD << I_V_CL)\r
349#define I_DOP (I_V_DOP << I_V_CL)\r
350#define I_CCC (I_V_CCC << I_V_CL)\r
351#define I_CCS (I_V_CCS << I_V_CL)\r
352#define I_SOPR (I_V_SOPR << I_V_CL)\r
353\r
354static const int32 masks[] = {\r
3550177777, 0177770, 0177700, 0177770,\r
3560177700+I_D, 0177400+I_D, 0177700, 0177400,\r
3570177400, 0177000, 0177000, 0177400,\r
3580177400+I_D+I_L, 0170000, 0177777, 0177777,\r
3590177000\r
360};\r
361\r
362static const char *opcode[] = {\r
363"HALT","WAIT","RTI","BPT",\r
364"IOT","RESET","RTT","MFPT",\r
365"JMP","RTS","SPL",\r
366"NOP","CLC","CLV","CLV CLC",\r
367"CLZ","CLZ CLC","CLZ CLV","CLZ CLV CLC",\r
368"CLN","CLN CLC","CLN CLV","CLN CLV CLC",\r
369"CLN CLZ","CLN CLZ CLC","CLN CLZ CLC","CCC",\r
370"NOP","SEC","SEV","SEV SEC",\r
371"SEZ","SEZ SEC","SEZ SEV","SEZ SEV SEC",\r
372"SEN","SEN SEC","SEN SEV","SEN SEV SEC",\r
373"SEN SEZ","SEN SEZ SEC","SEN SEZ SEC","SCC",\r
374"SWAB","BR","BNE","BEQ",\r
375"BGE","BLT","BGT","BLE",\r
376"JSR",\r
377"CLR","COM","INC","DEC",\r
378"NEG","ADC","SBC","TST",\r
379"ROR","ROL","ASR","ASL",\r
380"MARK","MFPI","MTPI","SXT",\r
381"CSM", "TSTSET","WRTLCK",\r
382"MOV","CMP","BIT","BIC",\r
383"BIS","ADD",\r
384"MUL","DIV","ASH","ASHC",\r
385"XOR", \r
386"FADD","FSUB","FMUL","FDIV",\r
387"L2DR",\r
388"MOVC","MOVRC","MOVTC",\r
389"LOCC","SKPC","SCANC","SPANC",\r
390"CMPC","MATC",\r
391"ADDN","SUBN","CMPN","CVTNL",\r
392"CVTPN","CVTNP","ASHN","CVTLN",\r
393"L3DR",\r
394"ADDP","SUBP","CMPP","CVTPL",\r
395"MULP","DIVP","ASHP","CVTLP",\r
396"MOVCI","MOVRCI","MOVTCI",\r
397"LOCCI","SKPCI","SCANCI","SPANCI",\r
398"CMPCI","MATCI",\r
399"ADDNI","SUBNI","CMPNI","CVTNLI",\r
400"CVTPNI","CVTNPI","ASHNI","CVTLNI",\r
401"ADDPI","SUBPI","CMPPI","CVTPLI",\r
402"MULPI","DIVPI","ASHPI","CVTLPI",\r
403"SOB",\r
404"BPL","BMI","BHI","BLOS",\r
405"BVC","BVS","BCC","BCS",\r
406"BHIS","BLO", /* encode only */\r
407"EMT","TRAP",\r
408"CLRB","COMB","INCB","DECB",\r
409"NEGB","ADCB","SBCB","TSTB",\r
410"RORB","ROLB","ASRB","ASLB",\r
411"MTPS","MFPD","MTPD","MFPS",\r
412"MOVB","CMPB","BITB","BICB",\r
413"BISB","SUB",\r
414"CFCC","SETF","SETI","SETD","SETL",\r
415"LDFPS","STFPS","STST",\r
416"CLRF","CLRD","TSTF","TSTD",\r
417"ABSF","ABSD","NEGF","NEGD",\r
418"MULF","MULD","MODF","MODD",\r
419"ADDF","ADDD","LDF","LDD",\r
420"SUBF","SUBD","CMPF","CMPD",\r
421"STF","STD","DIVF","DIVD",\r
422"STEXP",\r
423"STCFI","STCDI","STCFL","STCDL",\r
424"STCFD","STCDF",\r
425"LDEXP",\r
426"LDCIF","LDCID","LDCLF","LDCLD",\r
427"LDCFD","LDCDF",\r
428NULL\r
429};\r
430\r
431static const int32 opc_val[] = {\r
4320000000+I_NPN, 0000001+I_NPN, 0000002+I_NPN, 0000003+I_NPN,\r
4330000004+I_NPN, 0000005+I_NPN, 0000006+I_NPN, 0000007+I_NPN,\r
4340000100+I_SOP, 0000200+I_REG, 0000230+I_3B,\r
4350000240+I_CCC, 0000241+I_CCC, 0000242+I_CCC, 0000243+I_NPN, \r
4360000244+I_CCC, 0000245+I_NPN, 0000246+I_NPN, 0000247+I_NPN, \r
4370000250+I_CCC, 0000251+I_NPN, 0000252+I_NPN, 0000253+I_NPN, \r
4380000254+I_NPN, 0000255+I_NPN, 0000256+I_NPN, 0000257+I_CCC, \r
4390000260+I_CCS, 0000261+I_CCS, 0000262+I_CCS, 0000263+I_NPN, \r
4400000264+I_CCS, 0000265+I_NPN, 0000266+I_NPN, 0000267+I_NPN, \r
4410000270+I_CCS, 0000271+I_NPN, 0000272+I_NPN, 0000273+I_NPN, \r
4420000274+I_NPN, 0000275+I_NPN, 0000276+I_NPN, 0000277+I_CCS, \r
4430000300+I_SOP, 0000400+I_BR, 0001000+I_BR, 0001400+I_BR,\r
4440002000+I_BR, 0002400+I_BR, 0003000+I_BR, 0003400+I_BR,\r
4450004000+I_RSOP,\r
4460005000+I_SOP, 0005100+I_SOP, 0005200+I_SOP, 0005300+I_SOP,\r
4470005400+I_SOP, 0005500+I_SOP, 0005600+I_SOP, 0005700+I_SOP,\r
4480006000+I_SOP, 0006100+I_SOP, 0006200+I_SOP, 0006300+I_SOP,\r
4490006400+I_6B, 0006500+I_SOP, 0006600+I_SOP, 0006700+I_SOP,\r
4500007000+I_SOP, 0007200+I_SOP, 0007300+I_SOP,\r
4510010000+I_DOP, 0020000+I_DOP, 0030000+I_DOP, 0040000+I_DOP,\r
4520050000+I_DOP, 0060000+I_DOP,\r
4530070000+I_SOPR, 0071000+I_SOPR, 0072000+I_SOPR, 0073000+I_SOPR,\r
4540074000+I_RSOP,\r
4550075000+I_REG, 0075010+I_REG, 0075020+I_REG, 0075030+I_REG,\r
4560076020+I_REG,\r
4570076030+I_NPN, 0076031+I_NPN, 0076032+I_NPN,\r
4580076040+I_NPN, 0076041+I_NPN, 0076042+I_NPN, 0076043+I_NPN,\r
4590076044+I_NPN, 0076045+I_NPN, \r
4600076050+I_NPN, 0076051+I_NPN, 0076052+I_NPN, 0076053+I_NPN,\r
4610076054+I_NPN, 0076055+I_NPN, 0076056+I_NPN, 0076057+I_NPN,\r
4620076060+I_REG,\r
4630076070+I_NPN, 0076071+I_NPN, 0076072+I_NPN, 0076073+I_NPN,\r
4640076074+I_NPN, 0076075+I_NPN, 0076076+I_NPN, 0076077+I_NPN,\r
4650076130+I_NPN, 0076131+I_NPN, 0076132+I_NPN,\r
4660076140+I_NPN, 0076141+I_NPN, 0076142+I_NPN, 0076143+I_NPN,\r
4670076144+I_NPN, 0076145+I_NPN, \r
4680076150+I_NPN, 0076151+I_NPN, 0076152+I_NPN, 0076153+I_NPN,\r
4690076154+I_NPN, 0076155+I_NPN, 0076156+I_NPN, 0076157+I_NPN,\r
4700076170+I_NPN, 0076171+I_NPN, 0076172+I_NPN, 0076173+I_NPN,\r
4710076174+I_NPN, 0076175+I_NPN, 0076176+I_NPN, 0076177+I_NPN,\r
4720077000+I_SOB,\r
4730100000+I_BR, 0100400+I_BR, 0101000+I_BR, 0101400+I_BR,\r
4740102000+I_BR, 0102400+I_BR, 0103000+I_BR, 0103400+I_BR,\r
4750103000+I_BR, 0103400+I_BR,\r
4760104000+I_8B, 0104400+I_8B,\r
4770105000+I_SOP, 0105100+I_SOP, 0105200+I_SOP, 0105300+I_SOP,\r
4780105400+I_SOP, 0105500+I_SOP, 0105600+I_SOP, 0105700+I_SOP,\r
4790106000+I_SOP, 0106100+I_SOP, 0106200+I_SOP, 0106300+I_SOP,\r
4800106400+I_SOP, 0106500+I_SOP, 0106600+I_SOP, 0106700+I_SOP,\r
4810110000+I_DOP, 0120000+I_DOP, 0130000+I_DOP, 0140000+I_DOP,\r
4820150000+I_DOP, 0160000+I_DOP,\r
4830170000+I_NPN, 0170001+I_NPN, 0170002+I_NPN, 0170011+I_NPN, 0170012+I_NPN,\r
4840170100+I_SOP, 0170200+I_SOP, 0170300+I_SOP,\r
4850170400+I_FOP, 0170400+I_FOP+I_D, 0170500+I_FOP, 0170500+I_FOP+I_D,\r
4860170600+I_FOP, 0170600+I_FOP+I_D, 0170700+I_FOP, 0170700+I_FOP+I_D,\r
4870171000+I_AFOP, 0171000+I_AFOP+I_D, 0171400+I_AFOP, 0171400+I_AFOP+I_D,\r
4880172000+I_AFOP, 0172000+I_AFOP+I_D, 0172400+I_AFOP, 0172400+I_AFOP+I_D, \r
4890173000+I_AFOP, 0173000+I_AFOP+I_D, 0173400+I_AFOP, 0173400+I_AFOP+I_D,\r
4900174000+I_AFOP, 0174000+I_AFOP+I_D, 0174400+I_AFOP, 0174400+I_AFOP+I_D,\r
4910175000+I_ASOP,\r
4920175400+I_ASMD, 0175400+I_ASMD+I_D, 0175400+I_ASMD+I_L, 0175400+I_ASMD+I_D+I_L, \r
4930176000+I_AFOP, 0176000+I_AFOP+I_D,\r
4940176400+I_ASOP, \r
4950177000+I_ASMD, 0177000+I_ASMD+I_D, 0177000+I_ASMD+I_L, 0177000+I_ASMD+I_D+I_L, \r
4960177400+I_AFOP, 0177400+I_AFOP+I_D,\r
497-1\r
498};\r
499\r
500static const char *rname [] = {\r
501 "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC"\r
502 };\r
503\r
504static const char *fname [] = {\r
505 "F0", "F1", "F2", "F3", "F4", "F5", "?6", "?7"\r
506 };\r
507\r
508static const char r50_to_asc[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789";\r
509\r
510/* Specifier decode\r
511\r
512 Inputs:\r
513 *of = output stream\r
514 addr = current PC\r
515 spec = specifier\r
516 nval = next word\r
517 flag = TRUE if decoding for CPU\r
518 iflag = TRUE if decoding integer instruction\r
519 Outputs:\r
520 count = -number of extra words retired\r
521*/\r
522\r
523int32 fprint_spec (FILE *of, t_addr addr, int32 spec, t_value nval,\r
524 int32 flag, int32 iflag)\r
525{\r
526int32 reg, mode;\r
527static const int32 rgwd[8] = { 0, 0, 0, 0, 0, 0, -1, -1 };\r
528static const int32 pcwd[8] = { 0, 0, -1, -1, 0, 0, -1, -1 };\r
529\r
530reg = spec & 07;\r
531mode = ((spec >> 3) & 07);\r
532switch (mode) {\r
533\r
534 case 0:\r
535 if (iflag)\r
536 fprintf (of, "%s", rname[reg]);\r
537 else fprintf (of, "%s", fname[reg]);\r
538 break;\r
539\r
540 case 1:\r
541 fprintf (of, "(%s)", rname[reg]);\r
542 break;\r
543\r
544 case 2:\r
545 if (reg != 7)\r
546 fprintf (of, "(%s)+", rname[reg]);\r
547 else fprintf (of, "#%-o", nval);\r
548 break;\r
549\r
550 case 3:\r
551 if (reg != 7)\r
552 fprintf (of, "@(%s)+", rname[reg]);\r
553 else fprintf (of, "@#%-o", nval);\r
554 break;\r
555\r
556 case 4:\r
557 fprintf (of, "-(%s)", rname[reg]);\r
558 break;\r
559\r
560 case 5:\r
561 fprintf (of, "@-(%s)", rname[reg]);\r
562 break;\r
563\r
564 case 6:\r
565 if ((reg != 7) || !flag)\r
566 fprintf (of, "%-o(%s)", nval, rname[reg]);\r
567 else fprintf (of, "%-o", (nval + addr + 4) & 0177777);\r
568 break;\r
569\r
570 case 7:\r
571 if ((reg != 7) || !flag)\r
572 fprintf (of, "@%-o(%s)", nval, rname[reg]);\r
573 else fprintf (of, "@%-o", (nval + addr + 4) & 0177777);\r
574 break;\r
575 } /* end case */\r
576\r
577return ((reg == 07)? pcwd[mode]: rgwd[mode]);\r
578}\r
579\r
580/* Symbolic decode\r
581\r
582 Inputs:\r
583 *of = output stream\r
584 addr = current PC\r
585 *val = values to decode\r
586 *uptr = pointer to unit\r
587 sw = switches\r
588 Outputs:\r
589 return = if >= 0, error code\r
590 if < 0, number of extra words retired\r
591*/\r
592\r
593t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,\r
594 UNIT *uptr, int32 sw)\r
595{\r
596int32 cflag, i, j, c1, c2, c3, inst, fac, srcm, srcr, dstm, dstr;\r
597int32 bflag, l8b, brdisp, wd1, wd2;\r
598extern int32 FPS;\r
599\r
600bflag = 0; /* assume 16b */\r
601cflag = (uptr == NULL) || (uptr == &cpu_unit); /* cpu? */\r
602if (!cflag) { /* not cpu? */\r
603 DEVICE *dptr = find_dev_from_unit (uptr);\r
604 if (dptr == NULL)\r
605 return SCPE_IERR;\r
606 if (dptr->dwidth < 16)\r
607 bflag = 1;\r
608 }\r
609\r
610if (sw & SWMASK ('A')) { /* ASCII? */\r
611 if (bflag)\r
612 c1 = val[0] & 0177;\r
613 else c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0177;\r
614 fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);\r
615 return 0;\r
616 }\r
617if (sw & SWMASK ('B')) { /* byte? */\r
618 if (bflag)\r
619 c1 = val[0] & 0177;\r
620 else c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0377;\r
621 fprintf (of, "%o", c1);\r
622 return 0;\r
623 }\r
624if (bflag) return SCPE_ARG; /* 16b only */\r
625\r
626if (sw & SWMASK ('C')) { /* character? */\r
627 c1 = val[0] & 0177;\r
628 c2 = (val[0] >> 8) & 0177;\r
629 fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);\r
630 fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);\r
631 return -1;\r
632 }\r
633if (sw & SWMASK ('R')) { /* radix 50? */\r
634 if (val[0] > 0174777) return SCPE_ARG; /* max value */\r
635 c3 = val[0] % 050;\r
636 c2 = (val[0] / 050) % 050;\r
637 c1 = val[0] / (050 * 050);\r
638 fprintf (of, "%c%c%c", r50_to_asc[c1],\r
639 r50_to_asc[c2], r50_to_asc[c3]);\r
640 return -1;\r
641 }\r
642if (!(sw & SWMASK ('M'))) return SCPE_ARG;\r
643\r
644inst = val[0] | ((FPS << (I_V_L - FPS_V_L)) & I_L) |\r
645 ((FPS << (I_V_D - FPS_V_D)) & I_D); /* inst + fp mode */\r
646for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r
647 j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */\r
648 if ((opc_val[i] & 0777777) == (inst & masks[j])) { /* match? */\r
649 srcm = (inst >> 6) & 077; /* opr fields */\r
650 srcr = srcm & 07;\r
651 fac = srcm & 03;\r
652 dstm = inst & 077;\r
653 dstr = dstm & 07;\r
654 l8b = inst & 0377;\r
655 wd1 = wd2 = 0;\r
656 switch (j) { /* case on class */\r
657\r
658 case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */\r
659 fprintf (of, "%s", opcode[i]);\r
660 break;\r
661\r
662 case I_V_REG: /* reg */\r
663 fprintf (of, "%s %-s", opcode[i], rname[dstr]);\r
664 break;\r
665\r
666 case I_V_SOP: /* sop */\r
667 fprintf (of, "%s ", opcode[i]);\r
668 wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);\r
669 break;\r
670\r
671 case I_V_3B: /* 3b */\r
672 fprintf (of, "%s %-o", opcode[i], dstr);\r
673 break;\r
674\r
675 case I_V_FOP: /* fop */\r
676 fprintf (of, "%s ", opcode[i]);\r
677 wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE);\r
678 break;\r
679\r
680 case I_V_AFOP: /* afop */\r
681 fprintf (of, "%s %s,", opcode[i], fname[fac]);\r
682 wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE);\r
683 break;\r
684\r
685 case I_V_6B: /* 6b */\r
686 fprintf (of, "%s %-o", opcode[i], dstm);\r
687 break;\r
688\r
689 case I_V_BR: /* cond branch */\r
690 fprintf (of, "%s ", opcode[i]);\r
691 brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777;\r
692 if (cflag)\r
693 fprintf (of, "%-o", (addr + brdisp) & 0177777);\r
694 else if (brdisp < 01000)\r
695 fprintf (of, ".+%-o", brdisp);\r
696 else fprintf (of, ".-%-o", 0200000 - brdisp);\r
697 break;\r
698\r
699 case I_V_8B: /* 8b */\r
700 fprintf (of, "%s %-o", opcode[i], l8b);\r
701 break;\r
702\r
703 case I_V_SOB: /* sob */\r
704 fprintf (of, "%s %s,", opcode[i], rname[srcr]);\r
705 brdisp = (dstm * 2) - 2;\r
706 if (cflag)\r
707 fprintf (of, "%-o", (addr - brdisp) & 0177777);\r
708 else if (brdisp <= 0)\r
709 fprintf (of, ".+%-o", -brdisp);\r
710 else fprintf (of, ".-%-o", brdisp);\r
711 break;\r
712\r
713 case I_V_RSOP: /* rsop */\r
714 fprintf (of, "%s %s,", opcode[i], rname[srcr]);\r
715 wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);\r
716 break;\r
717\r
718 case I_V_SOPR: /* sopr */\r
719 fprintf (of, "%s ", opcode[i]);\r
720 wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);\r
721 fprintf (of, ",%s", rname[srcr]);\r
722 break;\r
723\r
724 case I_V_ASOP: case I_V_ASMD: /* asop, asmd */\r
725 fprintf (of, "%s %s,", opcode[i], fname[fac]);\r
726 wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);\r
727 break;\r
728\r
729 case I_V_DOP: /* dop */\r
730 fprintf (of, "%s ", opcode[i]);\r
731 wd1 = fprint_spec (of, addr, srcm, val[1], cflag, TRUE);\r
732 fprintf (of, ",");\r
733 wd2 = fprint_spec (of, addr - wd1 - wd1, dstm,\r
734 val[1 - wd1], cflag, TRUE);\r
735 break;\r
736 } /* end case */\r
737 return ((wd1 + wd2) * 2) - 1;\r
738 } /* end if */\r
739 } /* end for */\r
740return SCPE_ARG; /* no match */\r
741}\r
742\r
743#define A_PND 100 /* # seen */\r
744#define A_MIN 040 /* -( seen */\r
745#define A_PAR 020 /* (Rn) seen */\r
746#define A_REG 010 /* Rn seen */\r
747#define A_PLS 004 /* + seen */\r
748#define A_NUM 002 /* number seen */\r
749#define A_REL 001 /* relative addr seen */\r
750\r
751/* Register number\r
752\r
753 Inputs:\r
754 *cptr = pointer to input string\r
755 *strings = pointer to register names\r
756 mchar = character to match after register name\r
757 Outputs:\r
758 rnum = 0..7 if a legitimate register\r
759 < 0 if error\r
760*/\r
761\r
762int32 get_reg (char *cptr, const char *strings[], char mchar)\r
763{\r
764int32 i;\r
765\r
766if (*(cptr + 2) != mchar) return -1;\r
767for (i = 0; i < 8; i++) {\r
768 if (strncmp (cptr, strings[i], 2) == 0)\r
769 return i;\r
770 }\r
771return -1;\r
772}\r
773\r
774/* Number or memory address\r
775\r
776 Inputs:\r
777 *cptr = pointer to input string\r
778 *dptr = pointer to output displacement\r
779 *pflag = pointer to accumulating flags\r
780 Outputs:\r
781 cptr = pointer to next character in input string\r
782 NULL if parsing error\r
783\r
784 Flags: 0 (no result), A_NUM (number), A_REL (relative)\r
785*/\r
786\r
787char *get_addr (char *cptr, int32 *dptr, int32 *pflag)\r
788{\r
789int32 val, minus;\r
790char *tptr;\r
791\r
792minus = 0;\r
793\r
794if (*cptr == '.') { /* relative? */\r
795 *pflag = *pflag | A_REL;\r
796 cptr++;\r
797 }\r
798if (*cptr == '+') { /* +? */\r
799 *pflag = *pflag | A_NUM;\r
800 cptr++;\r
801 }\r
802if (*cptr == '-') { /* -? */\r
803 *pflag = *pflag | A_NUM;\r
804 minus = 1;\r
805 cptr++;\r
806 }\r
807errno = 0;\r
808val = strtoul (cptr, &tptr, 8);\r
809if (cptr == tptr) { /* no number? */\r
810 if (*pflag == (A_REL + A_NUM)) /* .+, .-? */\r
811 return NULL;\r
812 *dptr = 0;\r
813 return cptr;\r
814 }\r
815if (errno || (*pflag == A_REL)) /* .n? */\r
816 return NULL;\r
817*dptr = (minus? -val: val) & 0177777;\r
818*pflag = *pflag | A_NUM;\r
819return tptr;\r
820}\r
821\r
822/* Specifier decode\r
823\r
824 Inputs:\r
825 *cptr = pointer to input string\r
826 addr = current PC\r
827 n1 = 0 if no extra word used\r
828 -1 if extra word used in prior decode\r
829 *sptr = pointer to output specifier\r
830 *dptr = pointer to output displacement\r
831 cflag = true if parsing for the CPU\r
832 iflag = true if integer specifier\r
833 Outputs:\r
834 status = = -1 extra word decoded\r
835 = 0 ok\r
836 = +1 error\r
837*/\r
838\r
839t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr,\r
840 int32 cflag, int32 iflag)\r
841{\r
842int32 reg, indir, pflag, disp;\r
843\r
844indir = 0; /* no indirect */\r
845pflag = 0;\r
846\r
847if (*cptr == '@') { /* indirect? */\r
848 indir = 010;\r
849 cptr++;\r
850 }\r
851if (*cptr == '#') { /* literal? */\r
852 pflag = pflag | A_PND;\r
853 cptr++;\r
854 }\r
855if (strncmp (cptr, "-(", 2) == 0) { /* autodecrement? */\r
856 pflag = pflag | A_MIN;\r
857 cptr++;\r
858 }\r
859else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) return 1;\r
860if (*cptr == '(') { /* register index? */\r
861 pflag = pflag | A_PAR;\r
862 if ((reg = get_reg (cptr + 1, rname, ')')) < 0)\r
863 return 1;\r
864 cptr = cptr + 4;\r
865 if (*cptr == '+') { /* autoincrement? */\r
866 pflag = pflag | A_PLS;\r
867 cptr++;\r
868 }\r
869 }\r
870else if ((reg = get_reg (cptr, iflag? rname: fname, 0)) >= 0) {\r
871 pflag = pflag | A_REG;\r
872 cptr = cptr + 2;\r
873 }\r
874if (*cptr != 0) /* all done? */\r
875 return 1;\r
876switch (pflag) { /* case on syntax */\r
877\r
878 case A_REG: /* Rn, @Rn */\r
879 *sptr = indir + reg;\r
880 return 0;\r
881\r
882 case A_PAR: /* (Rn), @(Rn) */\r
883 if (indir) { /* @(Rn) = @0(Rn) */\r
884 *sptr = 070 + reg;\r
885 *dptr = 0;\r
886 return -1;\r
887 }\r
888 else *sptr = 010 + reg;\r
889 return 0;\r
890\r
891 case A_PAR+A_PLS: /* (Rn)+, @(Rn)+ */\r
892 *sptr = 020 + indir + reg;\r
893 return 0;\r
894\r
895 case A_MIN+A_PAR: /* -(Rn), @-(Rn) */\r
896 *sptr = 040 + indir + reg;\r
897 return 0;\r
898\r
899 case A_NUM+A_PAR: /* d(Rn), @d(Rn) */\r
900 *sptr = 060 + indir + reg;\r
901 *dptr = disp;\r
902 return -1;\r
903\r
904 case A_PND+A_REL: case A_PND+A_REL+A_NUM: /* #.+n, @#.+n */\r
905 if (!cflag)\r
906 return 1;\r
907 disp = (disp + addr) & 0177777; /* fall through */\r
908 case A_PND+A_NUM: /* #n, @#n */\r
909 *sptr = 027 + indir;\r
910 *dptr = disp;\r
911 return -1;\r
912\r
913 case A_REL: case A_REL+A_NUM: /* .+n, @.+n */\r
914 *sptr = 067 + indir;\r
915 *dptr = (disp - 4 + (2 * n1)) & 0177777;\r
916 return -1;\r
917\r
918 case A_NUM: /* n, @n */\r
919 if (cflag) { /* CPU - use rel */\r
920 *sptr = 067 + indir;\r
921 *dptr = (disp - addr - 4 + (2 * n1)) & 0177777;\r
922 }\r
923 else {\r
924 if (indir) return 1; /* other - use abs */\r
925 *sptr = 037;\r
926 *dptr = disp;\r
927 }\r
928 return -1;\r
929\r
930 default:\r
931 return 1;\r
932 } /* end case */\r
933}\r
934\r
935/* Symbolic input\r
936\r
937 Inputs:\r
938 *cptr = pointer to input string\r
939 addr = current PC\r
940 *uptr = pointer to unit\r
941 *val = pointer to output values\r
942 sw = switches\r
943 Outputs:\r
944 status = > 0 error code\r
945 <= 0 -number of extra words\r
946*/\r
947\r
948t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)\r
949{\r
950int32 bflag, cflag, d, i, j, reg, spec, n1, n2, disp, pflag;\r
951t_value by;\r
952t_stat r;\r
953char *tptr, gbuf[CBUFSIZE];\r
954\r
955bflag = 0; /* assume 16b */\r
956cflag = (uptr == NULL) || (uptr == &cpu_unit); /* cpu? */\r
957if (!cflag) { /* not cpu? */\r
958 DEVICE *dptr = find_dev_from_unit (uptr);\r
959 if (dptr == NULL)\r
960 return SCPE_IERR;\r
961 if (dptr->dwidth < 16)\r
962 bflag = 1;\r
963 }\r
964\r
965while (isspace (*cptr)) cptr++; /* absorb spaces */\r
966if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */\r
967 if (cptr[0] == 0) /* must have 1 char */\r
968 return SCPE_ARG;\r
969 if (bflag)\r
970 val[0] = (t_value) cptr[0];\r
971 else val[0] = (addr & 1)?\r
972 (val[0] & 0377) | (((t_value) cptr[0]) << 8):\r
973 (val[0] & ~0377) | ((t_value) cptr[0]);\r
974 return 0;\r
975 }\r
976if (sw & SWMASK ('B')) { /* byte? */\r
977 by = get_uint (cptr, 8, 0377, &r); /* get byte */\r
978 if (r != SCPE_OK)\r
979 return SCPE_ARG;\r
980 if (bflag)\r
981 val[0] = by;\r
982 else val[0] = (addr & 1)?\r
983 (val[0] & 0377) | (by << 8):\r
984 (val[0] & ~0377) | by;\r
985 return 0;\r
986 }\r
987if (bflag) return SCPE_ARG;\r
988\r
989if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */\r
990 if (cptr[0] == 0) /* must have 1 char */\r
991 return SCPE_ARG;\r
992 val[0] = ((t_value) cptr[1] << 8) | (t_value) cptr[0];\r
993 return -1;\r
994 }\r
995if (sw & SWMASK ('R')) /* radix 50 */\r
996 return SCPE_ARG;\r
997\r
998cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r
999n1 = n2 = pflag = 0;\r
1000for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r
1001if (opcode[i] == NULL)\r
1002 return SCPE_ARG;\r
1003val[0] = opc_val[i] & 0177777; /* get value */\r
1004j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */\r
1005\r
1006switch (j) { /* case on class */\r
1007\r
1008 case I_V_NPN: /* no operand */\r
1009 break;\r
1010\r
1011 case I_V_REG: /* register */\r
1012 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r
1013 if ((reg = get_reg (gbuf, rname, 0)) < 0)\r
1014 return SCPE_ARG;\r
1015 val[0] = val[0] | reg;\r
1016 break;\r
1017\r
1018 case I_V_3B: case I_V_6B: case I_V_8B: /* xb literal */\r
1019 cptr = get_glyph (cptr, gbuf, 0); /* get literal */\r
1020 d = get_uint (gbuf, 8, (1 << j) - 1, &r);\r
1021 if (r != SCPE_OK)\r
1022 return SCPE_ARG;\r
1023 val[0] = val[0] | d; /* put in place */\r
1024 break;\r
1025\r
1026 case I_V_BR: /* cond br */\r
1027 cptr = get_glyph (cptr, gbuf, 0); /* get address */\r
1028 tptr = get_addr (gbuf, &disp, &pflag); /* parse */\r
1029 if ((tptr == NULL) || (*tptr != 0))\r
1030 return SCPE_ARG;\r
1031 if ((pflag & A_REL) == 0) {\r
1032 if (cflag) disp = (disp - addr) & 0177777;\r
1033 else return SCPE_ARG;\r
1034 }\r
1035 if ((disp & 1) || (disp > 0400) && (disp < 0177402))\r
1036 return SCPE_ARG;\r
1037 val[0] = val[0] | (((disp - 2) >> 1) & 0377);\r
1038 break;\r
1039\r
1040 case I_V_SOB: /* sob */\r
1041 cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r
1042 if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;\r
1043 val[0] = val[0] | (reg << 6);\r
1044 cptr = get_glyph (cptr, gbuf, 0); /* get address */\r
1045 tptr = get_addr (gbuf, &disp, &pflag); /* parse */\r
1046 if ((tptr == NULL) || (*tptr != 0))\r
1047 return SCPE_ARG;\r
1048 if ((pflag & A_REL) == 0) {\r
1049 if (cflag) disp = (disp - addr) & 0177777;\r
1050 else return SCPE_ARG;\r
1051 }\r
1052 if ((disp & 1) || ((disp > 2) && (disp < 0177604)))\r
1053 return SCPE_ARG;\r
1054 val[0] = val[0] | (((2 - disp) >> 1) & 077);\r
1055 break;\r
1056\r
1057 case I_V_RSOP: /* reg, sop */\r
1058 cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r
1059 if ((reg = get_reg (gbuf, rname, 0)) < 0)\r
1060 return SCPE_ARG;\r
1061 val[0] = val[0] | (reg << 6); /* fall through */\r
1062 case I_V_SOP: /* sop */\r
1063 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r
1064 if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)\r
1065 return SCPE_ARG;\r
1066 val[0] = val[0] | spec;\r
1067 break;\r
1068\r
1069 case I_V_SOPR: /* dop, reg */\r
1070 cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r
1071 if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)\r
1072 return SCPE_ARG;\r
1073 val[0] = val[0] | spec;\r
1074 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r
1075 if ((reg = get_reg (gbuf, rname, 0)) < 0)\r
1076 return SCPE_ARG;\r
1077 val[0] = val[0] | (reg << 6);\r
1078 break;\r
1079\r
1080 case I_V_AFOP: case I_V_ASOP: case I_V_ASMD: /* fac, (s)fop */\r
1081 cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r
1082 if ((reg = get_reg (gbuf, fname, 0)) < 0)\r
1083 return SCPE_ARG;\r
1084 if (reg > 3)\r
1085 return SCPE_ARG;\r
1086 val[0] = val[0] | (reg << 6); /* fall through */\r
1087 case I_V_FOP: /* fop */\r
1088 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r
1089 if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, \r
1090 (j == I_V_ASOP) || (j == I_V_ASMD))) > 0)\r
1091 return SCPE_ARG;\r
1092 val[0] = val[0] | spec;\r
1093 break;\r
1094\r
1095 case I_V_DOP: /* double op */\r
1096 cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r
1097 if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)\r
1098 return SCPE_ARG;\r
1099 val[0] = val[0] | (spec << 6);\r
1100 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r
1101 if ((n2 = get_spec (gbuf, addr, n1, &spec, &val[1 - n1],\r
1102 cflag, TRUE)) > 0)\r
1103 return SCPE_ARG;\r
1104 val[0] = val[0] | spec;\r
1105 break;\r
1106\r
1107 case I_V_CCC: case I_V_CCS: /* cond code oper */\r
1108 for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;\r
1109 cptr = get_glyph (cptr, gbuf, 0)) {\r
1110 for (i = 0; (opcode[i] != NULL) &&\r
1111 (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r
1112 if ((((opc_val[i] >> I_V_CL) & I_M_CL) != j) ||\r
1113 (opcode[i] == NULL))\r
1114 return SCPE_ARG;\r
1115 val[0] = val[0] | (opc_val[i] & 0177777);\r
1116 }\r
1117 break;\r
1118\r
1119 default:\r
1120 return SCPE_ARG;\r
1121 }\r
1122\r
1123if (*cptr != 0) /* junk at end? */\r
1124 return SCPE_ARG;\r
1125return ((n1 + n2) * 2) - 1;\r
1126}\r