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

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