root/src/dps8/dps8_sys.c

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

DEFINITIONS

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

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

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