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_execute_switches
  7. do_restart
  8. set_sys_polling_interval
  9. set_sys_slow_polling_interval
  10. set_sys_poll_check_rate
  11. dps_debug_mme_cntdwn
  12. dps_debug_skip
  13. dps_debug_start
  14. dps_debug_stop
  15. dps_debug_break
  16. dps_debug_segno
  17. dps_debug_ringno
  18. dps_debug_bar
  19. abs_addr_n
  20. abs_addr
  21. lookup_book_segment
  22. add_book_segment
  23. add_book_component
  24. lookup_system_book_address
  25. lookup_address
  26. lookup_system_book_name
  27. list_source
  28. stack_trace
  29. list_source_at
  30. load_system_book
  31. add_system_book_entry
  32. lookup_system_book
  33. fetchSDW
  34. virtAddrN
  35. virt_address
  36. set_search_path
  37. brkbrk
  38. sbreak
  39. dfx1entry
  40. dfx1exit
  41. dv2scale
  42. dfx2entry
  43. mdfx3entry
  44. smfx1entry
  45. search_memory
  46. set_dbg_cpu_mask
  47. scraper
  48. clear_yield
  49. yield
  50. set_luf
  51. dbgevent_compar
  52. dbgevent_lookup
  53. set_dbgevent
  54. rewind_media
  55. load_media
  56. ready_media
  57. trkw
  58. trkr
  59. usr1_signal_handler
  60. systabInit
  61. hash32s
  62. dps8_init
  63. dps8_exit
  64. getAddress
  65. parse_addr
  66. fprint_addr
  67. fprint_sym
  68. parse_sym
  69. sys_show_config
  70. sys_set_break
  71. sys_show_break
  72. sys_set_config
  73. sys_reset
  74. 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 // SKIPBOOT [UNIT]: skip a record on the boot tape (default unit 0). The
1811 // T&D tape's first record is for DPS8s; the second (after the tape mark)
1812 // is for DPS8/Ms. T&D boots from drive 1 (device 0 of a tape controller
1813 // is the controller), so it needs "SKIPBOOT 1".
1814 
1815 static t_stat boot_skip (int32 UNUSED arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1816   {
1817     uint32 skipped;
1818     uint unit = 0;
1819     if (buf && * buf && sscanf (buf, "%u", & unit) != 1)
1820       return SCPE_ARG;
1821     if (unit >= N_MT_UNITS_MAX)
1822       return SCPE_ARG;
1823     t_stat rc = sim_tape_sprecsf (& mt_unit[unit], 1, & skipped);
1824     if (rc == SCPE_OK)
1825       tape_states[unit].rec_num ++;
1826     return rc;
1827   }
1828 
1829 // Simulate pressing the 'EXECUTE FAULT' button. Used as an
1830 // emergency interrupt of Multics if it hangs and becomes
1831 // unresponsive to the operators console.
1832 
1833 static t_stat do_execute_fault (UNUSED int32 arg,  UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1834   {
1835     // Assume bootload CPU
1836     setG7fault (0, FAULT_EXF);
1837     return SCPE_OK;
1838   }
1839 
1840 // EXECUTE DATA SWITCHES: execute the instruction in the data switches
1841 // (set them first, e.g. "set cpu0 config=data=000124717000" for XED 124)
1842 
1843 static t_stat do_execute_switches (UNUSED int32 arg,  UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1844   {
1845     // Assume bootload CPU
1846     press_execute_switches (0);
1847     return SCPE_OK;
1848   }
1849 
1850 // Simulate pressing the 'XED 10000' sequence; this starts BCE
1851 //
1852 //  sim> restart
1853 //  sim> go
1854 
1855 static t_stat do_restart (UNUSED int32 arg,  UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1856   {
1857     if (sim_is_running)
1858       {
1859         sim_printf ("Don't restart a running system....\r\n");
1860         return SCPE_ARG;
1861       }
1862     int n = 010000; //-V536
1863     if (buf)
1864       {
1865         n = (int) strtol (buf, NULL, 0);
1866       }
1867     sim_printf ("Restart entry 0%o\r\n", n);
1868 
1869     cpu_state_t * cpup = _cpup;
1870 
1871 
1872 
1873 
1874 
1875 
1876 
1877 
1878 
1879 
1880 
1881 
1882 
1883     cpu_reset_unit_idx (0, false);
1884     cpu.restart         = true;
1885     cpu.restart_address = (uint) n;
1886 
1887     t_stat rc = run_cmd (RU_CONT, "");
1888     return rc;
1889   }
1890 
1891 static t_stat set_sys_polling_interval (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1892   {
1893     if (! buf)
1894       return SCPE_ARG;
1895     int n = atoi (buf);
1896     if (n < 1 || n > 1000) // 1 millisecond to 1 second
1897       {
1898         sim_printf ("POLL %d: must be 1 (1 millisecond) to 1000 (1 second)\r\n", n);
1899         return SCPE_ARG;
1900       }
1901     sim_printf ("Polling set to %d milliseconds\r\n", n);
1902     sys_opts.sys_poll_interval = (uint) n;
1903     return SCPE_OK;
1904   }
1905 
1906 static t_stat set_sys_slow_polling_interval (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1907   {
1908     if (! buf)
1909       return SCPE_ARG;
1910     int n = atoi (buf);
1911     if (n < 1 || n > 1000) // 1 - slow poll every pool; 1000 - slow poll every 1000 polls
1912       {
1913         sim_printf ("SLOWPOLL %d: must be 1 (1 slow poll per pol) to 1000 (1 slow poll per 1000 polls)\r\n", n);
1914         return SCPE_ARG;
1915       }
1916     sim_printf ("Slow polling set to %d polls\r\n", n);
1917     sys_opts.sys_slow_poll_interval = (uint) n;
1918     return SCPE_OK;
1919   }
1920 
1921 static t_stat set_sys_poll_check_rate (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1922   {
1923     if (! buf)
1924       return SCPE_ARG;
1925     int n = atoi (buf);
1926     if (n < 1 || n > 1024*1024) // 1 - poll check rate in CPY cycles: 1 - check every cycle; 1024 check every 1024 cycles
1927       {
1928         sim_printf ("CHECKPOLL %d: must be 1 (check every cycle) to 1048576 (check every million cycles\r\n", n);
1929         return SCPE_ARG;
1930       }
1931     sim_printf ("Poll check rate set to %d CPU cycles\r\n", n);
1932     sys_opts.sys_poll_check_rate = (uint) n;
1933     return SCPE_OK;
1934   }
1935 #endif /* if !defined(PERF_STRIP) */
1936 
1937 //
1938 // Debugging commands
1939 //
1940 
1941 #if defined(TESTING)
1942 
1943 // Filter settings for our customized sim_debug
1944 
1945 // Start debug output at CPU cycle N.
1946 uint64 sim_deb_start      = 0;
1947 // Stop debug output at CPU cycle N.
1948 uint64 sim_deb_stop       = 0;
1949 // Break to scp prompt at CPU cycle N.
1950 uint64 sim_deb_break      = 0;
1951 // Enable CPU sim_debug iff PPR.PSR == N
1952 bool sim_deb_segno_on     = false;
1953 # if defined(NO_C_ELLIPSIS)
1954 bool sim_deb_segno[DEBUG_SEGNO_LIMIT];
1955 # else
1956 bool sim_deb_segno[DEBUG_SEGNO_LIMIT] = { [0 ... DEBUG_SEGNO_LIMIT - 1] = false };
1957 # endif
1958 // Enable CPU sim_debug iff PPR.PRR == N
1959 uint64 sim_deb_ringno     = NO_SUCH_RINGNO;
1960 // Suppress CPU sim_debug calls that pass all
1961 // of the filters after N times
1962 uint64 sim_deb_skip_limit = 0;
1963 // Suppress the first N CPU sim_debug calls
1964 // that pass all of the filters
1965 uint64 sim_deb_skip_cnt   = 0;
1966 // Suppress sim_debug until the MME instruction
1967 // has been executed N times
1968 uint64 sim_deb_mme_cntdwn = 0;
1969 // Suppress CPU sim_debug unless CPU number bit set
1970 uint dbgCPUMask           = 0377; // default all 8 on
1971 
1972 // Suppress CPU sim_debug unless BAR mode
1973 bool sim_deb_bar          = false;
1974 
1975 // Set the various filters
1976 
1977 static t_stat dps_debug_mme_cntdwn (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1978   {
1979     sim_deb_mme_cntdwn = strtoull (buf, NULL, 0);
1980     sim_msg ("Debug MME countdown set to %llu\r\n", (long long unsigned int)sim_deb_mme_cntdwn);
1981     return SCPE_OK;
1982   }
1983 
1984 static t_stat dps_debug_skip (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1985   {
1986     sim_deb_skip_cnt   = 0;
1987     sim_deb_skip_limit = strtoull (buf, NULL, 0);
1988     sim_msg ("Debug skip set to %llu\r\n", (long long unsigned int)sim_deb_skip_limit);
1989     return SCPE_OK;
1990   }
1991 
1992 static t_stat dps_debug_start (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
1993   {
1994     sim_deb_start = strtoull (buf, NULL, 0);
1995     sim_msg ("Debug set to start at cycle: %llu\r\n", (long long unsigned int)sim_deb_start);
1996     return SCPE_OK;
1997   }
1998 
1999 static t_stat dps_debug_stop (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2000   {
2001     sim_deb_stop = strtoull (buf, NULL, 0);
2002     sim_msg ("Debug set to stop at cycle: %llu\r\n", (long long unsigned int)sim_deb_stop);
2003     return SCPE_OK;
2004   }
2005 
2006 static t_stat dps_debug_break (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2007   {
2008     sim_deb_break = strtoull (buf, NULL, 0);
2009     if (buf[0] == '+')
2010       sim_deb_break += sim_deb_start;
2011     sim_msg ("Debug set to break at cycle: %llu\r\n", (long long unsigned int)sim_deb_break);
2012     return SCPE_OK;
2013   }
2014 
2015 static t_stat dps_debug_segno (int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2016   {
2017     if (arg)
2018       {
2019         unsigned long segno = strtoul (buf, NULL, 0);
2020         if (segno >= DEBUG_SEGNO_LIMIT)
2021           {
2022             sim_printf ("out of range; 0 to %u %d.\r\n", DEBUG_SEGNO_LIMIT, DEBUG_SEGNO_LIMIT);
2023             return SCPE_ARG;
2024           }
2025         sim_deb_segno[segno] = true;
2026         sim_deb_segno_on     = true;
2027         sim_msg ("Debug set for segno %llo %llu.\r\n",
2028                 (long long unsigned int)segno, (long long unsigned int) segno);
2029       }
2030     else
2031       {
2032         (void)memset (sim_deb_segno, 0, sizeof (sim_deb_segno));
2033         sim_deb_segno_on = false;
2034         sim_msg ("Debug set for all segments\r\n");
2035       }
2036     return SCPE_OK;
2037   }
2038 
2039 static t_stat dps_debug_ringno (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2040   {
2041     sim_deb_ringno = strtoull (buf, NULL, 0);
2042     sim_msg ("Debug set to ringno %llo\r\n", (long long unsigned int)sim_deb_ringno);
2043     return SCPE_OK;
2044   }
2045 
2046 static t_stat dps_debug_bar (int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2047   {
2048     sim_deb_bar = arg;
2049     if (arg)
2050       sim_msg ("Debug set BAR %llo\r\n", (long long unsigned int)sim_deb_ringno);
2051     else
2052       sim_msg ("Debug unset BAR %llo\r\n", (long long unsigned int)sim_deb_ringno);
2053     return SCPE_OK;
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 
2247 
2248 
2249 
2250 
2251 
2252 
2253 
2254 
2255 
2256 
2257 
2258 
2259 
2260 
2261 
2262 
2263 
2264 
2265 
2266 // Translate seg:offset to absolute address
2267 
2268 static t_stat abs_addr_n (int segno, uint offset)
     /* [previous][next][first][last][top][bottom][index][help] */
2269   {
2270     word24 res;
2271 
2272     //t_stat rc = computeAbsAddrN (& res, segno, offset);
2273     if (dbgLookupAddress ((word18) segno, offset, & res, NULL))
2274       return SCPE_ARG;
2275 
2276     sim_msg ("Address is %08o\r\n", res);
2277     return SCPE_OK;
2278   }
2279 
2280 // ABS segno:offset
2281 // scp command to translate segno:offset to absolute address
2282 
2283 static t_stat abs_addr (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2284   {
2285     uint segno;
2286     uint offset;
2287     if (sscanf (buf, "%o:%o", & segno, & offset) != 2)
2288       return SCPE_ARG;
2289     return abs_addr_n ((int) segno, offset);
2290   }
2291 
2292 // LOAD_SYSTEM_BOOK <filename>
2293 
2294 // Read a system_book segment, extracting segment names and numbers
2295 // and component names, offsets, and lengths
2296 
2297 # define BOOT_SEGMENTS_MAX 1024
2298 # define BOOT_COMPONENTS_MAX 4096
2299 # define BOOK_SEGMENT_NAME_LEN 33
2300 
2301 static struct book_segment
2302   {
2303     char * segname;
2304     int  segno;
2305   } book_segments[BOOT_SEGMENTS_MAX];
2306 
2307 static int n_book_segments = 0;
2308 
2309 static struct book_component
2310   {
2311     char * compname;
2312     int  book_segment_number;
2313     uint txt_start, txt_length;
2314     int  intstat_start, intstat_length, symbol_start, symbol_length;
2315   } book_components[BOOT_COMPONENTS_MAX];
2316 
2317 static int n_book_components = 0;
2318 
2319 static int lookup_book_segment (char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
2320   {
2321     for (int i = 0; i < n_book_segments; i ++)
2322       if (strcmp (name, book_segments[i].segname) == 0)
2323         return i;
2324     return -1;
2325   }
2326 
2327 static int add_book_segment (char * name, int segno)
     /* [previous][next][first][last][top][bottom][index][help] */
2328   {
2329     int n = lookup_book_segment (name);
2330     if (n >= 0)
2331       return n;
2332     if (n_book_segments >= BOOT_SEGMENTS_MAX)
2333       return -1;
2334     book_segments[n_book_segments].segname = strdup (name);
2335     if (!book_segments[n_book_segments].segname)
2336       {
2337         (void)sir_emerg ("FATAL: Out of memory! Aborting at %s[%s:%d]",
2338                          __func__, __FILE__, __LINE__);
2339 # if defined(USE_BACKTRACE)
2340 #  if defined(SIGUSR2)
2341         (void)raise(SIGUSR2);
2342         /*NOTREACHED*/ /* unreachable */
2343 #  endif /* if defined(SIGUSR2) */
2344 # endif /* if defined(USE_BACKTRACE) */
2345         abort();
2346       }
2347     book_segments[n_book_segments].segno   = segno;
2348     n = n_book_segments;
2349     n_book_segments ++;
2350     return n;
2351   }
2352 
2353 static int add_book_component (int segnum, char * name, uint txt_start,
     /* [previous][next][first][last][top][bottom][index][help] */
2354                                uint txt_length, int intstat_start,
2355                                int intstat_length, int symbol_start,
2356                                int symbol_length)
2357   {
2358     if (n_book_components >= BOOT_COMPONENTS_MAX)
2359       return -1;
2360     book_components[n_book_components].compname            = strdup (name);
2361     if (!book_components[n_book_components].compname)
2362       {
2363         (void)sir_emerg ("FATAL: Out of memory! Aborting at %s[%s:%d]",
2364                          __func__, __FILE__, __LINE__);
2365 # if defined(USE_BACKTRACE)
2366 #  if defined(SIGUSR2)
2367         (void)raise(SIGUSR2);
2368         /*NOTREACHED*/ /* unreachable */
2369 #  endif /* if defined(SIGUSR2) */
2370 # endif /* if defined(USE_BACKTRACE) */
2371         abort();
2372       }
2373     book_components[n_book_components].book_segment_number = segnum;
2374     book_components[n_book_components].txt_start           = txt_start;
2375     book_components[n_book_components].txt_length          = txt_length;
2376     book_components[n_book_components].intstat_start       = intstat_start;
2377     book_components[n_book_components].intstat_length      = intstat_length;
2378     book_components[n_book_components].symbol_start        = symbol_start;
2379     book_components[n_book_components].symbol_length       = symbol_length;
2380     int n = n_book_components;
2381     n_book_components ++;
2382     return n;
2383   }
2384 
2385 // Given a segno:offset, try to translate to
2386 // component name and offset in the component
2387 
2388 // Warning: returns ptr to static buffer
2389 static char * lookup_system_book_address (word18 segno, word18 offset,
     /* [previous][next][first][last][top][bottom][index][help] */
2390                                          char * * compname, word18 * compoffset)
2391   {
2392     static char buf[129];
2393     int i;
2394 
2395     for (i = 0; i < n_book_segments; i ++)
2396       if (book_segments[i].segno == (int) segno)
2397         break;
2398 
2399     if (i >= n_book_segments)
2400       return NULL;
2401 
2402     int best = -1;
2403     uint bestoffset = 0;
2404 
2405     for (int j = 0; j < n_book_components; j ++)
2406       {
2407         if (book_components[j].book_segment_number != i)
2408           continue;
2409         if (book_components[j].txt_start <= offset &&
2410             book_components[j].txt_start + book_components[j].txt_length > offset)
2411           {
2412             (void)sprintf (buf, "%s:%s+0%0o", book_segments[i].segname,
2413                            book_components[j].compname,
2414                            offset - book_components[j].txt_start);
2415             if (compname)
2416               * compname = book_components[j].compname;
2417             if (compoffset)
2418               * compoffset = offset - book_components[j].txt_start;
2419             return buf;
2420           }
2421         if (book_components[j].txt_start <= offset &&
2422             book_components[j].txt_start > bestoffset)
2423           {
2424             best = j;
2425             bestoffset = book_components[j].txt_start;
2426           }
2427       }
2428 
2429     if (best != -1)
2430       {
2431         // Didn't find a component track bracketed the offset; return the
2432         // component that was before the offset
2433         if (compname)
2434           * compname = book_components[best].compname;
2435         if (compoffset)
2436           * compoffset = offset - book_components[best].txt_start;
2437         (void)sprintf (buf, "%s:%s+0%0o", book_segments[i].segname,
2438                        book_components[best].compname,
2439                        offset - book_components[best].txt_start);
2440         return buf;
2441       }
2442 
2443     // Found a segment, but it had no components. Return the segment name
2444     // as the component name
2445 
2446     if (compname)
2447       * compname = book_segments[i].segname;
2448     if (compoffset)
2449       * compoffset = offset;
2450     (void)sprintf (buf, "%s:+0%0o", book_segments[i].segname,
2451                    offset);
2452     return buf;
2453   }
2454 
2455 // Given a segno and offset, find the component name and its
2456 // offset in the segment
2457 
2458 char * lookup_address (word18 segno, word18 offset, char * * compname,
     /* [previous][next][first][last][top][bottom][index][help] */
2459                        word18 * compoffset)
2460   {
2461     if (compname)
2462       * compname = NULL;
2463     if (compoffset)
2464       * compoffset = 0;
2465 
2466     // Magic numbers!
2467     // Multics seems to have a copy of hpchs_ (segno 0162) in segment 0322;
2468     // This little tweak allows source code level tracing for segment 0322,
2469     // and has no operational significance to the emulator
2470     // Hmmm. What is happening is that these segments are being loaded into
2471     // ring 4, and assigned segment #'s; the assigned number will vary
2472     // depending on the exact sequence of events.
2473     if (segno == 0322)
2474       segno = 0162;
2475     if (segno == 0310)
2476       segno = 041;
2477     if (segno == 0314)
2478       segno = 041;
2479     if (segno == 0313)
2480       segno = 040;
2481     if (segno == 0317)
2482       segno = 0161;
2483 
2484 
2485 
2486 
2487 
2488 
2489 
2490 
2491 
2492 
2493 
2494 
2495 
2496 
2497 
2498 
2499 
2500 
2501 
2502 
2503 
2504 
2505 
2506 
2507 
2508 
2509 
2510 
2511 
2512 
2513 
2514 
2515     char * ret = lookup_system_book_address (segno, offset, compname, compoffset);
2516     return ret;
2517   }
2518 
2519 // Given a segment name and component name, return the
2520 // components segment number and offset
2521 
2522 // Warning: returns ptr to static buffer
2523 static int lookup_system_book_name (char * segname, char * compname, long * segno,
     /* [previous][next][first][last][top][bottom][index][help] */
2524                                     long * offset)
2525   {
2526     int i;
2527     for (i = 0; i < n_book_segments; i ++)
2528       if (strcmp (book_segments[i].segname, segname) == 0)
2529         break;
2530     if (i >= n_book_segments)
2531       return -1;
2532 
2533     for (int j = 0; j < n_book_components; j ++)
2534       {
2535         if (book_components[j].book_segment_number != i)
2536           continue;
2537         if (strcmp (book_components[j].compname, compname) == 0)
2538           {
2539             * segno = book_segments[i].segno;
2540             * offset = (long) book_components[j].txt_start;
2541             return 0;
2542           }
2543       }
2544 
2545    return -1;
2546  }
2547 
2548 static char * source_search_path = NULL;
2549 
2550 // Given a component name and an offset in the component,
2551 // find the listing file of the component and try to
2552 // print the source code line that generated the code at
2553 // component:offset
2554 
2555 void list_source (char * compname, word18 offset, uint dflag)
     /* [previous][next][first][last][top][bottom][index][help] */
2556   {
2557     cpu_state_t * cpup = _cpup;
2558     const int offset_str_len = 10;
2559     //char offset_str[offset_str_len + 1];
2560     char offset_str[17];
2561     (void)sprintf (offset_str, "    %06o", offset);
2562 
2563     char path[(source_search_path ? strlen (source_search_path) : 1) +
2564                1 + // "/"
2565                (compname ? strlen (compname) : 1) +
2566                 1 + strlen (".list") + 1];
2567     char * searchp = source_search_path ? source_search_path : ".";
2568     // find <search path>/<compname>.list
2569     while (* searchp)
2570       {
2571         size_t pathlen = strcspn (searchp, ":");
2572         strncpy (path, searchp, pathlen);
2573         path[pathlen] = '\0';
2574         if (searchp[pathlen] == ':')
2575           searchp += pathlen + 1;
2576         else
2577           searchp += pathlen;
2578 
2579         if (compname)
2580           {
2581             strcat (path, "/");
2582             strcat (path, compname);
2583           }
2584         strcat (path, ".list");
2585         //sim_msg ("<%s>\r\n", path);
2586         FILE * listing = fopen (path, "r");
2587         if (listing)
2588           {
2589             char line[1025];
2590             if (feof (listing))
2591               goto fileDone;
2592             fgets (line, 1024, listing);
2593             if (strncmp (line, "ASSEMBLY LISTING", 16) == 0)
2594               {
2595                 // Search ALM listing file
2596                 // sim_msg ("found <%s>\r\n", path);
2597 
2598                 // ALM listing files look like:
2599                 //     000226  4a  4 00010 7421 20  \tstx2]tbootload_0$entry_stack_ptr,id
2600                 while (! feof (listing))
2601                   {
2602                     fgets (line, 1024, listing);
2603                     if (strncmp (line, offset_str, (size_t) offset_str_len) == 0)
2604                       {
2605                         if (! dflag)
2606                           sim_msg ("%s", line);
2607                         else
2608                           sim_debug (dflag, & cpu_dev, "%s", line);
2609                         //break;
2610                       }
2611                     if (strcmp (line, "\fLITERALS\n") == 0) //-NLOK
2612                       break;
2613                   }
2614               } // if assembly listing
2615             else if (strncmp (line, "\tCOMPILATION LISTING", 20) == 0)
2616               {
2617                 // Search PL/I listing file
2618 
2619                 // PL/I files have a line location table
2620                 //     "   LINE    LOC      LINE    LOC ...."
2621 
2622                 bool foundTable = false;
2623                 while (! feof (listing))
2624                   {
2625                     fgets (line, 1024, listing);
2626                     if (strncmp (line, "   LINE    LOC", 14) != 0)
2627                       continue;
2628                     foundTable = true;
2629                     // Found the table
2630                     // Table lines look like
2631                     //     "     13 000705    275 000713 ...
2632                     // But some times
2633                     //     "     10 000156 21  84 000164
2634                     //     "      8 000214     65 000222   4  84 000225
2635                     //
2636                     //     "    349 001442    351 001445     353 001454 1   9 001456 1  11 001461 1  12 001463 1  13 001470
2637                     //     " 1   18 001477    357 001522     361 001525   363 001544   364 001546   365 001547   366 001553
2638 
2639                     //  I think the numbers refer to include files...
2640                     //   But of course the format is slightly off...
2641                     //    table    ".1...18
2642                     //    listing  ".1....18
2643                     int best = -1;
2644                     char bestLines[8] = {0, 0, 0, 0, 0, 0, 0};
2645                     while (! feof (listing))
2646                       {
2647                         int loc[7];
2648                         char linenos[7][8];
2649                         (void)memset (linenos, 0, sizeof (linenos));
2650                         fgets (line, 1024, listing);
2651                         // sometimes the leading columns are blank...
2652                         while (strncmp (line,
2653                                         "                 ", 8 + 6 + 3) == 0)
2654                           memmove (line, line + 8 + 6 + 3,
2655                                    strlen (line + 8 + 6 + 3));
2656                         // deal with the extra numbers...
2657 
2658                         int cnt = sscanf (line,
2659                           // " %d %o %d %o %d %o %d %o %d %o %d %o %d %o",
2660                           "%8c%o%*3c"
2661                           "%8c%o%*3c"
2662                           "%8c%o%*3c"
2663                           "%8c%o%*3c"
2664                           "%8c%o%*3c"
2665                           "%8c%o%*3c"
2666                           "%8c%o",
2667                           (char *) & linenos[0], (uint *) & loc[0],
2668                           (char *) & linenos[1], (uint *) & loc[1],
2669                           (char *) & linenos[2], (uint *) & loc[2],
2670                           (char *) & linenos[3], (uint *) & loc[3],
2671                           (char *) & linenos[4], (uint *) & loc[4],
2672                           (char *) & linenos[5], (uint *) & loc[5],
2673                           (char *) & linenos[6], (uint *) & loc[6]);
2674                         if (! (cnt == 2 || cnt == 4  || cnt == 6  ||
2675                                cnt == 8 || cnt == 10 || cnt == 12 ||
2676                                cnt == 14))
2677                           break; // end of table
2678                         int n;
2679                         for (n = 0; n < cnt / 2; n ++)
2680                           {
2681                             if (loc[n] > best && loc[n] <= (int) offset)
2682                               {
2683                                 best = loc[n];
2684                                 memcpy (bestLines, linenos[n],
2685                                         sizeof (bestLines));
2686                               }
2687                           }
2688                         if (best == (int) offset)
2689                           break;
2690                       }
2691                     if (best == -1)
2692                       goto fileDone; // Not found in table
2693 
2694                     //   But of course the format is slightly off...
2695                     //    table    ".1...18
2696                     //    listing  ".1....18
2697                     // bestLines "21   84 "
2698                     // listing   " 21    84 "
2699                     char searchPrefix[10];
2700                     searchPrefix[0] = ' ';
2701                     searchPrefix[1] = bestLines[0];
2702                     searchPrefix[2] = bestLines[1];
2703                     searchPrefix[3] = ' ';
2704                     searchPrefix[4] = bestLines[2];
2705                     searchPrefix[5] = bestLines[3];
2706                     searchPrefix[6] = bestLines[4];
2707                     searchPrefix[7] = bestLines[5];
2708                     searchPrefix[8] = bestLines[6];
2709                     // ignore trailing space; some times it's a tab
2710                     // searchPrefix[ 9] = bestLines[ 7];
2711                     searchPrefix[9] = '\0';
2712 
2713                     // Look for the line in the listing
2714                     rewind (listing);
2715                     while (! feof (listing))
2716                       {
2717                         fgets (line, 1024, listing);
2718                         if (strncmp (line, "\f\tSOURCE", 8) == 0)
2719                           goto fileDone; // end of source code listing
2720                         char prefix[10];
2721                         strncpy (prefix, line, 9);
2722                         prefix[9] = '\0';
2723                         if (strcmp (prefix, searchPrefix) != 0)
2724                           continue;
2725                         // Got it
2726                         if (!dflag)
2727                           sim_msg ("%s", line);
2728                         else
2729                           sim_debug (dflag, & cpu_dev, "%s", line);
2730                         //break;
2731                       }
2732                     goto fileDone;
2733                   } // if table start
2734                 if (! foundTable)
2735                   {
2736                     // Can't find the LINE/LOC table; look for listing
2737                     rewind (listing);
2738                     while (! feof (listing))
2739                       {
2740                         fgets (line, 1024, listing);
2741                         if (strncmp (line,
2742                                      offset_str + 4,
2743                                      offset_str_len - 4) == 0)
2744                           {
2745                             if (! dflag)
2746                               sim_msg ("%s", line);
2747                             else
2748                               sim_debug (dflag, & cpu_dev, "%s", line);
2749                             //break;
2750                           }
2751                         //if (strcmp (line, "\fLITERALS\n") == 0) //-NLOK
2752                           //break;
2753                       }
2754                   } // if ! tableFound
2755               } // if PL/I listing
2756 
2757 fileDone:
2758             fclose (listing);
2759           } // if (listing)
2760       }
2761   }
2762 
2763 // STK
2764 
2765 static t_stat stack_trace (UNUSED int32 arg,  UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2766   {
2767     cpu_state_t * cpup = _cpup;
2768     char * msg;
2769 
2770     word15 icSegno = cpu.PPR.PSR;
2771     word18 icOffset = cpu.PPR.IC;
2772 
2773     sim_msg ("Entry ptr   %05o:%06o\r\n", icSegno, icOffset);
2774 
2775     char * compname;
2776     word18 compoffset;
2777     char * where = lookup_address (icSegno, icOffset,
2778                                    & compname, & compoffset);
2779     if (where)
2780       {
2781         sim_msg ("%05o:%06o %s\r\n", icSegno, icOffset, where);
2782         list_source (compname, compoffset, 0);
2783       }
2784     sim_msg ("\r\n");
2785 
2786     // According to AK92
2787     //
2788     //  pr0/ap operator segment pointer
2789     //  pr6/sp stack frame pointer
2790     //  pr4/lp linkage section for the executing procedure
2791     //  pr7/sb stack base
2792 
2793     word15 fpSegno  = cpu.PR[6].SNR;
2794     word18 fpOffset = cpu.PR[6].WORDNO;
2795 
2796     for (uint frameNo = 1; ; frameNo ++)
2797       {
2798         sim_msg ("Frame %d %05o:%06o\r\n",
2799                     frameNo, fpSegno, fpOffset);
2800 
2801         word24 fp;
2802         if (dbgLookupAddress (fpSegno, fpOffset, & fp, & msg))
2803           {
2804             sim_msg ("can't lookup fp (%05o:%06o) because %s\r\n",
2805                     fpSegno, fpOffset, msg);
2806             break;
2807           }
2808 
2809         word15 prevfpSegno  = (word15) ((M[fp + 16] >> 18) & MASK15);
2810         word18 prevfpOffset = (word18) ((M[fp + 17] >> 18) & MASK18);
2811 
2812         sim_msg ("Previous FP %05o:%06o\r\n", prevfpSegno, prevfpOffset);
2813 
2814         word15 returnSegno  = (word15) ((M[fp + 20] >> 18) & MASK15);
2815         word18 returnOffset = (word18) ((M[fp + 21] >> 18) & MASK18);
2816 
2817         sim_msg ("Return ptr  %05o:%06o\r\n", returnSegno, returnOffset);
2818 
2819         if (returnOffset == 0)
2820           {
2821             if (frameNo == 1)
2822               {
2823                 // try rX[7] as the return address
2824                 sim_msg ("guessing X7 has a return address....\r\n");
2825                 where = lookup_address (icSegno, cpu.rX[7] - 1,
2826                                         & compname, & compoffset);
2827                 if (where)
2828                   {
2829                     sim_msg ("%05o:%06o %s\r\n", icSegno, cpu.rX[7] - 1, where);
2830                     list_source (compname, compoffset, 0);
2831                   }
2832               }
2833           }
2834         else
2835           {
2836             where = lookup_address (returnSegno, returnOffset - 1,
2837                                     & compname, & compoffset);
2838             if (where)
2839               {
2840                 sim_msg ("%05o:%06o %s\r\n",
2841                             returnSegno, returnOffset - 1, where);
2842                 list_source (compname, compoffset, 0);
2843               }
2844           }
2845 
2846         word15 entrySegno  = (word15) ((M[fp + 22] >> 18) & MASK15);
2847         word18 entryOffset = (word18) ((M[fp + 23] >> 18) & MASK18);
2848 
2849         sim_msg ("Entry ptr   %05o:%06o\r\n", entrySegno, entryOffset);
2850 
2851         where = lookup_address (entrySegno, entryOffset,
2852                                 & compname, & compoffset);
2853         if (where)
2854           {
2855             sim_msg ("%05o:%06o %s\r\n", entrySegno, entryOffset, where);
2856             list_source (compname, compoffset, 0);
2857           }
2858 
2859         word15 argSegno  = (word15) ((M[fp + 26] >> 18) & MASK15);
2860         word18 argOffset = (word18) ((M[fp + 27] >> 18) & MASK18);
2861         sim_msg ("Arg ptr     %05o:%06o\r\n", argSegno, argOffset);
2862 
2863         word24 ap;
2864         if (dbgLookupAddress (argSegno, argOffset, & ap, & msg))
2865           {
2866             sim_msg ("can't lookup arg ptr (%05o:%06o) because %s\r\n",
2867                     argSegno, argOffset, msg);
2868             goto skipArgs;
2869           }
2870 
2871         word16 argCount  = (word16) ((M[ap + 0] >> 19) & MASK17);
2872         word18 callType  = (word18) (M[ap + 0] & MASK18);
2873         word16 descCount = (word16) ((M[ap + 1] >> 19) & MASK17);
2874         sim_msg ("arg_count   %d\r\n", argCount);
2875         switch (callType)
2876           {
2877             case 0u:
2878               sim_msg ("call_type Quick internal call\r\n");
2879               break;
2880             case 4u:
2881               sim_msg ("call_type Inter-segment\r\n");
2882               break;
2883             case 8u:
2884               sim_msg ("call_type Environment pointer\r\n");
2885               break;
2886             default:
2887               sim_msg ("call_type Unknown (%o)\r\n", callType);
2888               goto skipArgs;
2889               }
2890         sim_msg ("desc_count  %d\r\n", descCount);
2891 
2892 
2893 
2894 
2895 
2896 
2897 
2898 
2899           {
2900             for (uint argno = 0; argno < argCount; argno ++)
2901               {
2902                 uint argnoos       = ap + 2 + argno * 2;
2903                 word15 argnoSegno  = (word15) ((M[argnoos] >> 18) & MASK15);
2904                 word18 argnoOffset = (word18) ((M[argnoos + 1] >> 18) & MASK18);
2905                 word24 argnop;
2906                 if (dbgLookupAddress (argnoSegno, argnoOffset, & argnop, & msg))
2907                   {
2908                     sim_msg ("can't lookup arg%d ptr (%05o:%06o) because %s\r\n",
2909                                 argno, argSegno, argOffset, msg);
2910                     continue;
2911                   }
2912                 word36 argv = M[argnop];
2913                 sim_msg ("arg%d value   %05o:%06o[%08o] "
2914                             "%012llo (%llu)\r\n",
2915                             argno, argSegno, argOffset, argnop,
2916                             (unsigned long long int)argv, (unsigned long long int)argv);
2917                 sim_msg ("\r\n");
2918              }
2919          }
2920 skipArgs:;
2921 
2922         sim_msg ("End of frame %d\r\n\r\n", frameNo);
2923 
2924         if (prevfpSegno == 077777 && prevfpOffset == 1)
2925           break;
2926         fpSegno  = prevfpSegno;
2927         fpOffset = prevfpOffset;
2928       }
2929     return SCPE_OK;
2930   }
2931 
2932 static t_stat list_source_at (UNUSED int32 arg, UNUSED const char *  buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2933   {
2934     // list seg:offset
2935     uint segno;
2936     uint offset;
2937     if (sscanf (buf, "%o:%o", & segno, & offset) != 2)
2938       return SCPE_ARG;
2939     char * compname;
2940     word18 compoffset;
2941     char * where = lookup_address ((word18) segno, offset,
2942                                    & compname, & compoffset);
2943     if (where)
2944       {
2945         sim_msg ("%05o:%06o %s\r\n", segno, offset, where);
2946         list_source (compname, compoffset, 0);
2947       }
2948     return SCPE_OK;
2949   }
2950 
2951 static t_stat load_system_book (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
2952   {
2953 // Quietly ignore if not debug enabled
2954 # if !defined(SPEED)
2955     // Multics 12.5 assigns segment number to collection 3 starting at 0244.
2956     uint c3 = 0244;
2957 
2958 #  define bufSz 257
2959     char filebuf[bufSz];
2960     int  current = -1;
2961 
2962     FILE * fp = fopen (buf, "r");
2963     if (! fp)
2964       {
2965         sim_msg ("error opening file %s\r\n", buf);
2966         return SCPE_ARG;
2967       }
2968     for (;;)
2969       {
2970         char * bufp = fgets (filebuf, bufSz, fp);
2971         if (! bufp)
2972           break;
2973         //sim_msg ("<%s\n>", filebuf); //-NLOK
2974         char name[BOOK_SEGMENT_NAME_LEN];
2975         uint segno, p0, p1, p2;
2976 
2977         // 32 is BOOK_SEGMENT_NAME_LEN - 1
2978         int cnt = sscanf (filebuf, "%32s %o  (%o, %o, %o)", name, & segno,
2979           & p0, & p1, & p2);
2980         if (filebuf[0] != '\t' && cnt == 5)
2981           {
2982             //sim_msg ("A: %s %d\r\n", name, segno);
2983             int rc = add_book_segment (name, (int) segno);
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         else
2993           {
2994             // Check for collection 3 segment
2995             // 32 is BOOK_SEGMENT_NAME_LEN - 1
2996             cnt = sscanf (filebuf, "%32s  (%o, %o, %o)", name,
2997               & p0, & p1, & p2);
2998             if (filebuf[0] != '\t' && cnt == 4)
2999               {
3000                 if (strstr (name, "fw.") || strstr (name, ".ec"))
3001                   continue;
3002                 //sim_msg ("A: %s %d\r\n", name, segno);
3003                 int rc = add_book_segment (name, (int) (c3 ++));
3004                 if (rc < 0)
3005                   {
3006                     sim_warn ("error adding segment name\r\n");
3007                     fclose (fp);
3008                     return SCPE_ARG;
3009                   }
3010                 continue;
3011               }
3012           }
3013         cnt = sscanf (filebuf, "Bindmap for >ldd>h>e>%32s", name);
3014         if (cnt != 1)
3015           cnt = sscanf (filebuf, "Bindmap for >ldd>hard>e>%32s", name);
3016         if (cnt == 1)
3017           {
3018             //sim_msg ("B: %s\r\n", name);
3019             //int rc = add_book_segment (name);
3020             int rc = lookup_book_segment (name);
3021             if (rc < 0)
3022               {
3023                 // The collection 3.0 segments do not have segment numbers,
3024                 // and the 1st digit of the 3-tuple is 1, not 0. Ignore
3025                 // them for now.
3026                 current = -1;
3027                 continue;
3028                 //sim_warn ("error adding segment name\r\n");
3029                 //return SCPE_ARG;
3030               }
3031             current = rc;
3032             continue;
3033           }
3034 
3035         uint txt_start, txt_length;
3036         int intstat_start, intstat_length, symbol_start, symbol_length;
3037         cnt = sscanf (filebuf, "%32s %o %o %o %o %o %o", name, & txt_start,
3038                       & txt_length, & intstat_start, & intstat_length,
3039                       & symbol_start, & symbol_length);
3040 
3041         if (cnt == 7)
3042           {
3043             //sim_msg ("C: %s\r\n", name);
3044             if (current >= 0)
3045               {
3046                 add_book_component (current, name, txt_start, txt_length,
3047                                     intstat_start, intstat_length, symbol_start,
3048                                     symbol_length);
3049               }
3050             continue;
3051           }
3052 
3053         cnt = sscanf (filebuf, "%32s %o  (%o, %o, %o)", name, & segno,
3054           & p0, & p1, & p2);
3055         if (filebuf[0] == '\t' && cnt == 5)
3056           {
3057             //sim_msg ("D: %s %d\r\n", name, segno);
3058             int rc = add_book_segment (name, (int) segno);
3059             if (rc < 0)
3060               {
3061                 sim_warn ("error adding segment name\r\n");
3062                 fclose (fp);
3063                 return SCPE_ARG;
3064               }
3065             continue;
3066           }
3067 
3068       }
3069     fclose (fp);
3070 
3071 
3072 
3073 
3074 
3075 
3076 
3077 
3078 
3079 
3080 
3081 
3082 
3083 
3084 
3085 
3086 
3087 
3088 
3089 
3090 
3091 # endif
3092     return SCPE_OK;
3093   }
3094 
3095 static t_stat add_system_book_entry (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3096   {
3097     // asbe segname compname seg txt_start txt_len intstat_start intstat_length
3098     // symbol_start symbol_length
3099     char segname[BOOK_SEGMENT_NAME_LEN];
3100     char compname[BOOK_SEGMENT_NAME_LEN];
3101     uint segno;
3102     uint txt_start, txt_len;
3103     uint  intstat_start, intstat_length;
3104     uint  symbol_start, symbol_length;
3105 
3106     // 32 is BOOK_SEGMENT_NAME_LEN - 1
3107     if (sscanf (buf, "%32s %32s %o %o %o %o %o %o %o",
3108                 segname, compname, & segno,
3109                 & txt_start, & txt_len, & intstat_start, & intstat_length,
3110                 & symbol_start, & symbol_length) != 9)
3111       return SCPE_ARG;
3112 
3113     int idx = add_book_segment (segname, (int) segno);
3114     if (idx < 0)
3115       return SCPE_ARG;
3116 
3117     if (add_book_component (idx, compname, txt_start, txt_len, (int) intstat_start,
3118                            (int) intstat_length, (int) symbol_start,
3119                            (int) symbol_length) < 0)
3120       return SCPE_ARG;
3121 
3122     return SCPE_OK;
3123   }
3124 
3125 // LSB n:n   given a segment number and offset, return a segment name,
3126 //           component and offset in that component
3127 //     sname:cname+offset
3128 //           given a segment name, component name and offset, return
3129 //           the segment number and offset
3130 
3131 static t_stat lookup_system_book (UNUSED int32  arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3132   {
3133     char w1[strlen (buf)];
3134     char w2[strlen (buf)];
3135     char w3[strlen (buf)];
3136     long segno, offset;
3137 
3138     size_t colon = strcspn (buf, ":");
3139     if (buf[colon] != ':')
3140       return SCPE_ARG;
3141 
3142     strncpy (w1, buf, colon);
3143     w1[colon] = '\0';
3144     //sim_msg ("w1 <%s>\r\n", w1);
3145 
3146     size_t plus = strcspn (buf + colon + 1, "+");
3147     if (buf[colon + 1 + plus] == '+')
3148       {
3149         strncpy (w2, buf + colon + 1, plus);
3150         w2[plus] = '\0';
3151         (void)strcpy (w3, buf + colon + 1 + plus + 1);
3152       }
3153     else
3154       {
3155         (void)strcpy (w2, buf + colon + 1);
3156         (void)strcpy (w3, "");
3157       }
3158     //sim_msg ("w1 <%s>\r\n", w1);
3159     //sim_msg ("w2 <%s>\r\n", w2);
3160     //sim_msg ("w3 <%s>\r\n", w3);
3161 
3162     char * end1;
3163     segno = strtol (w1, & end1, 8);
3164     char * end2;
3165     offset = strtol (w2, & end2, 8);
3166 
3167     if (* end1 == '\0' && * end2 == '\0' && * w3 == '\0')
3168       {
3169         // n:n
3170         char * ans = lookup_address ((word18) segno, (word18) offset, NULL, NULL);
3171         sim_warn ("%s\r\n", ans ? ans : "not found");
3172       }
3173     else
3174       {
3175         if (* w3)
3176           {
3177             char * end3;
3178             offset = strtol (w3, & end3, 8);
3179             if (* end3 != '\0')
3180               return SCPE_ARG;
3181           }
3182         else
3183           offset = 0;
3184         long comp_offset;
3185         int rc = lookup_system_book_name (w1, w2, & segno, & comp_offset);
3186         if (rc)
3187           {
3188             sim_warn ("not found\r\n");
3189             return SCPE_OK;
3190           }
3191         sim_msg ("0%o:0%o\r\n", (uint) segno, (uint) (comp_offset + offset));
3192         abs_addr_n  ((int) segno, (uint) (comp_offset + offset));
3193       }
3194 /*
3195     if (sscanf (buf, "%o:%o", & segno, & offset) != 2)
3196       return SCPE_ARG;
3197     char * ans = lookup_address (segno, offset);
3198     sim_msg ("%s\r\n", ans ? ans : "not found");
3199 */
3200     return SCPE_OK;
3201   }
3202 
3203 // Assumes unpaged DSBR
3204 
3205 static sdw0_s *fetchSDW (word15 segno)
     /* [previous][next][first][last][top][bottom][index][help] */
3206   {
3207     cpu_state_t * cpup = _cpup;
3208     word36 SDWeven, SDWodd;
3209 
3210     core_read2 (cpup, (cpu.DSBR.ADDR + 2u * segno) & PAMASK, & SDWeven, & SDWodd,
3211                  __func__);
3212 
3213     // even word
3214 
3215     sdw0_s *SDW = & cpu._s;
3216     (void)memset (SDW, 0, sizeof (cpu._s));
3217 
3218     SDW->ADDR   = (SDWeven >> 12) & 077777777;
3219     SDW->R1     = (SDWeven >> 9)  & 7;
3220     SDW->R2     = (SDWeven >> 6)  & 7;
3221     SDW->R3     = (SDWeven >> 3)  & 7;
3222     SDW->DF     = TSTBIT (SDWeven,  2);
3223     SDW->FC     = SDWeven & 3;
3224 
3225     // odd word
3226     SDW->BOUND  = (SDWodd >> 21) & 037777;
3227     SDW->R      = TSTBIT (SDWodd,  20);
3228     SDW->E      = TSTBIT (SDWodd,  19);
3229     SDW->W      = TSTBIT (SDWodd,  18);
3230     SDW->P      = TSTBIT (SDWodd,  17);
3231     SDW->U      = TSTBIT (SDWodd,  16);
3232     SDW->G      = TSTBIT (SDWodd,  15);
3233     SDW->C      = TSTBIT (SDWodd,  14);
3234     SDW->EB     = SDWodd & 037777;
3235 
3236     return SDW;
3237   }
3238 
3239 static t_stat virtAddrN (uint address)
     /* [previous][next][first][last][top][bottom][index][help] */
3240   {
3241     cpu_state_t * cpup = _cpup;
3242     if (cpu.DSBR.U) {
3243         for(word15 segno = 0; 2u * segno < 16u * (cpu.DSBR.BND + 1u); segno += 1)
3244         {
3245             sdw0_s *s = fetchSDW(segno);
3246             if (address >= s -> ADDR && address < s -> ADDR + s -> BOUND * 16u)
3247               sim_msg ("  %06o:%06o\r\n", segno, address - s -> ADDR);
3248         }
3249     } else {
3250         for(word15 segno = 0;
3251             2u * segno < 16u * (cpu.DSBR.BND + 1u);
3252             segno += 512u)
3253         {
3254             word24 y1 = (2u * segno) % 1024u;
3255             word24 x1 = (2u * segno - y1) / 1024u;
3256             word36 PTWx1;
3257             core_read (cpup, (cpu.DSBR.ADDR + x1) & PAMASK, & PTWx1, __func__);
3258 
3259             ptw_s PTW1;
3260             PTW1.ADDR = GETHI(PTWx1);
3261             PTW1.U    = TSTBIT(PTWx1, 9);
3262             PTW1.M    = TSTBIT(PTWx1, 6);
3263             PTW1.DF   = TSTBIT(PTWx1, 2);
3264             PTW1.FC   = PTWx1 & 3;
3265 
3266             if (PTW1.DF == 0)
3267                 continue;
3268             //sim_msg ("%06o  Addr %06o U %o M %o DF %o FC %o\r\n",
3269             //            segno, PTW1.ADDR, PTW1.U, PTW1.M, PTW1.DF, PTW1.FC);
3270             //sim_msg ("    Target segment page table\r\n");
3271             for (word15 tspt = 0; tspt < 512u; tspt ++)
3272             {
3273                 word36 SDWeven, SDWodd;
3274                 core_read2(cpup, ((PTW1.ADDR << 6) + tspt * 2u) & PAMASK, & SDWeven,
3275                            & SDWodd, __func__);
3276                 sdw0_s SDW0;
3277                 // even word
3278                 SDW0.ADDR  = (SDWeven >> 12) & PAMASK;
3279                 SDW0.R1    = (SDWeven >> 9)  & 7u;
3280                 SDW0.R2    = (SDWeven >> 6)  & 7u;
3281                 SDW0.R3    = (SDWeven >> 3)  & 7u;
3282                 SDW0.DF    = TSTBIT(SDWeven,   2);
3283                 SDW0.FC    = SDWeven & 3u;
3284 
3285                 // odd word
3286                 SDW0.BOUND = (SDWodd >> 21) & 037777;
3287                 SDW0.R     = TSTBIT(SDWodd,   20);
3288                 SDW0.E     = TSTBIT(SDWodd,   19);
3289                 SDW0.W     = TSTBIT(SDWodd,   18);
3290                 SDW0.P     = TSTBIT(SDWodd,   17);
3291                 SDW0.U     = TSTBIT(SDWodd,   16);
3292                 SDW0.G     = TSTBIT(SDWodd,   15);
3293                 SDW0.C     = TSTBIT(SDWodd,   14);
3294                 SDW0.EB    = SDWodd & 037777;
3295 
3296                 if (SDW0.DF == 0)
3297                     continue;
3298                 //sim_msg ("    %06o Addr %06o %o,%o,%o F%o BOUND %06o "
3299                 //          "%c%c%c%c%c\r\n",
3300                 //          tspt, SDW0.ADDR, SDW0.R1, SDW0.R2, SDW0.R3, SDW0.F,
3301                 //          SDW0.BOUND, SDW0.R ? 'R' : '.', SDW0.E ? 'E' : '.',
3302                 //          SDW0.W ? 'W' : '.', SDW0.P ? 'P' : '.',
3303                 //          SDW0.U ? 'U' : '.');
3304                 if (SDW0.U == 0)
3305                 {
3306                     for (word18 offset = 0;
3307                          offset < 16u * (SDW0.BOUND + 1u);
3308                          offset += 1024)
3309                     {
3310                         word24 y2 = offset % 1024;
3311                         word24 x2 = (offset - y2) / 1024;
3312 
3313                         // 10. Fetch the target segment PTW(x2) from
3314                         //     SDW(segno).ADDR + x2.
3315 
3316                         word36 PTWx2;
3317                         core_read (cpup, (SDW0.ADDR + x2) & PAMASK, & PTWx2, __func__);
3318 
3319                         ptw_s PTW2;
3320                         PTW2.ADDR = GETHI(PTWx2);
3321                         PTW2.U    = TSTBIT(PTWx2, 9);
3322                         PTW2.M    = TSTBIT(PTWx2, 6);
3323                         PTW2.DF   = TSTBIT(PTWx2, 2);
3324                         PTW2.FC   = PTWx2 & 3;
3325 
3326                         //sim_msg ("        %06o  Addr %06o U %o M %o F %o "
3327                         //            "FC %o\r\n",
3328                         //            offset, PTW2.ADDR, PTW2.U, PTW2.M, PTW2.F,
3329                         //            PTW2.FC);
3330                         if (address >= PTW2.ADDR + offset &&
3331                             address < PTW2.ADDR + offset + 1024)
3332                           sim_msg ("  %06o:%06o\r\n", tspt, (address - offset) - PTW2.ADDR);
3333 
3334                       }
3335                   }
3336                 else
3337                   {
3338                     if (address >= SDW0.ADDR &&
3339                         address < SDW0.ADDR + SDW0.BOUND * 16u)
3340                       sim_msg ("  %06o:%06o\r\n", tspt, address - SDW0.ADDR);
3341                   }
3342             }
3343         }
3344     }
3345 
3346     return SCPE_OK;
3347 
3348   }
3349 
3350 // VIRTUAL address
3351 
3352 static t_stat virt_address (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3353   {
3354     uint address;
3355     if (sscanf (buf, "%o", & address) != 1)
3356       return SCPE_ARG;
3357     return virtAddrN (address);
3358   }
3359 
3360 // search path is path:path:path....
3361 
3362 static t_stat set_search_path (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3363   {
3364 // Quietly ignore if debugging not enabled
3365 # if !defined(SPEED)
3366     if (source_search_path)
3367       FREE (source_search_path);
3368     source_search_path = strdup (buf);
3369     if (!source_search_path)
3370       {
3371         (void)sir_emerg ("FATAL: Out of memory! Aborting at %s[%s:%d]",
3372                          __func__, __FILE__, __LINE__);
3373 #  if defined(USE_BACKTRACE)
3374 #   if defined(SIGUSR2)
3375         (void)raise(SIGUSR2);
3376         /*NOTREACHED*/ /* unreachable */
3377 #   endif /* if defined(SIGUSR2) */
3378 #  endif /* if defined(USE_BACKTRACE) */
3379         abort();
3380       }
3381 # endif
3382     return SCPE_OK;
3383   }
3384 
3385 // Hook for gdb
3386 //
3387 // The idea is that if you want to set a gdb breakpoint for a particularly
3388 // complex condition, you can add a test for the condition to the emulator
3389 // code and call brkbrk() when the condition is met; by doing a gdb
3390 // 'b brkbrk', gdb will see when the condition is met.
3391 //
3392 
3393 t_stat brkbrk (UNUSED int32 arg, UNUSED const char *  buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3394   {
3395     //list_source (buf, 0);
3396     return SCPE_OK;
3397   }
3398 
3399 // SBREAK segno:offset
3400 
3401 static t_stat sbreak (int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3402   {
3403     //(void)printf (">> <%s>\r\n", buf);
3404     int segno, offset;
3405     int where;
3406     int cnt = sscanf (buf, "%o:%o%n", & segno, & offset, & where);
3407     if (cnt != 2)
3408       {
3409         return SCPE_ARG;
3410       }
3411     char reformatted[strlen (buf) + 20];
3412     (void)sprintf (reformatted, "0%04o%06o%s", segno, offset, buf + where);
3413     //(void)printf (">> <%s>\r\n", reformatted);
3414     t_stat rc = brk_cmd (arg, reformatted);
3415     return rc;
3416   }
3417 
3418 # if defined(DVFDBG)
3419 static t_stat dfx1entry (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3420   {
3421 // divide_fx1, divide_fx3
3422     sim_msg ("dfx1entry\r\n");
3423     sim_msg ("rA %012"PRIo64" (%llu)\r\n", rA, rA);
3424     sim_msg ("rQ %012"PRIo64" (%llu)\r\n", rQ, rQ);
3425     // Figure out the caller's text segment, according to pli_operators.
3426     // sp:tbp -> PR[6].SNR:046
3427     word24 pa;
3428     char * msg;
3429     if (dbgLookupAddress (cpu.PR[6].SNR, 046, & pa, & msg))
3430       {
3431         sim_msg ("text segment number lookup failed because %s\r\n", msg);
3432       }
3433     else
3434       {
3435         sim_msg ("text segno %012"PRIo64" (%llu)\r\n", M[pa], M[pa]);
3436       }
3437 sim_msg ("%05o:%06o\r\n", cpu.PR[2].SNR, cpu.rX[0]);
3438 //dbgStackTrace ();
3439     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.rX[0], & pa, & msg))
3440       {
3441         sim_msg ("return address lookup failed because %s\r\n", msg);
3442       }
3443     else
3444       {
3445         sim_msg ("scale %012"PRIo64" (%llu)\r\n", M[pa], M[pa]);
3446       }
3447     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.PR[2].WORDNO, & pa, & msg))
3448       {
3449         sim_msg ("divisor address lookup failed because %s\r\n", msg);
3450       }
3451     else
3452       {
3453         sim_msg ("divisor %012"PRIo64" (%llu)\r\n", M[pa], M[pa]);
3454       }
3455     return SCPE_OK;
3456   }
3457 
3458 static t_stat dfx1exit (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3459   {
3460     sim_msg ("dfx1exit\r\n");
3461     sim_msg ("rA %012"PRIo64" (%llu)\r\n", rA, rA);
3462     sim_msg ("rQ %012"PRIo64" (%llu)\r\n", rQ, rQ);
3463     return SCPE_OK;
3464   }
3465 
3466 static t_stat dv2scale (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3467   {
3468     sim_msg ("dv2scale\r\n");
3469     sim_msg ("rQ %012"PRIo64" (%llu)\r\n", rQ, rQ);
3470     return SCPE_OK;
3471   }
3472 
3473 static t_stat dfx2entry (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3474   {
3475 // divide_fx2
3476     sim_msg ("dfx2entry\r\n");
3477     sim_msg ("rA %012"PRIo64" (%llu)\r\n", rA, rA);
3478     sim_msg ("rQ %012"PRIo64" (%llu)\r\n", rQ, rQ);
3479     // Figure out the caller's text segment, according to pli_operators.
3480     // sp:tbp -> PR[6].SNR:046
3481     word24 pa;
3482     char * msg;
3483     if (dbgLookupAddress (cpu.PR[6].SNR, 046, & pa, & msg))
3484       {
3485         sim_msg ("text segment number lookup failed because %s\r\n", msg);
3486       }
3487     else
3488       {
3489         sim_msg ("text segno %012"PRIo64" (%llu)\r\n", M[pa], M[pa]);
3490       }
3491 
3492 
3493 
3494 
3495 
3496 
3497 
3498 
3499 
3500 
3501 
3502 
3503 
3504 
3505 
3506 
3507 
3508 
3509 
3510 
3511 
3512 
3513 
3514 
3515 
3516 
3517     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.PR[2].WORDNO, & pa, & msg))
3518       {
3519         sim_msg ("divisor address lookup failed because %s\r\n", msg);
3520       }
3521     else
3522       {
3523         sim_msg ("divisor %012"PRIo64" (%llu)\r\n", M[pa], M[pa]);
3524         sim_msg ("divisor %012"PRIo64" (%llu)\r\n", M[pa + 1], M[pa + 1]);
3525       }
3526     return SCPE_OK;
3527   }
3528 
3529 static t_stat mdfx3entry (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3530   {
3531 // operator to form mod(fx2,fx1)
3532 // entered with first arg in q, bp pointing at second
3533 
3534 // divide_fx1, divide_fx2
3535     sim_msg ("mdfx3entry\r\n");
3536     //sim_msg ("rA %012"PRIo64" (%llu)\r\n", rA, rA);
3537     sim_msg ("rQ %012"PRIo64" (%llu)\r\n", rQ, rQ);
3538     // Figure out the caller's text segment, according to pli_operators.
3539     // sp:tbp -> PR[6].SNR:046
3540     word24 pa;
3541     char * msg;
3542     if (dbgLookupAddress (cpu.PR[6].SNR, 046, & pa, & msg))
3543       {
3544         sim_msg ("text segment number lookup failed because %s\r\n", msg);
3545       }
3546     else
3547       {
3548         sim_msg ("text segno %012"PRIo64" (%llu)\r\n", M[pa], M[pa]);
3549       }
3550 //sim_msg ("%05o:%06o\r\n", cpu.PR[2].SNR, cpu.rX[0]);
3551 //dbgStackTrace ();
3552 
3553 
3554 
3555 
3556 
3557 
3558 
3559 
3560 
3561 
3562     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.PR[2].WORDNO, & pa, & msg))
3563       {
3564         sim_msg ("divisor address lookup failed because %s\r\n", msg);
3565       }
3566     else
3567       {
3568         sim_msg ("divisor %012"PRIo64" (%llu)\r\n", M[pa], M[pa]);
3569       }
3570     return SCPE_OK;
3571   }
3572 
3573 static t_stat smfx1entry (UNUSED int32 arg, UNUSED const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3574   {
3575 // operator to form mod(fx2,fx1)
3576 // entered with first arg in q, bp pointing at second
3577 
3578 // divide_fx1, divide_fx2
3579     sim_msg ("smfx1entry\r\n");
3580     //sim_msg ("rA %012"PRIo64" (%llu)\r\n", rA, rA);
3581     sim_msg ("rQ %012"PRIo64" (%llu)\r\n", rQ, rQ);
3582     // Figure out the caller's text segment, according to pli_operators.
3583     // sp:tbp -> PR[6].SNR:046
3584     word24 pa;
3585     char * msg;
3586     if (dbgLookupAddress (cpu.PR[6].SNR, 046, & pa, & msg))
3587       {
3588         sim_msg ("text segment number lookup failed because %s\r\n", msg);
3589       }
3590     else
3591       {
3592         sim_msg ("text segno %012"PRIo64" (%llu)\r\n", M[pa], M[pa]);
3593       }
3594 sim_msg ("%05o:%06o\r\n", cpu.PR[2].SNR, cpu.rX[0]);
3595 //dbgStackTrace ();
3596     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.rX[0], & pa, & msg))
3597       {
3598         sim_msg ("return address lookup failed because %s\r\n", msg);
3599       }
3600     else
3601       {
3602         sim_msg ("scale %012"PRIo64" (%llu)\r\n", M[pa], M[pa]);
3603       }
3604     if (dbgLookupAddress (cpu.PR[2].SNR, cpu.PR[2].WORDNO, & pa, & msg))
3605       {
3606         sim_msg ("divisor address lookup failed because %s\r\n", msg);
3607       }
3608     else
3609       {
3610         sim_msg ("divisor %012"PRIo64" (%llu)\r\n", M[pa], M[pa]);
3611       }
3612     return SCPE_OK;
3613   }
3614 # endif // DVFDBG
3615 
3616 // SEARCHMEMORY value
3617 
3618 static t_stat search_memory (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3619   {
3620     word36 value;
3621     if (sscanf (buf, "%llo", & value) != 1)
3622       return SCPE_ARG;
3623 
3624     uint i;
3625     for (i = 0; i < MEMSIZE; i ++)
3626       if ((M[i] & DMASK) == value)
3627         sim_msg ("%08o\r\n", i);
3628     return SCPE_OK;
3629   }
3630 
3631 static t_stat set_dbg_cpu_mask (int32 UNUSED arg, const char * UNUSED buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3632   {
3633     uint msk;
3634     int cnt = sscanf (buf, "%u", & msk);
3635     if (cnt != 1)
3636       {
3637         sim_msg ("Huh?\r\n");
3638         return SCPE_ARG;
3639       }
3640     sim_msg ("mask set to %u\r\n", msk);
3641     dbgCPUMask = msk;
3642     return SCPE_OK;
3643   }
3644 
3645 #endif // TESTING
3646 
3647 //
3648 // Misc. commands
3649 //
3650 
3651 #if defined(PANEL68)
3652 static t_stat scraper (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3653   {
3654     if (strcasecmp (buf, "start") == 0)
3655       return panelScraperStart ();
3656     if (strcasecmp (buf, "stop") == 0)
3657       return panelScraperStop ();
3658     if (strcasecmp (buf, "msg") == 0)
3659       {
3660         return panelScraperMsg (NULL);
3661       }
3662     if (strncasecmp (buf, "msg ", 4) == 0)
3663       {
3664         const char * p = buf + 4;
3665         while (* p == ' ')
3666           p ++;
3667         return panelScraperMsg (p);
3668       }
3669     sim_msg ("err: scraper start|stop|msg\r\n");
3670     return SCPE_ARG;
3671   }
3672 #endif
3673 
3674 #if defined(YIELD)
3675 static t_stat clear_yield (int32 flag, UNUSED const char * cptr)
     /* [previous][next][first][last][top][bottom][index][help] */
3676   {
3677     return SCPE_OK;
3678   }
3679 
3680 static t_stat yield (int32 flag, UNUSED const char * cptr)
     /* [previous][next][first][last][top][bottom][index][help] */
3681   {
3682     return SCPE_OK;
3683   }
3684 #endif
3685 
3686 #if !defined(PERF_STRIP)
3687 static t_stat set_luf (int32 flag, UNUSED const char * cptr)
     /* [previous][next][first][last][top][bottom][index][help] */
3688   {
3689     luf_flag = flag;
3690     return SCPE_OK;
3691   }
3692 #endif /* if !defined(PERF_STRIP) */
3693 
3694 #if defined(DBGEVENT)
3695 uint n_dbgevents;
3696 struct dbgevent_t dbgevents[max_dbgevents];
3697 struct timespec dbgevent_t0;
3698 
3699 static int dbgevent_compar (const void * a, const void * b)
     /* [previous][next][first][last][top][bottom][index][help] */
3700   {
3701     struct dbgevent_t * ea = (struct dbgevent_t *) a;
3702     struct dbgevent_t * eb = (struct dbgevent_t *) b;
3703     if (ea->segno < eb->segno)
3704       return -1;
3705     if (ea->segno > eb->segno)
3706       return 1;
3707     if (ea->offset < eb->offset)
3708       return -1;
3709     if (ea->offset > eb->offset)
3710       return 1;
3711     return 0;
3712   }
3713 
3714 int dbgevent_lookup (word15 segno, word18 offset)
     /* [previous][next][first][last][top][bottom][index][help] */
3715   {
3716     struct dbgevent_t key = {segno, offset, false};
3717     struct dbgevent_t * p = (struct dbgevent_t *) bsearch (& key, dbgevents, (size_t) n_dbgevents,
3718             sizeof (struct dbgevent_t), dbgevent_compar);
3719     if (! p)
3720       return -1;
3721     return (int) (p - dbgevents);
3722   }
3723 
3724 // "dbbevent segno:offset"
3725 //
3726 // arg: 0 set t0 event
3727 //      1 set event
3728 //      2 clear event
3729 //      3 list events
3730 //      4 clear all events
3731 
3732 // XXX think about per-thread timing?
3733 
3734 static t_stat set_dbgevent (int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3735   {
3736     if (arg == 0 || arg == 1)
3737       {
3738         if (n_dbgevents >= max_dbgevents)
3739           {
3740             sim_printf ("too many dbgevents %u/%u\r\n", n_dbgevents, max_dbgevents);
3741             return SCPE_ARG;
3742           }
3743         if (strlen (buf) > dbgevent_tagsize - 1)
3744           {
3745             sim_printf ("command too long %lu/%u\r\n", strlen (buf), dbgevent_tagsize -1);
3746             return SCPE_ARG;
3747           }
3748 
3749         uint segno;
3750         uint offset;
3751         if (sscanf (buf, "%o:%o", & segno, & offset) != 2)
3752           return SCPE_ARG;
3753         if (segno > MASK15 || offset > MASK18)
3754           return SCPE_ARG;
3755         if (dbgevent_lookup ((word15) segno, (word18) offset) != -1)
3756           {
3757             sim_printf ("not adding duplicate 0%o:0%o\r\n", segno, offset);
3758             return SCPE_ARG;
3759           }
3760         dbgevents[n_dbgevents].segno                     = (word15) segno;
3761         dbgevents[n_dbgevents].offset                    = (word18) offset;
3762         dbgevents[n_dbgevents].t0                        = arg == 0;
3763         strncpy (dbgevents[n_dbgevents].tag, buf, dbgevent_tagsize - 1);
3764         dbgevents[n_dbgevents].tag[dbgevent_tagsize - 1] = 0;
3765         sim_printf ("%o:%o %u(%d) %s\r\n", dbgevents[n_dbgevents].segno,
3766             dbgevents[n_dbgevents].offset,
3767                 dbgevents[n_dbgevents].t0, arg, dbgevents[n_dbgevents].tag);
3768         n_dbgevents ++;
3769         qsort (dbgevents, n_dbgevents, sizeof (struct dbgevent_t), dbgevent_compar);
3770       }
3771     else if (arg == 2)
3772       {
3773         uint segno;
3774         uint offset;
3775         if (sscanf (buf, "%o:%o", & segno, & offset) != 2)
3776           return SCPE_ARG;
3777         int n = dbgevent_lookup ((word15) segno, (word18) offset);
3778         if (n < 0)
3779           {
3780             sim_printf ("0%o:0%o not found\r\n", segno, offset);
3781             return SCPE_ARG;
3782           }
3783         for (int i = n; i < n_dbgevents - 1; i ++)
3784           dbgevents[i] = dbgevents[i + 1];
3785         n_dbgevents --;
3786       }
3787     else if (arg == 3)
3788       {
3789         for (int i = 0; i < n_dbgevents; i ++)
3790          sim_printf ("    %s %05o:%06o %s\r\n", dbgevents[i].t0 ? "T0" : "  ", dbgevents[i].segno,
3791                  dbgevents[i].offset,dbgevents[i].tag);
3792       }
3793     else if (arg == 4)
3794       {
3795         n_dbgevents = 0;
3796         sim_printf ("dbgevents cleared\r\n");
3797       }
3798     else
3799       {
3800         sim_printf ("set_dbgevent bad arg %d\r\n", arg);
3801         return SCPE_ARG;
3802       }
3803     return SCPE_OK;
3804   }
3805 #endif
3806 
3807 //  REWIND name
3808 //
3809 //  rewind tapa_05
3810 //
3811 
3812 t_stat rewind_media (int32 arg, const char * buf) {
     /* [previous][next][first][last][top][bottom][index][help] */
3813   char name[strlen (buf) + 1];
3814 
3815   int rc = sscanf (buf, "%s", name);
3816   if (rc != 1)
3817     return SCPE_ARG;
3818 
3819   for (uint i = 0; i < N_MT_UNITS_MAX; i ++) {
3820     if (strcmp (tape_states[i].device_name, name) == 0) {
3821       UNIT * unitp = & mt_unit [i];
3822       return sim_tape_rewind (unitp);
3823     }
3824   }
3825 
3826   sim_printf ("Can't find name '%s'\r\n", name);
3827   sim_printf ("REWIND device_name\r\n");
3828   return SCPE_ARG;
3829 }
3830 
3831 // [UN]LOAD  name  image_name ro|rw
3832 //
3833 //  load tapea_05  data.tap ro
3834 //
3835 //  load diskb_01  data.dsk rw
3836 //
3837 
3838 t_stat load_media (int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3839   {
3840     // arg 1: load
3841     //     0: unload
3842 
3843     char  name[strlen (buf) + 1];
3844     char fname[strlen (buf) + 1];
3845     char  perm[strlen (buf) + 1];
3846     bool ro = false;
3847     if (arg)
3848       {
3849         int rc = sscanf (buf, "%s %s %s", name, fname, perm);
3850         if (rc != 3)
3851           return SCPE_ARG;
3852         if (strcasecmp (perm, "rw") == 0)
3853           ro = false;
3854         else if (strcasecmp (perm, "ro") == 0)
3855           ro = true;
3856         else
3857           {
3858              sim_print ("'%s' not 'ro' or 'rw'\r\n", perm);
3859              goto usage;
3860           }
3861       }
3862     else
3863       {
3864         int rc = sscanf (buf, "%s", name);
3865         if (rc != 1)
3866           return SCPE_ARG;
3867       }
3868 
3869     for (uint i = 0; i < N_DSK_UNITS_MAX; i ++)
3870       if (strcmp (dsk_states[i].device_name, name) == 0)
3871         {
3872           if (arg)
3873             return loadDisk (i, fname, ro);
3874           return unloadDisk (i);
3875         }
3876 
3877     for (uint i = 0; i < N_MT_UNITS_MAX; i ++)
3878       if (strcmp (tape_states[i].device_name, name) == 0)
3879         {
3880           if (arg)
3881             return loadTape (i, fname, ro);
3882           return unloadTape (i);
3883         }
3884 
3885     sim_printf ("Can't find name '%s'\r\n", name);
3886 usage:
3887     sim_printf ("[UN]LOAD device_name image_name ro|rw\r\n");
3888     return SCPE_ARG;
3889   }
3890 
3891 t_stat ready_media (int32 arg, const char * buf) {
     /* [previous][next][first][last][top][bottom][index][help] */
3892   char name[strlen (buf) + 1];
3893   int rc = sscanf (buf, "%s", name);
3894   if (rc != 1)
3895     return SCPE_ARG;
3896 
3897   for (uint i = 0; i < N_DSK_UNITS_MAX; i ++) {
3898     if (strcmp (dsk_states[i].device_name, name) == 0) {
3899       return signal_disk_ready (i);
3900     }
3901   }
3902 
3903   for (uint i = 0; i < N_MT_UNITS_MAX; i ++) {
3904     if (strcmp (tape_states[i].device_name, name) == 0) {
3905       return signal_tape (i, 0, 020 /* tape drive to ready */); //-V536
3906     }
3907   }
3908 
3909   sim_printf ("Can't find name '%s'\r\n", name);
3910   sim_printf ("[UN]LOAD device_name image_name ro|rw\r\n");
3911   return SCPE_ARG;
3912 }
3913 
3914 ////////////////////////////////////////////////////////////////////////////////
3915 //
3916 // s*mh Command table
3917 //
3918 
3919 #if defined(TESTING)
3920 # include "tracker.h"
3921 
3922 static t_stat trkw (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3923   {
3924     trk_init (true);
3925     return SCPE_OK;
3926   }
3927 
3928 static t_stat trkr (UNUSED int32 arg, const char * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
3929   {
3930     trk_init (false);
3931     return SCPE_OK;
3932   }
3933 #endif
3934 
3935 #if !defined(PERF_STRIP)
3936 static CTAB dps8_cmds[] =
3937   {
3938 //
3939 // System configuration
3940 //
3941 
3942     {"DEFAULT_BASE_SYSTEM", set_default_base_system,  0, "Set configuration to defaults\r\n",             NULL, NULL},
3943 
3944     {"CABLE",               sys_cable,                0, "String a cable.\r\n",                           NULL, NULL},
3945     {"UNCABLE",             sys_cable,                1, "Unstring a cable.\r\n",                         NULL, NULL},
3946     {"CABLE_RIPOUT",        sys_cable_ripout,         0, "Remove all cables from the configuration.\r\n", NULL, NULL},
3947     {"CABLE_SHOW",          sys_cable_show,           0, "Show the current cabling configuration.\r\n",   NULL, NULL},
3948 
3949     {"FNPSERVERPORT",       set_fnp_server_port,      0, "Set the FNP dialin TELNET port number\r\n",     NULL, NULL},
3950     {"FNPSERVERADDRESS",    set_fnp_server_address,   0, "Set the FNP dialin server binding address\r\n", NULL, NULL},
3951     {"FNPSERVER3270PORT",   set_fnp_3270_server_port, 0, "Set the FNP TN3270 dialin port number\r\n",     NULL, NULL},
3952 
3953 //
3954 // System control
3955 //
3956 
3957     {"SKIPBOOT",  boot_skip,                     0, "Skip forward on boot tape (SKIPBOOT [unit])\r\n",                  NULL, NULL},
3958     {"FNPSTART",  fnp_start,                     0, "Directs the simulator to immediately start listening for FNP connections.\r\n",
3959                                                                                                                         NULL, NULL},
3960     {"MOUNT",     mount_tape,                    0, "Mount tape image and signal Multics\r\n",                          NULL, NULL},
3961     {"LOAD",      load_media,                    1, "Mount disk or tape image and signal Multics\r\n",                  NULL, NULL},
3962     {"UNLOAD",    load_media,                    0, "Unmount disk or tape image and signal Multics\r\n",                NULL, NULL},
3963     {"READY",     ready_media,                   0, "Signal Multics that media is ready\r\n",                           NULL, NULL},
3964     {"REWIND",    rewind_media,                  0, "Rewind tape\r\n",                                                  NULL, NULL},
3965     {"XF",        do_execute_fault,              0, "Execute fault: Press the execute fault button\r\n",                NULL, NULL},
3966     {"XS",        do_execute_switches,           0, "Execute switches: Execute the instruction in the data switches\r\n", NULL, NULL},
3967     {"RESTART",   do_restart,                    0, "Execute fault: Press the execute fault button\r\n",                NULL, NULL},
3968     {"POLL",      set_sys_polling_interval,      0, "Set polling interval (in milliseconds)\r\n",                       NULL, NULL},
3969     {"SLOWPOLL",  set_sys_slow_polling_interval, 0, "Set slow polling interval (in polling intervals).\r\n",            NULL, NULL},
3970     {"CHECKPOLL", set_sys_poll_check_rate,       0, "Set polling check rate (in polling intervals).\r\n",               NULL, NULL},
3971     {"BURST",     burst_printer,                 0, "Burst process output from printer.\r\n",                           NULL, NULL},
3972 
3973 //
3974 // Debugging
3975 //
3976 
3977 # if defined(TESTING)
3978     {"TRKW",               trkw,                  0, "Start tracking to track.dat\r\n",                            NULL, NULL},
3979     {"TRKR",               trkr,                  0, "Start comparing with track.dat\r\n",                         NULL, NULL},
3980     {"DBGMMECNTDWN",       dps_debug_mme_cntdwn,  0, "Enable debug after n MMEs\r\n",                              NULL, NULL},
3981     {"DBGSKIP",            dps_debug_skip,        0, "Skip first n TRACE debugs\r\n",                              NULL, NULL},
3982     {"DBGSTART",           dps_debug_start,       0, "Limit debugging to N > Cycle count\r\n",                     NULL, NULL},
3983     {"DBGSTOP",            dps_debug_stop,        0, "Limit debugging to N < Cycle count\r\n",                     NULL, NULL},
3984     {"DBGBREAK",           dps_debug_break,       0, "Break when N >= Cycle count\r\n",                            NULL, NULL},
3985     {"DBGSEGNO",           dps_debug_segno,       1, "Limit debugging to PSR == segno\r\n",                        NULL, NULL},
3986     {"NODBGSEGNO",         dps_debug_segno,       0, "Reset to debugging all segments\r\n",                        NULL, NULL},
3987     {"DBGRINGNO",          dps_debug_ringno,      0, "Limit debugging to PRR == ringno\r\n",                       NULL, NULL},
3988     {"DBGBAR",             dps_debug_bar,         1, "Limit debugging to BAR mode\r\n",                            NULL, NULL},
3989     {"NODBGBAR",           dps_debug_bar,         0, "Limit debugging to BAR mode\r\n",                            NULL, NULL},
3990     {"HDBG",               hdbg_size,             0, "Set history debugger buffer size\r\n",                       NULL, NULL},
3991     {"HDSEG",              hdbgSegmentNumber,     0, "Set history debugger segment number\r\n",                    NULL, NULL},
3992     {"HDBL",               hdbgBlacklist,         0, "Set history debugger blacklist\r\n",                         NULL, NULL},
3993     {"PHDBG",              hdbg_print,            0, "Dump history buffer to 'hdbg0000.list'\r\n",                 NULL, NULL},
3994     {"HDBG_CPU_MASK",      hdbg_cpu_mask,         0, "Set which CPUs to track (by mask)\r\n",                      NULL, NULL},
3995     {"ABSOLUTE",           abs_addr,              0, "Compute the absolute address of segno:offset\r\n",           NULL, NULL},
3996     {"STK",                stack_trace,           0, "Print a stack trace\r\n",                                    NULL, NULL},
3997     {"LIST",               list_source_at,        0, "List source for address / segno:offset\r\n",                 NULL, NULL},
3998     {"LD_SYSTEM_BOOK",     load_system_book,      0, "Load a Multics system book for symbolic debugging\r\n",      NULL, NULL},
3999     {"ASBE",               add_system_book_entry, 0, "Add an entry to the system book\r\n",                        NULL, NULL},
4000     {"LOOKUP_SYSTEM_BOOK", lookup_system_book,    0, "Lookup an address or symbol in the Multics system book\r\n", NULL, NULL},
4001     {"LSB",                lookup_system_book,    0, "Lookup an address or symbol in the Multics system book\r\n", NULL, NULL},
4002     {"VIRTUAL",            virt_address,          0, "Compute the virtual address(es) of segno:offset\r\n",        NULL, NULL},
4003     {"SPATH",              set_search_path,       0, "Set source code search path\r\n",                            NULL, NULL},
4004     {"TEST",               brkbrk,                0, "GDB test hook\r\n",                                          NULL, NULL},
4005 #  if defined(DBGEVENT)
4006     {"DBG0EVENT",          set_dbgevent,          0, "Set t0 debug event\r\n",                                     NULL, NULL},
4007     {"DBGEVENT",           set_dbgevent,          1, "Set debug event\r\n",                                        NULL, NULL},
4008     {"DBGNOEVENT",         set_dbgevent,          2, "Clear debug event\r\n",                                      NULL, NULL},
4009     {"DBGLISTEVENTS",      set_dbgevent,          3, "List debug events\r\n",                                      NULL, NULL},
4010     {"DBGCLEAREVENTS",     set_dbgevent,          4, "Clear debug events\r\n",                                     NULL, NULL},
4011 #  endif /* if defined(DBGEVENT) */
4012 #  define SSH_ST 0        /* set */
4013 #  define SSH_SH 1        /* show */
4014 #  define SSH_CL 2        /* clear */
4015     {"SBREAK",       sbreak,           SSH_ST, "Set a breakpoint with segno:offset syntax\r\n", NULL, NULL},
4016     {"NOSBREAK",     sbreak,           SSH_CL, "Unset an SBREAK\r\n",                           NULL, NULL},
4017 #  if defined(DVFDBG)
4018     // dvf debugging
4019     {"DFX1ENTRY",    dfx1entry,        0,      "\r\n",                                          NULL, NULL},
4020     {"DFX2ENTRY",    dfx2entry,        0,      "\r\n",                                          NULL, NULL},
4021     {"DFX1EXIT",     dfx1exit,         0,      "\r\n",                                          NULL, NULL},
4022     {"DV2SCALE",     dv2scale,         0,      "\r\n",                                          NULL, NULL},
4023     {"MDFX3ENTRY",   mdfx3entry,       0,      "\r\n",                                          NULL, NULL},
4024     {"SMFX1ENTRY",   smfx1entry,       0,      "\r\n",                                          NULL, NULL},
4025 #  endif /* if defined(DVFDBG) */
4026 #  if !defined(SPEED)
4027     {"WATCH",        set_mem_watch,    1,      "Watch memory location\r\n",                     NULL, NULL},
4028     {"NOWATCH",      set_mem_watch,    0,      "Unwatch memory location\r\n",                   NULL, NULL},
4029 #  endif /* if !defined(SPEED) */
4030     {"SEARCHMEMORY", search_memory,    0,      "Search memory for value\r\n",                   NULL, NULL},
4031     {"DBGCPUMASK",   set_dbg_cpu_mask, 0,      "Set per-CPU debug enable mask\r\n",             NULL, NULL},
4032 # endif /* if defined(TESTING) */
4033 
4034     {"SEGLDR",       segment_loader,   0,      "Segment Loader\r\n",                            NULL, NULL},
4035 
4036 //
4037 // Statistics
4038 //
4039 
4040 # if defined(MATRIX)
4041     {"DISPLAYMATRIX", display_the_matrix,  0, "Display instruction usage counts\r\n", NULL, NULL},
4042 # endif
4043 
4044 //
4045 // Console scripting
4046 //
4047 
4048     {"AUTOINPUT",     add_opc_autoinput,   0, "Set primary console auto-input\r\n",     NULL, NULL},
4049     {"AI",            add_opc_autoinput,   0, "Set primary console auto-input\r\n",     NULL, NULL},
4050     {"AUTOINPUT2",    add_opc_autoinput,   1, "Set secondary console auto-input\r\n",   NULL, NULL},
4051     {"AI2",           add_opc_autoinput,   1, "Set secondary console auto-input\r\n",   NULL, NULL},
4052     {"CLRAUTOINPUT",  clear_opc_autoinput, 0, "Clear primary console auto-input\r\n",   NULL, NULL},
4053     {"CLRAUTOINPUT2", clear_opc_autoinput, 1, "Clear secondary console auto-input\r\n", NULL, NULL},
4054 
4055 //
4056 // Tuning
4057 //
4058 
4059 # if YIELD
4060     {"CLEAR_YIELD",   clear_yield,         1, "Clear yield data points\r\n",            NULL, NULL},
4061     {"YIELD",         yield,               1, "Define yield data point\r\n",            NULL, NULL},
4062 # endif
4063 
4064 //
4065 // Hacks
4066 //
4067 
4068     {"LUF",           set_luf,             1, "Enable normal LUF handling\r\n",         NULL, NULL},
4069     {"NOLUF",         set_luf,             0, "Disable normal LUF handling\r\n",        NULL, NULL},
4070 
4071 //
4072 // Misc.
4073 //
4074 
4075 # if defined(PANEL68)
4076     {"SCRAPER",       scraper,             0, "Control panel scraper\r\n", NULL, NULL},
4077 # endif /* if defined(PANEL68) */
4078     { NULL,           NULL,                0, NULL,                      NULL, NULL}
4079   }; // dps8_cmds
4080 
4081 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) && !defined(PERF_STRIP)
4082 static void usr1_signal_handler (UNUSED int sig)
     /* [previous][next][first][last][top][bottom][index][help] */
4083   {
4084     sim_msg ("USR1 signal caught; pressing the EXF button\r\n");
4085     // Assume the bootload CPU
4086     setG7fault (ASSUME0, FAULT_EXF);
4087     return;
4088   }
4089 # endif
4090 
4091 static struct symbol_s symbols [] = {
4092     { "commit_id",              SYM_STATE_OFFSET,  SYM_STRING,    offsetof (struct system_state_s, commit_id)   },
4093     { "M[]",                    SYM_STATE_OFFSET,  SYM_ARRAY,     offsetof (struct system_state_s, M)           },
4094     { "sizeof(*M)",             SYM_STRUCT_SZ,     SYM_SZ,        sizeof (word36) },
4095 
4096     { "cpus[]",                 SYM_STATE_OFFSET,  SYM_ARRAY,     offsetof (struct system_state_s, cpus)        },
4097     { "sizeof(*cpus)",          SYM_STRUCT_SZ,     SYM_SZ,        sizeof (cpu_state_t) },
4098 
4099     { "cpus[].PPR",             SYM_STRUCT_OFFSET, SYM_PTR,       offsetof (cpu_state_t,           PPR)         },
4100     { "cpus[].PPR.PRR",         SYM_STRUCT_OFFSET, SYM_UINT8_3,   offsetof (struct ppr_s,          PRR)         },
4101     { "cpus[].PPR.PSR",         SYM_STRUCT_OFFSET, SYM_UINT16_15, offsetof (struct ppr_s,          PSR)         },
4102     { "cpus[].PPR.P",           SYM_STRUCT_OFFSET, SYM_UINT8_1,   offsetof (struct ppr_s,          P)           },
4103     { "cpus[].PPR.IC",          SYM_STRUCT_OFFSET, SYM_UINT32_18, offsetof (struct ppr_s,          IC)          },
4104 
4105     { "cpus[].cu",              SYM_STRUCT_OFFSET, SYM_PTR,       offsetof (cpu_state_t,           cu)          },
4106     { "cpus[].cu.IWB",          SYM_STRUCT_OFFSET, SYM_UINT64_36, offsetof (ctl_unit_data_t,       IWB)         },
4107     { "cpus[].cu.IR",           SYM_STRUCT_OFFSET, SYM_UINT32_18, offsetof (ctl_unit_data_t,       IR)          },
4108 
4109     { "cpus[].rA",              SYM_STRUCT_OFFSET, SYM_UINT64_36, offsetof (cpu_state_t,           rA)          },
4110 
4111     { "cpus[].rQ",              SYM_STRUCT_OFFSET, SYM_UINT64_36, offsetof (cpu_state_t,           rQ)          },
4112 
4113     { "cpus[].rE",              SYM_STRUCT_OFFSET, SYM_UINT64_36, offsetof (cpu_state_t,           rE)          },
4114 
4115     { "cpus[].rX[]",            SYM_STRUCT_OFFSET, SYM_ARRAY,     offsetof (cpu_state_t,           rX)          },
4116     { "sizeof(*rX)",            SYM_STRUCT_SZ,     SYM_SZ,        sizeof (word18) },
4117     { "cpus[].rX",              SYM_STRUCT_OFFSET, SYM_UINT32_18, 0 },
4118 
4119     { "cpus[].rTR",             SYM_STRUCT_OFFSET, SYM_UINT32_27, offsetof (cpu_state_t,           rTR)         },
4120 
4121     { "cpus[].rRALR",           SYM_STRUCT_OFFSET, SYM_UINT8_3,   offsetof (cpu_state_t,           rRALR)       },
4122 
4123     { "cpus[].PAR[]",           SYM_STRUCT_OFFSET, SYM_ARRAY,     offsetof (cpu_state_t,           PAR)         },
4124     { "sizeof(*PAR)",           SYM_STRUCT_SZ,     SYM_SZ,        sizeof (struct par_s) },
4125 
4126     { "cpus[].PAR[].SNR",       SYM_STRUCT_OFFSET, SYM_UINT16_15, offsetof (struct par_s,          SNR)         },
4127     { "cpus[].PAR[].RNR",       SYM_STRUCT_OFFSET, SYM_UINT8_3,   offsetof (struct par_s,          RNR)         },
4128     { "cpus[].PAR[].PR_BITNO",  SYM_STRUCT_OFFSET, SYM_UINT8_6,   offsetof (struct par_s,          PR_BITNO)    },
4129     { "cpus[].PAR[].WORDNO",    SYM_STRUCT_OFFSET, SYM_UINT32_18, offsetof (struct par_s,          WORDNO)      },
4130 
4131     { "cpus[].BAR",             SYM_STRUCT_OFFSET, SYM_PTR,       offsetof (cpu_state_t,           BAR)         },
4132     { "cpus[].BAR.BASE",        SYM_STRUCT_OFFSET, SYM_UINT16_9,  offsetof (struct bar_s,          BASE)        },
4133     { "cpus[].BAR.BOUND",       SYM_STRUCT_OFFSET, SYM_UINT16_9,  offsetof (struct bar_s,          BOUND)       },
4134 
4135     { "cpus[].TPR",             SYM_STRUCT_OFFSET, SYM_PTR,       offsetof (cpu_state_t,           TPR)         },
4136     { "cpus[].TPR.TRR",         SYM_STRUCT_OFFSET, SYM_UINT8_3,   offsetof (struct tpr_s,          TRR)         },
4137     { "cpus[].TPR.TSR",         SYM_STRUCT_OFFSET, SYM_UINT16_15, offsetof (struct tpr_s,          TSR)         },
4138     { "cpus[].TPR.TBR",         SYM_STRUCT_OFFSET, SYM_UINT8_6,   offsetof (struct tpr_s,          TBR)         },
4139     { "cpus[].TPR.CA",          SYM_STRUCT_OFFSET, SYM_UINT32_18, offsetof (struct tpr_s,          CA)          },
4140 
4141     { "cpus[].DSBR",            SYM_STRUCT_OFFSET, SYM_PTR,       offsetof (cpu_state_t,           DSBR)        },
4142     { "cpus[].DSBR.ADDR",       SYM_STRUCT_OFFSET, SYM_UINT32_24, offsetof (struct dsbr_s,         ADDR)        },
4143     { "cpus[].DSBR.BND",        SYM_STRUCT_OFFSET, SYM_UINT16_14, offsetof (struct dsbr_s,         BND)         },
4144     { "cpus[].DSBR.U",          SYM_STRUCT_OFFSET, SYM_UINT8_1,   offsetof (struct dsbr_s,         U)           },
4145     { "cpus[].DSBR.STACK",      SYM_STRUCT_OFFSET, SYM_UINT16_12, offsetof (struct dsbr_s,         STACK)       },
4146 
4147     { "cpus[].faultNumber",     SYM_STRUCT_OFFSET, SYM_UINT32,    offsetof (cpu_state_t,           faultNumber) },
4148 # define SYMTAB_ENUM32(e) { #e, SYM_ENUM,          SYM_UINT32,    e }
4149     SYMTAB_ENUM32 (FAULT_SDF),
4150     SYMTAB_ENUM32 (FAULT_STR),
4151     SYMTAB_ENUM32 (FAULT_MME),
4152     SYMTAB_ENUM32 (FAULT_F1),
4153     SYMTAB_ENUM32 (FAULT_TRO),
4154     SYMTAB_ENUM32 (FAULT_CMD),
4155     SYMTAB_ENUM32 (FAULT_DRL),
4156     SYMTAB_ENUM32 (FAULT_LUF),
4157     SYMTAB_ENUM32 (FAULT_CON),
4158     SYMTAB_ENUM32 (FAULT_PAR),
4159     SYMTAB_ENUM32 (FAULT_IPR),
4160     SYMTAB_ENUM32 (FAULT_ONC),
4161     SYMTAB_ENUM32 (FAULT_SUF),
4162     SYMTAB_ENUM32 (FAULT_OFL),
4163     SYMTAB_ENUM32 (FAULT_DIV),
4164     SYMTAB_ENUM32 (FAULT_EXF),
4165     SYMTAB_ENUM32 (FAULT_DF0),
4166     SYMTAB_ENUM32 (FAULT_DF1),
4167     SYMTAB_ENUM32 (FAULT_DF2),
4168     SYMTAB_ENUM32 (FAULT_DF3),
4169     SYMTAB_ENUM32 (FAULT_ACV),
4170     SYMTAB_ENUM32 (FAULT_MME2),
4171     SYMTAB_ENUM32 (FAULT_MME3),
4172     SYMTAB_ENUM32 (FAULT_MME4),
4173     SYMTAB_ENUM32 (FAULT_F2),
4174     SYMTAB_ENUM32 (FAULT_F3),
4175     SYMTAB_ENUM32 (FAULT_UN1),
4176     SYMTAB_ENUM32 (FAULT_UN2),
4177     SYMTAB_ENUM32 (FAULT_UN3),
4178     SYMTAB_ENUM32 (FAULT_UN4),
4179     SYMTAB_ENUM32 (FAULT_UN5),
4180     SYMTAB_ENUM32 (FAULT_TRB),
4181 
4182     { "",                       SYM_EMPTY,         SYM_UNDEF,     0 },
4183   };
4184 
4185 static void systabInit (void) {
     /* [previous][next][first][last][top][bottom][index][help] */
4186   strncpy (system_state->symbolTable.symtabHdr, SYMTAB_HDR, sizeof (system_state->symbolTable.symtabHdr));
4187   system_state->symbolTable.symtabVer = SYMTAB_VER;
4188   memcpy (system_state->symbolTable.symbols, symbols, sizeof (symbols)); //-V1086
4189 }
4190 #endif /* if !defined(PERF_STRIP) */
4191 
4192 static inline uint32_t
4193 hash32s(const void *buf, size_t len, uint32_t h)
     /* [previous][next][first][last][top][bottom][index][help] */
4194 {
4195   const unsigned char *p = buf;
4196 
4197   for (size_t i = 0; i < len; i++)
4198     h = h * 31 + p[i];
4199 
4200   h ^= h >> 17;
4201   h *= UINT32_C(0xed5ad4bb);
4202   h ^= h >> 11;
4203   h *= UINT32_C(0xac4c1b51);
4204   h ^= h >> 15;
4205   h *= UINT32_C(0x31848bab);
4206   h ^= h >> 14;
4207 
4208   return h;
4209 }
4210 
4211 // Once-only initialization; invoked via SCP
4212 
4213 static void dps8_init (void) {
     /* [previous][next][first][last][top][bottom][index][help] */
4214   int st1ret;
4215   (void)fflush(stderr);
4216   (void)fflush(stdout);
4217 #if !defined(PERF_STRIP)
4218   if (!sim_quiet) {
4219 # if defined(GENERATED_MAKE_VER_H) && defined(VER_H_GIT_VERSION)
4220 #  if defined(VER_H_GIT_PATCH_INT) && defined(VER_H_GIT_PATCH)
4221 #   if VER_H_GIT_PATCH_INT < 1
4222     sim_msg ("%s simulator %s (%ld-bit)",
4223              sim_name, VER_H_GIT_VERSION,
4224              (long)(CHAR_BIT*sizeof(void *)));
4225 #   else
4226     sim_msg ("%s simulator %s+%s (%ld-bit)",
4227              sim_name, VER_H_GIT_VERSION, VER_H_GIT_PATCH,
4228              (long)(CHAR_BIT*sizeof(void *)));
4229 #   endif
4230 #  else
4231     sim_msg ("%s simulator %s (%ld-bit)",
4232              sim_name, VER_H_GIT_VERSION,
4233              (long)(CHAR_BIT*sizeof(void *)));
4234 #  endif
4235 # endif
4236 # if !defined(VER_H_GIT_VERSION) || !defined(GENERATED_MAKE_VER_H)
4237     sim_msg ("%s simulator (%ld-bit)",
4238              sim_name, (long)(CHAR_BIT*sizeof(void *)));
4239 # endif
4240 
4241 /* TESTING */
4242 # if defined(TESTING)
4243     sim_msg ("\r\n Options: ");
4244 #  if !defined(HAVE_DPSOPT)
4245 #   define HAVE_DPSOPT 1
4246 #  endif
4247     sim_msg ("TESTING");
4248 # endif /* if defined(TESTING) */
4249 
4250 /* ISOLTS */
4251 # if defined(ISOLTS)
4252 #  if defined(HAVE_DPSOPT)
4253     sim_msg (", ");
4254 #  else
4255     sim_msg ("\r\n Options: ");
4256 #  endif
4257 #  if !defined(HAVE_DPSOPT)
4258 #   define HAVE_DPSOPT 1
4259 #  endif
4260     sim_msg ("ISOLTS");
4261 # endif /* if defined(ISOLTS) */
4262 
4263 /* NEED_128 */
4264 # if defined(NEED_128)
4265 #  if defined(HAVE_DPSOPT)
4266     sim_msg (", ");
4267 #  else
4268     sim_msg ("\r\n Options: ");
4269 #  endif
4270 #  if !defined(HAVE_DPSOPT)
4271 #   define HAVE_DPSOPT 1
4272 #  endif
4273     sim_msg ("NEED_128");
4274 # endif /* if defined(NEED_128) */
4275 
4276 /* NO_LOCKLESS */
4277 # if !defined(LOCKLESS)
4278 #  if defined(HAVE_DPSOPT)
4279     sim_msg (", ");
4280 #  else
4281     sim_msg ("\r\n Options: ");
4282 #  endif
4283 #  if !defined(HAVE_DPSOPT)
4284 #   define HAVE_DPSOPT 1
4285 #  endif
4286     sim_msg ("NO_LOCKLESS");
4287 # endif /* if !defined(LOCKLESS) */
4288 
4289 /* PANEL68 */
4290 # if defined(PANEL68)
4291 #  if defined(HAVE_DPSOPT)
4292     sim_msg (", ");
4293 #  else
4294     sim_msg ("\r\n Options: ");
4295 #  endif
4296 #  if !defined(HAVE_DPSOPT)
4297 #   define HAVE_DPSOPT 1
4298 #  endif
4299     sim_msg ("PANEL68");
4300 # endif /* if defined(PANEL68) */
4301 
4302 /* ABSI */  /* XXX: Change to !ABSI once code is non-experimental */
4303 # if defined(WITH_ABSI_DEV)
4304 #  if defined(HAVE_DPSOPT)
4305     sim_msg (", ");
4306 #  else
4307     sim_msg ("\r\n Options: ");
4308 #  endif
4309 #  if !defined(HAVE_DPSOPT)
4310 #   define HAVE_DPSOPT 1
4311 #  endif
4312     sim_msg ("ABSI");
4313 # endif /* if defined(WITH_ABSI_DEV) */
4314 
4315 /* SOCKET */  /* XXX: Change to !SOCKET once code is non-experimental */
4316 # if defined(WITH_SOCKET_DEV)
4317 #  if defined(HAVE_DPSOPT)
4318     sim_msg (", ");
4319 #  else
4320     sim_msg ("\r\n Options: ");
4321 #  endif
4322 #  if !defined(HAVE_DPSOPT)
4323 #   define HAVE_DPSOPT 1
4324 #  endif
4325     sim_msg ("SOCKET");
4326 # endif /* if defined(WITH_SOCKET_DEV) */
4327 
4328 /* CHAOSNET */
4329 # if !defined(WITH_MGP_DEV)
4330 #  if defined(HAVE_DPSOPT)
4331     sim_msg (", ");
4332 #  else
4333     sim_msg ("\r\n Options: ");
4334 #  endif
4335 #  if !defined(HAVE_DPSOPT)
4336 #   define HAVE_DPSOPT 1
4337 #  endif
4338     sim_msg ("NO_CHAOSNET");
4339 # endif /* if !defined(WITH_MGP_DEV) */
4340 
4341 /* INTERNET */
4342 # if !defined(WITH_NET_DEV)
4343 #  if defined(HAVE_DPSOPT)
4344     sim_msg (", ");
4345 #  else
4346     sim_msg ("\r\n Options: ");
4347 #  endif
4348 #  if !defined(HAVE_DPSOPT)
4349 #   define HAVE_DPSOPT 1
4350 #  endif
4351     sim_msg ("NO_INTERNET");
4352 # endif /* if !defined(WITH_NET_DEV) */
4353 
4354 /* DUMA */
4355 # if defined(USE_DUMA)
4356 #  if defined(HAVE_DPSOPT)
4357     sim_msg (", ");
4358 #  else
4359     sim_msg ("\r\n Options: ");
4360 #  endif
4361 #  if !defined(HAVE_DPSOPT)
4362 #   define HAVE_DPSOPT 1
4363 #  endif
4364     sim_msg ("DUMA");
4365 # endif /* if defined(USE_DUMA) */
4366 
4367 # if defined(GENERATED_MAKE_VER_H) && defined(VER_H_GIT_HASH)
4368     sim_msg ("\r\n  Commit: %s", VER_H_GIT_HASH);
4369 # endif
4370     sim_msg ("\r\n\r\n");
4371     (void)fflush(stderr);
4372     (void)fflush(stdout);
4373   }
4374 
4375   // special dps8 initialization stuff that can't be done in reset, etc. ...
4376 
4377 # if defined(TESTING)
4378   // These are part of the scp interface
4379   sim_vm_parse_addr  = parse_addr;
4380   sim_vm_fprint_addr = fprint_addr;
4381 # endif /* if defined(TESTING) */
4382 
4383   sim_vm_cmd = dps8_cmds;
4384 
4385   // This is needed to make sbreak work
4386   sim_brk_types = sim_brk_dflt = SWMASK ('E');
4387 
4388 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64)
4389   // Wire the XF button to signal USR1
4390   signal (SIGUSR1, usr1_signal_handler);
4391   // On line 4,739 of the libuv man page, it recommends this.
4392   signal(SIGPIPE, SIG_IGN);
4393 # endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64) */
4394 
4395 #endif
4396 
4397 #if defined(__MINGW64__) || defined(__MINGW32__)
4398 # include "bsd_random.h"
4399 # define random  bsd_random
4400 # define srandom bsd_srandom
4401 #endif /* if defined(__MINGW64__) || defined(__MINGW32__) */
4402 
4403   char   rcap = 0;
4404   char   rnum = 0;
4405   struct timespec ts;
4406 
4407   char   rssuffix[24];
4408   (void)memset(rssuffix, 0, 24);
4409 
4410   char   statenme[32];
4411   (void)memset(statenme, 0, 32);
4412 
4413 #if defined(USE_MONOTONIC)
4414   st1ret = clock_gettime(CLOCK_MONOTONIC, &ts);
4415 #else
4416   st1ret = clock_gettime(CLOCK_REALTIME, &ts);
4417 #endif /* if defined(USE_MONOTONIC) */
4418   if (st1ret != 0)
4419     {
4420       (void)sir_emerg ("FATAL: clock_gettime failure! Aborting at %s[%s:%d]",
4421                        __func__, __FILE__, __LINE__);
4422 #if defined(USE_BACKTRACE)
4423 # if defined(SIGUSR2)
4424       (void)raise(SIGUSR2);
4425       /*NOTREACHED*/ /* unreachable */
4426 # endif /* if defined(SIGUSR2) */
4427 #endif /* if defined(USE_BACKTRACE) */
4428       abort();
4429     }
4430 
4431   uint32_t h = 0;  /* initial hash value */
4432 #if __STDC_VERSION__ < 201112L
4433   /* LINTED E_OLD_STYLE_FUNC_DECL */
4434   void *(*mallocptr)() = malloc;
4435   h = hash32s(&mallocptr, sizeof(mallocptr), h);
4436 #endif /* if __STDC_VERSION__ < 201112L */
4437   void *ptr = &ptr;
4438   h = hash32s(&ptr, sizeof(ptr), h);
4439   time_t t = time(0);
4440   h = hash32s(&t, sizeof(t), h);
4441 #if !defined(_AIX) && !defined(__managarm__)
4442   for (int i = 0; i < 1000; i++)
4443     {
4444       unsigned long counter = 0;
4445       clock_t start = clock();
4446       while (clock() == start)
4447         {
4448           counter++;
4449         }
4450       h = hash32s(&start, sizeof(start), h);
4451       h = hash32s(&counter, sizeof(counter), h);
4452     }
4453 #endif /* if !defined(_AIX) */
4454   int mypid = (int)_sir_getpid();
4455   h = hash32s(&mypid, sizeof(mypid), h);
4456   char rnd[4];
4457   FILE *f = fopen("/dev/urandom", "rb");
4458   if (f)
4459     {
4460       if (fread(rnd, sizeof(rnd), 1, f))
4461         {
4462           h = hash32s(rnd, sizeof(rnd), h);
4463         }
4464       fclose(f);
4465     }
4466   srandom(h); /* seed rng */
4467 
4468   for (int i = 1; i < 21; ++i) {
4469     rcap = (int)random() % 2;
4470     rnum = (int)random() % 3;
4471     if (!rnum) rnum = (((int)random() % 10) + 48);
4472     if (!rcap) rcap = 33;
4473     if (rnum >= 48) rssuffix[i-1]=rnum;
4474     else rssuffix[i-1]=(char)(((long)random() % 26) + 64) + rcap;
4475   }
4476 
4477 #if defined(__MINGW64__)   || \
4478     defined(__MINGW32__)   || \
4479     defined(CROSS_MINGW32) || \
4480     defined(CROSS_MINGW64)
4481   system_state = aligned_malloc (sizeof (struct system_state_s));
4482 #else
4483   if (sim_randstate)
4484     (void)sprintf(statenme, "%s.state", rssuffix);
4485   else
4486     (void)sprintf(statenme, "state");
4487   if (!sim_nostate)
4488     system_state = (struct system_state_s *)
4489       create_shm (statenme, sizeof (struct system_state_s));
4490   else
4491 # if !defined(_AIX)
4492     system_state = aligned_malloc (sizeof (struct system_state_s));
4493 # else
4494     system_state = malloc (sizeof (struct system_state_s));
4495 # endif
4496 #endif
4497 
4498   if (!system_state) {
4499     int svErrno = errno;
4500     (void)fflush(stderr);
4501     (void)fflush(stdout);
4502     (void)sir_emerg ("FATAL: %s: aborting at %s[%s:%d]",
4503                      xstrerror_l(svErrno), __func__, __FILE__, __LINE__);
4504 #if defined(USE_BACKTRACE)
4505 # if defined(SIGUSR2)
4506     (void)raise(SIGUSR2);
4507     /*NOTREACHED*/ /* unreachable */
4508 # endif /* if defined(SIGUSR2) */
4509 #endif /* if defined(USE_BACKTRACE) */
4510     exit (svErrno);
4511   }
4512 #if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) && !defined(__PASE__)
4513   if (!sim_nostate) {
4514     if (0 == sim_free_memory || sim_free_memory >= 192000000) {
4515       if (mlock(system_state, sizeof(struct system_state_s)) == -1) {
4516         mlock_failure = true;
4517       }
4518     } else {
4519 # if defined(TESTING)
4520       sim_warn ("No memory locking attempted.\r\n");
4521 # else
4522       (void)system_state;
4523 # endif
4524     }
4525   }
4526 #endif
4527 
4528 #if !defined(PERF_STRIP)
4529 
4530 # if !defined(VER_H_GIT_HASH)
4531 #  define VER_H_GIT_HASH "0000000000000000000000000000000000000000"
4532 # endif /* if !defined(VER_H_GIT_HASH) */
4533 
4534   (void)fflush(stdout);
4535   (void)fflush(stderr);
4536   // An unshared state allocation contains no saved header.  In particular,
4537   // its contents must not be inspected before initialization under MSan.
4538   bool fresh_state = sim_nostate;
4539 # if defined(__MINGW64__) || defined(__MINGW32__) || defined(CROSS_MINGW64) || defined(CROSS_MINGW32)
4540   fresh_state = true; // Windows always uses a fresh aligned allocation above.
4541 # endif
4542   if (fresh_state) {
4543     (void)memset (system_state, 0, sizeof (*system_state));
4544   } else if (system_state->commit_id[0] == '\0') {
4545     if (!sim_quiet && sim_randstate && sim_randompst)
4546       sim_printf ("Initialized new system state file \"dps8m.%s\"\r\n",
4547                   statenme);
4548   } else {
4549     if (strncmp (system_state->commit_id, VER_H_GIT_HASH,
4550                  sizeof (system_state->commit_id)) != 0) {
4551       (void)memset(system_state, 0, sizeof(*system_state));
4552       sim_warn ("NOTE: State hash mismatch; system state reset.\r\n");
4553     }
4554   }
4555   (void)fflush(stderr);
4556   (void)fflush(stdout);
4557 
4558   strncpy (system_state->stateHdr, STATE_HDR, sizeof (system_state->stateHdr));
4559   system_state->stateVer = STATE_VER;
4560   strncpy (system_state->commit_id, VER_H_GIT_HASH, sizeof (system_state->commit_id));
4561 
4562   systabInit ();
4563 
4564   // sets connect to 0
4565   (void)memset (& sys_opts, 0, sizeof (sys_opts));
4566   // sys_poll_interval 10 ms (100 Hz)
4567   sys_opts.sys_poll_interval      = 10;
4568   // sys_slow_poll_interval 100 polls (1 Hz)
4569   sys_opts.sys_slow_poll_interval = 100;
4570   // sys_poll_check_rate in CPU cycles
4571   sys_opts.sys_poll_check_rate    = 1024;
4572 #endif // ! PERF_STRIP
4573 
4574 #if defined(PERF_STRIP)
4575   cpu_init ();
4576 #else
4577   sysCableInit ();
4578   iom_init ();
4579   disk_init ();
4580   mt_init ();
4581 # if defined(WITH_SOCKET_DEV)
4582 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
4583   sk_init ();
4584 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
4585 # endif /* if defined(WITH_SOCKET_DEV) */
4586   fnpInit ();
4587   console_init (); // must come after fnpInit due to libuv initialization
4588   scu_init ();
4589   cpu_init ();
4590   rdr_init ();
4591   pun_init ();
4592   prt_init ();
4593   urp_init ();
4594 
4595 # if defined(WITH_ABSI_DEV)
4596 #  if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32)
4597   absi_init ();
4598 #  endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW64) && !defined(CROSS_MINGW32) */
4599 # endif /* if defined(WITH_ABSI_DEV) */
4600 
4601 # if defined(WITH_MGP_DEV)
4602   mgp_init ();
4603 # endif /* if defined(WITH_MGP_DEV) */
4604 
4605 # if defined(WITH_NET_DEV)
4606   net_init ();
4607 # endif /* if defined(WITH_NET_DEV) */
4608 
4609   set_default_base_system (0, NULL);
4610 # if defined(PANEL68)
4611   panelScraperInit ();
4612 # endif /* if defined(PANEL68) */
4613 #endif
4614 #if defined(THREADZ) || defined(LOCKLESS)
4615   initThreadz ();
4616 #endif /* if defined(THREADZ) || defined(LOCKLESS) */
4617 }
4618 
4619 // Once-only shutdown; invoked via SCP
4620 
4621 static void dps8_exit (void) {
     /* [previous][next][first][last][top][bottom][index][help] */
4622   cpu_stop_poll_timer ();
4623   console_exit ();
4624   mt_exit ();
4625   fnpExit ();
4626 }
4627 
4628 #if defined(TESTING)
4629 static struct pr_table
4630   {
4631     char  * alias;    // pr alias
4632     int   n;          // number alias represents ....
4633   } _prtab[] =
4634   {
4635     { "pr0",   0 }, ///< pr0 - 7
4636     { "pr1",   1 },
4637     { "pr2",   2 },
4638     { "pr3",   3 },
4639     { "pr4",   4 },
4640     { "pr5",   5 },
4641     { "pr6",   6 },
4642     { "pr7",   7 },
4643 
4644     { "pr[0]", 0 }, ///< pr0 - 7
4645     { "pr[1]", 1 },
4646     { "pr[2]", 2 },
4647     { "pr[3]", 3 },
4648     { "pr[4]", 4 },
4649     { "pr[5]", 5 },
4650     { "pr[6]", 6 },
4651     { "pr[7]", 7 },
4652 
4653     // See: https://multicians.org/pg/mvm.html
4654     { "ap",    0 },
4655     { "ab",    1 },
4656     { "bp",    2 },
4657     { "bb",    3 },
4658     { "lp",    4 },
4659     { "lb",    5 },
4660     { "sp",    6 },
4661     { "sb",    7 },
4662     {    0,    0 }
4663   };
4664 
4665 static int getAddress(int segno, int offset)
     /* [previous][next][first][last][top][bottom][index][help] */
4666 {
4667     // XXX Do we need to 1st check SDWAM for segment entry?
4668 
4669     // get address of in-core segment descriptor word from DSBR
4670     sdw0_s *s = fetchSDW ((word15) segno);
4671 
4672     return (s->ADDR + (word18) offset) & 0xffffff; // keep to 24-bits
4673 }
4674 
4675 static t_addr parse_addr (UNUSED DEVICE * dptr, const char *cptr,
     /* [previous][next][first][last][top][bottom][index][help] */
4676                           const char **optr)
4677   {
4678     cpu_state_t * cpup = _cpup;
4679     // a segment reference?
4680     if (strchr(cptr, '|'))
4681     {
4682         static char addspec[256];
4683         (void)strcpy(addspec, cptr);
4684 
4685         *strchr(addspec, '|') = ' ';
4686 
4687         char seg[256], off[256];
4688         int params = sscanf(addspec, "%s %s", seg, off);
4689         if (params != 2)
4690         {
4691             sim_warn("parse_addr(): illegal number of parameters\r\n");
4692             *optr = cptr;   // signal error
4693             return 0;
4694         }
4695 
4696         // determine if segment is numeric or symbolic...
4697         char *endp;
4698         word18 PRoffset = 0;   // offset from PR[n] register (if any)
4699         int segno = (int)strtoll(seg, &endp, 8);
4700         if (endp == seg)
4701         {
4702             // not numeric...
4703             // 1st, see if it's a PR or alias thereof
4704             struct pr_table *prt = _prtab;
4705             while (prt->alias)
4706             {
4707                 if (strcasecmp(seg, prt->alias) == 0)
4708                 {
4709                     segno = cpu.PR[prt->n].SNR;
4710                     PRoffset = cpu.PR[prt->n].WORDNO;
4711                     break;
4712                 }
4713 
4714                 prt += 1;
4715             }
4716 
4717             if (!prt->alias)    // not a PR or alias
4718             {
4719               return 0;
4720             }
4721         }
4722 
4723         // determine if offset is numeric or symbolic entry point/segdef...
4724         uint offset = (uint)strtoll(off, &endp, 8);
4725         if (endp == off)
4726         {
4727             // not numeric...
4728             return 0;
4729         }
4730 
4731         // if we get here then seg contains a segment# and offset.
4732         // So, fetch the actual address given the segment & offset ...
4733         // ... and return this absolute, 24-bit address
4734 
4735         word24 abs_addr = (word24) getAddress(segno, (int) (offset + PRoffset));
4736 
4737         // TODO: only by luck does this work FixMe
4738         *optr = endp;   //cptr + strlen(cptr);
4739 
4740         return abs_addr;
4741     }
4742     else
4743     {
4744         // a PR or alias thereof
4745         int segno = 0;
4746         word24 offset = 0;
4747         struct pr_table *prt = _prtab;
4748         while (prt->alias)
4749         {
4750             if (strncasecmp(cptr, prt->alias, strlen(prt->alias)) == 0)
4751             {
4752                 segno  = cpu.PR[prt->n].SNR;
4753                 offset = cpu.PR[prt->n].WORDNO;
4754                 break;
4755             }
4756 
4757             prt += 1;
4758         }
4759         if (prt->alias)    // a PR or alias
4760         {
4761             word24 abs_addr = (word24) getAddress(segno, (int) offset);
4762             *optr = cptr + strlen(prt->alias);
4763 
4764             return abs_addr;
4765         }
4766     }
4767 
4768     // No, determine absolute address given by cptr
4769     return (t_addr)strtol(cptr, (char **) optr, 8);
4770 }
4771 #endif // TESTING
4772 
4773 #if defined(TESTING)
4774 static void fprint_addr (FILE * stream, UNUSED DEVICE *  dptr, t_addr simh_addr)
     /* [previous][next][first][last][top][bottom][index][help] */
4775 {
4776     (void)fprintf(stream, "%06o", simh_addr);
4777 }
4778 #endif // TESTING
4779 
4780 // This is part of the scp interface
4781 // Based on the switch variable, symbolically output to stream ofile the data in
4782 //  array val at the specified addr in unit uptr.
4783 // "fprint_sym" - Based on the switch variable, symbolically output to
4784 // stream ofile the data in array val at the specified addr in unit uptr.
4785 
4786 t_stat fprint_sym (UNUSED FILE * ofile, UNUSED t_addr addr,
     /* [previous][next][first][last][top][bottom][index][help] */
4787                    UNUSED t_value *val, UNUSED UNIT *uptr, int32 UNUSED sw)
4788 {
4789 #if defined(TESTING)
4790 // XXX Bug: assumes single cpu
4791 // XXX CAC: This seems rather bogus; deciding the output format based on the
4792 // address of the UNIT? Would it be better to use sim_unit.u3 (or some such
4793 // as a word width?
4794 
4795     cpu_state_t * cpup = _cpup;
4796 
4797     if (!((uint) sw & SWMASK ('M')))
4798         return SCPE_ARG;
4799 
4800     if (uptr == &cpu_dev.units[0])
4801     {
4802         word36 word1 = *val;
4803         char buf[256];
4804         // get base syntax
4805         char *d = disassemble(buf, word1);
4806 
4807         (void)fprintf(ofile, "%s", d);
4808 
4809         // decode instruction
4810         DCDstruct ci;
4811         DCDstruct * p = & ci;
4812         decode_instruction (cpup, word1, p);
4813 
4814         // MW EIS?
4815         if (p->info->ndes > 1)
4816         {
4817             // Yup, just output word values (for now)
4818             // XXX Need to complete MW EIS support in disassemble()
4819 
4820             for(uint n = 0 ; n < p->info->ndes; n += 1)
4821                 (void)fprintf(ofile, " %012llo", (unsigned long long int)val[n + 1]);
4822 
4823             return (t_stat) -p->info->ndes;
4824         }
4825 
4826         return SCPE_OK;
4827 
4828         //(void)fprintf(ofile, "%012"PRIo64"", *val);
4829         //return SCPE_OK;
4830     }
4831 #endif
4832     return SCPE_ARG;
4833 }
4834 
4835 // This is part of the scp interface
4836 //  - Based on the switch variable, parse character string cptr for a
4837 //  symbolic value val at the specified addr in unit uptr.
4838 
4839 t_stat parse_sym (UNUSED const char * cptr, UNUSED t_addr addr,
     /* [previous][next][first][last][top][bottom][index][help] */
4840                   UNUSED UNIT * uptr, UNUSED t_value * val, UNUSED int32 sswitch)
4841   {
4842     return SCPE_ARG;
4843   }
4844 
4845 #if defined(THREADZ) || defined(LOCKLESS)
4846 volAtomic bool syncClockMode;
4847 volAtomic uint syncClockModeMasterIdx; // The CPU sync master
4848 #endif
4849 
4850 // from MM
4851 
4852 sysinfo_t sys_opts;
4853 
4854 static t_stat sys_show_config (UNUSED FILE * st, UNUSED UNIT * uptr,
     /* [previous][next][first][last][top][bottom][index][help] */
4855                                UNUSED int  val, UNUSED const void * desc)
4856   {
4857     sim_msg ("IOM connect time:         %d\r\n", sys_opts.iom_times.connect);
4858     sim_msg ("nosync                    %d\r\n", sys_opts.nosync);
4859     sim_msg ("tandd_io                  %d\r\n", sys_opts.tandd_io);
4860     return SCPE_OK;
4861 }
4862 
4863 static config_value_list_t cfg_timing_list[] =
4864   {
4865     { "disable", -1 },
4866     {  NULL,      0 }
4867   };
4868 
4869 bool breakEnable = false;
4870 
4871 static t_stat sys_set_break (UNUSED UNIT *  uptr, int32 value,
     /* [previous][next][first][last][top][bottom][index][help] */
4872                              UNUSED const char * cptr, UNUSED void * desc)
4873   {
4874     breakEnable = !! value;
4875     return SCPE_OK;
4876   }
4877 
4878 static t_stat sys_show_break (UNUSED FILE * st, UNUSED UNIT * uptr,
     /* [previous][next][first][last][top][bottom][index][help] */
4879                               UNUSED int  val, UNUSED const void * desc)
4880   {
4881     sim_msg ("BREAK %s\r\n", breakEnable ? "ON" : "OFF" );
4882     return SCPE_OK;
4883   }
4884 
4885 static config_value_list_t cfg_on_off [] =
4886   {
4887     { "off",     0 },
4888     { "on",      1 },
4889     { "disable", 0 },
4890     { "enable",  1 },
4891     {  NULL,     0 }
4892   };
4893 
4894 static config_list_t sys_config_list[] =
4895   {
4896     { "connect_time", -1,  100000, cfg_timing_list },
4897     { "nosync",        0,  1,      cfg_on_off      },
4898     { "color",         0,  1,      cfg_on_off      },
4899     { "tandd_io",      0,  1,      cfg_on_off      },
4900     { NULL,            0,  0,      NULL            }
4901  };
4902 
4903 static t_stat sys_set_config (UNUSED UNIT *  uptr, UNUSED int32 value,
     /* [previous][next][first][last][top][bottom][index][help] */
4904                               const char * cptr, UNUSED void * desc)
4905   {
4906     config_state_t cfg_state = { NULL, NULL };
4907 
4908     for (;;)
4909       {
4910         int64_t v;
4911         int rc = cfg_parse ("sys_set_config", cptr, sys_config_list, & cfg_state,
4912                            & v);
4913         if (rc == -1) // done
4914           {
4915             break;
4916           }
4917         if (rc == -2) // error
4918           {
4919             cfg_parse_done (& cfg_state);
4920             return SCPE_ARG;
4921           }
4922 
4923         const char * p = sys_config_list[rc].name;
4924         if (strcmp (p, "connect_time") == 0)
4925           sys_opts.iom_times.connect = (int) v;
4926         else if (strcmp (p, "color") == 0)
4927           sys_opts.no_color = ! v;
4928         else if (strcmp (p, "nosync") == 0)
4929           sys_opts.nosync = !! v;
4930         else if (strcmp (p, "tandd_io") == 0)
4931           sys_opts.tandd_io = !! v;
4932         else
4933           {
4934             sim_msg ("error: sys_set_config: Invalid cfg_parse rc <%ld>\r\n", (long) rc);
4935             cfg_parse_done (& cfg_state);
4936             return SCPE_ARG;
4937           }
4938       } // process statements
4939     cfg_parse_done (& cfg_state);
4940     return SCPE_OK;
4941   }
4942 
4943 static MTAB sys_mod[] =
4944   {
4945     {
4946       MTAB_dev_value,           /* Mask               */
4947       0,                        /* Match              */
4948       (char *) "CONFIG",        /* Print string       */
4949       (char *) "CONFIG",        /* Match string       */
4950       sys_set_config,           /* Validation routine */
4951       sys_show_config,          /* Display routine    */
4952       NULL,                     /* Value descriptor   */
4953       NULL,                     /* Help               */
4954     },
4955     {
4956       MTAB_dev_novalue,         /* Mask               */
4957       1,                        /* Match              */
4958       (char *) "BREAK",         /* Print string       */
4959       (char *) "BREAK",         /* Match string       */
4960       sys_set_break,            /* Validation routine */
4961       sys_show_break,           /* Display routine    */
4962       NULL,                     /* Value descriptor   */
4963       NULL,                     /* Help               */
4964     },
4965     {
4966       MTAB_dev_novalue,         /* Mask               */
4967       0,                        /* Match              */
4968       (char *) "NOBREAK",       /* Print string       */
4969       (char *) "NOBREAK",       /* Match string       */
4970       sys_set_break,            /* Validation routine */
4971       sys_show_break,           /* Display routine    */
4972       NULL,                     /* Value descriptor   */
4973       NULL,                     /* Help               */
4974     },
4975     MTAB_eol
4976   };
4977 
4978 static t_stat sys_reset (UNUSED DEVICE  * dptr)
     /* [previous][next][first][last][top][bottom][index][help] */
4979   {
4980     return SCPE_OK;
4981   }
4982 
4983 static DEVICE sys_dev = {
4984     "SYS",       /* Name                */
4985     NULL,        /* Units               */
4986     NULL,        /* Registers           */
4987     sys_mod,     /* Modifiers           */
4988     0,           /* #Units              */
4989     8,           /* Address radix       */
4990     PASIZE,      /* Address width       */
4991     1,           /* Address increment   */
4992     8,           /* Data radix          */
4993     36,          /* Data width          */
4994     NULL,        /* Examine routine     */
4995     NULL,        /* Deposit routine     */
4996     & sys_reset, /* Reset routine       */
4997     NULL,        /* Boot routine        */
4998     NULL,        /* Attach routine      */
4999     NULL,        /* Detach routine      */
5000     NULL,        /* Context             */
5001     0,           /* Flags               */
5002     0,           /* Debug control flags */
5003     0,           /* Debug flag names    */
5004     NULL,        /* Memory size change  */
5005     NULL,        /* Logical name        */
5006     NULL,        /* Help                */
5007     NULL,        /* Attach_help         */
5008     NULL,        /* Help_ctx            */
5009     NULL,        /* Description         */
5010     NULL         /* End                 */
5011 };
5012 
5013 // This is part of the scp interface
5014 DEVICE * sim_devices[] =
5015   {
5016     & cpu_dev, // dev[0] is special to the scp interface; it is the 'default device'
5017     & iom_dev,
5018     & tape_dev,
5019 #if defined(WITH_SOCKET_DEV)
5020 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64)
5021     & skc_dev,
5022 # endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64) */
5023 #endif /* if defined(WITH_SOCKET_DEV) */
5024     & mtp_dev,
5025     & fnp_dev,
5026     & dsk_dev,
5027     & ipc_dev,
5028     & msp_dev,
5029     & scu_dev,
5030     & opc_dev,
5031     & sys_dev,
5032     & urp_dev,
5033     & rdr_dev,
5034     & pun_dev,
5035     & prt_dev,
5036 
5037 #if defined(WITH_ABSI_DEV)
5038 # if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64)
5039     & absi_dev,
5040 # endif /* if !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64) */
5041 #endif /* if defined(WITH_ABSI_DEV) */
5042 
5043 #if defined(WITH_MGP_DEV)
5044     & mgp_dev,
5045 #endif /* if defined(WITH_MGP_DEV) */
5046 
5047 #if defined(WITH_NET_DEV)
5048     & net_dev,
5049 #endif /* if defined(WITH_NET_DEV) */
5050 
5051     NULL
5052   };
5053 
5054 #if defined(PERF_STRIP)
5055 void dps8_init_strip (void)
     /* [previous][next][first][last][top][bottom][index][help] */
5056   {
5057     dps8_init ();
5058   }
5059 #endif /* if defined(PERF_STRIP) */

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