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

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