| 1 | /* pdp1_sys.c: PDP-1 simulator interface\r |
| 2 | \r |
| 3 | Copyright (c) 1993-2007, 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 | 03-Jan-07 RMS Fixed bugs in block loader, char input\r |
| 27 | 21-Dec-06 RMS Added 16-channel sequence break support, PDP-1D support\r |
| 28 | 06-Apr-04 RMS Fixed bug in binary loader (found by Mark Crispin)\r |
| 29 | 08-Feb-04 PLB Merged display support\r |
| 30 | 08-Dec-03 RMS Added parallel drum support, drum mnemonics\r |
| 31 | 18-Oct-03 RMS Added DECtape off reel message\r |
| 32 | 01-Sep-03 RMS Added support for loading in multiple fields\r |
| 33 | 22-Jul-03 RMS Updated for "hardware" RIM loader\r |
| 34 | 05-Dec-02 RMS Added drum support\r |
| 35 | 21-Nov-02 RMS Changed typewriter to half duplex\r |
| 36 | 20-Aug-02 RMS Added DECtape support\r |
| 37 | 17-Sep-01 RMS Removed multiconsole support\r |
| 38 | 13-Jul-01 RMS Fixed RIM loader format\r |
| 39 | 27-May-01 RMS Added multiconsole support\r |
| 40 | 14-Mar-01 RMS Revised load/dump interface (again)\r |
| 41 | 30-Oct-00 RMS Added support for examine to file\r |
| 42 | 27-Oct-98 RMS V2.4 load interface\r |
| 43 | 20-Oct-97 RMS Fixed endian-dependence in RIM loader\r |
| 44 | (found by Michael Somos)\r |
| 45 | */\r |
| 46 | \r |
| 47 | #include "pdp1_defs.h"\r |
| 48 | #include <ctype.h>\r |
| 49 | \r |
| 50 | extern DEVICE cpu_dev;\r |
| 51 | extern DEVICE clk_dev;\r |
| 52 | extern DEVICE ptr_dev;\r |
| 53 | extern DEVICE ptp_dev;\r |
| 54 | extern DEVICE tti_dev;\r |
| 55 | extern DEVICE tto_dev;\r |
| 56 | extern DEVICE lpt_dev;\r |
| 57 | extern DEVICE dt_dev;\r |
| 58 | extern DEVICE drm_dev;\r |
| 59 | extern DEVICE drp_dev;\r |
| 60 | extern DEVICE dcs_dev, dcsl_dev;\r |
| 61 | extern DEVICE dpy_dev;\r |
| 62 | extern UNIT cpu_unit;\r |
| 63 | extern REG cpu_reg[];\r |
| 64 | extern int32 M[];\r |
| 65 | extern int32 PC;\r |
| 66 | extern int32 ascii_to_fiodec[], fiodec_to_ascii[];\r |
| 67 | extern int32 sc_map[];\r |
| 68 | extern int32 sim_switches;\r |
| 69 | \r |
| 70 | /* SCP data structures and interface routines\r |
| 71 | \r |
| 72 | sim_name simulator name string\r |
| 73 | sim_PC pointer to saved PC register descriptor\r |
| 74 | sim_emax number of words for examine\r |
| 75 | sim_devices array of pointers to simulated devices\r |
| 76 | sim_stop_messages array of pointers to stop messages\r |
| 77 | sim_load binary loader\r |
| 78 | */\r |
| 79 | \r |
| 80 | char sim_name[] = "PDP-1";\r |
| 81 | \r |
| 82 | REG *sim_PC = &cpu_reg[0];\r |
| 83 | \r |
| 84 | int32 sim_emax = 1;\r |
| 85 | \r |
| 86 | DEVICE *sim_devices[] = {\r |
| 87 | &cpu_dev,\r |
| 88 | &clk_dev,\r |
| 89 | &ptr_dev,\r |
| 90 | &ptp_dev,\r |
| 91 | &tti_dev,\r |
| 92 | &tto_dev,\r |
| 93 | &lpt_dev,\r |
| 94 | &dt_dev,\r |
| 95 | &drm_dev,\r |
| 96 | &drp_dev,\r |
| 97 | &dcs_dev,\r |
| 98 | &dcsl_dev,\r |
| 99 | /* &dpy_dev, */\r |
| 100 | NULL\r |
| 101 | };\r |
| 102 | \r |
| 103 | const char *sim_stop_messages[] = {\r |
| 104 | "Unknown error",\r |
| 105 | "Undefined instruction",\r |
| 106 | "HALT instruction",\r |
| 107 | "Breakpoint",\r |
| 108 | "Nested XCT's",\r |
| 109 | "Nested indirect addresses",\r |
| 110 | "Infinite I/O wait state",\r |
| 111 | "DECtape off reel"\r |
| 112 | };\r |
| 113 | \r |
| 114 | /* Binary loader - supports both RIM format and Macro block format */\r |
| 115 | \r |
| 116 | int32 pdp1_getw (FILE *inf)\r |
| 117 | {\r |
| 118 | int32 i, tmp, word;\r |
| 119 | \r |
| 120 | word = 0;\r |
| 121 | for (i = 0; i < 3;) {\r |
| 122 | if ((tmp = getc (inf)) == EOF) return -1;\r |
| 123 | if (tmp & 0200) {\r |
| 124 | word = (word << 6) | (tmp & 077);\r |
| 125 | i++;\r |
| 126 | }\r |
| 127 | }\r |
| 128 | return word;\r |
| 129 | }\r |
| 130 | \r |
| 131 | t_stat rim_load (FILE *inf, int32 fld)\r |
| 132 | {\r |
| 133 | int32 origin, val;\r |
| 134 | \r |
| 135 | for (;;) {\r |
| 136 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r |
| 137 | if (((val & 0760000) == OP_DIO) || /* DIO? */\r |
| 138 | ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */\r |
| 139 | origin = val & DAMASK;\r |
| 140 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r |
| 141 | M[fld | origin] = val;\r |
| 142 | }\r |
| 143 | else if ((val & 0760000) == OP_JMP) { /* JMP? */\r |
| 144 | PC = fld | (val & DAMASK);\r |
| 145 | break;\r |
| 146 | }\r |
| 147 | else return SCPE_FMT; /* bad instr */\r |
| 148 | }\r |
| 149 | return SCPE_OK; /* done */\r |
| 150 | }\r |
| 151 | \r |
| 152 | t_stat blk_load (FILE *inf, int32 fld)\r |
| 153 | {\r |
| 154 | int32 val, start, count, csum;\r |
| 155 | \r |
| 156 | for (;;) {\r |
| 157 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; /* get word, EOF? */\r |
| 158 | if ((val & 0760000) == OP_DIO) { /* DIO? */\r |
| 159 | csum = val; /* init checksum */\r |
| 160 | start = val & DAMASK; /* starting addr */\r |
| 161 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r |
| 162 | if ((val & 0760000) != OP_DIO) return SCPE_FMT;\r |
| 163 | csum = csum + val;\r |
| 164 | if (csum > DMASK) csum = (csum + 1) & DMASK;\r |
| 165 | count = (val & DAMASK) - start; /* block count */\r |
| 166 | if (count <= 0) return SCPE_FMT;\r |
| 167 | while (count--) { /* loop on data */\r |
| 168 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r |
| 169 | csum = csum + val;\r |
| 170 | if (csum > DMASK) csum = (csum + 1) & DMASK;\r |
| 171 | M[fld | start] = val;\r |
| 172 | start = (start + 1) & DAMASK;\r |
| 173 | }\r |
| 174 | if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r |
| 175 | if (val != csum) return SCPE_CSUM;\r |
| 176 | }\r |
| 177 | else if ((val & 0760000) == OP_JMP) { /* JMP? */\r |
| 178 | PC = fld | (val & DAMASK);\r |
| 179 | break;\r |
| 180 | }\r |
| 181 | else return SCPE_FMT; /* bad instr */\r |
| 182 | }\r |
| 183 | return SCPE_OK; /* done */\r |
| 184 | }\r |
| 185 | \r |
| 186 | t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)\r |
| 187 | {\r |
| 188 | t_stat sta;\r |
| 189 | int32 fld;\r |
| 190 | \r |
| 191 | if (flag != 0) return SCPE_ARG;\r |
| 192 | if (cptr && (*cptr != 0)) {\r |
| 193 | fld = get_uint (cptr, 8, AMASK, &sta);\r |
| 194 | if (sta != SCPE_OK) return sta;\r |
| 195 | fld = fld & EPCMASK;\r |
| 196 | }\r |
| 197 | else fld = 0;\r |
| 198 | sta = rim_load (fileref, fld);\r |
| 199 | if (sta != SCPE_OK) return sta;\r |
| 200 | if ((sim_switches & SWMASK ('B')) || match_ext (fnam, "BIN"))\r |
| 201 | return blk_load (fileref, fld);\r |
| 202 | return SCPE_OK;\r |
| 203 | }\r |
| 204 | \r |
| 205 | /* Symbol tables */\r |
| 206 | \r |
| 207 | #define I_V_FL 18 /* inst class */\r |
| 208 | #define I_M_FL 017 /* class mask */\r |
| 209 | #define I_V_NPN 0 /* no operand */\r |
| 210 | #define I_V_IOT 1 /* IOT */\r |
| 211 | #define I_V_LAW 2 /* LAW */\r |
| 212 | #define I_V_MRF 3 /* memory reference */\r |
| 213 | #define I_V_MRI 4 /* mem ref no ind */\r |
| 214 | #define I_V_OPR 5 /* OPR */\r |
| 215 | #define I_V_SKP 6 /* skip */\r |
| 216 | #define I_V_SHF 7 /* shift */\r |
| 217 | #define I_V_SPC 8 /* special */\r |
| 218 | #define I_NPN (I_V_NPN << I_V_FL) /* no operand */\r |
| 219 | #define I_IOT (I_V_IOT << I_V_FL) /* IOT */\r |
| 220 | #define I_LAW (I_V_LAW << I_V_FL) /* LAW */\r |
| 221 | #define I_MRF (I_V_MRF << I_V_FL) /* memory reference */\r |
| 222 | #define I_MRI (I_V_MRI << I_V_FL) /* mem ref no ind */\r |
| 223 | #define I_OPR (I_V_OPR << I_V_FL) /* OPR */\r |
| 224 | #define I_SKP (I_V_SKP << I_V_FL) /* skip */\r |
| 225 | #define I_SHF (I_V_SHF << I_V_FL) /* shift */\r |
| 226 | #define I_SPC (I_V_SPC << I_V_FL)\r |
| 227 | \r |
| 228 | static const int32 masks[] = {\r |
| 229 | 0777777, 0760077, 0760000, 0760000,\r |
| 230 | 0770000, 0760017, 0760077, 0777000,\r |
| 231 | 0760003\r |
| 232 | };\r |
| 233 | \r |
| 234 | static const char *opcode[] = {\r |
| 235 | "AND", "IOR", "XOR", "XCT", /* mem refs */\r |
| 236 | "LAC", "LIO", "DAC", "DAP",\r |
| 237 | "DIP", "DIO", "DZM", "ADD",\r |
| 238 | "SUB", "IDX", "ISP", "SAD",\r |
| 239 | "SAS", "MUL", "DIV", "JMP",\r |
| 240 | "JSP", "LCH", "DCH", "TAD",\r |
| 241 | \r |
| 242 | "CAL", "JDA", /* mem ref no ind */\r |
| 243 | \r |
| 244 | "LAW",\r |
| 245 | \r |
| 246 | "IOH", "RPA", "RPB", "RRB", /* I/O instructions */\r |
| 247 | "PPA", "PPB", "TYO", "TYI",\r |
| 248 | "DPY",\r |
| 249 | "DSC", "ASC", "ISC", "CAC",\r |
| 250 | "LSM", "ESM", "CBS",\r |
| 251 | "LEM", "EEM", "CKS",\r |
| 252 | "MSE", "MLC", "MRD", "MWR", "MRS",\r |
| 253 | "DIA", "DBA", "DWC", "DRA", "DCL",\r |
| 254 | "DRD", "DWR", "DBL", "DCN",\r |
| 255 | "DTD", "DSE", "DSP",\r |
| 256 | "LRG", "ERG", "LRM", "ERM",\r |
| 257 | "RNM", "RSM", "RCK", "CTB",\r |
| 258 | "RCH", "RCC", "TCC", "TCB",\r |
| 259 | "RRC", "SSB", "RSC",\r |
| 260 | \r |
| 261 | "SKP", "SKP I", "CLO", /* base as NPNs */\r |
| 262 | "SFT", "SPC", "OPR",\r |
| 263 | \r |
| 264 | "RAL", "RIL", "RCL", /* shifts */\r |
| 265 | "SAL", "SIL", "SCL",\r |
| 266 | "RAR", "RIR", "RCR",\r |
| 267 | "SAR", "SIR", "SCR",\r |
| 268 | \r |
| 269 | "SZF1", "SZF2", "SZF3", /* skips */\r |
| 270 | "SZF4", "SZF5", "SZF6", "SZF7",\r |
| 271 | "SZS1", "SZS1 SZF1", "SZS1 SZF2", "SZS1 SZ3",\r |
| 272 | "SZS1 SZF4", "SZS1 SZF5", "SZS1 SZF6", "SZS1 SZF7",\r |
| 273 | "SZS2", "SZS2 SZF1", "SZS2 SZF2", "SZS2 SZ3",\r |
| 274 | "SZS2 SZF4", "SZS2 SZF5", "SZS2 SZF6", "SZS2 SZF7",\r |
| 275 | "SZS3", "SZS3 SZF1", "SZS3 SZF2", "SZS3 SZ3",\r |
| 276 | "SZS3 SZF4", "SZS3 SZF5", "SZS3 SZF6", "SZS3 SZF7",\r |
| 277 | "SZS4", "SZS4 SZF1", "SZS4 SZF2", "SZS4 SZ3",\r |
| 278 | "SZS4 SZF4", "SZS4 SZF5", "SZS4 SZF6", "SZS4 SZF7",\r |
| 279 | "SZS5", "SZS5 SZF1", "SZS5 SZF2", "SZS5 SZ3",\r |
| 280 | "SZS5 SZF4", "SZS5 SZF5", "SZS5 SZF6", "SZS5 SZF7",\r |
| 281 | "SZS6", "SZS6 SZF1", "SZS6 SZF2", "SZS6 SZ3",\r |
| 282 | "SZS6 SZF4", "SZS6 SZF5", "SZS6 SZF6", "SZS6 SZF7",\r |
| 283 | "SZS7", "SZS7 SZF1", "SZS7 SZF2", "SZS7 SZ3",\r |
| 284 | "SZS7 SZF4", "SZS7 SZF5", "SZS7 SZF6", "SZS7 SZF7",\r |
| 285 | \r |
| 286 | "CLF1", "CLF2", "CLF3", /* operates */\r |
| 287 | "CLF4", "CLF5", "CLF6", "CLF7",\r |
| 288 | "STF1", "STF2", "STF3",\r |
| 289 | "STF4", "STF5", "STF6", "STF7",\r |
| 290 | \r |
| 291 | "FF1", "FF2", "FF3", /* specials */\r |
| 292 | \r |
| 293 | "SZA", "SPA", "SMA", /* uprog skips */\r |
| 294 | "SZO", "SPI", "SNI",\r |
| 295 | "I", /* encode only */\r |
| 296 | \r |
| 297 | "LIA", "LAI", "SWP", /* uprog opers */\r |
| 298 | "LAP", "CLA", "HLT",\r |
| 299 | "CMA", "LAT", "CLI",\r |
| 300 | "CMI",\r |
| 301 | \r |
| 302 | "CML", "CLL", "SZL", /* uprog specials */\r |
| 303 | "SCF", "SCI", "SCM",\r |
| 304 | "IDA", "IDC", "IFI",\r |
| 305 | "IIF",\r |
| 306 | \r |
| 307 | NULL, NULL, NULL, /* decode only */\r |
| 308 | NULL,\r |
| 309 | };\r |
| 310 | \r |
| 311 | static const int32 opc_val[] = {\r |
| 312 | 0020000+I_MRF, 0040000+I_MRF, 0060000+I_MRF, 0100000+I_MRF,\r |
| 313 | 0200000+I_MRF, 0220000+I_MRF, 0240000+I_MRF, 0260000+I_MRF,\r |
| 314 | 0300000+I_MRF, 0320000+I_MRF, 0340000+I_MRF, 0400000+I_MRF,\r |
| 315 | 0420000+I_MRF, 0440000+I_MRF, 0460000+I_MRF, 0500000+I_MRF,\r |
| 316 | 0520000+I_MRF, 0540000+I_MRF, 0560000+I_MRF, 0600000+I_MRF,\r |
| 317 | 0620000+I_MRF, 0120000+I_MRF, 0140000+I_MRF, 0360000+I_MRF,\r |
| 318 | \r |
| 319 | 0160000+I_MRI, 0170000+I_MRI,\r |
| 320 | \r |
| 321 | 0700000+I_LAW,\r |
| 322 | \r |
| 323 | 0730000+I_NPN, 0720001+I_IOT, 0720002+I_IOT, 0720030+I_IOT,\r |
| 324 | 0720005+I_IOT, 0720006+I_IOT, 0720003+I_IOT, 0720004+I_IOT,\r |
| 325 | 0720007+I_IOT,\r |
| 326 | 0720050+I_IOT, 0720051+I_IOT, 0720052+I_IOT, 0720053+I_NPN,\r |
| 327 | 0720054+I_NPN, 0720055+I_NPN, 0720056+I_NPN,\r |
| 328 | 0720074+I_NPN, 0724074+I_NPN, 0720033+I_NPN,\r |
| 329 | 0720301+I_NPN, 0720401+I_NPN, 0720501+I_NPN, 0720601+I_NPN, 0720701+I_NPN, \r |
| 330 | 0720061+I_NPN, 0722061+I_NPN, 0720062+I_NPN, 0722062+I_NPN, 0720063+I_NPN,\r |
| 331 | 0720161+I_NPN, 0721161+I_NPN, 0720162+I_NPN, 0721162+I_NPN,\r |
| 332 | 0720163+I_NPN, 0720164+I_NPN, 0721164+I_NPN,\r |
| 333 | 0720010+I_NPN, 0720011+I_NPN, 0720064+I_NPN, 0720065+I_NPN,\r |
| 334 | 0720066+I_IOT, 0720067+I_NPN, 0720032+I_NPN, 0720035+I_NPN,\r |
| 335 | 0720022+I_NPN, 0721022+I_NPN, 0725022+I_NPN, 0724022+I_NPN,\r |
| 336 | 0720122+I_NPN, 0724122+I_NPN, 0721122+I_NPN,\r |
| 337 | \r |
| 338 | 0640000+I_NPN, 0650000+I_NPN, 0651600+I_NPN,\r |
| 339 | 0660000+I_NPN, 0740000+I_NPN, 0760000+I_NPN,\r |
| 340 | \r |
| 341 | 0661000+I_SHF, 0662000+I_SHF, 0663000+I_SHF,\r |
| 342 | 0665000+I_SHF, 0666000+I_SHF, 0667000+I_SHF,\r |
| 343 | 0671000+I_SHF, 0672000+I_SHF, 0673000+I_SHF,\r |
| 344 | 0675000+I_SHF, 0676000+I_SHF, 0677000+I_SHF,\r |
| 345 | \r |
| 346 | 0640001+I_SKP, 0640002+I_SKP, 0640003+I_SKP,\r |
| 347 | 0640004+I_SKP, 0640005+I_SKP, 0640006+I_SKP, 0640007+I_SKP,\r |
| 348 | 0640010+I_SKP, 0640011+I_SKP, 0640012+I_SKP, 0640013+I_SKP,\r |
| 349 | 0640014+I_SKP, 0640015+I_SKP, 0640016+I_SKP, 0640017+I_SKP,\r |
| 350 | 0640020+I_SKP, 0640021+I_SKP, 0640022+I_SKP, 0640023+I_SKP,\r |
| 351 | 0640024+I_SKP, 0640025+I_SKP, 0640026+I_SKP, 0640027+I_SKP,\r |
| 352 | 0640030+I_SKP, 0640031+I_SKP, 0640032+I_SKP, 0640033+I_SKP,\r |
| 353 | 0640034+I_SKP, 0640035+I_SKP, 0640036+I_SKP, 0640037+I_SKP,\r |
| 354 | 0640040+I_SKP, 0640041+I_SKP, 0640042+I_SKP, 0640043+I_SKP,\r |
| 355 | 0640044+I_SKP, 0640045+I_SKP, 0640046+I_SKP, 0640047+I_SKP,\r |
| 356 | 0640050+I_SKP, 0640051+I_SKP, 0640052+I_SKP, 0640053+I_SKP,\r |
| 357 | 0640054+I_SKP, 0640055+I_SKP, 0640056+I_SKP, 0640057+I_SKP,\r |
| 358 | 0640060+I_SKP, 0640061+I_SKP, 0640062+I_SKP, 0640063+I_SKP,\r |
| 359 | 0640064+I_SKP, 0640065+I_SKP, 0640066+I_SKP, 0640067+I_SKP,\r |
| 360 | 0640070+I_SKP, 0640071+I_SKP, 0640072+I_SKP, 0640073+I_SKP,\r |
| 361 | 0640074+I_SKP, 0640075+I_SKP, 0640076+I_SKP, 0640077+I_SKP,\r |
| 362 | \r |
| 363 | 0760001+I_OPR, 0760002+I_OPR, 0760003+I_OPR,\r |
| 364 | 0760004+I_OPR, 0760005+I_OPR, 0760006+I_OPR, 0760007+I_OPR,\r |
| 365 | 0760011+I_OPR, 0760012+I_OPR, 0760013+I_OPR,\r |
| 366 | 0760014+I_OPR, 0760015+I_OPR, 0760016+I_OPR, 0760017+I_OPR,\r |
| 367 | \r |
| 368 | 0740001+I_SPC, 0740002+I_SPC, 0740003+I_OPR,\r |
| 369 | \r |
| 370 | 0640100+I_SKP, 0640200+I_SKP, 0640400+I_SKP,\r |
| 371 | 0641000+I_SKP, 0642000+I_SKP, 0644000+I_SKP,\r |
| 372 | 0010000+I_SKP, /* encode only */\r |
| 373 | \r |
| 374 | 0760020+I_OPR, 0760040+I_OPR, 0760060+I_NPN,\r |
| 375 | 0760100+I_OPR, 0760200+I_OPR, 0760400+I_OPR,\r |
| 376 | 0761000+I_OPR, 0762000+I_OPR, 0764000+I_OPR,\r |
| 377 | 0770000+I_OPR,\r |
| 378 | \r |
| 379 | 0740004+I_SPC, 0740010+I_SPC, 0740020+I_SPC,\r |
| 380 | 0740040+I_SPC, 0740100+I_SPC, 0740200+I_SPC,\r |
| 381 | 0740400+I_SPC, 0741000+I_SPC, 0742000+I_SPC,\r |
| 382 | 0744000+I_SPC,\r |
| 383 | \r |
| 384 | 0640000+I_SKP, 0740000+I_SPC, 0760000+I_OPR, /* decode only */\r |
| 385 | -1\r |
| 386 | };\r |
| 387 | \r |
| 388 | /* Operate or skip decode\r |
| 389 | \r |
| 390 | Inputs:\r |
| 391 | *of = output stream\r |
| 392 | inst = mask bits\r |
| 393 | class = instruction class code\r |
| 394 | sp = space needed?\r |
| 395 | Outputs:\r |
| 396 | status = space needed?\r |
| 397 | */\r |
| 398 | \r |
| 399 | int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp)\r |
| 400 | {\r |
| 401 | int32 i, j;\r |
| 402 | \r |
| 403 | for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r |
| 404 | j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r |
| 405 | if ((j == class) && (opc_val[i] & inst)) { /* same class? */\r |
| 406 | inst = inst & ~opc_val[i]; /* mask bit set? */\r |
| 407 | fprintf (of, (sp? " %s": "%s"), opcode[i]);\r |
| 408 | sp = 1;\r |
| 409 | }\r |
| 410 | }\r |
| 411 | return sp;\r |
| 412 | }\r |
| 413 | \r |
| 414 | /* Symbolic decode\r |
| 415 | \r |
| 416 | Inputs:\r |
| 417 | *of = output stream\r |
| 418 | addr = current PC\r |
| 419 | *val = pointer to values\r |
| 420 | *uptr = pointer to unit\r |
| 421 | sw = switches\r |
| 422 | Outputs:\r |
| 423 | return = status code\r |
| 424 | */\r |
| 425 | \r |
| 426 | #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)\r |
| 427 | #define SIXTOASC(x) fiodec_to_ascii[x]\r |
| 428 | #define ASCTOSIX(x) (ascii_to_fiodec[x] & 077)\r |
| 429 | \r |
| 430 | t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,\r |
| 431 | UNIT *uptr, int32 sw)\r |
| 432 | {\r |
| 433 | int32 cflag, i, j, sp, inst, disp, ma;\r |
| 434 | \r |
| 435 | inst = val[0];\r |
| 436 | cflag = (uptr == NULL) || (uptr == &cpu_unit);\r |
| 437 | if (sw & SWMASK ('A')) { /* ASCII? */\r |
| 438 | if (inst > 0377) return SCPE_ARG;\r |
| 439 | fprintf (of, FMTASC (inst & 0177));\r |
| 440 | return SCPE_OK;\r |
| 441 | }\r |
| 442 | if (sw & SWMASK ('F')) {\r |
| 443 | fputc (fiodec_to_ascii[inst & 077], of);\r |
| 444 | return SCPE_OK;\r |
| 445 | }\r |
| 446 | if (sw & SWMASK ('C')) { /* character? */\r |
| 447 | fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077));\r |
| 448 | fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077));\r |
| 449 | fprintf (of, "%c", SIXTOASC (inst & 077));\r |
| 450 | return SCPE_OK;\r |
| 451 | }\r |
| 452 | if (!(sw & SWMASK ('M'))) return SCPE_ARG;\r |
| 453 | \r |
| 454 | /* Instruction decode */\r |
| 455 | \r |
| 456 | disp = inst & 007777;\r |
| 457 | ma = (addr & EPCMASK) | disp;\r |
| 458 | for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r |
| 459 | j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r |
| 460 | if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */\r |
| 461 | \r |
| 462 | switch (j) { /* case on class */\r |
| 463 | \r |
| 464 | case I_V_NPN: /* no operands */\r |
| 465 | fprintf (of, "%s", opcode[i]); /* opcode */\r |
| 466 | break;\r |
| 467 | \r |
| 468 | case I_V_IOT: /* IOT */\r |
| 469 | disp = (inst - opc_val[i]) & 017777;\r |
| 470 | if (disp == IA) fprintf (of, "%s I", opcode[i]);\r |
| 471 | else if (disp) fprintf (of, "%s %-o", opcode[i], disp);\r |
| 472 | else fprintf (of, "%s", opcode[i]);\r |
| 473 | break;\r |
| 474 | \r |
| 475 | case I_V_LAW: /* LAW */\r |
| 476 | cflag = 0; /* fall thru to MRF */\r |
| 477 | case I_V_MRF: /* mem ref */\r |
| 478 | fprintf (of, "%s%s%-o", opcode[i],\r |
| 479 | ((inst & IA)? " I ": " "), (cflag? ma: disp));\r |
| 480 | break;\r |
| 481 | \r |
| 482 | case I_V_MRI: /* mem ref no ind */\r |
| 483 | fprintf (of, "%s %-o", opcode[i], (cflag? ma: disp));\r |
| 484 | break;\r |
| 485 | \r |
| 486 | case I_V_OPR: /* operates */\r |
| 487 | sp = fprint_opr (of, inst & 017760, j, 0);\r |
| 488 | if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);\r |
| 489 | break;\r |
| 490 | \r |
| 491 | case I_V_SKP: /* skips */\r |
| 492 | sp = fprint_opr (of, inst & 007700, j, 0);\r |
| 493 | if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]);\r |
| 494 | if (inst & IA) fprintf (of, sp? " I": "I");\r |
| 495 | break;\r |
| 496 | \r |
| 497 | case I_V_SPC: /* specials */\r |
| 498 | sp = fprint_opr (of, inst & 007774, j, 0);\r |
| 499 | if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]);\r |
| 500 | if (inst & IA) fprintf (of, sp? " I": "I");\r |
| 501 | break;\r |
| 502 | \r |
| 503 | case I_V_SHF: /* shifts */\r |
| 504 | fprintf (of, "%s %-d", opcode[i], sc_map[inst & 0777]);\r |
| 505 | break;\r |
| 506 | } /* end case */\r |
| 507 | \r |
| 508 | return SCPE_OK;\r |
| 509 | } /* end if */\r |
| 510 | } /* end for */\r |
| 511 | return SCPE_ARG;\r |
| 512 | }\r |
| 513 | \r |
| 514 | /* Get 18b signed number\r |
| 515 | \r |
| 516 | Inputs:\r |
| 517 | *cptr = pointer to input string\r |
| 518 | *sign = pointer to sign\r |
| 519 | *status = pointer to error status\r |
| 520 | Outputs:\r |
| 521 | val = output value\r |
| 522 | */\r |
| 523 | \r |
| 524 | t_value get_sint (char *cptr, int32 *sign, t_stat *status)\r |
| 525 | {\r |
| 526 | *sign = 1;\r |
| 527 | if (*cptr == '+') {\r |
| 528 | *sign = 0;\r |
| 529 | cptr++;\r |
| 530 | }\r |
| 531 | else if (*cptr == '-') {\r |
| 532 | *sign = -1;\r |
| 533 | cptr++;\r |
| 534 | }\r |
| 535 | return get_uint (cptr, 8, DMASK, status);\r |
| 536 | }\r |
| 537 | \r |
| 538 | /* Symbolic input\r |
| 539 | \r |
| 540 | Inputs:\r |
| 541 | *cptr = pointer to input string\r |
| 542 | addr = current PC\r |
| 543 | uptr = pointer to unit\r |
| 544 | *val = pointer to output values\r |
| 545 | sw = switches\r |
| 546 | Outputs:\r |
| 547 | status = error status\r |
| 548 | */\r |
| 549 | \r |
| 550 | t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)\r |
| 551 | {\r |
| 552 | int32 cflag, d, i, j, k, sign;\r |
| 553 | t_stat r;\r |
| 554 | static int32 sc_enc[10] = { 0, 01, 03, 07, 017, 037, 077, 0177, 0377, 0777 };\r |
| 555 | char gbuf[CBUFSIZE];\r |
| 556 | \r |
| 557 | cflag = (uptr == NULL) || (uptr == &cpu_unit);\r |
| 558 | while (isspace (*cptr)) cptr++;\r |
| 559 | for (i = 1; (i < 3) && (cptr[i] != 0); i++)\r |
| 560 | if (cptr[i] == 0) for (j = i + 1; j <= 3; j++) cptr[j] = 0;\r |
| 561 | if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */\r |
| 562 | if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r |
| 563 | val[0] = (t_value) cptr[0];\r |
| 564 | return SCPE_OK;\r |
| 565 | }\r |
| 566 | if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */\r |
| 567 | if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r |
| 568 | val[0] = ((ASCTOSIX (cptr[0]) & 077) << 12) |\r |
| 569 | ((ASCTOSIX (cptr[1]) & 077) << 6) |\r |
| 570 | (ASCTOSIX (cptr[2]) & 077);\r |
| 571 | return SCPE_OK;\r |
| 572 | }\r |
| 573 | \r |
| 574 | cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r |
| 575 | for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r |
| 576 | if (opcode[i] == NULL) return SCPE_ARG;\r |
| 577 | val[0] = opc_val[i] & DMASK; /* get value */\r |
| 578 | j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r |
| 579 | \r |
| 580 | switch (j) { /* case on class */\r |
| 581 | \r |
| 582 | case I_V_LAW: /* LAW */\r |
| 583 | cflag = 0; /* fall through */\r |
| 584 | case I_V_MRF: case I_V_MRI: /* mem ref */\r |
| 585 | cptr = get_glyph (cptr, gbuf, 0); /* get next field */\r |
| 586 | if ((j != I_V_MRI) && strcmp (gbuf, "I") == 0) { /* indirect? */\r |
| 587 | val[0] = val[0] | IA;\r |
| 588 | cptr = get_glyph (cptr, gbuf, 0);\r |
| 589 | }\r |
| 590 | d = get_uint (gbuf, 8, AMASK, &r);\r |
| 591 | if (r != SCPE_OK) return SCPE_ARG;\r |
| 592 | if (d <= DAMASK) val[0] = val[0] | d;\r |
| 593 | else if (cflag && (((addr ^ d) & EPCMASK) == 0))\r |
| 594 | val[0] = val[0] | (d & DAMASK);\r |
| 595 | else return SCPE_ARG;\r |
| 596 | break;\r |
| 597 | \r |
| 598 | case I_V_SHF: /* shift */\r |
| 599 | cptr = get_glyph (cptr, gbuf, 0);\r |
| 600 | d = get_uint (gbuf, 10, 9, &r);\r |
| 601 | if (r != SCPE_OK) return SCPE_ARG;\r |
| 602 | val[0] = val[0] | sc_enc[d];\r |
| 603 | break;\r |
| 604 | \r |
| 605 | case I_V_NPN: case I_V_IOT:\r |
| 606 | case I_V_OPR: case I_V_SKP: case I_V_SPC:\r |
| 607 | for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;\r |
| 608 | cptr = get_glyph (cptr, gbuf, 0)) {\r |
| 609 | for (i = 0; (opcode[i] != NULL) &&\r |
| 610 | (strcmp (opcode[i], gbuf) != 0); i++) ;\r |
| 611 | if (opcode[i] != NULL) {\r |
| 612 | k = opc_val[i] & DMASK;\r |
| 613 | if ((k != IA) && (((k ^ val[0]) & 0760000) != 0))\r |
| 614 | return SCPE_ARG;\r |
| 615 | val[0] = val[0] | k;\r |
| 616 | }\r |
| 617 | else {\r |
| 618 | d = get_sint (gbuf, &sign, &r);\r |
| 619 | if (r != SCPE_OK) return SCPE_ARG;\r |
| 620 | if (sign == 0) val[0] = val[0] + d; \r |
| 621 | else if (sign < 0) val[0] = val[0] - d;\r |
| 622 | else val[0] = val[0] | d;\r |
| 623 | }\r |
| 624 | }\r |
| 625 | break;\r |
| 626 | } /* end case */\r |
| 627 | if (*cptr != 0) return SCPE_ARG; /* junk at end? */\r |
| 628 | return SCPE_OK;\r |
| 629 | }\r |