root/src/dps8/dps8_sys.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. print_default_base_system_script
  2. do_ini_line
  3. set_default_base_system
  4. boot_skip
  5. do_execute_fault
  6. do_restart
  7. set_sys_polling_interval
  8. set_sys_slow_polling_interval
  9. set_sys_poll_check_rate
  10. dps_debug_mme_cntdwn
  11. dps_debug_skip
  12. dps_debug_start
  13. dps_debug_stop
  14. dps_debug_break
  15. dps_debug_segno
  16. dps_debug_ringno
  17. dps_debug_bar
  18. abs_addr_n
  19. abs_addr
  20. lookup_book_segment
  21. add_book_segment
  22. add_book_component
  23. lookup_system_book_address
  24. lookup_address
  25. lookup_system_book_name
  26. list_source
  27. stack_trace
  28. list_source_at
  29. load_system_book
  30. add_system_book_entry
  31. lookup_system_book
  32. fetchSDW
  33. virtAddrN
  34. virt_address
  35. set_search_path
  36. brkbrk
  37. sbreak
  38. dfx1entry
  39. dfx1exit
  40. dv2scale
  41. dfx2entry
  42. mdfx3entry
  43. smfx1entry
  44. search_memory
  45. set_dbg_cpu_mask
  46. scraper
  47. clear_yield
  48. yield
  49. set_luf
  50. dbgevent_compar
  51. dbgevent_lookup
  52. set_dbgevent
  53. rewind_media
  54. load_media
  55. ready_media
  56. trkw
  57. trkr
  58. usr1_signal_handler
  59. systabInit
  60. hash32s
  61. dps8_init
  62. dps8_exit
  63. getAddress
  64. parse_addr
  65. fprint_addr
  66. fprint_sym
  67. parse_sym
  68. sys_show_config
  69. sys_set_break
  70. sys_show_break
  71. sys_set_config
  72. sys_reset
  73. dps8_init_strip

   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * SPDX-License-Identifier: Multics
   5  * scspell-id: ff1a12fc-f62e-11ec-aea6-80ee73e9b8e7
   6  *
   7  * ---------------------------------------------------------------------------
   8  *
   9  * Copyright (c) 2007-2013 Michael Mondy
  10  * Copyright (c) 2012-2016 Harry Reed
  11  * Copyright (c) 2013-2021 Charles Anthony
  12  * Copyright (c) 2016 Michal Tomek
  13  * Copyright (c) 2021-2023 Jeffrey H. Johnson
  14  * Copyright (c) 2021-2024 The DPS8M Development Team
  15  *
  16  * This software is made available under the terms of the ICU License.
  17  * See the LICENSE.md file at the top-level directory of this distribution.
  18  *
  19  * ---------------------------------------------------------------------------
  20  *
  21  * This source file may contain code comments that adapt, include, and/or
  22  * incorporate Multics program code and/or documentation distributed under
  23  * the Multics License.  In the event of any discrepancy between code
  24  * comments herein and the original Multics materials, the original Multics
  25  * materials should be considered authoritative unless otherwise noted.
  26  * For more details and historical background, see the LICENSE.md file at
  27  * the top-level directory of this distribution.
  28  *
  29  * ---------------------------------------------------------------------------
  30  */
  31 
  32 #include <stdio.h>
  33 #if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
  34 # include <signal.h>
  35 #endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
  36 #include <time.h>
  37 #include <stdint.h>
  38 #include <unistd.h>
  39 #include <ctype.h>
  40 
  41 #if defined(__APPLE__)
  42 # include <pthread.h>
  43 #endif /* if defined(__APPLE__) */
  44 
  45 #include "dps8.h"
  46 #include "dps8_sys.h"
  47 #include "dps8_iom.h"
  48 #include "dps8_console.h"
  49 #include "dps8_cable.h"
  50 #include "dps8_cpu.h"
  51 #include "dps8_faults.h"
  52 #include "dps8_scu.h"
  53 #include "dps8_state.h"
  54 #include "dps8_ins.h"
  55 #include "dps8_math.h"
  56 #include "dps8_mt.h"
  57 #include "dps8_socket_dev.h"
  58 #include "dps8_disk.h"
  59 #include "dps8_append.h"
  60 #include "dps8_fnp2.h"
  61 #include "dps8_crdrdr.h"
  62 #include "dps8_crdpun.h"
  63 #include "dps8_prt.h"
  64 #include "dps8_urp.h"
  65 #include "dps8_absi.h"
  66 #include "dps8_mgp.h"
  67 #include "dps8_utils.h"
  68 #include "shm.h"
  69 #include "ver.h"
  70 
  71 #if defined(THREADZ) || defined(LOCKLESS)
  72 # include "threadz.h"
  73 #endif /* if defined(THREADZ) || defined(LOCKLESS) */
  74 
  75 #include "panelScraper.h"
  76 
  77 #include "segldr.h"
  78 
  79 #define DBG_CTR cpu.cycleCnt
  80 
  81 #define ASSUME0 0
  82 
  83 #if defined(FREE)
  84 # undef FREE
  85 #endif /* if defined(FREE) */
  86 #define FREE(p) do  \
  87   {                 \
  88     free((p));      \
  89     (p) = NULL;     \
  90   } while(0)
  91 
  92 // Strictly speaking, memory belongs in the SCU.
  93 // We will treat memory as viewed from the CPU and elide the
  94 // SCU configuration that maps memory across multiple SCUs.
  95 // I would guess that multiple SCUs helped relieve memory
  96 // contention across multiple CPUs, but that is a level of
  97 // emulation that will be ignored.
  98 
  99 struct system_state_s * system_state;
 100 
 101 vol word36 * M = NULL;  //-V707   // memory
 102 
 103 //
 104 // These are part of the scp interface
 105 //
 106 
 107 char sim_name[] = "DPS8/M";
 108 int32 sim_emax = 4;  // some EIS can take up to 4-words
 109 static void dps8_init(void);
 110 static void dps8_exit (void);
 111 void (*sim_vm_init) (void) = & dps8_init;  // CustomCmds;
 112 void (*sim_vm_exit) (void) = & dps8_exit;  // CustomCmds;
 113 
 114 #if defined(TESTING)
 115 static t_addr parse_addr(DEVICE *dptr, const char *cptr, const char **optr);
 116 static void fprint_addr(FILE *stream, DEVICE *dptr, t_addr addr);
 117 #endif // TESTING
 118 
 119 int32 luf_flag = 1;
 120 
 121 ////////////////////////////////////////////////////////////////////////////////
 122 //
 123 // SCP Commands
 124 //
 125 
 126 //
 127 // System configuration commands
 128 //
 129 
 130 // Script to string cables and set switches
 131 
 132 #if !defined(PERF_STRIP)
 133 static char * default_base_system_script [] =
 134   {
 135     // ;
 136     // ; Configure test system
 137     // ;
 138     // ; CPU, IOM * 2, MPC, TAPE * 16, DISK * 16, SCU * 4, OPC * 2, FNP, URP * 3,
 139     // ; PRT, RDR, PUN
 140     // ;
 141     // ;
 142     // ; From AN70-1 System Initialization PLM May 84, pg 8-4:
 143     // ;
 144     // ; All CPUs and IOMs must share the same layout of port assignments to
 145     // ; SCUs. Thus, if memory port B of CPU C goes to SCU D, the memory port
 146     // ; B of all other CPUs and IOMs must go to SCU D. All CPUs and IOMs must
 147     // ; describe this SCU the same; all must agree in memory sizes. Also, all
 148     // ; SCUs must agree on port assignments of CPUs and IOMs. This, if port 3
 149     // ; of SCU C goes to CPU A, the port 3 of all other SCUs must also go to
 150     // ; CPU A.
 151     // ;
 152     // ; Pg. 8-6:
 153     // ;
 154     // ; The actual memory size of the memory attached to the SCU attached to
 155     // ; the processor port in questions is 32K * 2 ** (encoded memory size).
 156     // ; The port assignment couples with the memory size to determine the base
 157     // ; address of the SCU connected to the specified CPU port (absolute
 158     // ; address of the first location in the memory attached to that SCU). The
 159     // ; base address of the SCU is the (actual memory size) * (port assignment).
 160     // ;
 161     // ; Pg. 8-6
 162     // ;
 163     // ; [bits 09-11 lower store size]
 164     // ;
 165     // ; A DPS-8 SCU may have up to four store units attached to it. If this is
 166     // ; the case, two stores units form a pair of units. The size of a pair of
 167     // ; units (or a single unit) is 32K * 2 ** (lower store size) above.
 168     // ;
 169     // ;
 170     // ;
 171     // ; Looking at bootload_io, it would appear that Multics is happier with
 172     // ; IOM0 being the bootload IOM, despite suggestions elsewhere that was
 173     // ; not a requirement.
 174 
 175 //
 176 // IOM channel assignments
 177 //
 178 // IOM A
 179 //
 180 //  012 MTP0           tape drives
 181 //  013 IPC0 port 0    FIPS disk controller
 182 //  014 MSP0 port 0    disk controller
 183 //  015 URP0           card reader controller
 184 //  016 URP1           card punch controller
 185 //  017 URP2           printer controller
 186 //  020 FNPD           comm line controller
 187 //  021 FNPA           comm line controller
 188 //  022 FNPB           comm line controller
 189 //  023 FNPC           comm line controller
 190 //  024 FNPE           comm line controller
 191 //  025 FNPF           comm line controller
 192 //  026 FNPG           comm line controller
 193 //  027 FNPH           comm line controller
 194 //  032 ABSI0          IMP controller
 195 //  033 MGP0           MGP Read controller
 196 //  034 MGP1           MGP Write controller
 197 //  036 OPC0           operator console
 198 //  040 SKCA
 199 //  041 SKCB
 200 //  042 SKCC
 201 //  043 SKCD
 202 //  044 SKCE
 203 //  045 SKCF
 204 //  046 SKCG
 205 //  047 SKCH
 206 //
 207 // IOM B
 208 //
 209 //  013 IPC0 port 1    FIPS disk controller
 210 //  014 MSP0 port 1    disk controller
 211 
 212     // ; Disconnect everything...
 213     "CABLE_RIPOUT",
 214 
 215     "SET CPU NUNITS=6",
 216     "SET IOM NUNITS=2",
 217     // ; 16 drives plus a placeholder for the controller
 218     "SET TAPE NUNITS=17",
 219     "SET MTP NUNITS=1",
 220     // ; 4 3381 drives; 2 controllers
 221     // ; 4 d501 drives; 2 controller
 222     // ; 4 d451 drives; same controller has d501s
 223     // ; 2 d500 drives; same controller has d501s
 224     "SET IPC NUNITS=2",
 225     "SET MSP NUNITS=2",
 226     "SET DISK NUNITS=26",
 227     "SET SCU NUNITS=4",
 228     "SET OPC NUNITS=2",
 229     "SET FNP NUNITS=8",
 230     "SET URP NUNITS=10",
 231     "SET RDR NUNITS=3",
 232     "SET PUN NUNITS=3",
 233     "SET PRT NUNITS=4",
 234 # if defined (WITH_ABSI_DEV)
 235 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
 236     "SET ABSI NUNITS=1",
 237 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
 238 # endif /* if defined(WITH_ABSI_DEV) */
 239 
 240 # if defined(WITH_MGP_DEV)
 241 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
 242     "SET MGP NUNITS=2",
 243 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
 244 # endif /* if defined(WITH_MGP_DEV) */
 245 
 246 # if defined(WITH_SOCKET_DEV)
 247 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
 248     "SET SKC NUNITS=64",
 249 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
 250 # endif /* if defined(WITH_SOCKET_DEV) */
 251 
 252 // CPU0
 253 
 254     "SET CPU0 CONFIG=FAULTBASE=Multics",
 255 
 256     "SET CPU0 CONFIG=NUM=0",
 257     // ; As per GB61-01 Operators Guide, App. A
 258     // ; switches: 4, 6, 18, 19, 20, 23, 24, 25, 26, 28
 259     "SET CPU0 CONFIG=DATA=024000717200",
 260     "SET CPU0 CONFIG=ADDRESS=000000000000",
 261 
 262     // ; enable ports 0 and 1 (scu connections)
 263     // ; portconfig: ABCD
 264     // ;   each is 3 bits addr assignment
 265     // ;           1 bit enabled
 266     // ;           1 bit sysinit enabled
 267     // ;           1 bit interlace enabled (interlace?)
 268     // ;           3 bit memory size
 269     // ;              0 - 32K
 270     // ;              1 - 64K
 271     // ;              2 - 128K
 272     // ;              3 - 256K
 273     // ;              4 - 512K
 274     // ;              5 - 1M
 275     // ;              6 - 2M
 276     // ;              7 - 4M
 277 
 278     "SET CPU0 CONFIG=PORT=A",
 279     "SET CPU0   CONFIG=ASSIGNMENT=0",
 280     "SET CPU0   CONFIG=INTERLACE=0",
 281     "SET CPU0   CONFIG=ENABLE=1",
 282     "SET CPU0   CONFIG=INIT_ENABLE=1",
 283     "SET CPU0   CONFIG=STORE_SIZE=4M",
 284 
 285     "SET CPU0 CONFIG=PORT=B",
 286     "SET CPU0   CONFIG=ASSIGNMENT=1",
 287     "SET CPU0   CONFIG=INTERLACE=0",
 288     "SET CPU0   CONFIG=ENABLE=1",
 289     "SET CPU0   CONFIG=INIT_ENABLE=1",
 290     "SET CPU0   CONFIG=STORE_SIZE=4M",
 291 
 292     "SET CPU0 CONFIG=PORT=C",
 293     "SET CPU0   CONFIG=ASSIGNMENT=2",
 294     "SET CPU0   CONFIG=INTERLACE=0",
 295     "SET CPU0   CONFIG=ENABLE=1",
 296     "SET CPU0   CONFIG=INIT_ENABLE=1",
 297     "SET CPU0   CONFIG=STORE_SIZE=4M",
 298 
 299     "SET CPU0 CONFIG=PORT=D",
 300     "SET CPU0   CONFIG=ASSIGNMENT=3",
 301     "SET CPU0   CONFIG=INTERLACE=0",
 302     "SET CPU0   CONFIG=ENABLE=1",
 303     "SET CPU0   CONFIG=INIT_ENABLE=1",
 304     "SET CPU0   CONFIG=STORE_SIZE=4M",
 305 
 306     // ; 0 = GCOS 1 = VMS
 307     "SET CPU0 CONFIG=MODE=Multics",
 308 
 309     "SET CPU0 CONFIG=ENABLE_CACHE=enable",
 310     "SET CPU0 CONFIG=SDWAM=enable",
 311     "SET CPU0 CONFIG=PTWAM=enable",
 312 
 313     // ; 0 = 8/70
 314     "SET CPU0 CONFIG=SPEED=0",
 315 
 316     "SET CPU0 CONFIG=DIS_ENABLE=enable",
 317     "SET CPU0 CONFIG=STEADY_CLOCK=disable",
 318     "SET CPU0 CONFIG=HALT_ON_UNIMPLEMENTED=disable",
 319     "SET CPU0 CONFIG=ENABLE_WAM=disable",
 320     "SET CPU0 CONFIG=REPORT_FAULTS=disable",
 321     "SET CPU0 CONFIG=TRO_ENABLE=enable",
 322     "SET CPU0 CONFIG=Y2K=disable",
 323     "SET CPU0 CONFIG=DRL_FATAL=disable",
 324     "SET CPU0 CONFIG=USEMAP=disable",
 325     "SET CPU0 CONFIG=PROM_INSTALLED=enable",
 326     "SET CPU0 CONFIG=HEX_MODE_INSTALLED=disable",
 327     "SET CPU0 CONFIG=CACHE_INSTALLED=enable",
 328     "SET CPU0 CONFIG=CLOCK_SLAVE_INSTALLED=enable",
 329 
 330 // CPU1
 331 
 332     "SET CPU1 CONFIG=FAULTBASE=Multics",
 333 
 334     "SET CPU1 CONFIG=NUM=1",
 335     // ; As per GB61-01 Operators Guide, App. A
 336     // ; switches: 4, 6, 18, 19, 20, 23, 24, 25, 26, 28
 337     "SET CPU1 CONFIG=DATA=024000717200",
 338     "SET CPU1 CONFIG=ADDRESS=000000000000",
 339 
 340     // ; enable ports 0 and 1 (scu connections)
 341     // ; portconfig: ABCD
 342     // ;   each is 3 bits addr assignment
 343     // ;           1 bit enabled
 344     // ;           1 bit sysinit enabled
 345     // ;           1 bit interlace enabled (interlace?)
 346     // ;           3 bit memory size
 347     // ;              0 - 32K
 348     // ;              1 - 64K
 349     // ;              2 - 128K
 350     // ;              3 - 256K
 351     // ;              4 - 512K
 352     // ;              5 - 1M
 353     // ;              6 - 2M
 354     // ;              7 - 4M
 355 
 356     "SET CPU1 CONFIG=PORT=A",
 357     "SET CPU1   CONFIG=ASSIGNMENT=0",
 358     "SET CPU1   CONFIG=INTERLACE=0",
 359     "SET CPU1   CONFIG=ENABLE=1",
 360     "SET CPU1   CONFIG=INIT_ENABLE=1",
 361     "SET CPU1   CONFIG=STORE_SIZE=4M",
 362 
 363     "SET CPU1 CONFIG=PORT=B",
 364     "SET CPU1   CONFIG=ASSIGNMENT=1",
 365     "SET CPU1   CONFIG=INTERLACE=0",
 366     "SET CPU1   CONFIG=ENABLE=1",
 367     "SET CPU1   CONFIG=INIT_ENABLE=1",
 368     "SET CPU1   CONFIG=STORE_SIZE=4M",
 369 
 370     "SET CPU1 CONFIG=PORT=C",
 371     "SET CPU1   CONFIG=ASSIGNMENT=2",
 372     "SET CPU1   CONFIG=INTERLACE=0",
 373     "SET CPU1   CONFIG=ENABLE=1",
 374     "SET CPU1   CONFIG=INIT_ENABLE=1",
 375     "SET CPU1   CONFIG=STORE_SIZE=4M",
 376 
 377     "SET CPU1 CONFIG=PORT=D",
 378     "SET CPU1   CONFIG=ASSIGNMENT=3",
 379     "SET CPU1   CONFIG=INTERLACE=0",
 380     "SET CPU1   CONFIG=ENABLE=1",
 381     "SET CPU1   CONFIG=INIT_ENABLE=1",
 382     "SET CPU1   CONFIG=STORE_SIZE=4M",
 383 
 384     // ; 0 = GCOS 1 = VMS
 385     "SET CPU1 CONFIG=MODE=Multics",
 386 
 387     "SET CPU1 CONFIG=ENABLE_CACHE=enable",
 388     "SET CPU1 CONFIG=SDWAM=enable",
 389     "SET CPU1 CONFIG=PTWAM=enable",
 390 
 391     // ; 0 = 8/70
 392     "SET CPU1 CONFIG=SPEED=0",
 393 
 394     "SET CPU1 CONFIG=DIS_ENABLE=enable",
 395     "SET CPU1 CONFIG=STEADY_CLOCK=disable",
 396     "SET CPU1 CONFIG=HALT_ON_UNIMPLEMENTED=disable",
 397     "SET CPU1 CONFIG=ENABLE_WAM=disable",
 398     "SET CPU1 CONFIG=REPORT_FAULTS=disable",
 399     "SET CPU1 CONFIG=TRO_ENABLE=enable",
 400     "SET CPU1 CONFIG=Y2K=disable",
 401     "SET CPU1 CONFIG=DRL_FATAL=disable",
 402     "SET CPU1 CONFIG=USEMAP=disable",
 403     "SET CPU1 CONFIG=PROM_INSTALLED=enable",
 404     "SET CPU1 CONFIG=HEX_MODE_INSTALLED=disable",
 405     "SET CPU1 CONFIG=CACHE_INSTALLED=enable",
 406     "SET CPU1 CONFIG=CLOCK_SLAVE_INSTALLED=enable",
 407 
 408 // CPU2
 409 
 410     "SET CPU2 CONFIG=FAULTBASE=Multics",
 411 
 412     "SET CPU2 CONFIG=NUM=2",
 413     // ; As per GB61-01 Operators Guide, App. A
 414     // ; switches: 4, 6, 18, 19, 20, 23, 24, 25, 26, 28
 415     "SET CPU2 CONFIG=DATA=024000717200",
 416     "SET CPU2 CONFIG=ADDRESS=000000000000",
 417 
 418     // ; enable ports 0 and 1 (scu connections)
 419     // ; portconfig: ABCD
 420     // ;   each is 3 bits addr assignment
 421     // ;           1 bit enabled
 422     // ;           1 bit sysinit enabled
 423     // ;           1 bit interlace enabled (interlace?)
 424     // ;           3 bit memory size
 425     // ;              0 - 32K
 426     // ;              1 - 64K
 427     // ;              2 - 128K
 428     // ;              3 - 256K
 429     // ;              4 - 512K
 430     // ;              5 - 1M
 431     // ;              6 - 2M
 432     // ;              7 - 4M
 433 
 434     "SET CPU2 CONFIG=PORT=A",
 435     "SET CPU2   CONFIG=ASSIGNMENT=0",
 436     "SET CPU2   CONFIG=INTERLACE=0",
 437     "SET CPU2   CONFIG=ENABLE=1",
 438     "SET CPU2   CONFIG=INIT_ENABLE=1",
 439     "SET CPU2   CONFIG=STORE_SIZE=4M",
 440 
 441     "SET CPU2 CONFIG=PORT=B",
 442     "SET CPU2   CONFIG=ASSIGNMENT=1",
 443     "SET CPU2   CONFIG=INTERLACE=0",
 444     "SET CPU2   CONFIG=ENABLE=1",
 445     "SET CPU2   CONFIG=INIT_ENABLE=1",
 446     "SET CPU2   CONFIG=STORE_SIZE=4M",
 447 
 448     "SET CPU2 CONFIG=PORT=C",
 449     "SET CPU2   CONFIG=ASSIGNMENT=2",
 450     "SET CPU2   CONFIG=INTERLACE=0",
 451     "SET CPU2   CONFIG=ENABLE=1",
 452     "SET CPU2   CONFIG=INIT_ENABLE=1",
 453     "SET CPU2   CONFIG=STORE_SIZE=4M",
 454 
 455     "SET CPU2 CONFIG=PORT=D",
 456     "SET CPU2   CONFIG=ASSIGNMENT=3",
 457     "SET CPU2   CONFIG=INTERLACE=0",
 458     "SET CPU2   CONFIG=ENABLE=1",
 459     "SET CPU2   CONFIG=INIT_ENABLE=1",
 460     "SET CPU2   CONFIG=STORE_SIZE=4M",
 461 
 462     // ; 0 = GCOS 1 = VMS
 463     "SET CPU2 CONFIG=MODE=Multics",
 464 
 465     "SET CPU2 CONFIG=ENABLE_CACHE=enable",
 466     "SET CPU2 CONFIG=SDWAM=enable",
 467     "SET CPU2 CONFIG=PTWAM=enable",
 468 
 469     // ; 0 = 8/70
 470     "SET CPU2 CONFIG=SPEED=0",
 471 
 472     "SET CPU2 CONFIG=DIS_ENABLE=enable",
 473     "SET CPU2 CONFIG=STEADY_CLOCK=disable",
 474     "SET CPU2 CONFIG=HALT_ON_UNIMPLEMENTED=disable",
 475     "SET CPU2 CONFIG=ENABLE_WAM=disable",
 476     "SET CPU2 CONFIG=REPORT_FAULTS=disable",
 477     "SET CPU2 CONFIG=TRO_ENABLE=enable",
 478     "SET CPU2 CONFIG=Y2K=disable",
 479     "SET CPU2 CONFIG=DRL_FATAL=disable",
 480     "SET CPU2 CONFIG=USEMAP=disable",
 481     "SET CPU2 CONFIG=PROM_INSTALLED=enable",
 482     "SET CPU2 CONFIG=HEX_MODE_INSTALLED=disable",
 483     "SET CPU2 CONFIG=CACHE_INSTALLED=enable",
 484     "SET CPU2 CONFIG=CLOCK_SLAVE_INSTALLED=enable",
 485 
 486 // CPU3
 487 
 488     "SET CPU3 CONFIG=FAULTBASE=Multics",
 489 
 490     "SET CPU3 CONFIG=NUM=3",
 491     // ; As per GB61-01 Operators Guide, App. A
 492     // ; switches: 4, 6, 18, 19, 20, 23, 24, 25, 26, 28
 493     "SET CPU3 CONFIG=DATA=024000717200",
 494     "SET CPU3 CONFIG=ADDRESS=000000000000",
 495 
 496     // ; enable ports 0 and 1 (scu connections)
 497     // ; portconfig: ABCD
 498     // ;   each is 3 bits addr assignment
 499     // ;           1 bit enabled
 500     // ;           1 bit sysinit enabled
 501     // ;           1 bit interlace enabled (interlace?)
 502     // ;           3 bit memory size
 503     // ;              0 - 32K
 504     // ;              1 - 64K
 505     // ;              2 - 128K
 506     // ;              3 - 256K
 507     // ;              4 - 512K
 508     // ;              5 - 1M
 509     // ;              6 - 2M
 510     // ;              7 - 4M
 511 
 512     "SET CPU3 CONFIG=PORT=A",
 513     "SET CPU3   CONFIG=ASSIGNMENT=0",
 514     "SET CPU3   CONFIG=INTERLACE=0",
 515     "SET CPU3   CONFIG=ENABLE=1",
 516     "SET CPU3   CONFIG=INIT_ENABLE=1",
 517     "SET CPU3   CONFIG=STORE_SIZE=4M",
 518 
 519     "SET CPU3 CONFIG=PORT=B",
 520     "SET CPU3   CONFIG=ASSIGNMENT=1",
 521     "SET CPU3   CONFIG=INTERLACE=0",
 522     "SET CPU3   CONFIG=ENABLE=1",
 523     "SET CPU3   CONFIG=INIT_ENABLE=1",
 524     "SET CPU3   CONFIG=STORE_SIZE=4M",
 525 
 526     "SET CPU3 CONFIG=PORT=C",
 527     "SET CPU3   CONFIG=ASSIGNMENT=2",
 528     "SET CPU3   CONFIG=INTERLACE=0",
 529     "SET CPU3   CONFIG=ENABLE=1",
 530     "SET CPU3   CONFIG=INIT_ENABLE=1",
 531     "SET CPU3   CONFIG=STORE_SIZE=4M",
 532 
 533     "SET CPU3 CONFIG=PORT=D",
 534     "SET CPU3   CONFIG=ASSIGNMENT=3",
 535     "SET CPU3   CONFIG=INTERLACE=0",
 536     "SET CPU3   CONFIG=ENABLE=1",
 537     "SET CPU3   CONFIG=INIT_ENABLE=1",
 538     "SET CPU3   CONFIG=STORE_SIZE=4M",
 539 
 540     // ; 0 = GCOS 1 = VMS
 541     "SET CPU3 CONFIG=MODE=Multics",
 542 
 543     "SET CPU3 CONFIG=ENABLE_CACHE=enable",
 544     "SET CPU3 CONFIG=SDWAM=enable",
 545     "SET CPU3 CONFIG=PTWAM=enable",
 546 
 547     // ; 0 = 8/70
 548     "SET CPU3 CONFIG=SPEED=0",
 549 
 550     "SET CPU3 CONFIG=DIS_ENABLE=enable",
 551     "SET CPU3 CONFIG=STEADY_CLOCK=disable",
 552     "SET CPU3 CONFIG=HALT_ON_UNIMPLEMENTED=disable",
 553     "SET CPU3 CONFIG=ENABLE_WAM=disable",
 554     "SET CPU3 CONFIG=REPORT_FAULTS=disable",
 555     "SET CPU3 CONFIG=TRO_ENABLE=enable",
 556     "SET CPU3 CONFIG=Y2K=disable",
 557     "SET CPU3 CONFIG=DRL_FATAL=disable",
 558     "SET CPU3 CONFIG=USEMAP=disable",
 559     "SET CPU3 CONFIG=PROM_INSTALLED=enable",
 560     "SET CPU3 CONFIG=HEX_MODE_INSTALLED=disable",
 561     "SET CPU3 CONFIG=CACHE_INSTALLED=enable",
 562     "SET CPU3 CONFIG=CLOCK_SLAVE_INSTALLED=enable",
 563 
 564 // CPU4
 565 
 566     "SET CPU4 CONFIG=FAULTBASE=Multics",
 567 
 568     "SET CPU4 CONFIG=NUM=4",
 569     // ; As per GB61-01 Operators Guide, App. A
 570     // ; switches: 4, 6, 18, 19, 20, 23, 24, 25, 26, 28
 571     "SET CPU4 CONFIG=DATA=024000717200",
 572     "SET CPU4 CONFIG=ADDRESS=000000000000",
 573 
 574     // ; enable ports 0 and 1 (scu connections)
 575     // ; portconfig: ABCD
 576     // ;   each is 3 bits addr assignment
 577     // ;           1 bit enabled
 578     // ;           1 bit sysinit enabled
 579     // ;           1 bit interlace enabled (interlace?)
 580     // ;           3 bit memory size
 581     // ;              0 - 32K
 582     // ;              1 - 64K
 583     // ;              2 - 128K
 584     // ;              3 - 256K
 585     // ;              4 - 512K
 586     // ;              5 - 1M
 587     // ;              6 - 2M
 588     // ;              7 - 4M
 589 
 590     "SET CPU4 CONFIG=PORT=A",
 591     "SET CPU4   CONFIG=ASSIGNMENT=0",
 592     "SET CPU4   CONFIG=INTERLACE=0",
 593     "SET CPU4   CONFIG=ENABLE=1",
 594     "SET CPU4   CONFIG=INIT_ENABLE=1",
 595     "SET CPU4   CONFIG=STORE_SIZE=4M",
 596 
 597     "SET CPU4 CONFIG=PORT=B",
 598     "SET CPU4   CONFIG=ASSIGNMENT=1",
 599     "SET CPU4   CONFIG=INTERLACE=0",
 600     "SET CPU4   CONFIG=ENABLE=1",
 601     "SET CPU4   CONFIG=INIT_ENABLE=1",
 602     "SET CPU4   CONFIG=STORE_SIZE=4M",
 603 
 604     "SET CPU4 CONFIG=PORT=C",
 605     "SET CPU4   CONFIG=ASSIGNMENT=2",
 606     "SET CPU4   CONFIG=INTERLACE=0",
 607     "SET CPU4   CONFIG=ENABLE=1",
 608     "SET CPU4   CONFIG=INIT_ENABLE=1",
 609     "SET CPU4   CONFIG=STORE_SIZE=4M",
 610 
 611     "SET CPU4 CONFIG=PORT=D",
 612     "SET CPU4   CONFIG=ASSIGNMENT=3",
 613     "SET CPU4   CONFIG=INTERLACE=0",
 614     "SET CPU4   CONFIG=ENABLE=1",
 615     "SET CPU4   CONFIG=INIT_ENABLE=1",
 616     "SET CPU4   CONFIG=STORE_SIZE=4M",
 617 
 618     // ; 0 = GCOS 1 = VMS
 619     "SET CPU4 CONFIG=MODE=Multics",
 620 
 621     "SET CPU4 CONFIG=ENABLE_CACHE=enable",
 622     "SET CPU4 CONFIG=SDWAM=enable",
 623     "SET CPU4 CONFIG=PTWAM=enable",
 624 
 625     // ; 0 = 8/70
 626     "SET CPU4 CONFIG=SPEED=0",
 627 
 628     "SET CPU4 CONFIG=DIS_ENABLE=enable",
 629     "SET CPU4 CONFIG=STEADY_CLOCK=disable",
 630     "SET CPU4 CONFIG=HALT_ON_UNIMPLEMENTED=disable",
 631     "SET CPU4 CONFIG=ENABLE_WAM=disable",
 632     "SET CPU4 CONFIG=REPORT_FAULTS=disable",
 633     "SET CPU4 CONFIG=TRO_ENABLE=enable",
 634     "SET CPU4 CONFIG=Y2K=disable",
 635     "SET CPU4 CONFIG=DRL_FATAL=disable",
 636     "SET CPU4 CONFIG=USEMAP=disable",
 637     "SET CPU4 CONFIG=PROM_INSTALLED=enable",
 638     "SET CPU4 CONFIG=HEX_MODE_INSTALLED=disable",
 639     "SET CPU4 CONFIG=CACHE_INSTALLED=enable",
 640     "SET CPU4 CONFIG=CLOCK_SLAVE_INSTALLED=enable",
 641 
 642 // CPU5
 643 
 644     "SET CPU5 CONFIG=FAULTBASE=Multics",
 645 
 646     "SET CPU5 CONFIG=NUM=5",
 647     // ; As per GB61-01 Operators Guide, App. A
 648     // ; switches: 4, 6, 18, 19, 20, 23, 24, 25, 26, 28
 649     "SET CPU5 CONFIG=DATA=024000717200",
 650     "SET CPU5 CONFIG=ADDRESS=000000000000",
 651 
 652     // ; enable ports 0 and 1 (scu connections)
 653     // ; portconfig: ABCD
 654     // ;   each is 3 bits addr assignment
 655     // ;           1 bit enabled
 656     // ;           1 bit sysinit enabled
 657     // ;           1 bit interlace enabled (interlace?)
 658     // ;           3 bit memory size
 659     // ;              0 - 32K
 660     // ;              1 - 64K
 661     // ;              2 - 128K
 662     // ;              3 - 256K
 663     // ;              4 - 512K
 664     // ;              5 - 1M
 665     // ;              6 - 2M
 666     // ;              7 - 4M
 667 
 668     "SET CPU5 CONFIG=PORT=A",
 669     "SET CPU5   CONFIG=ASSIGNMENT=0",
 670     "SET CPU5   CONFIG=INTERLACE=0",
 671     "SET CPU5   CONFIG=ENABLE=1",
 672     "SET CPU5   CONFIG=INIT_ENABLE=1",
 673     "SET CPU5   CONFIG=STORE_SIZE=4M",
 674 
 675     "SET CPU5 CONFIG=PORT=B",
 676     "SET CPU5   CONFIG=ASSIGNMENT=1",
 677     "SET CPU5   CONFIG=INTERLACE=0",
 678     "SET CPU5   CONFIG=ENABLE=1",
 679     "SET CPU5   CONFIG=INIT_ENABLE=1",
 680     "SET CPU5   CONFIG=STORE_SIZE=4M",
 681 
 682     "SET CPU5 CONFIG=PORT=C",
 683     "SET CPU5   CONFIG=ASSIGNMENT=2",
 684     "SET CPU5   CONFIG=INTERLACE=0",
 685     "SET CPU5   CONFIG=ENABLE=1",
 686     "SET CPU5   CONFIG=INIT_ENABLE=1",
 687     "SET CPU5   CONFIG=STORE_SIZE=4M",
 688 
 689     "SET CPU5 CONFIG=PORT=D",
 690     "SET CPU5   CONFIG=ASSIGNMENT=3",
 691     "SET CPU5   CONFIG=INTERLACE=0",
 692     "SET CPU5   CONFIG=ENABLE=1",
 693     "SET CPU5   CONFIG=INIT_ENABLE=1",
 694     "SET CPU5   CONFIG=STORE_SIZE=4M",
 695 
 696     // ; 0 = GCOS 1 = VMS
 697     "SET CPU5 CONFIG=MODE=Multics",
 698 
 699     "SET CPU5 CONFIG=ENABLE_CACHE=enable",
 700     "SET CPU5 CONFIG=SDWAM=enable",
 701     "SET CPU5 CONFIG=PTWAM=enable",
 702 
 703     // ; 0 = 8/70
 704     "SET CPU5 CONFIG=SPEED=0",
 705 
 706     "SET CPU5 CONFIG=DIS_ENABLE=enable",
 707     "SET CPU5 CONFIG=STEADY_CLOCK=disable",
 708     "SET CPU5 CONFIG=HALT_ON_UNIMPLEMENTED=disable",
 709     "SET CPU5 CONFIG=ENABLE_WAM=disable",
 710     "SET CPU5 CONFIG=REPORT_FAULTS=disable",
 711     "SET CPU5 CONFIG=TRO_ENABLE=enable",
 712     "SET CPU5 CONFIG=Y2K=disable",
 713     "SET CPU5 CONFIG=DRL_FATAL=disable",
 714     "SET CPU5 CONFIG=USEMAP=disable",
 715     "SET CPU5 CONFIG=PROM_INSTALLED=enable",
 716     "SET CPU5 CONFIG=HEX_MODE_INSTALLED=disable",
 717     "SET CPU5 CONFIG=CACHE_INSTALLED=enable",
 718     "SET CPU5 CONFIG=CLOCK_SLAVE_INSTALLED=enable",
 719 
 720 
 721 
 722 
 723 
 724 
 725 
 726 
 727 
 728 
 729 
 730 
 731 
 732 
 733 
 734 
 735 
 736 
 737 
 738 
 739 
 740 
 741 
 742 
 743 
 744 
 745 
 746 
 747 
 748 
 749 
 750 
 751 
 752 
 753 
 754 
 755 
 756 
 757 
 758 
 759 
 760 
 761 
 762 
 763 
 764 
 765 
 766 
 767 
 768 
 769 
 770 
 771 
 772 
 773 
 774 
 775 
 776 
 777 
 778 
 779 
 780 
 781 
 782 
 783 
 784 
 785 
 786 
 787 
 788 
 789 
 790 
 791 
 792 
 793 
 794 
 795 
 796 
 797 
 798 
 799 
 800 
 801 
 802 
 803 
 804 
 805 
 806 
 807 
 808 
 809 
 810 
 811 
 812 
 813 
 814 
 815 
 816 
 817 
 818 
 819 
 820 
 821 
 822 
 823 
 824 
 825 
 826 
 827 
 828 
 829 
 830 
 831 
 832 
 833 
 834 
 835 
 836 
 837 
 838 
 839 
 840 
 841 
 842 
 843 
 844 
 845 
 846 
 847 
 848 
 849 
 850 
 851 
 852 
 853 
 854 
 855 
 856 
 857 
 858 
 859 
 860 
 861 
 862 
 863 
 864 
 865 
 866 
 867 
 868 
 869 
 870 
 871 
 872 
 873 
 874 
 875 
 876 
 877 
 878 
 879 
 880 
 881 
 882 
 883 // IOM0
 884 
 885     "SET IOM0 CONFIG=IOM_BASE=Multics",
 886     "SET IOM0 CONFIG=MULTIPLEX_BASE=0120",
 887     "SET IOM0 CONFIG=OS=Multics",
 888     "SET IOM0 CONFIG=BOOT=tape",
 889     "SET IOM0 CONFIG=TAPECHAN=012",
 890     "SET IOM0 CONFIG=CARDCHAN=011",
 891     "SET IOM0 CONFIG=SCUPORT=0",
 892 
 893     "SET IOM0 CONFIG=PORT=0",
 894     "SET IOM0   CONFIG=ADDR=0",
 895     "SET IOM0   CONFIG=INTERLACE=0",
 896     "SET IOM0   CONFIG=ENABLE=1",
 897     "SET IOM0   CONFIG=INITENABLE=0",
 898     "SET IOM0   CONFIG=HALFSIZE=0",
 899     "SET IOM0   CONFIG=STORE_SIZE=4M",
 900 
 901     "SET IOM0 CONFIG=PORT=1",
 902     "SET IOM0   CONFIG=ADDR=1",
 903     "SET IOM0   CONFIG=INTERLACE=0",
 904     "SET IOM0   CONFIG=ENABLE=1",
 905     "SET IOM0   CONFIG=INITENABLE=0",
 906     "SET IOM0   CONFIG=HALFSIZE=0",
 907     "SET IOM0   CONFIG=STORE_SIZE=4M",
 908 
 909     "SET IOM0 CONFIG=PORT=2",
 910     "SET IOM0   CONFIG=ADDR=2",
 911     "SET IOM0   CONFIG=INTERLACE=0",
 912     "SET IOM0   CONFIG=ENABLE=1",
 913     "SET IOM0   CONFIG=INITENABLE=0",
 914     "SET IOM0   CONFIG=HALFSIZE=0",
 915     "SET IOM0   CONFIG=STORE_SIZE=4M",
 916 
 917     "SET IOM0 CONFIG=PORT=3",
 918     "SET IOM0   CONFIG=ADDR=3",
 919     "SET IOM0   CONFIG=INTERLACE=0",
 920     "SET IOM0   CONFIG=ENABLE=1",
 921     "SET IOM0   CONFIG=INITENABLE=0",
 922     "SET IOM0   CONFIG=HALFSIZE=0",
 923     "SET IOM0   CONFIG=STORE_SIZE=4M",
 924 
 925     "SET IOM0 CONFIG=PORT=4",
 926     "SET IOM0   CONFIG=ENABLE=0",
 927 
 928     "SET IOM0 CONFIG=PORT=5",
 929     "SET IOM0   CONFIG=ENABLE=0",
 930 
 931     "SET IOM0 CONFIG=PORT=6",
 932     "SET IOM0   CONFIG=ENABLE=0",
 933 
 934     "SET IOM0 CONFIG=PORT=7",
 935     "SET IOM0   CONFIG=ENABLE=0",
 936 
 937 // IOM1
 938 
 939     "SET IOM1 CONFIG=IOM_BASE=Multics2",
 940     "SET IOM1 CONFIG=MULTIPLEX_BASE=0121",
 941     "SET IOM1 CONFIG=OS=Multics",
 942     "SET IOM1 CONFIG=BOOT=tape",
 943     "SET IOM1 CONFIG=TAPECHAN=012",
 944     "SET IOM1 CONFIG=CARDCHAN=011",
 945     "SET IOM1 CONFIG=SCUPORT=0",
 946 
 947     "SET IOM1 CONFIG=PORT=0",
 948     "SET IOM1   CONFIG=ADDR=0",
 949     "SET IOM1   CONFIG=INTERLACE=0",
 950     "SET IOM1   CONFIG=ENABLE=1",
 951     "SET IOM1   CONFIG=INITENABLE=0",
 952     "SET IOM1   CONFIG=HALFSIZE=0",
 953 
 954     "SET IOM1 CONFIG=PORT=1",
 955     "SET IOM1   CONFIG=ADDR=1",
 956     "SET IOM1   CONFIG=INTERLACE=0",
 957     "SET IOM1   CONFIG=ENABLE=1",
 958     "SET IOM1   CONFIG=INITENABLE=0",
 959     "SET IOM1   CONFIG=HALFSIZE=0",
 960 
 961     "SET IOM1 CONFIG=PORT=2",
 962     "SET IOM1   CONFIG=ENABLE=0",
 963     "SET IOM1 CONFIG=PORT=3",
 964     "SET IOM1   CONFIG=ENABLE=0",
 965     "SET IOM1 CONFIG=PORT=4",
 966     "SET IOM1   CONFIG=ENABLE=0",
 967     "SET IOM1 CONFIG=PORT=5",
 968     "SET IOM1   CONFIG=ENABLE=0",
 969     "SET IOM1 CONFIG=PORT=6",
 970     "SET IOM1   CONFIG=ENABLE=0",
 971     "SET IOM1 CONFIG=PORT=7",
 972     "SET IOM1   CONFIG=ENABLE=0",
 973 
 974 
 975 
 976 
 977 
 978 
 979 
 980 
 981 
 982 
 983 
 984 
 985 
 986 
 987 
 988 
 989 
 990 
 991 
 992 
 993 
 994 
 995 
 996 
 997 
 998 
 999 
1000 
1001 
1002 
1003 
1004 
1005 
1006 
1007 
1008 
1009 
1010 
1011 
1012 
1013 
1014 
1015 
1016 
1017 
1018 
1019 
1020 
1021 
1022 
1023 
1024 
1025 
1026 
1027 
1028 
1029 
1030 
1031 
1032 
1033 
1034 
1035 
1036 
1037 
1038 
1039 
1040 
1041 
1042 
1043 
1044 
1045 
1046 
1047 
1048 
1049 
1050 
1051 // SCU0
1052 
1053     "SET SCU0 CONFIG=MODE=program",
1054     "SET SCU0 CONFIG=PORT0=enable",
1055     "SET SCU0 CONFIG=PORT1=enable",
1056     "SET SCU0 CONFIG=PORT2=enable",
1057     "SET SCU0 CONFIG=PORT3=enable",
1058     "SET SCU0 CONFIG=PORT4=enable",
1059     "SET SCU0 CONFIG=PORT5=enable",
1060     "SET SCU0 CONFIG=PORT6=enable",
1061     "SET SCU0 CONFIG=PORT7=enable",
1062     "SET SCU0 CONFIG=MASKA=7",
1063     "SET SCU0 CONFIG=MASKB=off",
1064     "SET SCU0 CONFIG=LWRSTORESIZE=7",
1065     "SET SCU0 CONFIG=CYCLIC=0040",
1066     "SET SCU0 CONFIG=NEA=0200",
1067     "SET SCU0 CONFIG=ONL=014",
1068     "SET SCU0 CONFIG=INT=0",
1069     "SET SCU0 CONFIG=LWR=0",
1070 
1071 // SCU1
1072 
1073     "SET SCU1 CONFIG=MODE=program",
1074     "SET SCU1 CONFIG=PORT0=enable",
1075     "SET SCU1 CONFIG=PORT1=enable",
1076     "SET SCU1 CONFIG=PORT2=enable",
1077     "SET SCU1 CONFIG=PORT3=enable",
1078     "SET SCU1 CONFIG=PORT4=enable",
1079     "SET SCU1 CONFIG=PORT5=enable",
1080     "SET SCU1 CONFIG=PORT6=enable",
1081     "SET SCU1 CONFIG=PORT7=enable",
1082     "SET SCU1 CONFIG=MASKA=off",
1083     "SET SCU1 CONFIG=MASKB=off",
1084     "SET SCU1 CONFIG=LWRSTORESIZE=7",
1085     "SET SCU1 CONFIG=CYCLIC=0040",
1086     "SET SCU1 CONFIG=NEA=0200",
1087     "SET SCU1 CONFIG=ONL=014",
1088     "SET SCU1 CONFIG=INT=0",
1089     "SET SCU1 CONFIG=LWR=0",
1090 
1091 // SCU2
1092 
1093     "SET SCU2 CONFIG=MODE=program",
1094     "SET SCU2 CONFIG=PORT0=enable",
1095     "SET SCU2 CONFIG=PORT1=enable",
1096     "SET SCU2 CONFIG=PORT2=enable",
1097     "SET SCU2 CONFIG=PORT3=enable",
1098     "SET SCU2 CONFIG=PORT4=enable",
1099     "SET SCU2 CONFIG=PORT5=enable",
1100     "SET SCU2 CONFIG=PORT6=enable",
1101     "SET SCU2 CONFIG=PORT7=enable",
1102     "SET SCU2 CONFIG=MASKA=off",
1103     "SET SCU2 CONFIG=MASKB=off",
1104     "SET SCU2 CONFIG=LWRSTORESIZE=7",
1105     "SET SCU2 CONFIG=CYCLIC=0040",
1106     "SET SCU2 CONFIG=NEA=0200",
1107     "SET SCU2 CONFIG=ONL=014",
1108     "SET SCU2 CONFIG=INT=0",
1109     "SET SCU2 CONFIG=LWR=0",
1110 
1111 // SCU3
1112 
1113     "SET SCU3 CONFIG=MODE=program",
1114     "SET SCU3 CONFIG=PORT0=enable",
1115     "SET SCU3 CONFIG=PORT1=enable",
1116     "SET SCU3 CONFIG=PORT2=enable",
1117     "SET SCU3 CONFIG=PORT3=enable",
1118     "SET SCU3 CONFIG=PORT4=enable",
1119     "SET SCU3 CONFIG=PORT5=enable",
1120     "SET SCU3 CONFIG=PORT6=enable",
1121     "SET SCU3 CONFIG=PORT7=enable",
1122     "SET SCU3 CONFIG=MASKA=off",
1123     "SET SCU3 CONFIG=MASKB=off",
1124     "SET SCU3 CONFIG=LWRSTORESIZE=7",
1125     "SET SCU3 CONFIG=CYCLIC=0040",
1126     "SET SCU3 CONFIG=NEA=0200",
1127     "SET SCU3 CONFIG=ONL=014",
1128     "SET SCU3 CONFIG=INT=0",
1129     "SET SCU3 CONFIG=LWR=0",
1130 
1131 
1132 
1133 
1134 
1135 
1136 
1137 
1138 
1139 
1140 
1141 
1142 
1143 
1144 
1145 
1146 
1147 
1148 
1149 
1150 
1151 
1152 
1153 
1154 
1155 
1156 
1157 
1158 
1159 
1160 
1161 
1162 
1163 
1164 
1165 
1166 
1167 
1168 
1169 
1170 
1171 
1172 
1173 
1174 
1175 
1176 
1177 
1178 
1179 
1180 
1181 
1182 
1183 
1184 
1185 
1186 
1187 
1188 
1189 
1190 
1191 
1192 
1193 
1194 
1195 
1196 
1197 
1198 
1199 
1200 
1201 
1202 
1203 
1204 
1205 
1206 
1207 
1208 
1209 
1210 
1211 
1212 
1213     // ; DO NOT CHANGE THE CONFIGURATION OF THE FNP UNITS.
1214     // ; Restrictions in the FNP code that REQUIRE the simulator
1215     // ; unit numbers to be the same as the Multics unit numbers!
1216     // ; i.e. fnp0 == fnpa, etc.
1217     // ;
1218     // ; FNP a 3400
1219     // ; FNP b 3700
1220     // ; FNP c 4200
1221     // ; FNP d 4500
1222     // ; FNP e 5000
1223     // ; FNP f 5300
1224     // ; FNP g 5600
1225     // ; FNP h 6100
1226 
1227     "SET FNP0 CONFIG=MAILBOX=03400",
1228     "SET FNP0 IPC_NAME=fnp-a",
1229     "SET FNP1 CONFIG=MAILBOX=03700",
1230     "SET FNP1 IPC_NAME=fnp-b",
1231     "SET FNP2 CONFIG=MAILBOX=04200",
1232     "SET FNP2 IPC_NAME=fnp-c",
1233     "SET FNP3 CONFIG=MAILBOX=04500",
1234     "SET FNP3 IPC_NAME=fnp-d",
1235     "SET FNP4 CONFIG=MAILBOX=05000",
1236     "SET FNP4 IPC_NAME=fnp-e",
1237     "SET FNP5 CONFIG=MAILBOX=05300",
1238     "SET FNP5 IPC_NAME=fnp-f",
1239     "SET FNP6 CONFIG=MAILBOX=05600",
1240     "SET FNP6 IPC_NAME=fnp-g",
1241     "SET FNP7 CONFIG=MAILBOX=06100",
1242     "SET FNP7 IPC_NAME=fnp-h",
1243 
1244     //XXX"set mtp0 boot_drive=1",
1245     // ; Attach tape MPC to IOM 0, chan 012, dev_code 0
1246     "SET MTP0 BOOT_DRIVE=0",
1247     "SET MTP0 NAME=MTP0",
1248     // ; Attach TAPE unit 0 to IOM 0, chan 012, dev_code 1
1249     "CABLE IOM0 012 MTP0 0",
1250     "CABLE IOM1 012 MTP0 1",
1251     "CABLE MTP0 1 TAPE1",
1252     "SET TAPE1 NAME=tapa_01",
1253     "CABLE MTP0 2 TAPE2",
1254     "SET TAPE2 NAME=tapa_02",
1255     "CABLE MTP0 3 TAPE3",
1256     "SET TAPE3 NAME=tapa_03",
1257     "CABLE MTP0 4 TAPE4",
1258     "SET TAPE4 NAME=tapa_04",
1259     "CABLE MTP0 5 TAPE5",
1260     "SET TAPE5 NAME=tapa_05",
1261     "CABLE MTP0 6 TAPE6",
1262     "SET TAPE6 NAME=tapa_06",
1263     "CABLE MTP0 7 TAPE7",
1264     "SET TAPE7 NAME=tapa_07",
1265     "CABLE MTP0 8 TAPE8",
1266     "SET TAPE8 NAME=tapa_08",
1267     "CABLE MTP0 9 TAPE9",
1268     "SET TAPE9 NAME=tapa_09",
1269     "CABLE MTP0 10 TAPE10",
1270     "SET TAPE10 NAME=tapa_10",
1271     "CABLE MTP0 11 TAPE11",
1272     "SET TAPE11 NAME=tapa_11",
1273     "CABLE MTP0 12 TAPE12",
1274     "SET TAPE12 NAME=tapa_12",
1275     "CABLE MTP0 13 TAPE13",
1276     "SET TAPE13 NAME=tapa_13",
1277     "CABLE MTP0 14 TAPE14",
1278     "SET TAPE14 NAME=tapa_14",
1279     "CABLE MTP0 15 TAPE15",
1280     "SET TAPE15 NAME=tapa_15",
1281     "CABLE MTP0 16 TAPE16",
1282     "SET TAPE16 NAME=tapa_16",
1283 
1284 // 4 3381 disks
1285 
1286     "SET IPC0 NAME=IPC0",
1287     "CABLE IOM0 013 IPC0 0",
1288     "CABLE IOM1 013 IPC0 1",
1289     // ; Attach DISK unit 0 to IPC0 dev_code 0",
1290     "CABLE IPC0 0 DISK0",
1291     "SET DISK0 TYPE=3381",
1292     "SET DISK0 NAME=dska_00",
1293     // ; Attach DISK unit 1 to IPC0 dev_code 1",
1294     "cable IPC0 1 DISK1",
1295     "set disk1 type=3381",
1296     "set disk1 name=dska_01",
1297     // ; Attach DISK unit 2 to IPC0 dev_code 2",
1298     "CABLE IPC0 2 DISK2",
1299     "SET DISK2 TYPE=3381",
1300     "SET DISK2 NAME=dska_02",
1301     // ; Attach DISK unit 3 to IPC0 dev_code 3",
1302     "CABLE IPC0 3 DISK3",
1303     "SET DISK3 TYPE=3381",
1304     "SET DISK3 NAME=dska_03",
1305 
1306 // 4 d501 disks + 4 d451 disks + 2 d500 disks
1307     "SET MSP0 NAME=MSP0",
1308     "CABLE IOM0 014 MSP0 0",
1309     "CABLE IOM1 014 MSP0 1",
1310 
1311     // ; Attach DISK unit 4 to MSP0 dev_code 1",
1312     "CABLE MSP0 1 DISK4",
1313     "SET disk4 TYPE=d501",
1314     "SET disk4 NAME=dskb_01",
1315     // ; Attach DISK unit 5 to MSP0 dev_code 2",
1316     "CABLE MSP0 2 DISK5",
1317     "SET DISK5 TYPE=d501",
1318     "SET DISK5 NAME=dskb_02",
1319     // ; Attach DISK unit 6 to MSP0 dev_code 3",
1320     "CABLE MSP0 3 DISK6",
1321     "SET DISK6 TYPE=d501",
1322     "SET DISK6 NAME=dskb_03",
1323     // ; Attach DISK unit 7 to MSP0 dev_code 4",
1324     "CABLE MSP0 4 DISK7",
1325     "SET DISK7 TYPE=d501",
1326     "SET DISK7 NAME=dskb_04",
1327 
1328     // ; Attach DISK unit 8 to MSP0 dev_code 5",
1329     "CABLE MSP0 5 DISK8",
1330     "SET DISK8 TYPE=d451",
1331     "SET DISK8 NAME=dskb_05",
1332     // ; Attach DISK unit 9 to MSP0 dev_code 6",
1333     "CABLE MSP0 6 DISK9",
1334     "SET DISK9 TYPE=d451",
1335     "SET DISK9 NAME=dskb_06",
1336     // ; Attach DISK unit 10 to MSP0 dev_code 7",
1337     "CABLE MSP0 7 DISK10",
1338     "SET DISK10 TYPE=d451",
1339     "SET DISK10 NAME=dskb_07",
1340     // ; Attach DISK unit 11 to MSP0 dev_code 8",
1341     "CABLE MSP0 8 DISK11",
1342     "SET DISK11 TYPE=d451",
1343     "SET DISK11 NAME=dskb_08",
1344     // ; Attach DISK unit 12 to MSP0 dev_code 9",
1345     "CABLE MSP0 9 DISK12",
1346     "SET DISK12 TYPE=d500",
1347     "SET DISK12 NAME=dskb_09",
1348     // ; Attach DISK unit 13 to MSP0 dev_code 10",
1349     "CABLE MSP0 10 DISK13",
1350     "SET DISK13 TYPE=d500",
1351     "SET DISK13 NAME=dskb_10",
1352 
1353     // since we define 16 (decimal) 3381s in the default config deck, we need to add another 12
1354     // ; Attach DISK unit 14 to IPC0 dev_code 4",
1355     "CABLE IPC0 4 DISK14",
1356     "SET DISK14 TYPE=3381",
1357     "SET DISK14 NAME=dska_04",
1358     // ; Attach DISK unit 15 to IPC0 dev_code 5",
1359     "CABLE IPC0 5 DISK15",
1360     "SET DISK15 TYPE=3381",
1361     "SET DISK15 NAME=dska_05",
1362     // ; Attach DISK unit 16 to IPC0 dev_code 6",
1363     "CABLE IPC0 6 DISK16",
1364     "SET DISK16 TYPE=3381",
1365     "SET DISK16 NAME=dska_06",
1366     // ; Attach DISK unit 17 to IPC0 dev_code 7",
1367     "CABLE IPC0 7 DISK17",
1368     "SET DISK17 TYPE=3381",
1369     "SET DISK17 NAME=dska_07",
1370     // ; Attach DISK unit 18 to IPC0 dev_code 8",
1371     "CABLE IPC0 8 DISK18",
1372     "SET DISK18 TYPE=3381",
1373     "SET DISK18 NAME=dska_08",
1374     // ; Attach DISK unit 19 to IPC0 dev_code 9",
1375     "CABLE IPC0 9 DISK19",
1376     "SET DISK19 TYPE=3381",
1377     "SET DISK19 NAME=dska_09",
1378     // ; Attach DISK unit 20 to IPC0 dev_code 10",
1379     "CABLE IPC0 10 DISK20",
1380     "SET DISK20 TYPE=3381",
1381     "SET DISK20 NAME=dska_10",
1382     // ; Attach DISK unit 21 to IPC0 dev_code 11",
1383     "CABLE IPC0 11 DISK21",
1384     "SET DISK21 TYPE=3381",
1385     "SET DISK21 NAME=dska_11",
1386     // ; Attach DISK unit 22 to IPC0 dev_code 12",
1387     "CABLE IPC0 12 DISK22",
1388     "SET DISK22 TYPE=3381",
1389     "SET DISK22 NAME=dska_12",
1390     // ; Attach DISK unit 23 to IPC0 dev_code 13",
1391     "CABLE IPC0 13 DISK23",
1392     "SET DISK23 TYPE=3381",
1393     "SET DISK23 NAME=dska_13",
1394     // ; Attach DISK unit 24 to IPC0 dev_code 14",
1395     "CABLE IPC0 14 DISK24",
1396     "SET DISK24 TYPE=3381",
1397     "SET DISK24 NAME=dska_14",
1398     // ; Attach DISK unit 25 to IPC0 dev_code 15",
1399     "CABLE IPC0 15 DISK25",
1400     "SET DISK25 TYPE=3381",
1401     "SET DISK25 NAME=dska_15",
1402 
1403     // ; Attach OPC unit 0 to IOM A, chan 036, dev_code 0
1404     "CABLE IOMA 036 OPC0",
1405     // ; Attach OPC unit 1 to IOM A, chan 053, dev_code 0
1406     "CABLE IOMA 053 OPC1",
1407     "SET OPC1 CONFIG=MODEL=m6601",
1408     // No "devices" for console, so no 'CABLE OPC0 # CONx', etc.
1409 
1410     // ;;;
1411     // ;;; FNP
1412     // ;;;
1413 
1414     // ; Attach FNP unit 3 (d) to IOM A, chan 020, dev_code 0
1415     "CABLE IOMA 020 FNPD",
1416     // ; Attach FNP unit 0 (a) to IOM A, chan 021, dev_code 0
1417     "CABLE IOMA 021 FNPA",
1418     // ; Attach FNP unit 1 (b) to IOM A, chan 022, dev_code 0
1419     "CABLE IOMA 022 FNPB",
1420     // ; Attach FNP unit 2 (c) to IOM A, chan 023, dev_code 0
1421     "CABLE IOMA 023 FNPC",
1422     // ; Attach FNP unit 4 (e) to IOM A, chan 024, dev_code 0
1423     "CABLE IOMA 024 FNPE",
1424     // ; Attach FNP unit 5 (f) to IOM A, chan 025, dev_code 0
1425     "CABLE IOMA 025 FNPF",
1426     // ; Attach FNP unit 6 (g) to IOM A, chan 026, dev_code 0
1427     "CABLE IOMA 026 FNPG",
1428     // ; Attach FNP unit 7 (h) to IOM A, chan 027, dev_code 0
1429     "CABLE IOMA 027 FNPH",
1430 
1431     // ;;;
1432     // ;;; MPC
1433     // ;;;
1434 
1435     // ; Attach MPC unit 0 to IOM 0, char 015, dev_code 0
1436     "CABLE IOM0 015 URP0",
1437     "SET URP0 NAME=urpa",
1438 
1439     // ; Attach RDR unit 0 to IOM 0, chan 015, dev_code 1
1440     "CABLE URP0 1 RDR0",
1441     "SET RDR0 NAME=rdra",
1442 
1443     // ; Attach MPC unit 1 to IOM 0, char 016, dev_code 0
1444     "CABLE IOM0 016 URP1",
1445     "SET URP1 NAME=urpb",
1446 
1447     // ; Attach PUN unit 0 to IOM 0, chan 016, dev_code 1
1448     "CABLE URP1 1 PUN0",
1449     "SET PUN0 NAME=puna",
1450 
1451     // ; Attach MPC unit 2 to IOM 0, char 017, dev_code 0
1452     "CABLE IOM0 017 URP2",
1453     "SET URP2 NAME=urpc",
1454 
1455     // ; Attach PRT unit 0 to IOM 0, chan 017, dev_code 1
1456     "CABLE URP2 1 PRT0",
1457     "SET PRT0 NAME=prta",
1458 //    "SET PRT0 MODEL=1600",    // Needs polts fixes
1459 
1460     // ; Attach MPC unit 3 to IOM 0, char 050, dev_code 0
1461     "CABLE IOMA 050 URP3",
1462     "SET URP3 NAME=urpd",
1463 
1464     // ; Attach PRT unit 1 to IOM 0, chan 050, dev_code 1
1465     "CABLE URP3 1 PRT1",
1466     "SET PRT1 NAME=prtb",
1467 //    "SET PRT1 MODEL=303",    // Needs polts fixes
1468 
1469     // ; Attach MPC unit 4 to IOM 0, char 051, dev_code 0
1470     "CABLE IOMA 051 URP4",
1471     "SET URP4 NAME=urpe",
1472 
1473     // ; Attach PRT unit 2 to IOM 0, chan 051, dev_code 1
1474     "CABLE URP4 1 PRT2",
1475     "SET PRT2 NAME=prtc",
1476 //    "SET PRT2 MODEL=300",    // Needs polts fixes
1477 
1478     // ; Attach MPC unit 5 to IOM 0, chan 052, dev_code 0
1479     "CABLE IOMA 052 URP5",
1480     "SET URP5 NAME=urpf",
1481 
1482     // ; Attach PRT unit 3 to IOM 0, chan 052, dev_code 1
1483     "CABLE URP5 1 PRT3",
1484     "SET PRT3 NAME=prtd",
1485 //    "SET PRT3 MODEL=202",    // Needs polts fixes
1486 
1487     // ; Attach MPC unit 6 to IOM 0, chan 055, dev_code 0
1488     "CABLE IOMA 055 URP6",
1489     "SET URP6 NAME=urpg",
1490 
1491     // ; Attach RDR unit 1 to IOM 0, chan 055, dev_code 1
1492     "CABLE URP6 1 RDRB",
1493     "SET RDR1 NAME=rdrb",
1494 
1495     // ; Attach MPC unit 7 to IOM 0, chan 056, dev_code 0
1496     "CABLE IOMA 056 URP7",
1497     "SET URP7 NAME=urph",
1498 
1499     // ; Attach RDR unit 2 to IOM 0, chan 056, dev_code 1
1500     "CABLE URP7 1 RDRC",
1501     "SET RDR2 NAME=rdrc",
1502 
1503     // ; Attach MPC unit 8 to IOM 0, chan 057, dev_code 0
1504     "CABLE IOMA 057 URP8",
1505     "SET URP8 NAME=urpi",
1506 
1507     // ; Attach PUN unit 1 to IOM 0, chan 057, dev_code 1
1508     "CABLE URP8 1 PUNB",
1509     "SET PUN1 NAME=punb",
1510 
1511     // ; Attach MPC unit 9 to IOM 0, chan 060, dev_code 0
1512     "CABLE IOMA 060 URP9",
1513     "SET URP9 NAME=urpj",
1514 
1515     // ; Attach PUN unit 2 to IOM 0, chan 060, dev_code 1
1516     "CABLE URP9 1 PUNC",
1517     "SET PUN2 NAME=punc",
1518 
1519 # if defined(WITH_SOCKET_DEV)
1520 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64)
1521     "CABLE IOMA 040 SKCA",
1522     "CABLE IOMA 041 SKCB",
1523     "CABLE IOMA 042 SKCC",
1524     "CABLE IOMA 043 SKCD",
1525     "CABLE IOMA 044 SKCE",
1526     "CABLE IOMA 045 SKCF",
1527     "CABLE IOMA 046 SKCG",
1528     "CABLE IOMA 047 SKCH",
1529 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64) */
1530 # endif /* if defined(WITH_SOCKET_DEV) */
1531 
1532 
1533 
1534 
1535 
1536 
1537 
1538 
1539 
1540 
1541 
1542 
1543 
1544 
1545 
1546 
1547 
1548 
1549 
1550 
1551 
1552 
1553 
1554 
1555 
1556 
1557 
1558 
1559 
1560 
1561 
1562 
1563 
1564 
1565 
1566 
1567 
1568 
1569 
1570 
1571 
1572 
1573 
1574 
1575 
1576 
1577 
1578 
1579 
1580 
1581 
1582 
1583 
1584 
1585 
1586 
1587 
1588 
1589 
1590 
1591 
1592 
1593 
1594 
1595 
1596 # if defined(WITH_ABSI_DEV)
1597 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
1598     // ; Attach ABSI unit 0 to IOM 0, chan 032, dev_code 0
1599     "CABLE IOM0 032 ABSI0",
1600 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
1601 # endif /* if defined(WITH_ABSI_DEV) */
1602 
1603 # if defined(WITH_MGP_DEV)
1604 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
1605     // ; Attach MGPR unit 0 to IOM 0, chan 033, dev_code 0
1606     "CABLE IOM0 033 MGP0",
1607     // ; Attach MGPW unit 1 to IOM 0, chan 034, dev_code 0
1608     "CABLE IOM0 034 MGP1",
1609 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
1610 # endif /* if defined(WITH_MGP_DEV) */
1611 
1612     // ; Attach IOM unit 0 port A (0) to SCU unit 0, port 0
1613     "CABLE SCU0 0 IOM0 0", // SCU0 port 0 IOM0 port 0
1614 
1615     // ; Attach IOM unit 0 port B (1) to SCU unit 1, port 0
1616     "CABLE SCU1 0 IOM0 1", // SCU1 port 0 IOM0 port 1
1617 
1618     // ; Attach IOM unit 0 port C (2) to SCU unit 2, port 0
1619     "CABLE SCU2 0 IOM0 2", // SCU2 port 0 IOM0 port 2
1620 
1621     // ; Attach IOM unit 0 port D (3) to SCU unit 3, port 0
1622     "CABLE SCU3 0 IOM0 3", // SCU3 port 0 IOM0 port 3
1623 
1624     // ; Attach IOM unit 1 port A (0) to SCU unit 0, port 1
1625     "CABLE SCU0 1 IOM1 0", // SCU0 port 0 IOM0 port 0
1626 
1627     // ; Attach IOM unit 1 port B (1) to SCU unit 1, port 1
1628     "CABLE SCU1 1 IOM1 1", // SCU1 port 0 IOM0 port 1
1629 
1630     // ; Attach IOM unit 1 port C (2) to SCU unit 2, port 1
1631     "CABLE SCU2 1 IOM1 2", // SCU2 port 0 IOM0 port 2
1632 
1633     // ; Attach IOM unit 1 port D (3) to SCU unit 3, port 1
1634     "CABLE SCU3 1 IOM1 3", // SCU3 port 0 IOM0 port 3
1635 
1636 // SCU0 --> CPU0-5
1637 
1638     // ; Attach SCU unit 0 port 7 to CPU unit A (1), port 0
1639     "CABLE SCU0 7 CPU0 0",
1640 
1641     // ; Attach SCU unit 0 port 6 to CPU unit B (1), port 0
1642     "CABLE SCU0 6 CPU1 0",
1643 
1644     // ; Attach SCU unit 0 port 5 to CPU unit C (2), port 0
1645     "CABLE SCU0 5 CPU2 0",
1646 
1647     // ; Attach SCU unit 0 port 4 to CPU unit D (3), port 0
1648     "CABLE SCU0 4 CPU3 0",
1649 
1650     // ; Attach SCU unit 0 port 3 to CPU unit E (4), port 0
1651     "CABLE SCU0 3 CPU4 0",
1652 
1653     // ; Attach SCU unit 0 port 2 to CPU unit F (5), port 0
1654     "CABLE SCU0 2 CPU5 0",
1655 
1656 // SCU1 --> CPU0-5
1657 
1658     // ; Attach SCU unit 1 port 7 to CPU unit A (1), port 1
1659     "CABLE SCU1 7 CPU0 1",
1660 
1661     // ; Attach SCU unit 1 port 6 to CPU unit B (1), port 1
1662     "CABLE SCU1 6 CPU1 1",
1663 
1664     // ; Attach SCU unit 1 port 5 to CPU unit C (2), port 1
1665     "CABLE SCU1 5 CPU2 1",
1666 
1667     // ; Attach SCU unit 1 port 4 to CPU unit D (3), port 1
1668     "CABLE SCU1 4 CPU3 1",
1669 
1670     // ; Attach SCU unit 1 port 3 to CPU unit E (4), port 0
1671     "CABLE SCU1 3 CPU4 1",
1672 
1673     // ; Attach SCU unit 1 port 2 to CPU unit F (5), port 0
1674     "CABLE SCU1 2 CPU5 1",
1675 
1676 // SCU2 --> CPU0-5
1677 
1678     // ; Attach SCU unit 2 port 7 to CPU unit A (1), port 2
1679     "CABLE SCU2 7 CPU0 2",
1680 
1681     // ; Attach SCU unit 2 port 6 to CPU unit B (1), port 2
1682     "CABLE SCU2 6 CPU1 2",
1683 
1684     // ; Attach SCU unit 2 port 5 to CPU unit C (2), port 2
1685     "CABLE SCU2 5 CPU2 2",
1686 
1687     // ; Attach SCU unit 2 port 4 to CPU unit D (3), port 2
1688     "CABLE SCU2 4 CPU3 2",
1689 
1690     // ; Attach SCU unit 2 port 3 to CPU unit E (4), port 0
1691     "CABLE SCU2 3 CPU4 2",
1692 
1693     // ; Attach SCU unit 2 port 2 to CPU unit F (5), port 0
1694     "CABLE SCU2 2 CPU5 2",
1695 
1696 // SCU3 --> CPU0-5
1697 
1698     // ; Attach SCU unit 3 port 7 to CPU unit A (1), port 3
1699     "CABLE SCU3 7 CPU0 3",
1700 
1701     // ; Attach SCU unit 3 port 6 to CPU unit B (1), port 3
1702     "CABLE SCU3 6 CPU1 3",
1703 
1704     // ; Attach SCU unit 3 port 5 to CPU unit C (2), port 3
1705     "CABLE SCU3 5 CPU2 3",
1706 
1707     // ; Attach SCU unit 3 port 4 to CPU unit D (3), port 3
1708     "CABLE SCU3 4 CPU3 3",
1709 
1710     // ; Attach SCU unit 3 port 3 to CPU unit E (4), port 0
1711     "CABLE SCU3 3 CPU4 3",
1712 
1713     // ; Attach SCU unit 3 port 2 to CPU unit F (5), port 0
1714     "CABLE SCU3 2 CPU5 3",
1715 
1716     "SET CPU0 RESET",
1717     "SET SCU0 RESET",
1718     "SET SCU1 RESET",
1719     "SET SCU2 RESET",
1720     "SET SCU3 RESET",
1721     "SET IOM0 RESET",
1722 
1723 # if defined(THREADZ) || defined(LOCKLESS)
1724     "SET CPU NUNITS=6",
1725 # else
1726 #  if defined(ROUND_ROBIN)
1727     "SET CPU NUNITS=6",
1728 #  else
1729     "SET CPU NUNITS=1",
1730 #  endif
1731 # endif // THREADZ
1732     // "SET SYS CONFIG=ACTIVATE_TIME=8",
1733     // "SET SYS CONFIG=TERMINATE_TIME=8",
1734     "SET SYS CONFIG=CONNECT_TIME=-1",
1735   }; // default_base_system_script
1736 
1737 void print_default_base_system_script (void)
     /* [previous][next][first][last][top][bottom][index][help] */
1738   {
1739     int n_lines = sizeof (default_base_system_script) / sizeof (char *);
1740     sim_printf ("; DEFAULT_BASE_SYSTEM_SCRIPT (%lu lines follow)\n",
1741             (unsigned long)n_lines);
1742     for (int line = 0; line < n_lines; line ++)
1743     sim_printf ("%s\n", default_base_system_script[line]);
1744   }
1745 
1746 // Execute a line of script
1747 
1748 static void do_ini_line (char * text)
     /* [previous][next][first][last][top][bottom][index][help] */
1749   {
1750     //sim_msg ("<%s?\n", text);
1751     char gbuf[257];
1752     const char * cptr = get_glyph (text, gbuf, 0); /* get command glyph */
1753     CTAB *cmdp;
1754     if ((cmdp = find_cmd (gbuf)))            /* lookup command */
1755       {
1756         t_stat stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
1757         if (stat != SCPE_OK)
1758           sim_warn ("%s: %s\n", sim_error_text (SCPE_UNK), text);
1759       }
1760     else
1761       sim_warn ("%s: %s\n", sim_error_text (SCPE_UNK), text);
1762   }
1763 
1764 // Execute the base system script; this strings the cables
1765 // and sets the switches
1766 
1767 static t_stat set_default_base_system (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1768   {
1769 # if defined(PERF_STRIP)
1770     cpu_dev.numunits = 1;
1771 # else
1772     int n_lines = sizeof (default_base_system_script) / sizeof (char *);
1773     for (int line = 0; line < n_lines; line ++)
1774       do_ini_line (default_base_system_script [line]);
1775 # endif
1776     return SCPE_OK;
1777   }
1778 
1779 // Skip records on the boot tape.
1780 // The T&D tape first record is for testing DPS8s, the
1781 // second record (1st record / tape mark / 2nd record)
1782 // is for testing DPS8/Ms.
1783 // XXX assumes the boot tape is on tape unit 0
1784 
1785 static t_stat boot_skip (int32 UNUSED arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1786   {
1787     uint32 skipped;
1788     t_stat rc = sim_tape_sprecsf (& mt_unit[0], 1, & skipped);
1789     if (rc == SCPE_OK)
1790       tape_states[0].rec_num ++;
1791     return rc;
1792   }
1793 
1794 // Simulate pressing the 'EXECUTE FAULT' button. Used as an
1795 // emergency interrupt of Multics if it hangs and becomes
1796 // unresponsive to the operators console.
1797 
1798 static t_stat do_execute_fault (UNUSED int32 arg,  UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1799   {
1800     // Assume bootload CPU
1801     setG7fault (0, FAULT_EXF, fst_zero);
1802     return SCPE_OK;
1803   }
1804 
1805 // Simulate pressing the 'XED 10000' sequence; this starts BCE
1806 //
1807 //  sim> restart
1808 //  sim> go
1809 
1810 static t_stat do_restart (UNUSED int32 arg,  UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1811   {
1812     if (sim_is_running)
1813       {
1814         sim_printf ("Don't restart a running system....\r\n");
1815         return SCPE_ARG;
1816       }
1817     int n = 010000; //-V536
1818     if (buf)
1819       {
1820         n = (int) strtol (buf, NULL, 0);
1821       }
1822     sim_printf ("Restart entry 0%o\n", n);
1823 
1824     cpu_state_t * cpup = _cpup;
1825 
1826 
1827 
1828 
1829 
1830 
1831 
1832 
1833 
1834 
1835 
1836 
1837 
1838     cpu_reset_unit_idx (0, false);
1839     cpu.restart         = true;
1840     cpu.restart_address = (uint) n;
1841 
1842     t_stat rc = run_cmd (RU_CONT, "");
1843     return rc;
1844   }
1845 
1846 static t_stat set_sys_polling_interval (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1847   {
1848     if (! buf)
1849       return SCPE_ARG;
1850     int n = atoi (buf);
1851     if (n < 1 || n > 1000) // 1 millisecond to 1 second
1852       {
1853         sim_printf ("POLL %d: must be 1 (1 millisecond) to 1000 (1 second)\r\n", n);
1854         return SCPE_ARG;
1855       }
1856     sim_printf ("Polling set to %d milliseconds\r\n", n);
1857     sys_opts.sys_poll_interval = (uint) n;
1858     return SCPE_OK;
1859   }
1860 
1861 static t_stat set_sys_slow_polling_interval (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1862   {
1863     if (! buf)
1864       return SCPE_ARG;
1865     int n = atoi (buf);
1866     if (n < 1 || n > 1000) // 1 - slow poll every pool; 1000 - slow poll every 1000 polls
1867       {
1868         sim_printf ("SLOWPOLL %d: must be 1 (1 slow poll per pol) to 1000 (1 slow poll per 1000 polls)\r\n", n);
1869         return SCPE_ARG;
1870       }
1871     sim_printf ("Slow polling set to %d polls\r\n", n);
1872     sys_opts.sys_slow_poll_interval = (uint) n;
1873     return SCPE_OK;
1874   }
1875 
1876 static t_stat set_sys_poll_check_rate (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1877   {
1878     if (! buf)
1879       return SCPE_ARG;
1880     int n = atoi (buf);
1881     if (n < 1 || n > 1024*1024) // 1 - poll check rate in CPY cycles: 1 - check every cycle; 1024 check every 1024 cycles
1882       {
1883         sim_printf ("CHECKPOLL %d: must be 1 (check every cycle) to 1048576 (check every million cycles\r\n", n);
1884         return SCPE_ARG;
1885       }
1886     sim_printf ("Poll check rate set to %d CPU cycles\r\n", n);
1887     sys_opts.sys_poll_check_rate = (uint) n;
1888     return SCPE_OK;
1889   }
1890 #endif /* if !defined(PERF_STRIP) */
1891 
1892 //
1893 // Debugging commands
1894 //
1895 
1896 #if defined(TESTING)
1897 
1898 // Filter settings for our customized sim_debug
1899 
1900 // Start debug output at CPU cycle N.
1901 uint64 sim_deb_start      = 0;
1902 // Stop debug output at CPU cycle N.
1903 uint64 sim_deb_stop       = 0;
1904 // Break to scp prompt at CPU cycle N.
1905 uint64 sim_deb_break      = 0;
1906 // Enable CPU sim_debug iff PPR.PSR == N
1907 bool sim_deb_segno_on     = false;
1908 # if defined(NO_C_ELLIPSIS)
1909 bool sim_deb_segno[DEBUG_SEGNO_LIMIT];
1910 # else
1911 bool sim_deb_segno[DEBUG_SEGNO_LIMIT] = { [0 ... DEBUG_SEGNO_LIMIT - 1] = false };
1912 # endif
1913 // Enable CPU sim_debug iff PPR.PRR == N
1914 uint64 sim_deb_ringno     = NO_SUCH_RINGNO;
1915 // Suppress CPU sim_debug calls that pass all
1916 // of the filters after N times
1917 uint64 sim_deb_skip_limit = 0;
1918 // Suppress the first N CPU sim_debug calls
1919 // that pass all of the filters
1920 uint64 sim_deb_skip_cnt   = 0;
1921 // Suppress sim_debug until the MME instruction
1922 // has been executed N times
1923 uint64 sim_deb_mme_cntdwn = 0;
1924 // Suppress CPU sim_debug unless CPU number bit set
1925 uint dbgCPUMask           = 0377; // default all 8 on
1926 
1927 // Suppress CPU sim_debug unless BAR mode
1928 bool sim_deb_bar          = false;
1929 
1930 // Set the various filters
1931 
1932 static t_stat dps_debug_mme_cntdwn (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1933   {
1934     sim_deb_mme_cntdwn = strtoull (buf, NULL, 0);
1935     sim_msg ("Debug MME countdown set to %llu\n", (long long unsigned int)sim_deb_mme_cntdwn);
1936     return SCPE_OK;
1937   }
1938 
1939 static t_stat dps_debug_skip (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1940   {
1941     sim_deb_skip_cnt   = 0;
1942     sim_deb_skip_limit = strtoull (buf, NULL, 0);
1943     sim_msg ("Debug skip set to %llu\n", (long long unsigned int)sim_deb_skip_limit);
1944     return SCPE_OK;
1945   }
1946 
1947 static t_stat dps_debug_start (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1948   {
1949     sim_deb_start = strtoull (buf, NULL, 0);
1950     sim_msg ("Debug set to start at cycle: %llu\n", (long long unsigned int)sim_deb_start);
1951     return SCPE_OK;
1952   }
1953 
1954 static t_stat dps_debug_stop (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1955   {
1956     sim_deb_stop = strtoull (buf, NULL, 0);
1957     sim_msg ("Debug set to stop at cycle: %llu\n", (long long unsigned int)sim_deb_stop);
1958     return SCPE_OK;
1959   }
1960 
1961 static t_stat dps_debug_break (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1962   {
1963     sim_deb_break = strtoull (buf, NULL, 0);
1964     if (buf[0] == '+')
1965       sim_deb_break += sim_deb_start;
1966     sim_msg ("Debug set to break at cycle: %llu\n", (long long unsigned int)sim_deb_break);
1967     return SCPE_OK;
1968   }
1969 
1970 static t_stat dps_debug_segno (int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1971   {
1972     if (arg)
1973       {
1974         unsigned long segno = strtoul (buf, NULL, 0);
1975         if (segno >= DEBUG_SEGNO_LIMIT)
1976           {
1977             sim_printf ("out of range; 0 to %u %d.\n", DEBUG_SEGNO_LIMIT, DEBUG_SEGNO_LIMIT);
1978             return SCPE_ARG;
1979           }
1980         sim_deb_segno[segno] = true;
1981         sim_deb_segno_on     = true;
1982         sim_msg ("Debug set for segno %llo %llu.\n",
1983                 (long long unsigned int)segno, (long long unsigned int) segno);
1984       }
1985     else
1986       {
1987         (void)memset (sim_deb_segno, 0, sizeof (sim_deb_segno));
1988         sim_deb_segno_on = false;
1989         sim_msg ("Debug set for all segments\n");
1990       }
1991     return SCPE_OK;
1992   }
1993 
1994 static t_stat dps_debug_ringno (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1995   {
1996     sim_deb_ringno = strtoull (buf, NULL, 0);
1997     sim_msg ("Debug set to ringno %llo\n", (long long unsigned int)sim_deb_ringno);
1998     return SCPE_OK;
1999   }
2000 
2001 static t_stat dps_debug_bar (int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2002   {
2003     sim_deb_bar = arg;
2004     if (arg)
2005       sim_msg ("Debug set BAR %llo\n", (long long unsigned int)sim_deb_ringno);
2006     else
2007       sim_msg ("Debug unset BAR %llo\n", (long long unsigned int)sim_deb_ringno);
2008     return SCPE_OK;
2009   }
2010 
2011 
2012 
2013 
2014 
2015 
2016 
2017 
2018 
2019 
2020 
2021 
2022 
2023 
2024 
2025 
2026 
2027 
2028 
2029 
2030 
2031 
2032 
2033 
2034 
2035 
2036 
2037 
2038 
2039 
2040 
2041 
2042 
2043 
2044 
2045 
2046 
2047 
2048 
2049 
2050 
2051 
2052 
2053 
2054 
2055 
2056 
2057 
2058 
2059 
2060 
2061 
2062 
2063 
2064 
2065 
2066 
2067 
2068 
2069 
2070 
2071 
2072 
2073 
2074 
2075 
2076 
2077 
2078 
2079 
2080 
2081 
2082 
2083 
2084 
2085 
2086 
2087 
2088 
2089 
2090 
2091 
2092 
2093 
2094 
2095 
2096 
2097 
2098 
2099 
2100 
2101 
2102 
2103 
2104 
2105 
2106 
2107 
2108 
2109 
2110 
2111 
2112 
2113 
2114 
2115 
2116 
2117 
2118 
2119 
2120 
2121 
2122 
2123 
2124 
2125 
2126 
2127 
2128 
2129 
2130 
2131 
2132 
2133 
2134 
2135 
2136 
2137 
2138 
2139 
2140 
2141 
2142 
2143 
2144 
2145 
2146 
2147 
2148 
2149 
2150 
2151 
2152 
2153 
2154 
2155 
2156 
2157 
2158 
2159 
2160 
2161 
2162 
2163 
2164 
2165 
2166 
2167 
2168 
2169 
2170 
2171 
2172 
2173 
2174 
2175 
2176 
2177 
2178 
2179 
2180 
2181 
2182 
2183 
2184 
2185 
2186 
2187 
2188 
2189 
2190 
2191 
2192 
2193 
2194 
2195 
2196 
2197 
2198 
2199 
2200 
2201 
2202 
2203 
2204 
2205 
2206 
2207 
2208 
2209 
2210 
2211 
2212 
2213 
2214 
2215 
2216 
2217 
2218 
2219 
2220 
2221 // Translate seg:offset to absolute address
2222 
2223 static t_stat abs_addr_n (int segno, uint offset)
     /* [previous][next][first][last][top][bottom][index][help] */
2224   {
2225     word24 res;
2226 
2227     //t_stat rc = computeAbsAddrN (& res, segno, offset);
2228     if (dbgLookupAddress ((word18) segno, offset, & res, NULL))
2229       return SCPE_ARG;
2230 
2231     sim_msg ("Address is %08o\n", res);
2232     return SCPE_OK;
2233   }
2234 
2235 // ABS segno:offset
2236 // scp command to translate segno:offset to absolute address
2237 
2238 static t_stat abs_addr (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2239   {
2240     uint segno;
2241     uint offset;
2242     if (sscanf (buf, "%o:%o", & segno, & offset) != 2)
2243       return SCPE_ARG;
2244     return abs_addr_n ((int) segno, offset);
2245   }
2246 
2247 // LOAD_SYSTEM_BOOK <filename>
2248 
2249 // Read a system_book segment, extracting segment names and numbers
2250 // and component names, offsets, and lengths
2251 
2252 # define BOOT_SEGMENTS_MAX 1024
2253 # define BOOT_COMPONENTS_MAX 4096
2254 # define BOOK_SEGMENT_NAME_LEN 33
2255 
2256 static struct book_segment
2257   {
2258     char * segname;
2259     int  segno;
2260   } book_segments[BOOT_SEGMENTS_MAX];
2261 
2262 static int n_book_segments = 0;
2263 
2264 static struct book_component
2265   {
2266     char * compname;
2267     int  book_segment_number;
2268     uint txt_start, txt_length;
2269     int  intstat_start, intstat_length, symbol_start, symbol_length;
2270   } book_components[BOOT_COMPONENTS_MAX];
2271 
2272 static int n_book_components = 0;
2273 
2274 static int lookup_book_segment (char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
2275   {
2276     for (int i = 0; i < n_book_segments; i ++)
2277       if (strcmp (name, book_segments[i].segname) == 0)
2278         return i;
2279     return -1;
2280   }
2281 
2282 static int add_book_segment (char * name, int segno)
     /* [previous][next][first][last][top][bottom][index][help] */
2283   {
2284     int n = lookup_book_segment (name);
2285     if (n >= 0)
2286       return n;
2287     if (n_book_segments >= BOOT_SEGMENTS_MAX)
2288       return -1;
2289     book_segments[n_book_segments].segname = strdup (name);
2290     if (!book_segments[n_book_segments].segname)
2291       {
2292         (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
2293                        __func__, __FILE__, __LINE__);
2294 # if defined(USE_BACKTRACE)
2295 #  if defined(SIGUSR2)
2296         (void)raise(SIGUSR2);
2297         /*NOTREACHED*/ /* unreachable */
2298 #  endif /* if defined(SIGUSR2) */
2299 # endif /* if defined(USE_BACKTRACE) */
2300         abort();
2301       }
2302     book_segments[n_book_segments].segno   = segno;
2303     n = n_book_segments;
2304     n_book_segments ++;
2305     return n;
2306   }
2307 
2308 static int add_book_component (int segnum, char * name, uint txt_start,
     /* [previous][next][first][last][top][bottom][index][help] */
2309                                uint txt_length, int intstat_start,
2310                                int intstat_length, int symbol_start,
2311                                int symbol_length)
2312   {
2313     if (n_book_components >= BOOT_COMPONENTS_MAX)
2314       return -1;
2315     book_components[n_book_components].compname            = strdup (name);
2316     if (!book_components[n_book_components].compname)
2317       {
2318         (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
2319                        __func__, __FILE__, __LINE__);
2320 # if defined(USE_BACKTRACE)
2321 #  if defined(SIGUSR2)
2322         (void)raise(SIGUSR2);
2323         /*NOTREACHED*/ /* unreachable */
2324 #  endif /* if defined(SIGUSR2) */
2325 # endif /* if defined(USE_BACKTRACE) */
2326         abort();
2327       }
2328     book_components[n_book_components].book_segment_number = segnum;
2329     book_components[n_book_components].txt_start           = txt_start;
2330     book_components[n_book_components].txt_length          = txt_length;
2331     book_components[n_book_components].intstat_start       = intstat_start;
2332     book_components[n_book_components].intstat_length      = intstat_length;
2333     book_components[n_book_components].symbol_start        = symbol_start;
2334     book_components[n_book_components].symbol_length       = symbol_length;
2335     int n = n_book_components;
2336     n_book_components ++;
2337     return n;
2338   }
2339 
2340 // Given a segno:offset, try to translate to
2341 // component name and offset in the component
2342 
2343 // Warning: returns ptr to static buffer
2344 static char * lookup_system_book_address (word18 segno, word18 offset,
     /* [previous][next][first][last][top][bottom][index][help] */
2345                                          char * * compname, word18 * compoffset)
2346   {
2347     static char buf[129];
2348     int i;
2349 
2350     for (i = 0; i < n_book_segments; i ++)
2351       if (book_segments[i].segno == (int) segno)
2352         break;
2353 
2354     if (i >= n_book_segments)
2355       return NULL;
2356 
2357     int best = -1;
2358     uint bestoffset = 0;
2359 
2360     for (int j = 0; j < n_book_components; j ++)
2361       {
2362         if (book_components[j].book_segment_number != i)
2363           continue;
2364         if (book_components[j].txt_start <= offset &&
2365             book_components[j].txt_start + book_components[j].txt_length > offset)
2366           {
2367             (void)sprintf (buf, "%s:%s+0%0o", book_segments[i].segname,
2368                            book_components[j].compname,
2369                            offset - book_components[j].txt_start);
2370             if (compname)
2371               * compname = book_components[j].compname;
2372             if (compoffset)
2373               * compoffset = offset - book_components[j].txt_start;
2374             return buf;
2375           }
2376         if (book_components[j].txt_start <= offset &&
2377             book_components[j].txt_start > bestoffset)
2378           {
2379             best = j;
2380             bestoffset = book_components[j].txt_start;
2381           }
2382       }
2383 
2384     if (best != -1)
2385       {
2386         // Didn't find a component track bracketed the offset; return the
2387         // component that was before the offset
2388         if (compname)
2389           * compname = book_components[best].compname;
2390         if (compoffset)
2391           * compoffset = offset - book_components[best].txt_start;
2392         (void)sprintf (buf, "%s:%s+0%0o", book_segments[i].segname,
2393                        book_components[best].compname,
2394                        offset - book_components[best].txt_start);
2395         return buf;
2396       }
2397 
2398     // Found a segment, but it had no components. Return the segment name
2399     // as the component name
2400 
2401     if (compname)
2402       * compname = book_segments[i].segname;
2403     if (compoffset)
2404       * compoffset = offset;
2405     (void)sprintf (buf, "%s:+0%0o", book_segments[i].segname,
2406                    offset);
2407     return buf;
2408   }
2409 
2410 // Given a segno and offset, find the component name and its
2411 // offset in the segment
2412 
2413 char * lookup_address (word18 segno, word18 offset, char * * compname,
     /* [previous][next][first][last][top][bottom][index][help] */
2414                        word18 * compoffset)
2415   {
2416     if (compname)
2417       * compname = NULL;
2418     if (compoffset)
2419       * compoffset = 0;
2420 
2421     // Magic numbers!
2422     // Multics seems to have a copy of hpchs_ (segno 0162) in segment 0322;
2423     // This little tweak allows source code level tracing for segment 0322,
2424     // and has no operational significance to the emulator
2425     // Hmmm. What is happening is that these segments are being loaded into
2426     // ring 4, and assigned segment #'s; the assigned number will vary
2427     // depending on the exact sequence of events.
2428     if (segno == 0322)
2429       segno = 0162;
2430     if (segno == 0310)
2431       segno = 041;
2432     if (segno == 0314)
2433       segno = 041;
2434     if (segno == 0313)
2435       segno = 040;
2436     if (segno == 0317)
2437       segno = 0161;
2438 
2439 
2440 
2441 
2442 
2443 
2444 
2445 
2446 
2447 
2448 
2449 
2450 
2451 
2452 
2453 
2454 
2455 
2456 
2457 
2458 
2459 
2460 
2461 
2462 
2463 
2464 
2465 
2466 
2467 
2468 
2469 
2470     char * ret = lookup_system_book_address (segno, offset, compname, compoffset);
2471     return ret;
2472   }
2473 
2474 // Given a segment name and component name, return the
2475 // components segment number and offset
2476 
2477 // Warning: returns ptr to static buffer
2478 static int lookup_system_book_name (char * segname, char * compname, long * segno,
     /* [previous][next][first][last][top][bottom][index][help] */
2479                                     long * offset)
2480   {
2481     int i;
2482     for (i = 0; i < n_book_segments; i ++)
2483       if (strcmp (book_segments[i].segname, segname) == 0)
2484         break;
2485     if (i >= n_book_segments)
2486       return -1;
2487 
2488     for (int j = 0; j < n_book_components; j ++)
2489       {
2490         if (book_components[j].book_segment_number != i)
2491           continue;
2492         if (strcmp (book_components[j].compname, compname) == 0)
2493           {
2494             * segno = book_segments[i].segno;
2495             * offset = (long) book_components[j].txt_start;
2496             return 0;
2497           }
2498       }
2499 
2500    return -1;
2501  }
2502 
2503 static char * source_search_path = NULL;
2504 
2505 // Given a component name and an offset in the component,
2506 // find the listing file of the component and try to
2507 // print the source code line that generated the code at
2508 // component:offset
2509 
2510 void list_source (char * compname, word18 offset, uint dflag)
     /* [previous][next][first][last][top][bottom][index][help] */
2511   {
2512     cpu_state_t * cpup = _cpup;
2513     const int offset_str_len = 10;
2514     //char offset_str[offset_str_len + 1];
2515     char offset_str[17];
2516     (void)sprintf (offset_str, "    %06o", offset);
2517 
2518     char path[(source_search_path ? strlen (source_search_path) : 1) +
2519                1 + // "/"
2520                (compname ? strlen (compname) : 1) +
2521                 1 + strlen (".list") + 1];
2522     char * searchp = source_search_path ? source_search_path : ".";
2523     // find <search path>/<compname>.list
2524     while (* searchp)
2525       {
2526         size_t pathlen = strcspn (searchp, ":");
2527         strncpy (path, searchp, pathlen);
2528         path[pathlen] = '\0';
2529         if (searchp[pathlen] == ':')
2530           searchp += pathlen + 1;
2531         else
2532           searchp += pathlen;
2533 
2534         if (compname)
2535           {
2536             strcat (path, "/");
2537             strcat (path, compname);
2538           }
2539         strcat (path, ".list");
2540         //sim_msg ("<%s>\n", path);
2541         FILE * listing = fopen (path, "r");
2542         if (listing)
2543           {
2544             char line[1025];
2545             if (feof (listing))
2546               goto fileDone;
2547             fgets (line, 1024, listing);
2548             if (strncmp (line, "ASSEMBLY LISTING", 16) == 0)
2549               {
2550                 // Search ALM listing file
2551                 // sim_msg ("found <%s>\n", path);
2552 
2553                 // ALM listing files look like:
2554                 //     000226  4a  4 00010 7421 20  \tstx2]tbootload_0$entry_stack_ptr,id
2555                 while (! feof (listing))
2556                   {
2557                     fgets (line, 1024, listing);
2558                     if (strncmp (line, offset_str, (size_t) offset_str_len) == 0)
2559                       {
2560                         if (! dflag)
2561                           sim_msg ("%s", line);
2562                         else
2563                           sim_debug (dflag, & cpu_dev, "%s", line);
2564                         //break;
2565                       }
2566                     if (strcmp (line, "\fLITERALS\n") == 0)
2567                       break;
2568                   }
2569               } // if assembly listing
2570             else if (strncmp (line, "\tCOMPILATION LISTING", 20) == 0)
2571               {
2572                 // Search PL/I listing file
2573 
2574                 // PL/I files have a line location table
2575                 //     "   LINE    LOC      LINE    LOC ...."
2576 
2577                 bool foundTable = false;
2578                 while (! feof (listing))
2579                   {
2580                     fgets (line, 1024, listing);
2581                     if (strncmp (line, "   LINE    LOC", 14) != 0)
2582                       continue;
2583                     foundTable = true;
2584                     // Found the table
2585                     // Table lines look like
2586                     //     "     13 000705    275 000713 ...
2587                     // But some times
2588                     //     "     10 000156 21  84 000164
2589                     //     "      8 000214     65 000222   4  84 000225
2590                     //
2591                     //     "    349 001442    351 001445     353 001454 1   9 001456 1  11 001461 1  12 001463 1  13 001470
2592                     //     " 1   18 001477    357 001522     361 001525   363 001544   364 001546   365 001547   366 001553
2593 
2594                     //  I think the numbers refer to include files...
2595                     //   But of course the format is slightly off...
2596                     //    table    ".1...18
2597                     //    listing  ".1....18
2598                     int best = -1;
2599                     char bestLines[8] = {0, 0, 0, 0, 0, 0, 0};
2600                     while (! feof (listing))
2601                       {
2602                         int loc[7];
2603                         char linenos[7][8];
2604                         (void)memset (linenos, 0, sizeof (linenos));
2605                         fgets (line, 1024, listing);
2606                         // sometimes the leading columns are blank...
2607                         while (strncmp (line,
2608                                         "                 ", 8 + 6 + 3) == 0)
2609                           memmove (line, line + 8 + 6 + 3,
2610                                    strlen (line + 8 + 6 + 3));
2611                         // deal with the extra numbers...
2612 
2613                         int cnt = sscanf (line,
2614                           // " %d %o %d %o %d %o %d %o %d %o %d %o %d %o",
2615                           "%8c%o%*3c"
2616                           "%8c%o%*3c"
2617                           "%8c%o%*3c"
2618                           "%8c%o%*3c"
2619                           "%8c%o%*3c"
2620                           "%8c%o%*3c"
2621                           "%8c%o",
2622                           (char *) & linenos[0], (uint *) & loc[0],
2623                           (char *) & linenos[1], (uint *) & loc[1],
2624                           (char *) & linenos[2], (uint *) & loc[2],
2625                           (char *) & linenos[3], (uint *) & loc[3],
2626                           (char *) & linenos[4], (uint *) & loc[4],
2627                           (char *) & linenos[5], (uint *) & loc[5],
2628                           (char *) & linenos[6], (uint *) & loc[6]);
2629                         if (! (cnt == 2 || cnt == 4  || cnt == 6  ||
2630                                cnt == 8 || cnt == 10 || cnt == 12 ||
2631                                cnt == 14))
2632                           break; // end of table
2633                         int n;
2634                         for (n = 0; n < cnt / 2; n ++)
2635                           {
2636                             if (loc[n] > best && loc[n] <= (int) offset)
2637                               {
2638                                 best = loc[n];
2639                                 memcpy (bestLines, linenos[n],
2640                                         sizeof (bestLines));
2641                               }
2642                           }
2643                         if (best == (int) offset)
2644                           break;
2645                       }
2646                     if (best == -1)
2647                       goto fileDone; // Not found in table
2648 
2649                     //   But of course the format is slightly off...
2650                     //    table    ".1...18
2651                     //    listing  ".1....18
2652                     // bestLines "21   84 "
2653                     // listing   " 21    84 "
2654                     char searchPrefix[10];
2655                     searchPrefix[0] = ' ';
2656                     searchPrefix[1] = bestLines[0];
2657                     searchPrefix[2] = bestLines[1];
2658                     searchPrefix[3] = ' ';
2659                     searchPrefix[4] = bestLines[2];
2660                     searchPrefix[5] = bestLines[3];
2661                     searchPrefix[6] = bestLines[4];
2662                     searchPrefix[7] = bestLines[5];
2663                     searchPrefix[8] = bestLines[6];
2664                     // ignore trailing space; some times it's a tab
2665                     // searchPrefix[ 9] = bestLines[ 7];
2666                     searchPrefix[9] = '\0';
2667 
2668                     // Look for the line in the listing
2669                     rewind (listing);
2670                     while (! feof (listing))
2671                       {
2672                         fgets (line, 1024, listing);
2673                         if (strncmp (line, "\f\tSOURCE", 8) == 0)
2674                           goto fileDone; // end of source code listing
2675                         char prefix[10];
2676                         strncpy (prefix, line, 9);
2677                         prefix[9] = '\0';
2678                         if (strcmp (prefix, searchPrefix) != 0)
2679                           continue;
2680                         // Got it
2681                         if (!dflag)
2682                           sim_msg ("%s", line);
2683                         else
2684                           sim_debug (dflag, & cpu_dev, "%s", line);
2685                         //break;
2686                       }
2687                     goto fileDone;
2688                   } // if table start
2689                 if (! foundTable)
2690                   {
2691                     // Can't find the LINE/LOC table; look for listing
2692                     rewind (listing);
2693                     while (! feof (listing))
2694                       {
2695                         fgets (line, 1024, listing);
2696                         if (strncmp (line,
2697                                      offset_str + 4,
2698                                      offset_str_len - 4) == 0)
2699                           {
2700                             if (! dflag)
2701                               sim_msg ("%s", line);
2702                             else
2703                               sim_debug (dflag, & cpu_dev, "%s", line);
2704                             //break;
2705                           }
2706                         //if (strcmp (line, "\fLITERALS\n") == 0)
2707                           //break;
2708                       }
2709                   } // if ! tableFound
2710               } // if PL/I listing
2711 
2712 fileDone:
2713             fclose (listing);
2714           } // if (listing)
2715       }
2716   }
2717 
2718 // STK
2719 
2720 static t_stat stack_trace (UNUSED int32 arg,  UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2721   {
2722     cpu_state_t * cpup = _cpup;
2723     char * msg;
2724 
2725     word15 icSegno = cpu.PPR.PSR;
2726     word18 icOffset = cpu.PPR.IC;
2727 
2728     sim_msg ("Entry ptr   %05o:%06o\n", icSegno, icOffset);
2729 
2730     char * compname;
2731     word18 compoffset;
2732     char * where = lookup_address (icSegno, icOffset,
2733                                    & compname, & compoffset);
2734     if (where)
2735       {
2736         sim_msg ("%05o:%06o %s\n", icSegno, icOffset, where);
2737         list_source (compname, compoffset, 0);
2738       }
2739     sim_msg ("\n");
2740 
2741     // According to AK92
2742     //
2743     //  pr0/ap operator segment pointer
2744     //  pr6/sp stack frame pointer
2745     //  pr4/lp linkage section for the executing procedure
2746     //  pr7/sb stack base
2747 
2748     word15 fpSegno  = cpu.PR[6].SNR;
2749     word18 fpOffset = cpu.PR[6].WORDNO;
2750 
2751     for (uint frameNo = 1; ; frameNo ++)
2752       {
2753         sim_msg ("Frame %d %05o:%06o\n",
2754                     frameNo, fpSegno, fpOffset);
2755 
2756         word24 fp;
2757         if (dbgLookupAddress (fpSegno, fpOffset, & fp, & msg))
2758           {
2759             sim_msg ("can't lookup fp (%05o:%06o) because %s\n",
2760                     fpSegno, fpOffset, msg);
2761             break;
2762           }
2763 
2764         word15 prevfpSegno  = (word15) ((M[fp + 16] >> 18) & MASK15);
2765         word18 prevfpOffset = (word18) ((M[fp + 17] >> 18) & MASK18);
2766 
2767         sim_msg ("Previous FP %05o:%06o\n", prevfpSegno, prevfpOffset);
2768 
2769         word15 returnSegno  = (word15) ((M[fp + 20] >> 18) & MASK15);
2770         word18 returnOffset = (word18) ((M[fp + 21] >> 18) & MASK18);
2771 
2772         sim_msg ("Return ptr  %05o:%06o\n", returnSegno, returnOffset);
2773 
2774         if (returnOffset == 0)
2775           {
2776             if (frameNo == 1)
2777               {
2778                 // try rX[7] as the return address
2779                 sim_msg ("guessing X7 has a return address....\n");
2780                 where = lookup_address (icSegno, cpu.rX[7] - 1,
2781                                         & compname, & compoffset);
2782                 if (where)
2783                   {
2784                     sim_msg ("%05o:%06o %s\n", icSegno, cpu.rX[7] - 1, where);
2785                     list_source (compname, compoffset, 0);
2786                   }
2787               }
2788           }
2789         else
2790           {
2791             where = lookup_address (returnSegno, returnOffset - 1,
2792                                     & compname, & compoffset);
2793             if (where)
2794               {
2795                 sim_msg ("%05o:%06o %s\n",
2796                             returnSegno, returnOffset - 1, where);
2797                 list_source (compname, compoffset, 0);
2798               }
2799           }
2800 
2801         word15 entrySegno  = (word15) ((M[fp + 22] >> 18) & MASK15);
2802         word18 entryOffset = (word18) ((M[fp + 23] >> 18) & MASK18);
2803 
2804         sim_msg ("Entry ptr   %05o:%06o\n", entrySegno, entryOffset);
2805 
2806         where = lookup_address (entrySegno, entryOffset,
2807                                 & compname, & compoffset);
2808         if (where)
2809           {
2810             sim_msg ("%05o:%06o %s\n", entrySegno, entryOffset, where);
2811             list_source (compname, compoffset, 0);
2812           }
2813 
2814         word15 argSegno  = (word15) ((M[fp + 26] >> 18) & MASK15);
2815         word18 argOffset = (word18) ((M[fp + 27] >> 18) & MASK18);
2816         sim_msg ("Arg ptr     %05o:%06o\n", argSegno, argOffset);
2817 
2818         word24 ap;
2819         if (dbgLookupAddress (argSegno, argOffset, & ap, & msg))
2820           {
2821             sim_msg ("can't lookup arg ptr (%05o:%06o) because %s\n",
2822                     argSegno, argOffset, msg);
2823             goto skipArgs;
2824           }
2825 
2826         word16 argCount  = (word16) ((M[ap + 0] >> 19) & MASK17);
2827         word18 callType  = (word18) (M[ap + 0] & MASK18);
2828         word16 descCount = (word16) ((M[ap + 1] >> 19) & MASK17);
2829         sim_msg ("arg_count   %d\n", argCount);
2830         switch (callType)
2831           {
2832             case 0u:
2833               sim_msg ("call_type Quick internal call\n");
2834               break;
2835             case 4u:
2836               sim_msg ("call_type Inter-segment\n");
2837               break;
2838             case 8u:
2839               sim_msg ("call_type Environment pointer\n");
2840               break;
2841             default:
2842               sim_msg ("call_type Unknown (%o)\n", callType);
2843               goto skipArgs;
2844               }
2845         sim_msg ("desc_count  %d\n", descCount);
2846 
2847 
2848 
2849 
2850 
2851 
2852 
2853 
2854           {
2855             for (uint argno = 0; argno < argCount; argno ++)
2856               {
2857                 uint argnoos       = ap + 2 + argno * 2;
2858                 word15 argnoSegno  = (word15) ((M[argnoos] >> 18) & MASK15);
2859                 word18 argnoOffset = (word18) ((M[argnoos + 1] >> 18) & MASK18);
2860                 word24 argnop;
2861                 if (dbgLookupAddress (argnoSegno, argnoOffset, & argnop, & msg))
2862                   {
2863                     sim_msg ("can't lookup arg%d ptr (%05o:%06o) because %s\n",
2864                                 argno, argSegno, argOffset, msg);
2865                     continue;
2866                   }
2867                 word36 argv = M[argnop];
2868                 sim_msg ("arg%d value   %05o:%06o[%08o] "
2869                             "%012llo (%llu)\n",
2870                             argno, argSegno, argOffset, argnop,
2871                             (unsigned long long int)argv, (unsigned long long int)argv);
2872                 sim_msg ("\n");
2873              }
2874          }
2875 skipArgs:;
2876 
2877         sim_msg ("End of frame %d\n\n", frameNo);
2878 
2879         if (prevfpSegno == 077777 && prevfpOffset == 1)
2880           break;
2881         fpSegno  = prevfpSegno;
2882         fpOffset = prevfpOffset;
2883       }
2884     return SCPE_OK;
2885   }
2886 
2887 static t_stat list_source_at (UNUSED int32 arg, UNUSED const char *  buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2888   {
2889     // list seg:offset
2890     uint segno;
2891     uint offset;
2892     if (sscanf (buf, "%o:%o", & segno, & offset) != 2)
2893       return SCPE_ARG;
2894     char * compname;
2895     word18 compoffset;
2896     char * where = lookup_address ((word18) segno, offset,
2897                                    & compname, & compoffset);
2898     if (where)
2899       {
2900         sim_msg ("%05o:%06o %s\n", segno, offset, where);
2901         list_source (compname, compoffset, 0);
2902       }
2903     return SCPE_OK;
2904   }
2905 
2906 static t_stat load_system_book (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2907   {
2908 // Quietly ignore if not debug enabled
2909 # if !defined(SPEED)
2910     // Multics 12.5 assigns segment number to collection 3 starting at 0244.
2911     uint c3 = 0244;
2912 
2913 #  define bufSz 257
2914     char filebuf[bufSz];
2915     int  current = -1;
2916 
2917     FILE * fp = fopen (buf, "r");
2918     if (! fp)
2919       {
2920         sim_msg ("error opening file %s\n", buf);
2921         return SCPE_ARG;
2922       }
2923     for (;;)
2924       {
2925         char * bufp = fgets (filebuf, bufSz, fp);
2926         if (! bufp)
2927           break;
2928         //sim_msg ("<%s\n>", filebuf);
2929         char name[BOOK_SEGMENT_NAME_LEN];
2930         uint segno, p0, p1, p2;
2931 
2932         // 32 is BOOK_SEGMENT_NAME_LEN - 1
2933         int cnt = sscanf (filebuf, "%32s %o  (%o, %o, %o)", name, & segno,
2934           & p0, & p1, & p2);
2935         if (filebuf[0] != '\t' && cnt == 5)
2936           {
2937             //sim_msg ("A: %s %d\n", name, segno);
2938             int rc = add_book_segment (name, (int) segno);
2939             if (rc < 0)
2940               {
2941                 sim_warn ("error adding segment name\n");
2942                 fclose (fp);
2943                 return SCPE_ARG;
2944               }
2945             continue;
2946           }
2947         else
2948           {
2949             // Check for collection 3 segment
2950             // 32 is BOOK_SEGMENT_NAME_LEN - 1
2951             cnt = sscanf (filebuf, "%32s  (%o, %o, %o)", name,
2952               & p0, & p1, & p2);
2953             if (filebuf[0] != '\t' && cnt == 4)
2954               {
2955                 if (strstr (name, "fw.") || strstr (name, ".ec"))
2956                   continue;
2957                 //sim_msg ("A: %s %d\n", name, segno);
2958                 int rc = add_book_segment (name, (int) (c3 ++));
2959                 if (rc < 0)
2960                   {
2961                     sim_warn ("error adding segment name\n");
2962                     fclose (fp);
2963                     return SCPE_ARG;
2964                   }
2965                 continue;
2966               }
2967           }
2968         cnt = sscanf (filebuf, "Bindmap for >ldd>h>e>%32s", name);
2969         if (cnt != 1)
2970           cnt = sscanf (filebuf, "Bindmap for >ldd>hard>e>%32s", name);
2971         if (cnt == 1)
2972           {
2973             //sim_msg ("B: %s\n", name);
2974             //int rc = add_book_segment (name);
2975             int rc = lookup_book_segment (name);
2976             if (rc < 0)
2977               {
2978                 // The collection 3.0 segments do not have segment numbers,
2979                 // and the 1st digit of the 3-tuple is 1, not 0. Ignore
2980                 // them for now.
2981                 current = -1;
2982                 continue;
2983                 //sim_warn ("error adding segment name\n");
2984                 //return SCPE_ARG;
2985               }
2986             current = rc;
2987             continue;
2988           }
2989 
2990         uint txt_start, txt_length;
2991         int intstat_start, intstat_length, symbol_start, symbol_length;
2992         cnt = sscanf (filebuf, "%32s %o %o %o %o %o %o", name, & txt_start,
2993                       & txt_length, & intstat_start, & intstat_length,
2994                       & symbol_start, & symbol_length);
2995 
2996         if (cnt == 7)
2997           {
2998             //sim_msg ("C: %s\n", name);
2999             if (current >= 0)
3000               {
3001                 add_book_component (current, name, txt_start, txt_length,
3002                                     intstat_start, intstat_length, symbol_start,
3003                                     symbol_length);
3004               }
3005             continue;
3006           }
3007 
3008         cnt = sscanf (filebuf, "%32s %o  (%o, %o, %o)", name, & segno,
3009           & p0, & p1, & p2);
3010         if (filebuf[0] == '\t' && cnt == 5)
3011           {
3012             //sim_msg ("D: %s %d\n", name, segno);
3013             int rc = add_book_segment (name, (int) segno);
3014             if (rc < 0)
3015               {
3016                 sim_warn ("error adding segment name\n");
3017                 fclose (fp);
3018                 return SCPE_ARG;
3019               }
3020             continue;
3021           }
3022 
3023       }
3024     fclose (fp);
3025 
3026 
3027 
3028 
3029 
3030 
3031 
3032 
3033 
3034 
3035 
3036 
3037 
3038 
3039 
3040 
3041 
3042 
3043 
3044 
3045 
3046 # endif
3047     return SCPE_OK;
3048   }
3049 
3050 static t_stat add_system_book_entry (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3051   {
3052     // asbe segname compname seg txt_start txt_len intstat_start intstat_length
3053     // symbol_start symbol_length
3054     char segname[BOOK_SEGMENT_NAME_LEN];
3055     char compname[BOOK_SEGMENT_NAME_LEN];
3056     uint segno;
3057     uint txt_start, txt_len;
3058     uint  intstat_start, intstat_length;
3059     uint  symbol_start, symbol_length;
3060 
3061     // 32 is BOOK_SEGMENT_NAME_LEN - 1
3062     if (sscanf (buf, "%32s %32s %o %o %o %o %o %o %o",
3063                 segname, compname, & segno,
3064                 & txt_start, & txt_len, & intstat_start, & intstat_length,
3065                 & symbol_start, & symbol_length) != 9)
3066       return SCPE_ARG;
3067 
3068     int idx = add_book_segment (segname, (int) segno);
3069     if (idx < 0)
3070       return SCPE_ARG;
3071 
3072     if (add_book_component (idx, compname, txt_start, txt_len, (int) intstat_start,
3073                            (int) intstat_length, (int) symbol_start,
3074                            (int) symbol_length) < 0)
3075       return SCPE_ARG;
3076 
3077     return SCPE_OK;
3078   }
3079 
3080 // LSB n:n   given a segment number and offset, return a segment name,
3081 //           component and offset in that component
3082 //     sname:cname+offset
3083 //           given a segment name, component name and offset, return
3084 //           the segment number and offset
3085 
3086 static t_stat lookup_system_book (UNUSED int32  arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3087   {
3088     char w1[strlen (buf)];
3089     char w2[strlen (buf)];
3090     char w3[strlen (buf)];
3091     long segno, offset;
3092 
3093     size_t colon = strcspn (buf, ":");
3094     if (buf[colon] != ':')
3095       return SCPE_ARG;
3096 
3097     strncpy (w1, buf, colon);
3098     w1[colon] = '\0';
3099     //sim_msg ("w1 <%s>\n", w1);
3100 
3101     size_t plus = strcspn (buf + colon + 1, "+");
3102     if (buf[colon + 1 + plus] == '+')
3103       {
3104         strncpy (w2, buf + colon + 1, plus);
3105         w2[plus] = '\0';
3106         (void)strcpy (w3, buf + colon + 1 + plus + 1);
3107       }
3108     else
3109       {
3110         (void)strcpy (w2, buf + colon + 1);
3111         (void)strcpy (w3, "");
3112       }
3113     //sim_msg ("w1 <%s>\n", w1);
3114     //sim_msg ("w2 <%s>\n", w2);
3115     //sim_msg ("w3 <%s>\n", w3);
3116 
3117     char * end1;
3118     segno = strtol (w1, & end1, 8);
3119     char * end2;
3120     offset = strtol (w2, & end2, 8);
3121 
3122     if (* end1 == '\0' && * end2 == '\0' && * w3 == '\0')
3123       {
3124         // n:n
3125         char * ans = lookup_address ((word18) segno, (word18) offset, NULL, NULL);
3126         sim_warn ("%s\n", ans ? ans : "not found");
3127       }
3128     else
3129       {
3130         if (* w3)
3131           {
3132             char * end3;
3133             offset = strtol (w3, & end3, 8);
3134             if (* end3 != '\0')
3135               return SCPE_ARG;
3136           }
3137         else
3138           offset = 0;
3139         long comp_offset;
3140         int rc = lookup_system_book_name (w1, w2, & segno, & comp_offset);
3141         if (rc)
3142           {
3143             sim_warn ("not found\n");
3144             return SCPE_OK;
3145           }
3146         sim_msg ("0%o:0%o\n", (uint) segno, (uint) (comp_offset + offset));
3147         abs_addr_n  ((int) segno, (uint) (comp_offset + offset));
3148       }
3149 /*
3150     if (sscanf (buf, "%o:%o", & segno, & offset) != 2)
3151       return SCPE_ARG;
3152     char * ans = lookup_address (segno, offset);
3153     sim_msg ("%s\n", ans ? ans : "not found");
3154 */
3155     return SCPE_OK;
3156   }
3157 
3158 // Assumes unpaged DSBR
3159 
3160 static sdw0_s *fetchSDW (word15 segno)
     /* [previous][next][first][last][top][bottom][index][help] */
3161   {
3162     cpu_state_t * cpup = _cpup;
3163     word36 SDWeven, SDWodd;
3164 
3165     core_read2 (cpup, (cpu.DSBR.ADDR + 2u * segno) & PAMASK, & SDWeven, & SDWodd,
3166                  __func__);
3167 
3168     // even word
3169 
3170     sdw0_s *SDW = & cpu._s;
3171     (void)memset (SDW, 0, sizeof (cpu._s));
3172 
3173     SDW->ADDR   = (SDWeven >> 12) & 077777777;
3174     SDW->R1     = (SDWeven >> 9)  & 7;
3175     SDW->R2     = (SDWeven >> 6)  & 7;
3176     SDW->R3     = (SDWeven >> 3)  & 7;
3177     SDW->DF     = TSTBIT (SDWeven,  2);
3178     SDW->FC     = SDWeven & 3;
3179 
3180     // odd word
3181     SDW->BOUND  = (SDWodd >> 21) & 037777;
3182     SDW->R      = TSTBIT (SDWodd,  20);
3183     SDW->E      = TSTBIT (SDWodd,  19);
3184     SDW->W      = TSTBIT (SDWodd,  18);
3185     SDW->P      = TSTBIT (SDWodd,  17);
3186     SDW->U      = TSTBIT (SDWodd,  16);
3187     SDW->G      = TSTBIT (SDWodd,  15);
3188     SDW->C      = TSTBIT (SDWodd,  14);
3189     SDW->EB     = SDWodd & 037777;
3190 
3191     return SDW;
3192   }
3193 
3194 static t_stat virtAddrN (uint address)
     /* [previous][next][first][last][top][bottom][index][help] */
3195   {
3196     cpu_state_t * cpup = _cpup;
3197     if (cpu.DSBR.U) {
3198         for(word15 segno = 0; 2u * segno < 16u * (cpu.DSBR.BND + 1u); segno += 1)
3199         {
3200             sdw0_s *s = fetchSDW(segno);
3201             if (address >= s -> ADDR && address < s -> ADDR + s -> BOUND * 16u)
3202               sim_msg ("  %06o:%06o\n", segno, address - s -> ADDR);
3203         }
3204     } else {
3205         for(word15 segno = 0;
3206             2u * segno < 16u * (cpu.DSBR.BND + 1u);
3207             segno += 512u)
3208         {
3209             word24 y1 = (2u * segno) % 1024u;
3210             word24 x1 = (2u * segno - y1) / 1024u;
3211             word36 PTWx1;
3212             core_read (cpup, (cpu.DSBR.ADDR + x1) & PAMASK, & PTWx1, __func__);
3213 
3214             ptw_s PTW1;
3215             PTW1.ADDR = GETHI(PTWx1);
3216             PTW1.U    = TSTBIT(PTWx1, 9);
3217             PTW1.M    = TSTBIT(PTWx1, 6);
3218             PTW1.DF   = TSTBIT(PTWx1, 2);
3219             PTW1.FC   = PTWx1 & 3;
3220 
3221             if (PTW1.DF == 0)
3222                 continue;
3223             //sim_msg ("%06o  Addr %06o U %o M %o DF %o FC %o\n",
3224             //            segno, PTW1.ADDR, PTW1.U, PTW1.M, PTW1.DF, PTW1.FC);
3225             //sim_msg ("    Target segment page table\n");
3226             for (word15 tspt = 0; tspt < 512u; tspt ++)
3227             {
3228                 word36 SDWeven, SDWodd;
3229                 core_read2(cpup, ((PTW1.ADDR << 6) + tspt * 2u) & PAMASK, & SDWeven,
3230                            & SDWodd, __func__);
3231                 sdw0_s SDW0;
3232                 // even word
3233                 SDW0.ADDR  = (SDWeven >> 12) & PAMASK;
3234                 SDW0.R1    = (SDWeven >> 9)  & 7u;
3235                 SDW0.R2    = (SDWeven >> 6)  & 7u;
3236                 SDW0.R3    = (SDWeven >> 3)  & 7u;
3237                 SDW0.DF    = TSTBIT(SDWeven,   2);
3238                 SDW0.FC    = SDWeven & 3u;
3239 
3240                 // odd word
3241                 SDW0.BOUND = (SDWodd >> 21) & 037777;
3242                 SDW0.R     = TSTBIT(SDWodd,   20);
3243                 SDW0.E     = TSTBIT(SDWodd,   19);
3244                 SDW0.W     = TSTBIT(SDWodd,   18);
3245                 SDW0.P     = TSTBIT(SDWodd,   17);
3246                 SDW0.U     = TSTBIT(SDWodd,   16);
3247                 SDW0.G     = TSTBIT(SDWodd,   15);
3248                 SDW0.C     = TSTBIT(SDWodd,   14);
3249                 SDW0.EB    = SDWodd & 037777;
3250 
3251                 if (SDW0.DF == 0)
3252                     continue;
3253                 //sim_msg ("    %06o Addr %06o %o,%o,%o F%o BOUND %06o "
3254                 //          "%c%c%c%c%c\n",
3255                 //          tspt, SDW0.ADDR, SDW0.R1, SDW0.R2, SDW0.R3, SDW0.F,
3256                 //          SDW0.BOUND, SDW0.R ? 'R' : '.', SDW0.E ? 'E' : '.',
3257                 //          SDW0.W ? 'W' : '.', SDW0.P ? 'P' : '.',
3258                 //          SDW0.U ? 'U' : '.');
3259                 if (SDW0.U == 0)
3260                 {
3261                     for (word18 offset = 0;
3262                          offset < 16u * (SDW0.BOUND + 1u);
3263                          offset += 1024)
3264                     {
3265                         word24 y2 = offset % 1024;
3266                         word24 x2 = (offset - y2) / 1024;
3267 
3268                         // 10. Fetch the target segment PTW(x2) from
3269                         //     SDW(segno).ADDR + x2.
3270 
3271                         word36 PTWx2;
3272                         core_read (cpup, (SDW0.ADDR + x2) & PAMASK, & PTWx2, __func__);
3273 
3274                         ptw_s PTW2;
3275                         PTW2.ADDR = GETHI(PTWx2);
3276                         PTW2.U    = TSTBIT(PTWx2, 9);
3277                         PTW2.M    = TSTBIT(PTWx2, 6);
3278                         PTW2.DF   = TSTBIT(PTWx2, 2);
3279                         PTW2.FC   = PTWx2 & 3;
3280 
3281                         //sim_msg ("        %06o  Addr %06o U %o M %o F %o "
3282                         //            "FC %o\n",
3283                         //            offset, PTW2.ADDR, PTW2.U, PTW2.M, PTW2.F,
3284                         //            PTW2.FC);
3285                         if (address >= PTW2.ADDR + offset &&
3286                             address < PTW2.ADDR + offset + 1024)
3287                           sim_msg ("  %06o:%06o\n", tspt, (address - offset) - PTW2.ADDR);
3288 
3289                       }
3290                   }
3291                 else
3292                   {
3293                     if (address >= SDW0.ADDR &&
3294                         address < SDW0.ADDR + SDW0.BOUND * 16u)
3295                       sim_msg ("  %06o:%06o\n", tspt, address - SDW0.ADDR);
3296                   }
3297             }
3298         }
3299     }
3300 
3301     return SCPE_OK;
3302 
3303   }
3304 
3305 // VIRTUAL address
3306 
3307 static t_stat virt_address (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3308   {
3309     uint address;
3310     if (sscanf (buf, "%o", & address) != 1)
3311       return SCPE_ARG;
3312     return virtAddrN (address);
3313   }
3314 
3315 // search path is path:path:path....
3316 
3317 static t_stat set_search_path (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3318   {
3319 // Quietly ignore if debugging not enabled
3320 # if !defined(SPEED)
3321     if (source_search_path)
3322       FREE (source_search_path);
3323     source_search_path = strdup (buf);
3324     if (!source_search_path)
3325       {
3326         (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
3327                        __func__, __FILE__, __LINE__);
3328 #  if defined(USE_BACKTRACE)
3329 #   if defined(SIGUSR2)
3330         (void)raise(SIGUSR2);
3331         /*NOTREACHED*/ /* unreachable */
3332 #   endif /* if defined(SIGUSR2) */
3333 #  endif /* if defined(USE_BACKTRACE) */
3334         abort();
3335       }
3336 # endif
3337     return SCPE_OK;
3338   }
3339 
3340 // Hook for gdb
3341 //
3342 // The idea is that if you want to set a gdb breakpoint for a particularly
3343 // complex condition, you can add a test for the condition to the emulator
3344 // code and call brkbrk() when the condition is met; by doing a gdb
3345 // 'b brkbrk', gdb will see when the condition is met.
3346 //
3347 
3348 t_stat brkbrk (UNUSED int32 arg, UNUSED const char *  buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3349   {
3350     //list_source (buf, 0);
3351     return SCPE_OK;
3352   }
3353 
3354 // SBREAK segno:offset
3355 
3356 static t_stat sbreak (int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3357   {
3358     //(void)printf (">> <%s>\n", buf);
3359     int segno, offset;
3360     int where;
3361     int cnt = sscanf (buf, "%o:%o%n", & segno, & offset, & where);
3362     if (cnt != 2)
3363       {
3364         return SCPE_ARG;
3365       }
3366     char reformatted[strlen (buf) + 20];
3367     (void)sprintf (reformatted, "0%04o%06o%s", segno, offset, buf + where);
3368     //(void)printf (">> <%s>\n", reformatted);
3369     t_stat rc = brk_cmd (arg, reformatted);
3370     return rc;
3371   }
3372 
3373 # if defined(DVFDBG)
3374 static t_stat dfx1entry (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3375   {
3376 // divide_fx1, divide_fx3
3377     sim_msg ("dfx1entry\n");
3378     sim_msg ("rA %012"PRIo64" (%llu)\n", rA, rA);
3379     sim_msg ("rQ %012"PRIo64" (%llu)\n", rQ, rQ);
3380     // Figure out the caller's text segment, according to pli_operators.
3381     // sp:tbp -> PR[6].SNR:046
3382     word24 pa;
3383     char * msg;
3384     if (dbgLookupAddress (cpu.PR[6].SNR, 046, & pa, & msg))
3385       {
3386         sim_msg ("text segment number lookup failed because %s\n", msg);
3387       }
3388     else
3389       {
3390         sim_msg ("text segno %012"PRIo64" (%llu)\n", M[pa], M[pa]);
3391       }
3392 sim_msg ("%05o:%06o\n", cpu.PR[2].SNR, cpu.rX[0]);
3393 //dbgStackTrace ();
3394     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.rX[0], & pa, & msg))
3395       {
3396         sim_msg ("return address lookup failed because %s\n", msg);
3397       }
3398     else
3399       {
3400         sim_msg ("scale %012"PRIo64" (%llu)\n", M[pa], M[pa]);
3401       }
3402     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.PR[2].WORDNO, & pa, & msg))
3403       {
3404         sim_msg ("divisor address lookup failed because %s\n", msg);
3405       }
3406     else
3407       {
3408         sim_msg ("divisor %012"PRIo64" (%llu)\n", M[pa], M[pa]);
3409       }
3410     return SCPE_OK;
3411   }
3412 
3413 static t_stat dfx1exit (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3414   {
3415     sim_msg ("dfx1exit\n");
3416     sim_msg ("rA %012"PRIo64" (%llu)\n", rA, rA);
3417     sim_msg ("rQ %012"PRIo64" (%llu)\n", rQ, rQ);
3418     return SCPE_OK;
3419   }
3420 
3421 static t_stat dv2scale (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3422   {
3423     sim_msg ("dv2scale\n");
3424     sim_msg ("rQ %012"PRIo64" (%llu)\n", rQ, rQ);
3425     return SCPE_OK;
3426   }
3427 
3428 static t_stat dfx2entry (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3429   {
3430 // divide_fx2
3431     sim_msg ("dfx2entry\n");
3432     sim_msg ("rA %012"PRIo64" (%llu)\n", rA, rA);
3433     sim_msg ("rQ %012"PRIo64" (%llu)\n", rQ, rQ);
3434     // Figure out the caller's text segment, according to pli_operators.
3435     // sp:tbp -> PR[6].SNR:046
3436     word24 pa;
3437     char * msg;
3438     if (dbgLookupAddress (cpu.PR[6].SNR, 046, & pa, & msg))
3439       {
3440         sim_msg ("text segment number lookup failed because %s\n", msg);
3441       }
3442     else
3443       {
3444         sim_msg ("text segno %012"PRIo64" (%llu)\n", M[pa], M[pa]);
3445       }
3446 
3447 
3448 
3449 
3450 
3451 
3452 
3453 
3454 
3455 
3456 
3457 
3458 
3459 
3460 
3461 
3462 
3463 
3464 
3465 
3466 
3467 
3468 
3469 
3470 
3471 
3472     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.PR[2].WORDNO, & pa, & msg))
3473       {
3474         sim_msg ("divisor address lookup failed because %s\n", msg);
3475       }
3476     else
3477       {
3478         sim_msg ("divisor %012"PRIo64" (%llu)\n", M[pa], M[pa]);
3479         sim_msg ("divisor %012"PRIo64" (%llu)\n", M[pa + 1], M[pa + 1]);
3480       }
3481     return SCPE_OK;
3482   }
3483 
3484 static t_stat mdfx3entry (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3485   {
3486 // operator to form mod(fx2,fx1)
3487 // entered with first arg in q, bp pointing at second
3488 
3489 // divide_fx1, divide_fx2
3490     sim_msg ("mdfx3entry\n");
3491     //sim_msg ("rA %012"PRIo64" (%llu)\n", rA, rA);
3492     sim_msg ("rQ %012"PRIo64" (%llu)\n", rQ, rQ);
3493     // Figure out the caller's text segment, according to pli_operators.
3494     // sp:tbp -> PR[6].SNR:046
3495     word24 pa;
3496     char * msg;
3497     if (dbgLookupAddress (cpu.PR[6].SNR, 046, & pa, & msg))
3498       {
3499         sim_msg ("text segment number lookup failed because %s\n", msg);
3500       }
3501     else
3502       {
3503         sim_msg ("text segno %012"PRIo64" (%llu)\n", M[pa], M[pa]);
3504       }
3505 //sim_msg ("%05o:%06o\n", cpu.PR[2].SNR, cpu.rX[0]);
3506 //dbgStackTrace ();
3507 
3508 
3509 
3510 
3511 
3512 
3513 
3514 
3515 
3516 
3517     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.PR[2].WORDNO, & pa, & msg))
3518       {
3519         sim_msg ("divisor address lookup failed because %s\n", msg);
3520       }
3521     else
3522       {
3523         sim_msg ("divisor %012"PRIo64" (%llu)\n", M[pa], M[pa]);
3524       }
3525     return SCPE_OK;
3526   }
3527 
3528 static t_stat smfx1entry (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3529   {
3530 // operator to form mod(fx2,fx1)
3531 // entered with first arg in q, bp pointing at second
3532 
3533 // divide_fx1, divide_fx2
3534     sim_msg ("smfx1entry\n");
3535     //sim_msg ("rA %012"PRIo64" (%llu)\n", rA, rA);
3536     sim_msg ("rQ %012"PRIo64" (%llu)\n", rQ, rQ);
3537     // Figure out the caller's text segment, according to pli_operators.
3538     // sp:tbp -> PR[6].SNR:046
3539     word24 pa;
3540     char * msg;
3541     if (dbgLookupAddress (cpu.PR[6].SNR, 046, & pa, & msg))
3542       {
3543         sim_msg ("text segment number lookup failed because %s\n", msg);
3544       }
3545     else
3546       {
3547         sim_msg ("text segno %012"PRIo64" (%llu)\n", M[pa], M[pa]);
3548       }
3549 sim_msg ("%05o:%06o\n", cpu.PR[2].SNR, cpu.rX[0]);
3550 //dbgStackTrace ();
3551     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.rX[0], & pa, & msg))
3552       {
3553         sim_msg ("return address lookup failed because %s\n", msg);
3554       }
3555     else
3556       {
3557         sim_msg ("scale %012"PRIo64" (%llu)\n", M[pa], M[pa]);
3558       }
3559     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.PR[2].WORDNO, & pa, & msg))
3560       {
3561         sim_msg ("divisor address lookup failed because %s\n", msg);
3562       }
3563     else
3564       {
3565         sim_msg ("divisor %012"PRIo64" (%llu)\n", M[pa], M[pa]);
3566       }
3567     return SCPE_OK;
3568   }
3569 # endif // DVFDBG
3570 
3571 // SEARCHMEMORY value
3572 
3573 static t_stat search_memory (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3574   {
3575     word36 value;
3576     if (sscanf (buf, "%llo", & value) != 1)
3577       return SCPE_ARG;
3578 
3579     uint i;
3580     for (i = 0; i < MEMSIZE; i ++)
3581       if ((M[i] & DMASK) == value)
3582         sim_msg ("%08o\n", i);
3583     return SCPE_OK;
3584   }
3585 
3586 static t_stat set_dbg_cpu_mask (int32 UNUSED arg, const char * UNUSED buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3587   {
3588     uint msk;
3589     int cnt = sscanf (buf, "%u", & msk);
3590     if (cnt != 1)
3591       {
3592         sim_msg ("Huh?\n");
3593         return SCPE_ARG;
3594       }
3595     sim_msg ("mask set to %u\n", msk);
3596     dbgCPUMask = msk;
3597     return SCPE_OK;
3598   }
3599 
3600 #endif // TESTING
3601 
3602 //
3603 // Misc. commands
3604 //
3605 
3606 #if defined(PANEL68)
3607 static t_stat scraper (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3608   {
3609     if (strcasecmp (buf, "start") == 0)
3610       return panelScraperStart ();
3611     if (strcasecmp (buf, "stop") == 0)
3612       return panelScraperStop ();
3613     if (strcasecmp (buf, "msg") == 0)
3614       {
3615         return panelScraperMsg (NULL);
3616       }
3617     if (strncasecmp (buf, "msg ", 4) == 0)
3618       {
3619         const char * p = buf + 4;
3620         while (* p == ' ')
3621           p ++;
3622         return panelScraperMsg (p);
3623       }
3624     sim_msg ("err: scraper start|stop|msg\n");
3625     return SCPE_ARG;
3626   }
3627 #endif
3628 
3629 #if defined(YIELD)
3630 static t_stat clear_yield (int32 flag, UNUSED const char * cptr)
     /* [previous][next][first][last][top][bottom][index][help] */
3631   {
3632     return SCPE_OK;
3633   }
3634 
3635 static t_stat yield (int32 flag, UNUSED const char * cptr)
     /* [previous][next][first][last][top][bottom][index][help] */
3636   {
3637     return SCPE_OK;
3638   }
3639 #endif
3640 
3641 #if !defined(PERF_STRIP)
3642 static t_stat set_luf (int32 flag, UNUSED const char * cptr)
     /* [previous][next][first][last][top][bottom][index][help] */
3643   {
3644     luf_flag = flag;
3645     return SCPE_OK;
3646   }
3647 #endif /* if !defined(PERF_STRIP) */
3648 
3649 #if defined(DBGEVENT)
3650 uint n_dbgevents;
3651 struct dbgevent_t dbgevents[max_dbgevents];
3652 struct timespec dbgevent_t0;
3653 
3654 static int dbgevent_compar (const void * a, const void * b)
     /* [previous][next][first][last][top][bottom][index][help] */
3655   {
3656     struct dbgevent_t * ea = (struct dbgevent_t *) a;
3657     struct dbgevent_t * eb = (struct dbgevent_t *) b;
3658     if (ea->segno < eb->segno)
3659       return -1;
3660     if (ea->segno > eb->segno)
3661       return 1;
3662     if (ea->offset < eb->offset)
3663       return -1;
3664     if (ea->offset > eb->offset)
3665       return 1;
3666     return 0;
3667   }
3668 
3669 int dbgevent_lookup (word15 segno, word18 offset)
     /* [previous][next][first][last][top][bottom][index][help] */
3670   {
3671     struct dbgevent_t key = {segno, offset, false};
3672     struct dbgevent_t * p = (struct dbgevent_t *) bsearch (& key, dbgevents, (size_t) n_dbgevents,
3673             sizeof (struct dbgevent_t), dbgevent_compar);
3674     if (! p)
3675       return -1;
3676     return (int) (p - dbgevents);
3677   }
3678 
3679 // "dbbevent segno:offset"
3680 //
3681 // arg: 0 set t0 event
3682 //      1 set event
3683 //      2 clear event
3684 //      3 list events
3685 //      4 clear all events
3686 
3687 // XXX think about per-thread timing?
3688 
3689 static t_stat set_dbgevent (int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3690   {
3691     if (arg == 0 || arg == 1)
3692       {
3693         if (n_dbgevents >= max_dbgevents)
3694           {
3695             sim_printf ("too many dbgevents %u/%u\r\n", n_dbgevents, max_dbgevents);
3696             return SCPE_ARG;
3697           }
3698         if (strlen (buf) > dbgevent_tagsize - 1)
3699           {
3700             sim_printf ("command too long %lu/%u\r\n", strlen (buf), dbgevent_tagsize -1);
3701             return SCPE_ARG;
3702           }
3703 
3704         uint segno;
3705         uint offset;
3706         if (sscanf (buf, "%o:%o", & segno, & offset) != 2)
3707           return SCPE_ARG;
3708         if (segno > MASK15 || offset > MASK18)
3709           return SCPE_ARG;
3710         if (dbgevent_lookup ((word15) segno, (word18) offset) != -1)
3711           {
3712             sim_printf ("not adding duplicate 0%o:0%o\r\n", segno, offset);
3713             return SCPE_ARG;
3714           }
3715         dbgevents[n_dbgevents].segno                     = (word15) segno;
3716         dbgevents[n_dbgevents].offset                    = (word18) offset;
3717         dbgevents[n_dbgevents].t0                        = arg == 0;
3718         strncpy (dbgevents[n_dbgevents].tag, buf, dbgevent_tagsize - 1);
3719         dbgevents[n_dbgevents].tag[dbgevent_tagsize - 1] = 0;
3720         sim_printf ("%o:%o %u(%d) %s\r\n", dbgevents[n_dbgevents].segno,
3721             dbgevents[n_dbgevents].offset,
3722                 dbgevents[n_dbgevents].t0, arg, dbgevents[n_dbgevents].tag);
3723         n_dbgevents ++;
3724         qsort (dbgevents, n_dbgevents, sizeof (struct dbgevent_t), dbgevent_compar);
3725       }
3726     else if (arg == 2)
3727       {
3728         uint segno;
3729         uint offset;
3730         if (sscanf (buf, "%o:%o", & segno, & offset) != 2)
3731           return SCPE_ARG;
3732         int n = dbgevent_lookup ((word15) segno, (word18) offset);
3733         if (n < 0)
3734           {
3735             sim_printf ("0%o:0%o not found\r\n", segno, offset);
3736             return SCPE_ARG;
3737           }
3738         for (int i = n; i < n_dbgevents - 1; i ++)
3739           dbgevents[i] = dbgevents[i + 1];
3740         n_dbgevents --;
3741       }
3742     else if (arg == 3)
3743       {
3744         for (int i = 0; i < n_dbgevents; i ++)
3745          sim_printf ("    %s %05o:%06o %s\r\n", dbgevents[i].t0 ? "T0" : "  ", dbgevents[i].segno,
3746                  dbgevents[i].offset,dbgevents[i].tag);
3747       }
3748     else if (arg == 4)
3749       {
3750         n_dbgevents = 0;
3751         sim_printf ("dbgevents cleared\r\n");
3752       }
3753     else
3754       {
3755         sim_printf ("set_dbgevent bad arg %d\r\n", arg);
3756         return SCPE_ARG;
3757       }
3758     return SCPE_OK;
3759   }
3760 #endif
3761 
3762 //  REWIND name
3763 //
3764 //  rewind tapa_05
3765 //
3766 
3767 t_stat rewind_media (int32 arg, const char * buf) {
     /* [previous][next][first][last][top][bottom][index][help] */
3768   char name[strlen (buf)];
3769 
3770   int rc = sscanf (buf, "%s", name);
3771   if (rc != 1)
3772     return SCPE_ARG;
3773 
3774   for (uint i = 0; i < N_MT_UNITS_MAX; i ++) {
3775     if (strcmp (tape_states[i].device_name, name) == 0) {
3776       UNIT * unitp = & mt_unit [i];
3777       return sim_tape_rewind (unitp);
3778     }
3779   }
3780 
3781   sim_printf ("Can't find name '%s'\r\n", name);
3782   sim_printf ("REWIND device_name\r\n");
3783   return SCPE_ARG;
3784 }
3785 
3786 // [UN]LOAD  name  image_name ro|rw
3787 //
3788 //  load tapea_05  data.tap ro
3789 //
3790 //  load diskb_01  data.dsk rw
3791 //
3792 
3793 t_stat load_media (int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3794   {
3795     // arg 1: load
3796     //     0: unload
3797 
3798     char  name[strlen (buf)];
3799     char fname[strlen (buf)];
3800     char  perm[strlen (buf)];
3801     bool ro = false;
3802     if (arg)
3803       {
3804         int rc = sscanf (buf, "%s %s %s", name, fname, perm);
3805         if (rc != 3)
3806           return SCPE_ARG;
3807         if (strcasecmp (perm, "rw") == 0)
3808           ro = false;
3809         else if (strcasecmp (perm, "ro") == 0)
3810           ro = true;
3811         else
3812           {
3813              sim_print ("'%s' not 'ro' or 'rw'\r\n", perm);
3814              goto usage;
3815           }
3816       }
3817     else
3818       {
3819         int rc = sscanf (buf, "%s", name);
3820         if (rc != 1)
3821           return SCPE_ARG;
3822       }
3823 
3824     for (uint i = 0; i < N_DSK_UNITS_MAX; i ++)
3825       if (strcmp (dsk_states[i].device_name, name) == 0)
3826         {
3827           if (arg)
3828             return loadDisk (i, fname, ro);
3829           return unloadDisk (i);
3830         }
3831 
3832     for (uint i = 0; i < N_MT_UNITS_MAX; i ++)
3833       if (strcmp (tape_states[i].device_name, name) == 0)
3834         {
3835           if (arg)
3836             return loadTape (i, fname, ro);
3837           return unloadTape (i);
3838         }
3839 
3840     sim_printf ("Can't find name '%s'\r\n", name);
3841 usage:
3842     sim_printf ("[UN]LOAD device_name image_name ro|rw\r\n");
3843     return SCPE_ARG;
3844   }
3845 
3846 t_stat ready_media (int32 arg, const char * buf) {
     /* [previous][next][first][last][top][bottom][index][help] */
3847   char name[strlen (buf)];
3848   int rc = sscanf (buf, "%s", name);
3849   if (rc != 1)
3850     return SCPE_ARG;
3851 
3852   for (uint i = 0; i < N_DSK_UNITS_MAX; i ++) {
3853     if (strcmp (dsk_states[i].device_name, name) == 0) {
3854       return signal_disk_ready (i);
3855     }
3856   }
3857 
3858   for (uint i = 0; i < N_MT_UNITS_MAX; i ++) {
3859     if (strcmp (tape_states[i].device_name, name) == 0) {
3860       return signal_tape (i, 0, 020 /* tape drive to ready */); //-V536
3861     }
3862   }
3863 
3864   sim_printf ("Can't find name '%s'\r\n", name);
3865   sim_printf ("[UN]LOAD device_name image_name ro|rw\r\n");
3866   return SCPE_ARG;
3867 }
3868 
3869 ////////////////////////////////////////////////////////////////////////////////
3870 //
3871 // s*mh Command table
3872 //
3873 
3874 #if defined(TESTING)
3875 # include "tracker.h"
3876 
3877 static t_stat trkw (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3878   {
3879     trk_init (true);
3880     return SCPE_OK;
3881   }
3882 
3883 static t_stat trkr (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3884   {
3885     trk_init (false);
3886     return SCPE_OK;
3887   }
3888 #endif
3889 
3890 #if !defined(PERF_STRIP)
3891 static CTAB dps8_cmds[] =
3892   {
3893 //
3894 // System configuration
3895 //
3896 
3897     {"DEFAULT_BASE_SYSTEM", set_default_base_system,  0, "Set configuration to defaults\n",             NULL, NULL},
3898 
3899     {"CABLE",               sys_cable,                0, "String a cable.\n",                           NULL, NULL},
3900     {"UNCABLE",             sys_cable,                1, "Unstring a cable.\n",                         NULL, NULL},
3901     {"CABLE_RIPOUT",        sys_cable_ripout,         0, "Remove all cables from the configuration.\n", NULL, NULL},
3902     {"CABLE_SHOW",          sys_cable_show,           0, "Show the current cabling configuration.\n",   NULL, NULL},
3903 
3904     {"FNPSERVERPORT",       set_fnp_server_port,      0, "Set the FNP dialin TELNET port number\n",     NULL, NULL},
3905     {"FNPSERVERADDRESS",    set_fnp_server_address,   0, "Set the FNP dialin server binding address\n", NULL, NULL},
3906     {"FNPSERVER3270PORT",   set_fnp_3270_server_port, 0, "Set the FNP TN3270 dialin port number\n",     NULL, NULL},
3907 
3908 //
3909 // System control
3910 //
3911 
3912     {"SKIPBOOT",  boot_skip,                     0, "Skip forward on boot tape\n",                                    NULL, NULL},
3913     {"FNPSTART",  fnp_start,                     0, "Directs the simulator to immediately start listening for FNP connections.\n",
3914                                                                                                                       NULL, NULL},
3915     {"MOUNT",     mount_tape,                    0, "Mount tape image and signal Multics\n",                          NULL, NULL},
3916     {"LOAD",      load_media,                    1, "Mount disk or tape image and signal Multics\n",                  NULL, NULL},
3917     {"UNLOAD",    load_media,                    0, "Unmount disk or tape image and signal Multics\n",                NULL, NULL},
3918     {"READY",     ready_media,                   0, "Signal Multics that media is ready\n",                           NULL, NULL},
3919     {"REWIND",    rewind_media,                  0, "Rewind tape\n",                                                  NULL, NULL},
3920     {"XF",        do_execute_fault,              0, "Execute fault: Press the execute fault button\n",                NULL, NULL},
3921     {"RESTART",   do_restart,                    0, "Execute fault: Press the execute fault button\n",                NULL, NULL},
3922     {"POLL",      set_sys_polling_interval,      0, "Set polling interval (in milliseconds)\n",                       NULL, NULL},
3923     {"SLOWPOLL",  set_sys_slow_polling_interval, 0, "Set slow polling interval (in polling intervals).\n",            NULL, NULL},
3924     {"CHECKPOLL", set_sys_poll_check_rate,       0, "Set polling check rate (in polling intervals).\n",               NULL, NULL},
3925     {"BURST",     burst_printer,                 0, "Burst process output from printer.\n",                           NULL, NULL},
3926 
3927 //
3928 // Debugging
3929 //
3930 
3931 # if defined(TESTING)
3932     {"TRKW",               trkw,                  0, "Start tracking to track.dat\n",                            NULL, NULL},
3933     {"TRKR",               trkr,                  0, "Start comparing with track.dat\n",                         NULL, NULL},
3934     {"DBGMMECNTDWN",       dps_debug_mme_cntdwn,  0, "Enable debug after n MMEs\n",                              NULL, NULL},
3935     {"DBGSKIP",            dps_debug_skip,        0, "Skip first n TRACE debugs\n",                              NULL, NULL},
3936     {"DBGSTART",           dps_debug_start,       0, "Limit debugging to N > Cycle count\n",                     NULL, NULL},
3937     {"DBGSTOP",            dps_debug_stop,        0, "Limit debugging to N < Cycle count\n",                     NULL, NULL},
3938     {"DBGBREAK",           dps_debug_break,       0, "Break when N >= Cycle count\n",                            NULL, NULL},
3939     {"DBGSEGNO",           dps_debug_segno,       1, "Limit debugging to PSR == segno\n",                        NULL, NULL},
3940     {"NODBGSEGNO",         dps_debug_segno,       0, "Reset to debugging all segments\n",                        NULL, NULL},
3941     {"DBGRINGNO",          dps_debug_ringno,      0, "Limit debugging to PRR == ringno\n",                       NULL, NULL},
3942     {"DBGBAR",             dps_debug_bar,         1, "Limit debugging to BAR mode\n",                            NULL, NULL},
3943     {"NODBGBAR",           dps_debug_bar,         0, "Limit debugging to BAR mode\n",                            NULL, NULL},
3944     {"HDBG",               hdbg_size,             0, "Set history debugger buffer size\n",                       NULL, NULL},
3945     {"HDSEG",              hdbgSegmentNumber,     0, "Set history debugger segment number\n",                    NULL, NULL},
3946     {"HDBL",               hdbgBlacklist,         0, "Set history debugger blacklist\n",                         NULL, NULL},
3947     {"PHDBG",              hdbg_print,            0, "Display history size\n",                                   NULL, NULL},
3948     {"HDBG_CPU_MASK",      hdbg_cpu_mask,         0, "Set which CPUs to track (by mask)\n",                      NULL, NULL},
3949     {"ABSOLUTE",           abs_addr,              0, "Compute the absolute address of segno:offset\n",           NULL, NULL},
3950     {"STK",                stack_trace,           0, "Print a stack trace\n",                                    NULL, NULL},
3951     {"LIST",               list_source_at,        0, "List source for address / segno:offset\n",                 NULL, NULL},
3952     {"LD_SYSTEM_BOOK",     load_system_book,      0, "Load a Multics system book for symbolic debugging\n",      NULL, NULL},
3953     {"ASBE",               add_system_book_entry, 0, "Add an entry to the system book\n",                        NULL, NULL},
3954     {"LOOKUP_SYSTEM_BOOK", lookup_system_book,    0, "Lookup an address or symbol in the Multics system book\n", NULL, NULL},
3955     {"LSB",                lookup_system_book,    0, "Lookup an address or symbol in the Multics system book\n", NULL, NULL},
3956     {"VIRTUAL",            virt_address,          0, "Compute the virtual address(es) of segno:offset\n",        NULL, NULL},
3957     {"SPATH",              set_search_path,       0, "Set source code search path\n",                            NULL, NULL},
3958     {"TEST",               brkbrk,                0, "GDB test hook\n",                                          NULL, NULL},
3959 #  if defined(DBGEVENT)
3960     {"DBG0EVENT",          set_dbgevent,          0, "Set t0 debug event\n",                                     NULL, NULL},
3961     {"DBGEVENT",           set_dbgevent,          1, "Set debug event\n",                                        NULL, NULL},
3962     {"DBGNOEVENT",         set_dbgevent,          2, "Clear debug event\n",                                      NULL, NULL},
3963     {"DBGLISTEVENTS",      set_dbgevent,          3, "List debug events\n",                                      NULL, NULL},
3964     {"DBGCLEAREVENTS",     set_dbgevent,          4, "Clear debug events\n",                                     NULL, NULL},
3965 #  endif /* if defined(DBGEVENT) */
3966 #  define SSH_ST 0        /* set */
3967 #  define SSH_SH 1        /* show */
3968 #  define SSH_CL 2        /* clear */
3969     {"SBREAK",       sbreak,           SSH_ST, "Set a breakpoint with segno:offset syntax\n", NULL, NULL},
3970     {"NOSBREAK",     sbreak,           SSH_CL, "Unset an SBREAK\n",                           NULL, NULL},
3971 #  if defined(DVFDBG)
3972     // dvf debugging
3973     {"DFX1ENTRY",    dfx1entry,        0,      "\n",                                          NULL, NULL},
3974     {"DFX2ENTRY",    dfx2entry,        0,      "\n",                                          NULL, NULL},
3975     {"DFX1EXIT",     dfx1exit,         0,      "\n",                                          NULL, NULL},
3976     {"DV2SCALE",     dv2scale,         0,      "\n",                                          NULL, NULL},
3977     {"MDFX3ENTRY",   mdfx3entry,       0,      "\n",                                          NULL, NULL},
3978     {"SMFX1ENTRY",   smfx1entry,       0,      "\n",                                          NULL, NULL},
3979 #  endif /* if defined(DVFDBG) */
3980 #  if !defined(SPEED)
3981     {"WATCH",        set_mem_watch,    1,      "Watch memory location\n",                     NULL, NULL},
3982     {"NOWATCH",      set_mem_watch,    0,      "Unwatch memory location\n",                   NULL, NULL},
3983 #  endif /* if !defined(SPEED) */
3984     {"SEARCHMEMORY", search_memory,    0,      "Search memory for value\n",                   NULL, NULL},
3985     {"DBGCPUMASK",   set_dbg_cpu_mask, 0,      "Set per-CPU debug enable mask\n",             NULL, NULL},
3986 # endif /* if defined(TESTING) */
3987 
3988     {"SEGLDR",       segment_loader,   0,      "Segment Loader\n",                            NULL, NULL},
3989 
3990 //
3991 // Statistics
3992 //
3993 
3994 # if defined(MATRIX)
3995     {"DISPLAYMATRIX", display_the_matrix,  0, "Display instruction usage counts\n", NULL, NULL},
3996 # endif
3997 
3998 //
3999 // Console scripting
4000 //
4001 
4002     {"AUTOINPUT",     add_opc_autoinput,   0, "Set primary console auto-input\n",     NULL, NULL},
4003     {"AI",            add_opc_autoinput,   0, "Set primary console auto-input\n",     NULL, NULL},
4004     {"AUTOINPUT2",    add_opc_autoinput,   1, "Set secondary console auto-input\n",   NULL, NULL},
4005     {"AI2",           add_opc_autoinput,   1, "Set secondary console auto-input\n",   NULL, NULL},
4006     {"CLRAUTOINPUT",  clear_opc_autoinput, 0, "Clear primary console auto-input\n",   NULL, NULL},
4007     {"CLRAUTOINPUT2", clear_opc_autoinput, 1, "Clear secondary console auto-input\n", NULL, NULL},
4008 
4009 //
4010 // Tuning
4011 //
4012 
4013 # if YIELD
4014     {"CLEAR_YIELD",   clear_yield,         1, "Clear yield data points\n",            NULL, NULL},
4015     {"YIELD",         yield,               1, "Define yield data point\n",            NULL, NULL},
4016 # endif
4017 
4018 //
4019 // Hacks
4020 //
4021 
4022     {"LUF",           set_luf,             1, "Enable normal LUF handling\n",         NULL, NULL},
4023     {"NOLUF",         set_luf,             0, "Disable normal LUF handling\n",        NULL, NULL},
4024 
4025 //
4026 // Misc.
4027 //
4028 
4029 # if defined(PANEL68)
4030     {"SCRAPER",       scraper,             0, "Control panel scraper\n", NULL, NULL},
4031 # endif /* if defined(PANEL68) */
4032     { NULL,           NULL,                0, NULL,                      NULL, NULL}
4033   }; // dps8_cmds
4034 
4035 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) && !defined(PERF_STRIP)
4036 static void usr1_signal_handler (UNUSED int sig)
     /* [previous][next][first][last][top][bottom][index][help] */
4037   {
4038     sim_msg ("USR1 signal caught; pressing the EXF button\n");
4039     // Assume the bootload CPU
4040     setG7fault (ASSUME0, FAULT_EXF, fst_zero);
4041     return;
4042   }
4043 # endif
4044 
4045 static struct symbol_s symbols [] = {
4046     { "commit_id",              SYM_STATE_OFFSET,  SYM_STRING,    offsetof (struct system_state_s, commit_id)   },
4047     { "M[]",                    SYM_STATE_OFFSET,  SYM_ARRAY,     offsetof (struct system_state_s, M)           },
4048     { "sizeof(*M)",             SYM_STRUCT_SZ,     SYM_SZ,        sizeof (word36) },
4049 
4050     { "cpus[]",                 SYM_STATE_OFFSET,  SYM_ARRAY,     offsetof (struct system_state_s, cpus)        },
4051     { "sizeof(*cpus)",          SYM_STRUCT_SZ,     SYM_SZ,        sizeof (cpu_state_t) },
4052 
4053     { "cpus[].PPR",             SYM_STRUCT_OFFSET, SYM_PTR,       offsetof (cpu_state_t,           PPR)         },
4054     { "cpus[].PPR.PRR",         SYM_STRUCT_OFFSET, SYM_UINT8_3,   offsetof (struct ppr_s,          PRR)         },
4055     { "cpus[].PPR.PSR",         SYM_STRUCT_OFFSET, SYM_UINT16_15, offsetof (struct ppr_s,          PSR)         },
4056     { "cpus[].PPR.P",           SYM_STRUCT_OFFSET, SYM_UINT8_1,   offsetof (struct ppr_s,          P)           },
4057     { "cpus[].PPR.IC",          SYM_STRUCT_OFFSET, SYM_UINT32_18, offsetof (struct ppr_s,          IC)          },
4058 
4059     { "cpus[].cu",              SYM_STRUCT_OFFSET, SYM_PTR,       offsetof (cpu_state_t,           cu)          },
4060     { "cpus[].cu.IWB",          SYM_STRUCT_OFFSET, SYM_UINT64_36, offsetof (ctl_unit_data_t,       IWB)         },
4061     { "cpus[].cu.IR",           SYM_STRUCT_OFFSET, SYM_UINT32_18, offsetof (ctl_unit_data_t,       IR)          },
4062 
4063     { "cpus[].rA",              SYM_STRUCT_OFFSET, SYM_UINT64_36, offsetof (cpu_state_t,           rA)          },
4064 
4065     { "cpus[].rQ",              SYM_STRUCT_OFFSET, SYM_UINT64_36, offsetof (cpu_state_t,           rQ)          },
4066 
4067     { "cpus[].rE",              SYM_STRUCT_OFFSET, SYM_UINT64_36, offsetof (cpu_state_t,           rE)          },
4068 
4069     { "cpus[].rX[]",            SYM_STRUCT_OFFSET, SYM_ARRAY,     offsetof (cpu_state_t,           rX)          },
4070     { "sizeof(*rX)",            SYM_STRUCT_SZ,     SYM_SZ,        sizeof (word18) },
4071     { "cpus[].rX",              SYM_STRUCT_OFFSET, SYM_UINT32_18, 0 },
4072 
4073     { "cpus[].rTR",             SYM_STRUCT_OFFSET, SYM_UINT32_27, offsetof (cpu_state_t,           rTR)         },
4074 
4075     { "cpus[].rRALR",           SYM_STRUCT_OFFSET, SYM_UINT8_3,   offsetof (cpu_state_t,           rRALR)       },
4076 
4077     { "cpus[].PAR[]",           SYM_STRUCT_OFFSET, SYM_ARRAY,     offsetof (cpu_state_t,           PAR)         },
4078     { "sizeof(*PAR)",           SYM_STRUCT_SZ,     SYM_SZ,        sizeof (struct par_s) },
4079 
4080     { "cpus[].PAR[].SNR",       SYM_STRUCT_OFFSET, SYM_UINT16_15, offsetof (struct par_s,          SNR)         },
4081     { "cpus[].PAR[].RNR",       SYM_STRUCT_OFFSET, SYM_UINT8_3,   offsetof (struct par_s,          RNR)         },
4082     { "cpus[].PAR[].PR_BITNO",  SYM_STRUCT_OFFSET, SYM_UINT8_6,   offsetof (struct par_s,          PR_BITNO)    },
4083     { "cpus[].PAR[].WORDNO",    SYM_STRUCT_OFFSET, SYM_UINT32_18, offsetof (struct par_s,          WORDNO)      },
4084 
4085     { "cpus[].BAR",             SYM_STRUCT_OFFSET, SYM_PTR,       offsetof (cpu_state_t,           BAR)         },
4086     { "cpus[].BAR.BASE",        SYM_STRUCT_OFFSET, SYM_UINT16_9,  offsetof (struct bar_s,          BASE)        },
4087     { "cpus[].BAR.BOUND",       SYM_STRUCT_OFFSET, SYM_UINT16_9,  offsetof (struct bar_s,          BOUND)       },
4088 
4089     { "cpus[].TPR",             SYM_STRUCT_OFFSET, SYM_PTR,       offsetof (cpu_state_t,           TPR)         },
4090     { "cpus[].TPR.TRR",         SYM_STRUCT_OFFSET, SYM_UINT8_3,   offsetof (struct tpr_s,          TRR)         },
4091     { "cpus[].TPR.TSR",         SYM_STRUCT_OFFSET, SYM_UINT16_15, offsetof (struct tpr_s,          TSR)         },
4092     { "cpus[].TPR.TBR",         SYM_STRUCT_OFFSET, SYM_UINT8_6,   offsetof (struct tpr_s,          TBR)         },
4093     { "cpus[].TPR.CA",          SYM_STRUCT_OFFSET, SYM_UINT32_18, offsetof (struct tpr_s,          CA)          },
4094 
4095     { "cpus[].DSBR",            SYM_STRUCT_OFFSET, SYM_PTR,       offsetof (cpu_state_t,           DSBR)        },
4096     { "cpus[].DSBR.ADDR",       SYM_STRUCT_OFFSET, SYM_UINT32_24, offsetof (struct dsbr_s,         ADDR)        },
4097     { "cpus[].DSBR.BND",        SYM_STRUCT_OFFSET, SYM_UINT16_14, offsetof (struct dsbr_s,         BND)         },
4098     { "cpus[].DSBR.U",          SYM_STRUCT_OFFSET, SYM_UINT8_1,   offsetof (struct dsbr_s,         U)           },
4099     { "cpus[].DSBR.STACK",      SYM_STRUCT_OFFSET, SYM_UINT16_12, offsetof (struct dsbr_s,         STACK)       },
4100 
4101     { "cpus[].faultNumber",     SYM_STRUCT_OFFSET, SYM_UINT32,    offsetof (cpu_state_t,           faultNumber) },
4102 # define SYMTAB_ENUM32(e) { #e, SYM_ENUM,          SYM_UINT32,    e }
4103     SYMTAB_ENUM32 (FAULT_SDF),
4104     SYMTAB_ENUM32 (FAULT_STR),
4105     SYMTAB_ENUM32 (FAULT_MME),
4106     SYMTAB_ENUM32 (FAULT_F1),
4107     SYMTAB_ENUM32 (FAULT_TRO),
4108     SYMTAB_ENUM32 (FAULT_CMD),
4109     SYMTAB_ENUM32 (FAULT_DRL),
4110     SYMTAB_ENUM32 (FAULT_LUF),
4111     SYMTAB_ENUM32 (FAULT_CON),
4112     SYMTAB_ENUM32 (FAULT_PAR),
4113     SYMTAB_ENUM32 (FAULT_IPR),
4114     SYMTAB_ENUM32 (FAULT_ONC),
4115     SYMTAB_ENUM32 (FAULT_SUF),
4116     SYMTAB_ENUM32 (FAULT_OFL),
4117     SYMTAB_ENUM32 (FAULT_DIV),
4118     SYMTAB_ENUM32 (FAULT_EXF),
4119     SYMTAB_ENUM32 (FAULT_DF0),
4120     SYMTAB_ENUM32 (FAULT_DF1),
4121     SYMTAB_ENUM32 (FAULT_DF2),
4122     SYMTAB_ENUM32 (FAULT_DF3),
4123     SYMTAB_ENUM32 (FAULT_ACV),
4124     SYMTAB_ENUM32 (FAULT_MME2),
4125     SYMTAB_ENUM32 (FAULT_MME3),
4126     SYMTAB_ENUM32 (FAULT_MME4),
4127     SYMTAB_ENUM32 (FAULT_F2),
4128     SYMTAB_ENUM32 (FAULT_F3),
4129     SYMTAB_ENUM32 (FAULT_UN1),
4130     SYMTAB_ENUM32 (FAULT_UN2),
4131     SYMTAB_ENUM32 (FAULT_UN3),
4132     SYMTAB_ENUM32 (FAULT_UN4),
4133     SYMTAB_ENUM32 (FAULT_UN5),
4134     SYMTAB_ENUM32 (FAULT_TRB),
4135 
4136     { "",                       SYM_EMPTY,         SYM_UNDEF,     0 },
4137   };
4138 
4139 static void systabInit (void) {
     /* [previous][next][first][last][top][bottom][index][help] */
4140   strncpy (system_state->symbolTable.symtabHdr, SYMTAB_HDR, sizeof (system_state->symbolTable.symtabHdr));
4141   system_state->symbolTable.symtabVer = SYMTAB_VER;
4142   memcpy (system_state->symbolTable.symbols, symbols, sizeof (symbols)); //-V1086
4143 }
4144 #endif /* if !defined(PERF_STRIP) */
4145 
4146 static inline uint32_t
4147 hash32s(const void *buf, size_t len, uint32_t h)
     /* [previous][next][first][last][top][bottom][index][help] */
4148 {
4149   const unsigned char *p = buf;
4150 
4151   for (size_t i = 0; i < len; i++)
4152     h = h * 31 + p[i];
4153 
4154   h ^= h >> 17;
4155   h *= UINT32_C(0xed5ad4bb);
4156   h ^= h >> 11;
4157   h *= UINT32_C(0xac4c1b51);
4158   h ^= h >> 15;
4159   h *= UINT32_C(0x31848bab);
4160   h ^= h >> 14;
4161 
4162   return h;
4163 }
4164 
4165 // Once-only initialization; invoked via SCP
4166 
4167 static void dps8_init (void) {
     /* [previous][next][first][last][top][bottom][index][help] */
4168   int st1ret;
4169   (void)fflush(stderr);
4170   (void)fflush(stdout);
4171 #if !defined(PERF_STRIP)
4172   if (!sim_quiet) {
4173 # if defined(GENERATED_MAKE_VER_H) && defined(VER_H_GIT_VERSION)
4174 #  if defined(VER_H_GIT_PATCH_INT) && defined(VER_H_GIT_PATCH)
4175 #   if VER_H_GIT_PATCH_INT < 1
4176     sim_msg ("%s simulator %s (%ld-bit)",
4177              sim_name, VER_H_GIT_VERSION,
4178              (long)(CHAR_BIT*sizeof(void *)));
4179 #   else
4180     sim_msg ("%s simulator %s+%s (%ld-bit)",
4181              sim_name, VER_H_GIT_VERSION, VER_H_GIT_PATCH,
4182              (long)(CHAR_BIT*sizeof(void *)));
4183 #   endif
4184 #  else
4185     sim_msg ("%s simulator %s (%ld-bit)",
4186              sim_name, VER_H_GIT_VERSION,
4187              (long)(CHAR_BIT*sizeof(void *)));
4188 #  endif
4189 # endif
4190 # if !defined(VER_H_GIT_VERSION) || !defined(GENERATED_MAKE_VER_H)
4191     sim_msg ("%s simulator (%ld-bit)",
4192              sim_name, (long)(CHAR_BIT*sizeof(void *)));
4193 # endif
4194 
4195 /* TESTING */
4196 # if defined(TESTING)
4197     sim_msg ("\n Options: ");
4198 #  if !defined(HAVE_DPSOPT)
4199 #   define HAVE_DPSOPT 1
4200 #  endif
4201     sim_msg ("TESTING");
4202 # endif /* if defined(TESTING) */
4203 
4204 /* ISOLTS */
4205 # if defined(ISOLTS)
4206 #  if defined(HAVE_DPSOPT)
4207     sim_msg (", ");
4208 #  else
4209     sim_msg ("\n Options: ");
4210 #  endif
4211 #  if !defined(HAVE_DPSOPT)
4212 #   define HAVE_DPSOPT 1
4213 #  endif
4214     sim_msg ("ISOLTS");
4215 # endif /* if defined(ISOLTS) */
4216 
4217 /* NEED_128 */
4218 # if defined(NEED_128)
4219 #  if defined(HAVE_DPSOPT)
4220     sim_msg (", ");
4221 #  else
4222     sim_msg ("\n Options: ");
4223 #  endif
4224 #  if !defined(HAVE_DPSOPT)
4225 #   define HAVE_DPSOPT 1
4226 #  endif
4227     sim_msg ("NEED_128");
4228 # endif /* if defined(NEED_128) */
4229 
4230 /* NO_UCACHE */
4231 # if defined(NO_UCACHE)
4232 #  if defined(HAVE_DPSOPT)
4233     sim_msg (", ");
4234 #  else
4235     sim_msg ("\n Options: ");
4236 #  endif
4237 #  if !defined(HAVE_DPSOPT)
4238 #   define HAVE_DPSOPT 1
4239 #  endif
4240     sim_msg ("NO_UCACHE");
4241 # endif /* if defined(NO_UCACHE) */
4242 
4243 /* WAM */
4244 # if defined(WAM)
4245 #  if defined(HAVE_DPSOPT)
4246     sim_msg (", ");
4247 #  else
4248     sim_msg ("\n Options: ");
4249 #  endif
4250 #  if !defined(HAVE_DPSOPT)
4251 #   define HAVE_DPSOPT 1
4252 #  endif
4253     sim_msg ("WAM");
4254 # endif /* if defined(WAM) */
4255 
4256 /* ROUND_ROBIN */
4257 # if defined(ROUND_ROBIN)
4258 #  if defined(HAVE_DPSOPT)
4259     sim_msg (", ");
4260 #  else
4261     sim_msg ("\n Options: ");
4262 #  endif
4263 #  if !defined(HAVE_DPSOPT)
4264 #   define HAVE_DPSOPT 1
4265 #  endif
4266     sim_msg ("ROUND_ROBIN");
4267 # endif /* if defined(ROUND_ROBIN) */
4268 
4269 /* NO_LOCKLESS */
4270 # if !defined(LOCKLESS)
4271 #  if defined(HAVE_DPSOPT)
4272     sim_msg (", ");
4273 #  else
4274     sim_msg ("\n Options: ");
4275 #  endif
4276 #  if !defined(HAVE_DPSOPT)
4277 #   define HAVE_DPSOPT 1
4278 #  endif
4279     sim_msg ("NO_LOCKLESS");
4280 # endif /* if !defined(LOCKLESS) */
4281 
4282 /* ABSI */  /* XXX: Change to NO_ABSI once code is non-experimental */
4283 # if defined(WITH_ABSI_DEV)
4284 #  if defined(HAVE_DPSOPT)
4285     sim_msg (", ");
4286 #  else
4287     sim_msg ("\n Options: ");
4288 #  endif
4289 #  if !defined(HAVE_DPSOPT)
4290 #   define HAVE_DPSOPT 1
4291 #  endif
4292     sim_msg ("ABSI");
4293 # endif /* if defined(WITH_ABSI_DEV) */
4294 
4295 /* SOCKET */  /* XXX: Change to NO_SOCKET once code is non-experimental */
4296 # if defined(WITH_SOCKET_DEV)
4297 #  if defined(HAVE_DPSOPT)
4298     sim_msg (", ");
4299 #  else
4300     sim_msg ("\n Options: ");
4301 #  endif
4302 #  if !defined(HAVE_DPSOPT)
4303 #   define HAVE_DPSOPT 1
4304 #  endif
4305     sim_msg ("SOCKET");
4306 # endif /* if defined(WITH_SOCKET_DEV) */
4307 
4308 /* CHAOSNET */  /* XXX: Change to NO_CHAOSNET once code is non-experimental */
4309 # if defined(WITH_MGP_DEV)
4310 #  if defined(HAVE_DPSOPT)
4311     sim_msg (", ");
4312 #  else
4313     sim_msg ("\n Options: ");
4314 #  endif
4315 #  if !defined(HAVE_DPSOPT)
4316 #   define HAVE_DPSOPT 1
4317 #  endif
4318     sim_msg ("CHAOSNET");
4319 # endif /* if defined(WITH_MGP_DEV) */
4320 
4321 /* DUMA */
4322 # if defined(USE_DUMA)
4323 #  if defined(HAVE_DPSOPT)
4324     sim_msg (", ");
4325 #  else
4326     sim_msg ("\n Options: ");
4327 #  endif
4328 #  if !defined(HAVE_DPSOPT)
4329 #   define HAVE_DPSOPT 1
4330 #  endif
4331     sim_msg ("DUMA");
4332 # endif /* if defined(USE_DUMA) */
4333 
4334 # if defined(GENERATED_MAKE_VER_H) && defined(VER_H_GIT_HASH)
4335     sim_msg ("\n  Commit: %s", VER_H_GIT_HASH);
4336 # endif
4337     sim_msg ("\r\n\r\n");
4338     (void)fflush(stderr);
4339     (void)fflush(stdout);
4340   }
4341 
4342   // special dps8 initialization stuff that can't be done in reset, etc. ...
4343 
4344 # if defined(TESTING)
4345   // These are part of the scp interface
4346   sim_vm_parse_addr  = parse_addr;
4347   sim_vm_fprint_addr = fprint_addr;
4348 # endif /* if defined(TESTING) */
4349 
4350   sim_vm_cmd = dps8_cmds;
4351 
4352   // This is needed to make sbreak work
4353   sim_brk_types = sim_brk_dflt = SWMASK ('E');
4354 
4355 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64)
4356   // Wire the XF button to signal USR1
4357   signal (SIGUSR1, usr1_signal_handler);
4358   // On line 4,739 of the libuv man page, it recommends this.
4359   signal(SIGPIPE, SIG_IGN);
4360 # endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64) */
4361 
4362 #endif
4363 
4364 #if defined(__MINGW64__) || defined(__MINGW32__)
4365 # include "bsd_random.h"
4366 # define random  bsd_random
4367 # define srandom bsd_srandom
4368 #endif /* if defined(__MINGW64__) || defined(__MINGW32__) */
4369 
4370   char   rcap = 0;
4371   char   rnum = 0;
4372   struct timespec ts;
4373 
4374   char   rssuffix[24];
4375   (void)memset(rssuffix, 0, 24);
4376 
4377   char   statenme[32];
4378   (void)memset(statenme, 0, 32);
4379 
4380 #if defined(USE_MONOTONIC)
4381   st1ret = clock_gettime(CLOCK_MONOTONIC, &ts);
4382 #else
4383   st1ret = clock_gettime(CLOCK_REALTIME, &ts);
4384 #endif /* if defined(USE_MONOTONIC) */
4385   if (st1ret != 0)
4386     {
4387       (void)fprintf (stderr, "\rFATAL: clock_gettime failure! Aborting at %s[%s:%d]\r\n",
4388                      __func__, __FILE__, __LINE__);
4389 #if defined(USE_BACKTRACE)
4390 # if defined(SIGUSR2)
4391       (void)raise(SIGUSR2);
4392       /*NOTREACHED*/ /* unreachable */
4393 # endif /* if defined(SIGUSR2) */
4394 #endif /* if defined(USE_BACKTRACE) */
4395       abort();
4396     }
4397 
4398   uint32_t h = 0;  /* initial hash value */
4399 #if __STDC_VERSION__ < 201112L
4400   /* LINTED E_OLD_STYLE_FUNC_DECL */
4401   void *(*mallocptr)() = malloc;
4402   h = hash32s(&mallocptr, sizeof(mallocptr), h);
4403 #endif /* if __STDC_VERSION__ < 201112L */
4404   void *small = malloc(1);
4405   h = hash32s(&small, sizeof(small), h);
4406   FREE(small);
4407   void *big = malloc(1UL << 20);
4408   h = hash32s(&big, sizeof(big), h);
4409   FREE(big);
4410   void *ptr = &ptr;
4411   h = hash32s(&ptr, sizeof(ptr), h);
4412   time_t t = time(0);
4413   h = hash32s(&t, sizeof(t), h);
4414 #if !defined(_AIX)
4415   for (int i = 0; i < 1000; i++)
4416     {
4417       unsigned long counter = 0;
4418       clock_t start = clock();
4419       while (clock() == start)
4420         {
4421           counter++;
4422         }
4423       h = hash32s(&start, sizeof(start), h);
4424       h = hash32s(&counter, sizeof(counter), h);
4425     }
4426 #endif /* if !defined(_AIX) */
4427   int mypid = (int)getpid();
4428   h = hash32s(&mypid, sizeof(mypid), h);
4429   char rnd[4];
4430   FILE *f = fopen("/dev/urandom", "rb");
4431   if (f)
4432     {
4433       if (fread(rnd, sizeof(rnd), 1, f))
4434         {
4435           h = hash32s(rnd, sizeof(rnd), h);
4436         }
4437       fclose(f);
4438     }
4439   srandom(h); /* seed rng */
4440 
4441   for (int i = 1; i < 21; ++i) {
4442     rcap = (int)random() % 2;
4443     rnum = (int)random() % 3;
4444     if (!rnum) rnum = (((int)random() % 10) + 48);
4445     if (!rcap) rcap = 33;
4446     if (rnum >= 48) rssuffix[i-1]=rnum;
4447     else rssuffix[i-1]=(char)(((long)random() % 26) + 64) + rcap;
4448   }
4449 
4450 #if defined(__MINGW64__)   || \
4451     defined(__MINGW32__)   || \
4452     defined(CROSS_MINGW32) || \
4453     defined(CROSS_MINGW64)
4454   system_state = malloc (sizeof (struct system_state_s));
4455 #else
4456   if (sim_randstate)
4457     (void)sprintf(statenme, "%s.state", rssuffix);
4458   else
4459     (void)sprintf(statenme, "state");
4460   if (!sim_nostate)
4461     system_state = (struct system_state_s *)
4462       create_shm (statenme, sizeof (struct system_state_s));
4463   else
4464     system_state = malloc (sizeof (struct system_state_s));
4465 #endif
4466 
4467   if (!system_state) {
4468     int svErrno = errno;
4469     (void)fflush(stderr);
4470     (void)fflush(stdout);
4471     sim_warn ("\rFATAL: %s: aborting at %s[%s:%d]\r\n",
4472               xstrerror_l(svErrno),
4473               __func__, __FILE__, __LINE__);
4474 #if defined(USE_BACKTRACE)
4475 # if defined(SIGUSR2)
4476     (void)raise(SIGUSR2);
4477     /*NOTREACHED*/ /* unreachable */
4478 # endif /* if defined(SIGUSR2) */
4479 #endif /* if defined(USE_BACKTRACE) */
4480     exit (svErrno);
4481   }
4482 
4483 #if !defined(PERF_STRIP)
4484 
4485 # if !defined(VER_H_GIT_HASH)
4486 #  define VER_H_GIT_HASH "0000000000000000000000000000000000000000"
4487 # endif /* if !defined(VER_H_GIT_HASH) */
4488 
4489   (void)fflush(stdout);
4490   (void)fflush(stderr);
4491   if (strlen (system_state->commit_id) == 0) {
4492     if (!sim_quiet && sim_randstate && sim_randompst)
4493       sim_printf ("Initialized new system state file \"dps8m.%s\"\r\n",
4494                   statenme);
4495   } else {
4496     if (strcmp (system_state->commit_id, VER_H_GIT_HASH) != 0) {
4497       (void)memset(system_state, 0, sizeof(*system_state));
4498       sim_warn ("NOTE: State hash mismatch; system state reset.\r\n");
4499     }
4500   }
4501   (void)fflush(stderr);
4502   (void)fflush(stdout);
4503 
4504   strncpy (system_state->stateHdr, STATE_HDR, sizeof (system_state->stateHdr));
4505   system_state->stateVer = STATE_VER;
4506   strncpy (system_state->commit_id, VER_H_GIT_HASH, sizeof (system_state->commit_id));
4507 
4508   systabInit ();
4509 
4510   // sets connect to 0
4511   (void)memset (& sys_opts, 0, sizeof (sys_opts));
4512   // sys_poll_interval 10 ms (100 Hz)
4513   sys_opts.sys_poll_interval      = 10;
4514   // sys_slow_poll_interval 100 polls (1 Hz)
4515   sys_opts.sys_slow_poll_interval = 100;
4516   // sys_poll_check_rate in CPU cycles
4517   sys_opts.sys_poll_check_rate    = 1024;
4518 #endif // ! PERF_STRIP
4519 
4520 #if defined(PERF_STRIP)
4521   cpu_init ();
4522 #else
4523   sysCableInit ();
4524   iom_init ();
4525   disk_init ();
4526   mt_init ();
4527 # if defined(WITH_SOCKET_DEV)
4528 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
4529   sk_init ();
4530 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
4531 # endif /* if defined(WITH_SOCKET_DEV) */
4532   fnpInit ();
4533   console_init (); // must come after fnpInit due to libuv initialization
4534   scu_init ();
4535   cpu_init ();
4536   rdr_init ();
4537   pun_init ();
4538   prt_init ();
4539   urp_init ();
4540 
4541 # if defined(WITH_ABSI_DEV)
4542 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
4543   absi_init ();
4544 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
4545 # endif /* if defined(WITH_ABSI_DEV) */
4546 
4547 # if defined(WITH_MGP_DEV)
4548 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
4549   mgp_init ();
4550 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
4551 # endif /* if defined(WITH_MGP_DEV) */
4552 
4553   set_default_base_system (0, NULL);
4554 # if defined(PANEL68)
4555   panelScraperInit ();
4556 # endif /* if defined(PANEL68) */
4557 #endif
4558 #if defined(THREADZ) || defined(LOCKLESS)
4559   initThreadz ();
4560 #endif /* if defined(THREADZ) || defined(LOCKLESS) */
4561 }
4562 
4563 // Once-only shutdown; invoked via SCP
4564 
4565 static void dps8_exit (void) {
     /* [previous][next][first][last][top][bottom][index][help] */
4566   console_exit ();
4567   mt_exit ();
4568   fnpExit ();
4569 }
4570 
4571 #if defined(TESTING)
4572 static struct pr_table
4573   {
4574     char  * alias;    // pr alias
4575     int   n;          // number alias represents ....
4576   } _prtab[] =
4577   {
4578     { "pr0",   0 }, ///< pr0 - 7
4579     { "pr1",   1 },
4580     { "pr2",   2 },
4581     { "pr3",   3 },
4582     { "pr4",   4 },
4583     { "pr5",   5 },
4584     { "pr6",   6 },
4585     { "pr7",   7 },
4586 
4587     { "pr[0]", 0 }, ///< pr0 - 7
4588     { "pr[1]", 1 },
4589     { "pr[2]", 2 },
4590     { "pr[3]", 3 },
4591     { "pr[4]", 4 },
4592     { "pr[5]", 5 },
4593     { "pr[6]", 6 },
4594     { "pr[7]", 7 },
4595 
4596     // See: https://multicians.org/pg/mvm.html
4597     { "ap",    0 },
4598     { "ab",    1 },
4599     { "bp",    2 },
4600     { "bb",    3 },
4601     { "lp",    4 },
4602     { "lb",    5 },
4603     { "sp",    6 },
4604     { "sb",    7 },
4605     {    0,    0 }
4606   };
4607 
4608 static int getAddress(int segno, int offset)
     /* [previous][next][first][last][top][bottom][index][help] */
4609 {
4610     // XXX Do we need to 1st check SDWAM for segment entry?
4611 
4612     // get address of in-core segment descriptor word from DSBR
4613     sdw0_s *s = fetchSDW ((word15) segno);
4614 
4615     return (s->ADDR + (word18) offset) & 0xffffff; // keep to 24-bits
4616 }
4617 
4618 static t_addr parse_addr (UNUSED DEVICE * dptr, const char *cptr,
     /* [previous][next][first][last][top][bottom][index][help] */
4619                           const char **optr)
4620   {
4621     cpu_state_t * cpup = _cpup;
4622     // a segment reference?
4623     if (strchr(cptr, '|'))
4624     {
4625         static char addspec[256];
4626         (void)strcpy(addspec, cptr);
4627 
4628         *strchr(addspec, '|') = ' ';
4629 
4630         char seg[256], off[256];
4631         int params = sscanf(addspec, "%s %s", seg, off);
4632         if (params != 2)
4633         {
4634             sim_warn("parse_addr(): illegal number of parameters\n");
4635             *optr = cptr;   // signal error
4636             return 0;
4637         }
4638 
4639         // determine if segment is numeric or symbolic...
4640         char *endp;
4641         word18 PRoffset = 0;   // offset from PR[n] register (if any)
4642         int segno = (int)strtoll(seg, &endp, 8);
4643         if (endp == seg)
4644         {
4645             // not numeric...
4646             // 1st, see if it's a PR or alias thereof
4647             struct pr_table *prt = _prtab;
4648             while (prt->alias)
4649             {
4650                 if (strcasecmp(seg, prt->alias) == 0)
4651                 {
4652                     segno = cpu.PR[prt->n].SNR;
4653                     PRoffset = cpu.PR[prt->n].WORDNO;
4654                     break;
4655                 }
4656 
4657                 prt += 1;
4658             }
4659 
4660             if (!prt->alias)    // not a PR or alias
4661             {
4662               return 0;
4663             }
4664         }
4665 
4666         // determine if offset is numeric or symbolic entry point/segdef...
4667         uint offset = (uint)strtoll(off, &endp, 8);
4668         if (endp == off)
4669         {
4670             // not numeric...
4671             return 0;
4672         }
4673 
4674         // if we get here then seg contains a segment# and offset.
4675         // So, fetch the actual address given the segment & offset ...
4676         // ... and return this absolute, 24-bit address
4677 
4678         word24 abs_addr = (word24) getAddress(segno, (int) (offset + PRoffset));
4679 
4680         // TODO: only by luck does this work FixMe
4681         *optr = endp;   //cptr + strlen(cptr);
4682 
4683         return abs_addr;
4684     }
4685     else
4686     {
4687         // a PR or alias thereof
4688         int segno = 0;
4689         word24 offset = 0;
4690         struct pr_table *prt = _prtab;
4691         while (prt->alias)
4692         {
4693             if (strncasecmp(cptr, prt->alias, strlen(prt->alias)) == 0)
4694             {
4695                 segno  = cpu.PR[prt->n].SNR;
4696                 offset = cpu.PR[prt->n].WORDNO;
4697                 break;
4698             }
4699 
4700             prt += 1;
4701         }
4702         if (prt->alias)    // a PR or alias
4703         {
4704             word24 abs_addr = (word24) getAddress(segno, (int) offset);
4705             *optr = cptr + strlen(prt->alias);
4706 
4707             return abs_addr;
4708         }
4709     }
4710 
4711     // No, determine absolute address given by cptr
4712     return (t_addr)strtol(cptr, (char **) optr, 8);
4713 }
4714 #endif // TESTING
4715 
4716 #if defined(TESTING)
4717 static void fprint_addr (FILE * stream, UNUSED DEVICE *  dptr, t_addr simh_addr)
     /* [previous][next][first][last][top][bottom][index][help] */
4718 {
4719     (void)fprintf(stream, "%06o", simh_addr);
4720 }
4721 #endif // TESTING
4722 
4723 // This is part of the scp interface
4724 // Based on the switch variable, symbolically output to stream ofile the data in
4725 //  array val at the specified addr in unit uptr.
4726 // "fprint_sym" – Based on the switch variable, symbolically output to
4727 // stream ofile the data in array val at the specified addr in unit uptr.
4728 
4729 t_stat fprint_sym (UNUSED FILE * ofile, UNUSED t_addr addr,
     /* [previous][next][first][last][top][bottom][index][help] */
4730                    UNUSED t_value *val, UNUSED UNIT *uptr, int32 UNUSED sw)
4731 {
4732 #if defined(TESTING)
4733 // XXX Bug: assumes single cpu
4734 // XXX CAC: This seems rather bogus; deciding the output format based on the
4735 // address of the UNIT? Would it be better to use sim_unit.u3 (or some such
4736 // as a word width?
4737 
4738     cpu_state_t * cpup = _cpup;
4739 
4740     if (!((uint) sw & SWMASK ('M')))
4741         return SCPE_ARG;
4742 
4743     if (uptr == &cpu_dev.units[0])
4744     {
4745         word36 word1 = *val;
4746         char buf[256];
4747         // get base syntax
4748         char *d = disassemble(buf, word1);
4749 
4750         (void)fprintf(ofile, "%s", d);
4751 
4752         // decode instruction
4753         DCDstruct ci;
4754         DCDstruct * p = & ci;
4755         decode_instruction (cpup, word1, p);
4756 
4757         // MW EIS?
4758         if (p->info->ndes > 1)
4759         {
4760             // Yup, just output word values (for now)
4761             // XXX Need to complete MW EIS support in disassemble()
4762 
4763             for(uint n = 0 ; n < p->info->ndes; n += 1)
4764                 (void)fprintf(ofile, " %012llo", (unsigned long long int)val[n + 1]);
4765 
4766             return (t_stat) -p->info->ndes;
4767         }
4768 
4769         return SCPE_OK;
4770 
4771         //(void)fprintf(ofile, "%012"PRIo64"", *val);
4772         //return SCPE_OK;
4773     }
4774 #endif
4775     return SCPE_ARG;
4776 }
4777 
4778 // This is part of the scp interface
4779 //  – Based on the switch variable, parse character string cptr for a
4780 //  symbolic value val at the specified addr in unit uptr.
4781 
4782 t_stat parse_sym (UNUSED const char * cptr, UNUSED t_addr addr,
     /* [previous][next][first][last][top][bottom][index][help] */
4783                   UNUSED UNIT * uptr, UNUSED t_value * val, UNUSED int32 sswitch)
4784   {
4785     return SCPE_ARG;
4786   }
4787 
4788 // from MM
4789 
4790 sysinfo_t sys_opts;
4791 
4792 static t_stat sys_show_config (UNUSED FILE * st, UNUSED UNIT * uptr,
     /* [previous][next][first][last][top][bottom][index][help] */
4793                                UNUSED int  val, UNUSED const void * desc)
4794   {
4795     sim_msg ("IOM connect time:         %d\n",
4796                 sys_opts.iom_times.connect);
4797     return SCPE_OK;
4798 }
4799 
4800 static config_value_list_t cfg_timing_list[] =
4801   {
4802     { "disable", -1 },
4803     {  NULL,      0 }
4804   };
4805 
4806 bool breakEnable = false;
4807 
4808 static t_stat sys_set_break (UNUSED UNIT *  uptr, int32 value,
     /* [previous][next][first][last][top][bottom][index][help] */
4809                              UNUSED const char * cptr, UNUSED void * desc)
4810   {
4811     breakEnable = !! value;
4812     return SCPE_OK;
4813   }
4814 
4815 static t_stat sys_show_break (UNUSED FILE * st, UNUSED UNIT * uptr,
     /* [previous][next][first][last][top][bottom][index][help] */
4816                               UNUSED int  val, UNUSED const void * desc)
4817   {
4818     sim_msg ("BREAK %s\r\n", breakEnable ? "ON" : "OFF" );
4819     return SCPE_OK;
4820   }
4821 
4822 static config_value_list_t cfg_on_off [] =
4823   {
4824     { "off",     0 },
4825     { "on",      1 },
4826     { "disable", 0 },
4827     { "enable",  1 },
4828     {  NULL,     0 }
4829   };
4830 
4831 static config_list_t sys_config_list[] =
4832   {
4833     { "connect_time", -1,  100000, cfg_timing_list },
4834     { "color",         0,  1,      cfg_on_off      },
4835     { NULL,            0,  0,      NULL            }
4836  };
4837 
4838 static t_stat sys_set_config (UNUSED UNIT *  uptr, UNUSED int32 value,
     /* [previous][next][first][last][top][bottom][index][help] */
4839                               const char * cptr, UNUSED void * desc)
4840   {
4841     config_state_t cfg_state = { NULL, NULL };
4842 
4843     for (;;)
4844       {
4845         int64_t v;
4846         int rc = cfg_parse ("sys_set_config", cptr, sys_config_list, & cfg_state,
4847                            & v);
4848         if (rc == -1) // done
4849           {
4850             break;
4851           }
4852         if (rc == -2) // error
4853           {
4854             cfg_parse_done (& cfg_state);
4855             return SCPE_ARG;
4856           }
4857 
4858         const char * p = sys_config_list[rc].name;
4859         if (strcmp (p, "connect_time") == 0)
4860           sys_opts.iom_times.connect = (int) v;
4861         else if (strcmp (p, "color") == 0)
4862           sys_opts.no_color = ! v;
4863         else
4864           {
4865             sim_msg ("error: sys_set_config: Invalid cfg_parse rc <%ld>\n", (long) rc);
4866             cfg_parse_done (& cfg_state);
4867             return SCPE_ARG;
4868           }
4869       } // process statements
4870     cfg_parse_done (& cfg_state);
4871     return SCPE_OK;
4872   }
4873 
4874 static MTAB sys_mod[] =
4875   {
4876     {
4877       MTAB_dev_value,           /* Mask               */
4878       0,                        /* Match              */
4879       (char *) "CONFIG",        /* Print string       */
4880       (char *) "CONFIG",        /* Match string       */
4881       sys_set_config,           /* Validation routine */
4882       sys_show_config,          /* Display routine    */
4883       NULL,                     /* Value descriptor   */
4884       NULL,                     /* Help               */
4885     },
4886     {
4887       MTAB_dev_novalue,         /* Mask               */
4888       1,                        /* Match              */
4889       (char *) "BREAK",         /* Print string       */
4890       (char *) "BREAK",         /* Match string       */
4891       sys_set_break,            /* Validation routine */
4892       sys_show_break,           /* Display routine    */
4893       NULL,                     /* Value descriptor   */
4894       NULL,                     /* Help               */
4895     },
4896     {
4897       MTAB_dev_novalue,         /* Mask               */
4898       0,                        /* Match              */
4899       (char *) "NOBREAK",       /* Print string       */
4900       (char *) "NOBREAK",       /* Match string       */
4901       sys_set_break,            /* Validation routine */
4902       sys_show_break,           /* Display routine    */
4903       NULL,                     /* Value descriptor   */
4904       NULL,                     /* Help               */
4905     },
4906     MTAB_eol
4907   };
4908 
4909 static t_stat sys_reset (UNUSED DEVICE  * dptr)
     /* [previous][next][first][last][top][bottom][index][help] */
4910   {
4911     return SCPE_OK;
4912   }
4913 
4914 static DEVICE sys_dev = {
4915     "SYS",       /* Name                */
4916     NULL,        /* Units               */
4917     NULL,        /* Registers           */
4918     sys_mod,     /* Modifiers           */
4919     0,           /* #Units              */
4920     8,           /* Address radix       */
4921     PASIZE,      /* Address width       */
4922     1,           /* Address increment   */
4923     8,           /* Data radix          */
4924     36,          /* Data width          */
4925     NULL,        /* Examine routine     */
4926     NULL,        /* Deposit routine     */
4927     & sys_reset, /* Reset routine       */
4928     NULL,        /* Boot routine        */
4929     NULL,        /* Attach routine      */
4930     NULL,        /* Detach routine      */
4931     NULL,        /* Context             */
4932     0,           /* Flags               */
4933     0,           /* Debug control flags */
4934     0,           /* Debug flag names    */
4935     NULL,        /* Memory size change  */
4936     NULL,        /* Logical name        */
4937     NULL,        /* Help                */
4938     NULL,        /* Attach_help         */
4939     NULL,        /* Help_ctx            */
4940     NULL,        /* Description         */
4941     NULL         /* End                 */
4942 };
4943 
4944 // This is part of the scp interface
4945 DEVICE * sim_devices[] =
4946   {
4947     & cpu_dev, // dev[0] is special to the scp interface; it is the 'default device'
4948     & iom_dev,
4949     & tape_dev,
4950 #if defined(WITH_SOCKET_DEV)
4951 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64)
4952     & skc_dev,
4953 # endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64) */
4954 #endif /* if defined(WITH_SOCKET_DEV) */
4955     & mtp_dev,
4956     & fnp_dev,
4957     & dsk_dev,
4958     & ipc_dev,
4959     & msp_dev,
4960     & scu_dev,
4961     & opc_dev,
4962     & sys_dev,
4963     & urp_dev,
4964     & rdr_dev,
4965     & pun_dev,
4966     & prt_dev,
4967 
4968 #if defined(WITH_ABSI_DEV)
4969 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64)
4970     & absi_dev,
4971 # endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64) */
4972 #endif /* if defined(WITH_ABSI_DEV) */
4973 
4974 #if defined(WITH_MGP_DEV)
4975 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64)
4976     & mgp_dev,
4977 # endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64) */
4978 #endif /* if defined(WITH_MGP_DEV) */
4979 
4980     NULL
4981   };
4982 
4983 #if defined(PERF_STRIP)
4984 void dps8_init_strip (void)
     /* [previous][next][first][last][top][bottom][index][help] */
4985   {
4986     dps8_init ();
4987   }
4988 #endif /* if defined(PERF_STRIP) */

/* [previous][next][first][last][top][bottom][index][help] */