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

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