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

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