From 2bcd1e7c4c399c141192a4c6c682c22ea73d877e Mon Sep 17 00:00:00 2001 From: Bob Supnik Date: Fri, 17 Jan 2003 18:35:00 -0800 Subject: [PATCH] Notes For V2.10-2 1. New Features in 2.10-2 The build procedures have changed. There is only one UNIX makefile. To compile without Ethernet support, simply type gmake {target|all} To compile with Ethernet support, type gmake USE_NETWORK=1 {target|all} The Mingw batch files require Mingw release 2 and invoke the Unix makefile. There are still separate batch files for compilation with or without Ethernet support. 1.1 SCP and Libraries - The EVAL command will evaluate a symbolic type-in and display it in numeric form. - The ! command (with no arguments) will launch the host operating system command shell. The ! command (with an argument) executes the argument as a host operating system command. (Code from Mark Pizzolato) - Telnet sessions now recognize BREAK. How a BREAK is transmitted dependent on the particular Telnet client. (Code from Mark Pizzolato) - The sockets library includes code for active connections as well as listening connections. - The RESTORE command will restore saved memory size, if the simulator supports dynamic memory resizing. 1.2 PDP-1 - The PDP-1 supports the Type 24 serial drum (based on recently discovered documents). 1.3 18b PDP's - The PDP-4 supports the Type 24 serial drum (based on recently discovered documents). 1.4 PDP-11 - The PDP-11 implements a stub DEUNA/DELUA (XU). The real XU module will be included in a later release. 1.5 PDP-10 - The PDP-10 implements a stub DEUNA/DELUA (XU). The real XU module will be included in a later release. 1.6 HP 2100 - The IOP microinstruction set is supported for the 21MX as well as the 2100. - The HP2100 supports the Access Interprocessor Link (IPL). 1.7 VAX - If the VAX console is attached to a Telnet session, BREAK is interpreted as console halt. - The SET/SHOW HISTORY commands enable and display a history of the most recently executed instructions. (Code from Mark Pizzolato) 1.8 Terminals Multiplexors - BREAK detection was added to the HP, DEC, and Interdata terminal multiplexors. 1.9 Interdata 16b and 32b - First release. UNIX is not yet working. 1.10 SDS 940 - First release. 2. Bugs Fixed in 2.10-2 - PDP-11 console must default to 7b for early UNIX compatibility. - PDP-11/VAX TMSCP emulator was using the wrong packet length for read/write end packets. - Telnet IAC+IAC processing was fixed, both for input and output (found by Mark Pizzolato). - PDP-11/VAX Ethernet setting flag bits wrong for chained descriptors (found by Mark Pizzolato). 3. New Features in 2.10 vs prior releases 3.1 SCP and Libraries - The VT emulation package has been replaced by the capability to remote the console to a Telnet session. Telnet clients typically have more complete and robust VT100 emulation. - Simulated devices may now have statically allocated buffers, in addition to dynamically allocated buffers or disk-based data stores. - The DO command now takes substitutable arguments (max 9). In command files, %n represents substitutable argument n. - The initial command line is now interpreted as the command name and substitutable arguments for a DO command. This is backward compatible to prior versions. - The initial command line parses switches. -Q is interpreted as quiet mode; informational messages are suppressed. - The HELP command now takes an optional argument. HELP types help on the specified command. - Hooks have been added for implementing GUI-based consoles, as well as simulator-specific command extensions. A few internal data structures and definitions have changed. - Two new routines (tmxr_open_master, tmxr_close_master) have been added to sim_tmxr.c. The calling sequence for sim_accept_conn has been changed in sim_sock.c. - The calling sequence for the VM boot routine has been modified to add an additional parameter. - SAVE now saves, and GET now restores, controller and unit flags. - Library sim_ether.c has been added for Ethernet support. 3.2 VAX - Non-volatile RAM (NVR) can behave either like a memory or like a disk-based peripheral. If unattached, it behaves like memory and is saved and restored by SAVE and RESTORE, respectively. If attached, its contents are loaded from disk by ATTACH and written back to disk at DETACH and EXIT. - SHOW VECTOR displays the device's interrupt vector. A few devices allow the vector to be changed with SET VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The TK50 (TMSCP tape) has been added. - The DEQNA/DELQA (Qbus Ethernet controllers) have been added. - Autoconfiguration support has been added. - The paper tape reader has been removed from vax_stddev.c and now references a common implementation file, dec_pt.h. - Examine and deposit switches now work on all devices, not just the CPU. - Device address conflicts are not detected until simulation starts. 3.3 PDP-11 - SHOW VECTOR displays the device's interrupt vector. Most devices allow the vector to be changed with SET VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The TK50 (TMSCP tape), RK611/RK06/RK07 (cartridge disk), RX211 (double density floppy), and KW11P programmable clock have been added. - The DEQNA/DELQA (Qbus Ethernet controllers) have been added. - Autoconfiguration support has been added. - The paper tape reader has been removed from pdp11_stddev.c and now references a common implementation file, dec_pt.h. - Device bootstraps now use the actual CSR specified by the SET ADDRESS command, rather than just the default CSR. Note that PDP-11 operating systems may NOT support booting with non-standard addresses. - Specifying more than 256KB of memory, or changing the bus configuration, causes all peripherals that are not compatible with the current bus configuration to be disabled. - Device address conflicts are not detected until simulation starts. 3.4 PDP-10 - SHOW VECTOR displays the device's interrupt vector. A few devices allow the vector to be changed with SET VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The RX211 (double density floppy) has been added; it is off by default. - The paper tape now references a common implementation file, dec_pt.h. - Device address conflicts are not detected until simulation starts. 3.5 PDP-1 - DECtape (then known as MicroTape) support has been added. - The line printer and DECtape can be disabled and enabled. 3.6 PDP-8 - The RX28 (double density floppy) has been added as an option to the existing RX8E controller. - SHOW DEVNO displays the device's device number. Most devices allow the device number to be changed with SET DEVNO=nnn. - Device number conflicts are not detected until simulation starts. 3.7 IBM 1620 - The IBM 1620 simulator has been released. 3.8 AltairZ80 - A hard drive has been added for increased storage. - Several bugs have been fixed. 3.9 HP 2100 - The 12845A has been added and made the default line printer (LPT). The 12653A has been renamed LPS and is off by default. It also supports the diagnostic functions needed to run the DCPC and DMS diagnostics. - The 12557A/13210A disk defaults to the 13210A (7900/7901). - The 12559A magtape is off by default. - New CPU options (EAU/NOEAU) enable/disable the extended arithmetic instructions for the 2116. These instructions are standard on the 2100 and 21MX. - New CPU options (MPR/NOMPR) enable/disable memory protect for the 2100 and 21MX. - New CPU options (DMS/NODMS) enable/disable the dynamic mapping instructions for the 21MX. - The 12539 timebase generator autocalibrates. 3.10 Simulated Magtapes - Simulated magtapes recognize end of file and the marker 0xFFFFFFFF as end of medium. Only the TMSCP tape simulator can generate an end of medium marker. - The error handling in simulated magtapes was overhauled to be consistent through all simulators. 3.11 Simulated DECtapes - Added support for RT11 image file format (256 x 16b) to DECtapes. 4. Bugs Fixed in 2.10 vs prior releases - TS11/TSV05 was not simulating the XS0_MOT bit, causing failures under VMS. In addition, two of the CTL options were coded interchanged. - IBM 1401 tape was not setting a word mark under group mark for load mode reads. This caused the diagnostics to crash. - SCP bugs in ssh_break and set_logon were fixed (found by Dave Hittner). - Numerous bugs in the HP 2100 extended arithmetic, floating point, 21MX, DMS, and IOP instructions were fixed. Bugs were also fixed in the memory protect and DMS functions. The moving head disks (DP, DQ) were revised to simulate the hardware more accurately. Missing functions in DQ (address skip, read address) were added. - PDP-10 tape wouldn't boot, and then wouldn't read (reported by Michael Thompson and Harris Newman, respectively) - PDP-1 typewriter is half duplex, with only one shift state for both input and output (found by Derek Peschel) 5. General Notes WARNING: V2.10 has reorganized and renamed some of the definition files for the PDP-10, PDP-11, and VAX. Be sure to delete all previous source files before you unpack the Zip archive, or unpack it into a new directory structure. WARNING: V2.10 has a new, more comprehensive save file format. Restoring save files from previous releases will cause 'invalid register' errors and loss of CPU option flags, device enable/ disable flags, unit online/offline flags, and unit writelock flags. WARNING: If you are using Visual Studio .NET through the IDE, be sure to turn off the /Wp64 flag in the project settings, or dozens of spurious errors will be generated. WARNING: Compiling Ethernet support under Windows requires extra steps; see the Ethernet readme file. Ethernet support is currently available only for Windows, Linux, NetBSD, and OpenBSD. --- 0readme_210.txt | 156 ++- 0readme_ethernet.txt | 64 +- AltairZ80/altairZ80_sio.c | 18 +- GRI/gri_cpu.c | 110 +- GRI/gri_stddev.c | 10 +- GRI/gri_sys.c | 161 +-- H316/h316_cpu.c | 342 ++--- H316/h316_lp.c | 110 +- H316/h316_stddev.c | 100 +- H316/h316_sys.c | 62 +- HP2100/hp2100_cpu.c | 196 ++- HP2100/hp2100_defs.h | 3 + HP2100/hp2100_diag.txt | 24 +- HP2100/hp2100_doc.txt | 63 +- HP2100/hp2100_dp.c | 15 +- HP2100/hp2100_dq.c | 13 +- HP2100/hp2100_dr.c | 4 +- HP2100/hp2100_ipl.c | 465 +++++++ HP2100/hp2100_lps.c | 35 +- HP2100/hp2100_lpt.c | 23 +- HP2100/hp2100_ms.c | 4 +- HP2100/hp2100_mt.c | 4 +- HP2100/hp2100_mux.c | 47 +- HP2100/hp2100_stddev.c | 25 +- HP2100/hp2100_sys.c | 5 +- I1401/i1401_cpu.c | 458 ++++--- I1401/i1401_dp.c | 65 +- I1401/i1401_iq.c | 57 +- I1401/i1401_lp.c | 21 +- I1401/i1401_mt.c | 80 +- I1401/i1401_sys.c | 45 +- I1620/i1620_cd.c | 46 +- I1620/i1620_cpu.c | 33 +- I1620/i1620_lp.c | 36 +- I1620/i1620_pt.c | 130 +- I1620/i1620_tty.c | 74 +- Ibm1130/ibm1130_cpu.c | 4 +- Ibm1130/ibm1130_cr.c | 14 +- Ibm1130/ibm1130_defs.h | 2 +- Ibm1130/ibm1130_disk.c | 4 +- Ibm1130/ibm1130_gui.c | 2 +- Ibm1130/{ => utils}/asm1130.c | 10 +- Ibm1130/{ => utils}/asm1130.mak | 0 Ibm1130/{ => utils}/bindump.c | 0 Ibm1130/{ => utils}/bindump.mak | 0 Ibm1130/{ => utils}/checkdisk.c | 0 Ibm1130/{ => utils}/checkdisk.mak | 0 Ibm1130/{ => utils}/diskview.c | 0 Ibm1130/{ => utils}/diskview.mak | 0 Ibm1130/{ => utils}/mkboot.c | 0 Ibm1130/{ => utils}/mkboot.mak | 0 Ibm1130/{ => utils}/viewdeck.c | 0 Ibm1130/{ => utils}/viewdeck.mak | 0 Interdata/id16_cpu.c | 1718 ++++++++++++++++++++++++ Interdata/id16_dboot.c | 346 +++++ Interdata/id16_sys.c | 521 ++++++++ Interdata/id32_cpu.c | 2025 +++++++++++++++++++++++++++++ Interdata/id32_dboot.c | 308 +++++ Interdata/id32_sys.c | 641 +++++++++ Interdata/id_defs.h | 483 +++++++ Interdata/id_diag.txt | 908 +++++++++++++ Interdata/id_doc.txt | 960 ++++++++++++++ Interdata/id_dp.c | 547 ++++++++ Interdata/id_fd.c | 480 +++++++ Interdata/id_fp.c | 471 +++++++ Interdata/id_idc.c | 690 ++++++++++ Interdata/id_io.c | 542 ++++++++ Interdata/id_lp.c | 288 ++++ Interdata/id_mt.c | 529 ++++++++ Interdata/id_pas.c | 546 ++++++++ Interdata/id_pt.c | 350 +++++ Interdata/id_tt.c | 259 ++++ Interdata/id_ttp.c | 263 ++++ Interdata/id_uvc.c | 311 +++++ NOVA/eclipse_tt.c | 4 +- NOVA/nova_clk.c | 4 +- NOVA/nova_cpu.c | 587 +++++---- NOVA/nova_dkp.c | 34 +- NOVA/nova_doc.txt | 12 +- NOVA/nova_dsk.c | 20 +- NOVA/nova_lp.c | 2 +- NOVA/nova_mta.c | 105 +- NOVA/nova_pt.c | 4 +- NOVA/nova_sys.c | 224 ++-- NOVA/nova_tt.c | 7 +- NOVA/nova_tt1.c | 7 +- PDP1/pdp1_cpu.c | 254 ++-- PDP1/pdp1_defs.h | 5 +- PDP1/pdp1_doc.txt | 33 +- PDP1/pdp1_drm.c | 169 +++ PDP1/pdp1_dt.c | 148 ++- PDP1/pdp1_lp.c | 24 +- PDP1/pdp1_stddev.c | 18 +- PDP1/pdp1_sys.c | 102 +- PDP10/pdp10_cpu.c | 283 ++-- PDP10/pdp10_defs.h | 9 +- PDP10/pdp10_doc.txt | 17 +- PDP10/pdp10_fe.c | 2 + PDP10/pdp10_ksio.c | 42 +- PDP10/pdp10_lp20.c | 147 ++- PDP10/pdp10_mdfp.c | 144 +- PDP10/pdp10_pag.c | 171 +-- PDP10/pdp10_rp.c | 112 +- PDP10/pdp10_sys.c | 169 +-- PDP10/pdp10_tim.c | 4 +- PDP10/pdp10_tu.c | 210 +-- PDP10/pdp10_xtnd.c | 332 ++--- PDP11/pdp11_cis.c | 359 ++--- PDP11/pdp11_cpu.c | 1439 ++++++++++---------- PDP11/pdp11_doc.txt | 28 +- PDP11/pdp11_fp.c | 263 ++-- PDP11/pdp11_hk.c | 102 +- PDP11/pdp11_io.c | 27 +- PDP11/pdp11_lp.c | 2 +- PDP11/pdp11_mscp.h | 15 +- PDP11/pdp11_pclk.c | 17 +- PDP11/pdp11_rk.c | 67 +- PDP11/pdp11_rl.c | 81 +- PDP11/pdp11_rp.c | 115 +- PDP11/pdp11_rq.c | 4 +- PDP11/pdp11_rx.c | 112 +- PDP11/pdp11_stddev.c | 12 +- PDP11/pdp11_sys.c | 6 +- PDP11/pdp11_tc.c | 215 +-- PDP11/pdp11_tm.c | 85 +- PDP11/pdp11_tq.c | 16 +- PDP11/pdp11_ts.c | 243 ++-- PDP11/pdp11_xq.c | 572 ++++++-- PDP11/pdp11_xq.h | 13 + PDP11/pdp11_xu.c | 61 + PDP18B/pdp18b_cpu.c | 603 ++++----- PDP18B/pdp18b_defs.h | 5 +- PDP18B/pdp18b_doc.txt | 3 +- PDP18B/pdp18b_drm.c | 30 +- PDP18B/pdp18b_dt.c | 356 ++--- PDP18B/pdp18b_lp.c | 124 +- PDP18B/pdp18b_mt.c | 96 +- PDP18B/pdp18b_rf.c | 34 +- PDP18B/pdp18b_rp.c | 25 +- PDP18B/pdp18b_stddev.c | 31 +- PDP18B/pdp18b_sys.c | 168 +-- PDP18B/pdp18b_tt1.c | 8 +- PDP1o/pdp1_cpu.c | 795 ----------- PDP1o/pdp1_defs.h | 104 -- PDP1o/pdp1_doc.txt | 476 ------- PDP1o/pdp1_dt.c | 976 -------------- PDP1o/pdp1_lp.c | 172 --- PDP1o/pdp1_stddev.c | 427 ------ PDP1o/pdp1_sys.c | 458 ------- PDP8/pdp8_clk.c | 6 +- PDP8/pdp8_cpu.c | 669 +++++----- PDP8/pdp8_df.c | 21 +- PDP8/pdp8_dt.c | 287 ++-- PDP8/pdp8_lp.c | 4 +- PDP8/pdp8_mt.c | 111 +- PDP8/pdp8_pt.c | 4 +- PDP8/pdp8_rf.c | 25 +- PDP8/pdp8_rk.c | 50 +- PDP8/pdp8_rl.c | 51 +- PDP8/pdp8_rx.c | 51 +- PDP8/pdp8_sys.c | 213 +-- PDP8/pdp8_tt.c | 4 +- PDP8/pdp8_ttx.c | 28 +- S3/s3_defs.h | 1 - SDS/sds_cpu.c | 1247 ++++++++++++++++++ SDS/sds_defs.h | 401 ++++++ SDS/sds_diag.txt | 114 ++ SDS/sds_doc.txt | 527 ++++++++ SDS/sds_drm.c | 270 ++++ SDS/sds_dsk.c | 357 +++++ SDS/sds_io.c | 886 +++++++++++++ SDS/sds_lp.c | 283 ++++ SDS/sds_mt.c | 489 +++++++ SDS/sds_mux.c | 504 +++++++ SDS/sds_rad.c | 290 +++++ SDS/sds_stddev.c | 555 ++++++++ SDS/sds_sys.c | 576 ++++++++ VAX/vax_cpu.c | 1163 +++++++++-------- VAX/vax_cpu1.c | 159 +-- VAX/vax_defs.h | 11 +- VAX/vax_doc.txt | 27 + VAX/vax_fpa.c | 36 +- VAX/vax_io.c | 68 +- VAX/vax_mmu.c | 46 +- VAX/vax_stddev.c | 22 +- VAX/vax_sys.c | 256 ++-- VAX/vax_sysdev.c | 46 +- VAX/vaxmod_defs.h | 3 +- build_mingw.bat | 87 +- build_mingw_ether.bat | 87 +- dec_dz.h | 115 +- dec_pt.h | 20 +- descrip.mms | 2006 ++++++++++++++-------------- makefile | 157 ++- makefile_ether | 313 ----- scp.c | 510 +++++--- scp_tty.c | 82 +- sim_defs.h | 48 +- sim_ether.c | 198 ++- sim_ether.h | 14 + sim_rev.h | 48 +- sim_sock.c | 148 ++- sim_sock.h | 3 + sim_tmxr.c | 106 +- sim_tmxr.h | 2 + simh_doc.txt | 86 +- 206 files changed, 30253 insertions(+), 12114 deletions(-) create mode 100644 HP2100/hp2100_ipl.c rename Ibm1130/{ => utils}/asm1130.c (96%) rename Ibm1130/{ => utils}/asm1130.mak (100%) rename Ibm1130/{ => utils}/bindump.c (100%) rename Ibm1130/{ => utils}/bindump.mak (100%) rename Ibm1130/{ => utils}/checkdisk.c (100%) rename Ibm1130/{ => utils}/checkdisk.mak (100%) rename Ibm1130/{ => utils}/diskview.c (100%) rename Ibm1130/{ => utils}/diskview.mak (100%) rename Ibm1130/{ => utils}/mkboot.c (100%) rename Ibm1130/{ => utils}/mkboot.mak (100%) rename Ibm1130/{ => utils}/viewdeck.c (100%) rename Ibm1130/{ => utils}/viewdeck.mak (100%) create mode 100644 Interdata/id16_cpu.c create mode 100644 Interdata/id16_dboot.c create mode 100644 Interdata/id16_sys.c create mode 100644 Interdata/id32_cpu.c create mode 100644 Interdata/id32_dboot.c create mode 100644 Interdata/id32_sys.c create mode 100644 Interdata/id_defs.h create mode 100644 Interdata/id_diag.txt create mode 100644 Interdata/id_doc.txt create mode 100644 Interdata/id_dp.c create mode 100644 Interdata/id_fd.c create mode 100644 Interdata/id_fp.c create mode 100644 Interdata/id_idc.c create mode 100644 Interdata/id_io.c create mode 100644 Interdata/id_lp.c create mode 100644 Interdata/id_mt.c create mode 100644 Interdata/id_pas.c create mode 100644 Interdata/id_pt.c create mode 100644 Interdata/id_tt.c create mode 100644 Interdata/id_ttp.c create mode 100644 Interdata/id_uvc.c create mode 100644 PDP1/pdp1_drm.c create mode 100644 PDP11/pdp11_xu.c delete mode 100644 PDP1o/pdp1_cpu.c delete mode 100644 PDP1o/pdp1_defs.h delete mode 100644 PDP1o/pdp1_doc.txt delete mode 100644 PDP1o/pdp1_dt.c delete mode 100644 PDP1o/pdp1_lp.c delete mode 100644 PDP1o/pdp1_stddev.c delete mode 100644 PDP1o/pdp1_sys.c create mode 100644 SDS/sds_cpu.c create mode 100644 SDS/sds_defs.h create mode 100644 SDS/sds_diag.txt create mode 100644 SDS/sds_doc.txt create mode 100644 SDS/sds_drm.c create mode 100644 SDS/sds_dsk.c create mode 100644 SDS/sds_io.c create mode 100644 SDS/sds_lp.c create mode 100644 SDS/sds_mt.c create mode 100644 SDS/sds_mux.c create mode 100644 SDS/sds_rad.c create mode 100644 SDS/sds_stddev.c create mode 100644 SDS/sds_sys.c delete mode 100644 makefile_ether diff --git a/0readme_210.txt b/0readme_210.txt index 21e3137b..194a44b7 100644 --- a/0readme_210.txt +++ b/0readme_210.txt @@ -1,28 +1,97 @@ -Notes For V2.10-1 +Notes For V2.10-2 -WARNING: V2.10 has reorganized and renamed some of the definition -files for the PDP-10, PDP-11, and VAX. Be sure to delete all -previous source files before you unpack the Zip archive, or -unpack it into a new directory structure. +1. New Features in 2.10-2 -WARNING: V2.10 has a new, more comprehensive save file format. -Restoring save files from previous releases will cause 'invalid -register' errors and loss of CPU option flags, device enable/ -disable flags, unit online/offline flags, and unit writelock -flags. +The build procedures have changed. There is only one UNIX makefile. +To compile without Ethernet support, simply type -WARNING: If you are using Visual Studio .NET through the IDE, -be sure to turn off the /Wp64 flag in the project settings, or -dozens of spurious errors will be generated. + gmake {target|all} -WARNING: Compiling Ethernet support under Windows requires -extra steps; see the Ethernet readme file. Ethernet support is -currently available only for Windows, Linux, NetBSD, and OpenBSD. +To compile with Ethernet support, type -1. New Features + gmake USE_NETWORK=1 {target|all} + +The Mingw batch files require Mingw release 2 and invoke the Unix +makefile. There are still separate batch files for compilation +with or without Ethernet support. 1.1 SCP and Libraries +- The EVAL command will evaluate a symbolic type-in and display + it in numeric form. +- The ! command (with no arguments) will launch the host operating + system command shell. The ! command (with an argument) executes + the argument as a host operating system command. (Code from + Mark Pizzolato) +- Telnet sessions now recognize BREAK. How a BREAK is transmitted + dependent on the particular Telnet client. (Code from Mark + Pizzolato) +- The sockets library includes code for active connections as + well as listening connections. +- The RESTORE command will restore saved memory size, if the + simulator supports dynamic memory resizing. + +1.2 PDP-1 + +- The PDP-1 supports the Type 24 serial drum (based on recently + discovered documents). + +1.3 18b PDP's + +- The PDP-4 supports the Type 24 serial drum (based on recently + discovered documents). + +1.4 PDP-11 + +- The PDP-11 implements a stub DEUNA/DELUA (XU). The real XU + module will be included in a later release. + +1.5 PDP-10 + +- The PDP-10 implements a stub DEUNA/DELUA (XU). The real XU + module will be included in a later release. + +1.6 HP 2100 + +- The IOP microinstruction set is supported for the 21MX as well + as the 2100. +- The HP2100 supports the Access Interprocessor Link (IPL). + +1.7 VAX + +- If the VAX console is attached to a Telnet session, BREAK is + interpreted as console halt. +- The SET/SHOW HISTORY commands enable and display a history of + the most recently executed instructions. (Code from Mark + Pizzolato) + +1.8 Terminals Multiplexors + +- BREAK detection was added to the HP, DEC, and Interdata terminal + multiplexors. + +1.9 Interdata 16b and 32b + +- First release. UNIX is not yet working. + +1.10 SDS 940 + +- First release. + +2. Bugs Fixed in 2.10-2 + +- PDP-11 console must default to 7b for early UNIX compatibility. +- PDP-11/VAX TMSCP emulator was using the wrong packet length for + read/write end packets. +- Telnet IAC+IAC processing was fixed, both for input and output + (found by Mark Pizzolato). +- PDP-11/VAX Ethernet setting flag bits wrong for chained + descriptors (found by Mark Pizzolato). + +3. New Features in 2.10 vs prior releases + +3.1 SCP and Libraries + - The VT emulation package has been replaced by the capability to remote the console to a Telnet session. Telnet clients typically have more complete and robust VT100 emulation. @@ -49,7 +118,7 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD. - SAVE now saves, and GET now restores, controller and unit flags. - Library sim_ether.c has been added for Ethernet support. -1.2 VAX +3.2 VAX - Non-volatile RAM (NVR) can behave either like a memory or like a disk-based peripheral. If unattached, it behaves like memory @@ -69,7 +138,7 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD. the CPU. - Device address conflicts are not detected until simulation starts. -1.3 PDP-11 +3.3 PDP-11 - SHOW VECTOR displays the device's interrupt vector. Most devices allow the vector to be changed with SET @@ -91,7 +160,7 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD. with the current bus configuration to be disabled. - Device address conflicts are not detected until simulation starts. -1.4 PDP-10 +3.4 PDP-10 - SHOW VECTOR displays the device's interrupt vector. A few devices allow the vector to be changed with SET @@ -103,30 +172,30 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD. dec_pt.h. - Device address conflicts are not detected until simulation starts. -1.5 PDP-1 +3.5 PDP-1 - DECtape (then known as MicroTape) support has been added. - The line printer and DECtape can be disabled and enabled. -1.6 PDP-8 +3.6 PDP-8 - The RX28 (double density floppy) has been added as an option to the existing RX8E controller. - SHOW DEVNO displays the device's device number. Most devices allow the device number to be changed with SET DEVNO=nnn. -- Device number conflicts are not detected until simulation starts. +- Device number conflicts are not detected until simulation starts. -1.7 IBM 1620 +3.7 IBM 1620 - The IBM 1620 simulator has been released. -1.8 AltairZ80 +3.8 AltairZ80 - A hard drive has been added for increased storage. - Several bugs have been fixed. -1.9 HP 2100 +3.9 HP 2100 - The 12845A has been added and made the default line printer (LPT). The 12653A has been renamed LPS and is off by default. It also @@ -143,7 +212,7 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD. instructions for the 21MX. - The 12539 timebase generator autocalibrates. -1.10 Simulated Magtapes +3.10 Simulated Magtapes - Simulated magtapes recognize end of file and the marker 0xFFFFFFFF as end of medium. Only the TMSCP tape simulator @@ -151,13 +220,11 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD. - The error handling in simulated magtapes was overhauled to be consistent through all simulators. -1.11 Simulated DECtapes +3.11 Simulated DECtapes - Added support for RT11 image file format (256 x 16b) to DECtapes. -2. Release Notes - -2.1 Bugs Fixed +4. Bugs Fixed in 2.10 vs prior releases - TS11/TSV05 was not simulating the XS0_MOT bit, causing failures under VMS. In addition, two of the CTL options were coded @@ -176,18 +243,23 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD. - PDP-1 typewriter is half duplex, with only one shift state for both input and output (found by Derek Peschel) -2.2 HP 2100 Debugging +5. General Notes -- The HP 2100 CPU nows runs all of the CPU diagnostics. -- The peripherals run most of the peripheral diagnostics. There - is still a problem in overlapped seek operation on the disks. - See the file hp2100_diag.txt for details. +WARNING: V2.10 has reorganized and renamed some of the definition +files for the PDP-10, PDP-11, and VAX. Be sure to delete all +previous source files before you unpack the Zip archive, or +unpack it into a new directory structure. -3. In Progress +WARNING: V2.10 has a new, more comprehensive save file format. +Restoring save files from previous releases will cause 'invalid +register' errors and loss of CPU option flags, device enable/ +disable flags, unit online/offline flags, and unit writelock +flags. -These simulators are not finished and are available in a separate -Zip archive distribution. +WARNING: If you are using Visual Studio .NET through the IDE, +be sure to turn off the /Wp64 flag in the project settings, or +dozens of spurious errors will be generated. -- Interdata 16b/32b: coded, partially tested. See the file - id_diag.txt for details. -- SDS 940: coded, partially tested. +WARNING: Compiling Ethernet support under Windows requires +extra steps; see the Ethernet readme file. Ethernet support is +currently available only for Windows, Linux, NetBSD, and OpenBSD. diff --git a/0readme_ethernet.txt b/0readme_ethernet.txt index 0dfc0a98..9fc56ea2 100644 --- a/0readme_ethernet.txt +++ b/0readme_ethernet.txt @@ -2,6 +2,16 @@ This file contains information about the XQ/SIM_ETHER package. ------------------------------------------------------------------------------- +16-Jan-03 Release: + 1. Added VMScluster support (thanks to Mark Pizzolato) + 2. Verified VAX remote boot functionality (>>>B XQA0) + 3. Added major performance enhancements (thanks to Mark Pizzolato again) + 4. Changed _DEBUG tracers to XQ_DEBUG and ETH_DEBUG + 5. Added local packet processing + 6. Added system id broadcast + +------------------------------------------------------------------------------- + GOLD Changes: (08-Nov-02) 1. Added USE_NETWORK conditional to Sim_Ether 2. Fixed behaviour of SHOW XQ ETH if no devices exist @@ -68,19 +78,18 @@ supports Windows, Linux, and NetBSD. Currently, the Sim_Ether module sets the selected ethernet card into promiscuous mode to gather all packets, then filters out the packets that it -doesn't want. This method is somewhat inefficient and will be looked at in -future versions. Packets having the same source MAC address as the +doesn't want. In Windows, Packets having the same source MAC address as the controller are ignored for WinPCAP compatibility (see Windows notes below). If your ethernet card is plugged into a switch, the promiscuous mode setting should not cause much of a problem, since the switch will still filter out most of the undesirable traffic. You will only see "excessive" traffic if you -are on a hub(repeater) or a direct lan (thickwire/thinwire) segment. +are on a direct or hub(repeater) segment. ------------------------------------------------------------------------------- Windows notes: - 1. The Windows-specific code uses the WinPCAP 3.0 package from + 1. The Windows-specific code uses the WinPCAP 3.0 (or 2.3) package from http://winpcap.polito.it. This package for windows simulates the libpcap package that is freely available for unix systems. 2. You must *install* WinPCAP. @@ -91,8 +100,9 @@ Windows notes: but this defeats DECNET's duplicate node number detection scheme. A more correct fix for WinPCAP will be explored as time allows. 5. The first time the WinPCAP driver is used, it will be dynamically loaded, - and the user must be an Administrator on the machine to do so. See the - WinPCAP documentation for a static load workaround if needed. + and the user must be an Administrator on the machine to do so. If you need + to run as an unprivileged user, you must set the service to autostart. See + the WinPCAP documentation for details on the static load workaround. Building on Windows: 1. Install WinPCAP 3.0. @@ -109,8 +119,10 @@ Building on Windows: Linux, NetBSD, and OpenBSD notes: 1. You must run SIMH(scp) as root so that the ethernet card can be set into - promiscuous mode by the driver. + promiscuous mode by the driver. Alternative suggestions will be welcomed. +Building on Linux, NetBSD, and OpenBSD: + 1. Define USE_NETWORK if you want the network functionality. ------------------------------------------------------------------------------- @@ -136,28 +148,25 @@ Regression test criteria: 15. LAT loads sucessfully (passed) 16. SET HOST/LAT works from SIMH to real VAX LAT machine (passed) 17. SET HOST/LAT works from real VAX LAT machine to SIMH (passed) +18. SIMH node joins VMSCluster (passed) +19. SIMH node mounts other VMSCluster disks (passed) +20. SIMH node MSCP serves disks to other nodes (passed) +21. SIMH node remote boots into VMScluster (>>>B XQAO) (passed) -I have NOT tested the following, but have reports that the following work: - 1. Operation with the PDP-11 emulator (RSX) - 2. Remote booting of NetBSD (via >>> B XQA0) - -I have tested the following, and they do NOT work correctly: - 1. VMS NI Clustering (LAVC) - 2. Remote VAX booting (>>>B XQA0) into a VMScluster; - the remote boot works, but VMS BUGCHECKs when joining the cluster +The following are known to NOT work: + 1. PDP-11 using RSTS/E v10.1 (fails to enable device - needs bootrom support) +I have reports that the following work: + 1. PDP-11 using RSX + 2. VAX remote booting of NetBSD (via >>> B XQA0) + ------------------------------------------------------------------------------- Things planned for future releases: - 1. Loopback packet processing - 2. Full MOP implementation - 3. Identity broadcast, which should occur every 8-10 minutes - 4. Full support for network boot (>> B XQA0) - 5. VMS NI Cluster (LAVC) support - 6. More efficient Sim_Ether module implementation for windows - 7. PDP-11 bootstrap - 8. DESQA support (if someone can get me the user manuals) - 9. DETQA support [DELQA-Turbo] (I have the manual) + 1. Full MOP implementation + 2. PDP-11 bootstrap/bootrom + 3. DESQA support (if someone can get me the user manuals) + 4. DETQA support [DELQA-Turbo] (I have the manual) ------------------------------------------------------------------------------- @@ -166,16 +175,13 @@ Things which I need help with: 2. Information about Remote MOP processing 3. PDP-11 bootstrap code. 4. VAX hardware diagnotics image file and docs, to test XQ thoroughly. - 5. Feedback on the ethernet timing clock interval. - 6. Feedback on operation with other VAX OS's. - 7. Feedback on operation of PDP-11 OS's. + 5. Feedback on operation with other VAX OS's. + 6. Feedback on operation with PDP-11 OS's. ------------------------------------------------------------------------------- Please send all patches, questions, feedback, clarifications, and help to: dhittner AT northropgrumman DOT com -NOTE: I _have_ corrected my email address!! Sorry about the confusion! - Thanks, and Enjoy!! Dave diff --git a/AltairZ80/altairZ80_sio.c b/AltairZ80/altairZ80_sio.c index 621c9de3..77d09e99 100644 --- a/AltairZ80/altairZ80_sio.c +++ b/AltairZ80/altairZ80_sio.c @@ -93,10 +93,10 @@ int32 sio0s (int32 port, int32 io, int32 data); int32 sio1d (int32 port, int32 io, int32 data); int32 sio1s (int32 port, int32 io, int32 data); void reset_sio_terminals(int32 useDefault); -t_stat simh_dev_reset(void); +t_stat simh_dev_reset(DEVICE *dptr); t_stat simh_svc(UNIT *uptr); -t_stat simh_dev_set_timeron(void); -t_stat simh_dev_set_timeroff(void); +t_stat simh_dev_set_timeron(UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat simh_dev_set_timeroff(UNIT *uptr, int32 val, char *cptr, void *desc); int32 simh_in(void); int32 simh_out(int32 data); void attachCPM(UNIT *uptr); @@ -641,7 +641,7 @@ struct tm *currentTime = NULL; uint32 markTime[splimit]; char version[] = "SIMH002"; -t_stat simh_dev_reset(void) { +t_stat simh_dev_reset(DEVICE *dptr) { currentTime = NULL; ClockZSDOSDelta = 0; setClockZSDOSPos = 0; @@ -658,12 +658,12 @@ t_stat simh_dev_reset(void) { lastCPMStatus = SCPE_OK; timerInterrupt = FALSE; if (simh_unit.flags & UNIT_SIMH_TIMERON) { - simh_dev_set_timeron(); + simh_dev_set_timeron(NULL, 0, NULL, NULL); } return SCPE_OK; } -t_stat simh_dev_set_timeron(void) { +t_stat simh_dev_set_timeron(UNIT *uptr, int32 val, char *cptr, void *desc) { if (rtc_avail) { timeOfNextInterrupt = sim_os_msec() + timerDelta; return sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ @@ -674,7 +674,7 @@ t_stat simh_dev_set_timeron(void) { } } -t_stat simh_dev_set_timeroff(void) { +t_stat simh_dev_set_timeroff(UNIT *uptr, int32 val, char *cptr, void *desc) { timerInterrupt = FALSE; sim_cancel(&simh_unit); return SCPE_OK; @@ -997,14 +997,14 @@ int32 simh_out(int32 data) { cpu_unit.flags &= ~UNIT_CHIP; break; case startTimerInterruptsCmd: - if (simh_dev_set_timeron() == SCPE_OK) { + if (simh_dev_set_timeron(NULL, 0, NULL, NULL) == SCPE_OK) { timerInterrupt = FALSE; simh_unit.flags |= UNIT_SIMH_TIMERON; } break; case stopTimerInterruptsCmd: simh_unit.flags &= ~UNIT_SIMH_TIMERON; - simh_dev_set_timeroff(); + simh_dev_set_timeroff(NULL, 0, NULL, NULL); break; case setTimerDeltaCmd: setTimerDeltaPos = 0; diff --git a/GRI/gri_cpu.c b/GRI/gri_cpu.c index 9bb2ead3..8113b3f3 100644 --- a/GRI/gri_cpu.c +++ b/GRI/gri_cpu.c @@ -395,10 +395,10 @@ else if ((dev_done & (INT_PENDING | ISR)) > (INT_PENDING)) { /* intr? */ int32 i, vec; t = dev_done & ISR; /* find hi pri */ for (i = 15; i >= 0; i--) { - if ((t >> i) & 1) break; } + if ((t >> i) & 1) break; } if ((i < 0) || ((vec = vec_map[i]) < 0)) { /* undefined? */ - reason = STOP_ILLINT; /* stop */ - break; } + reason = STOP_ILLINT; /* stop */ + break; } dev_done = dev_done & ~INT_ON; /* int off */ M[vec] = SC; /* save SC */ SC = vec + 1; /* new SC */ @@ -433,39 +433,39 @@ else if ((src != U_MEM) && (dst == U_TRP)) { /* cond jump */ t = dev_tab[src].Src (src); /* get source */ switch (op >> 1) { /* case on jump */ case 00: /* never */ - jmp = 0; - break; + jmp = 0; + break; case 01: /* always */ - jmp = 1; - break; + jmp = 1; + break; case 02: /* src == 0 */ - jmp = (t == 0); - break; + jmp = (t == 0); + break; case 03: /* src != 0 */ - jmp = (t != 0); - break; + jmp = (t != 0); + break; case 04: /* src < 0 */ - jmp = (t >= SIGN); - break; + jmp = (t >= SIGN); + break; case 05: /* src >= 0 */ - jmp = (t < SIGN); - break; - case 06: - jmp = (t == 0) || (t & SIGN); /* src <= 0 */ - break; - case 07: - jmp = (t != 0) && !(t & SIGN); /* src > 0 */ - break; } + jmp = (t < SIGN); + break; + case 06: /* src <= 0 */ + jmp = (t == 0) || (t & SIGN); + break; + case 07: /* src > 0 */ + jmp = (t != 0) && !(t & SIGN); + break; } if (jmp) { /* jump taken? */ - SCQ_ENTRY; /* save SC */ - SC = (SC + 1) & AMASK; /* incr SC once */ - MA = M[SC]; /* get jump addr */ - if (op & TRP_DEF) { /* defer? */ - t = (M[MA] + 1) & DMASK; /* autoinc */ - if (MEM_ADDR_OK (MA)) M[MA] = t; - MA = t & AMASK; } /* ind addr */ - TRP = SC; /* save SC */ - SC = MA; } /* load new SC */ + SCQ_ENTRY; /* save SC */ + SC = (SC + 1) & AMASK; /* incr SC once */ + MA = M[SC]; /* get jump addr */ + if (op & TRP_DEF) { /* defer? */ + t = (M[MA] + 1) & DMASK; /* autoinc */ + if (MEM_ADDR_OK (MA)) M[MA] = t; + MA = t & AMASK; } /* ind addr */ + TRP = SC; /* save SC */ + SC = MA; } /* load new SC */ else SC = (SC + 2) & AMASK; } /* incr SC twice */ else if ((src != U_MEM) && (dst != U_MEM)) { /* reg-reg? */ @@ -481,31 +481,31 @@ else if ((src != U_MEM) && (dst != U_MEM)) { /* reg-reg? */ else { SC = (SC + 1) & AMASK; /* incr SC */ switch (op & MEM_MOD) { /* case on addr mode */ case MEM_DIR: /* direct */ - MA = M[SC] & AMASK; /* get address */ - SC = (SC + 1) & AMASK; /* incr SC again */ - reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ - break; + MA = M[SC] & AMASK; /* get address */ + SC = (SC + 1) & AMASK; /* incr SC again */ + reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ + break; case MEM_DEF: /* defer */ - MA = M[SC] & AMASK; /* get ind addr */ - SC = (SC + 1) & AMASK; /* incr SC again */ - t = (M[MA] + 1) & DMASK; /* autoinc */ - if (MEM_ADDR_OK (MA)) M[MA] = t; - MA = t & AMASK; /* ind addr */ - reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ - break; + MA = M[SC] & AMASK; /* get ind addr */ + SC = (SC + 1) & AMASK; /* incr SC again */ + t = (M[MA] + 1) & DMASK; /* autoinc */ + if (MEM_ADDR_OK (MA)) M[MA] = t; + MA = t & AMASK; /* ind addr */ + reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ + break; case MEM_IMM: /* immediate */ - MA = SC; /* eff addr */ - reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ - SC = (SC + 1) & AMASK; /* incr SC again */ - break; + MA = SC; /* eff addr */ + reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ + SC = (SC + 1) & AMASK; /* incr SC again */ + break; case MEM_IDF: /* immediate defer */ - MA = SC; /* get ind addr */ - t = (M[MA] + 1) & DMASK; /* autoinc */ - if (MEM_ADDR_OK (MA)) M[MA] = t; - MA = t & AMASK; /* ind addr */ - SC = (SC + 1) & AMASK; /* incr SC again */ - reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ - break; } /* end switch */ + MA = SC; /* get ind addr */ + t = (M[MA] + 1) & DMASK; /* autoinc */ + if (MEM_ADDR_OK (MA)) M[MA] = t; + MA = t & AMASK; /* ind addr */ + SC = (SC + 1) & AMASK; /* incr SC again */ + reason = bus_op (src, op & BUS_FNC, dst); /* xmt and modify */ + break; } /* end switch */ } /* end mem ref */ } /* end while */ @@ -775,9 +775,9 @@ if (op == EAO_MUL) { /* mul? */ GR[0] = t & DMASK; } if (op == EAO_DIV) { /* div? */ if (AY && (AX < AY)) { - t = (AX << 16) | GR[0]; /* AX'GR1 / AY */ - GR[0] = t / AY; /* quo to GR1 */ - AX = t % AY; } /* rem to AX */ + t = (AX << 16) | GR[0]; /* AX'GR1 / AY */ + GR[0] = t / AY; /* quo to GR1 */ + AX = t % AY; } /* rem to AX */ } return SCPE_OK; } diff --git a/GRI/gri_stddev.c b/GRI/gri_stddev.c index fa880be8..f30b429f 100644 --- a/GRI/gri_stddev.c +++ b/GRI/gri_stddev.c @@ -29,6 +29,7 @@ hsp S42-006 high speed punch rtc real time clock + 22-Dec-02 RMS Added break support 01-Nov-02 RMS Added 7b/8B support to terminal */ @@ -228,7 +229,8 @@ int32 c; sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (tti_unit.flags & UNIT_KSR) { /* KSR? */ +if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */ +else if (tti_unit.flags & UNIT_KSR) { /* KSR? */ c = c & 0177; /* force 7b */ if (islower (c)) c = toupper (c); /* cvt to UC */ tti_unit.buf = c | 0200; } /* add TTY bit */ @@ -316,8 +318,8 @@ if ((hsr_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (hsr_stopioe, SCPE_UNATT); if ((temp = getc (hsr_unit.fileref)) == EOF) { /* read char */ if (feof (hsr_unit.fileref)) { /* err or eof? */ - if (hsr_stopioe) printf ("HSR end of file\n"); - else return SCPE_OK; } + if (hsr_stopioe) printf ("HSR end of file\n"); + else return SCPE_OK; } else perror ("HSR I/O error"); clearerr (hsr_unit.fileref); return SCPE_IOERR; } @@ -388,4 +390,4 @@ t_stat rtc_reset (DEVICE *dhsr) dev_done = dev_done & ~INT_RTC; /* clear ready */ sim_cancel (&rtc_unit); /* stop clock */ return SCPE_OK; -} \ No newline at end of file +} diff --git a/GRI/gri_sys.c b/GRI/gri_sys.c index 6fab34e3..8280bac2 100644 --- a/GRI/gri_sys.c +++ b/GRI/gri_sys.c @@ -96,17 +96,17 @@ for (;;) { /* until EOF */ if (c == EOF) break; /* EOF? done */ for ( ; c != 0; ) { /* loop until ctl = 0 */ /* ign ctrl frame */ - if ((c = getc (fileref)) == EOF) /* get high byte */ - return SCPE_FMT; /* EOF is error */ - if (!MEM_ADDR_OK (org)) return SCPE_NXM; - M[org] = ((c & 0377) << 8); /* store high */ - if ((c = getc (fileref)) == EOF) /* get low byte */ - return SCPE_FMT; /* EOF is error */ - M[org] = M[org] | (c & 0377); /* store low */ - org = org + 1; /* incr origin */ - if ((c = getc (fileref)) == EOF) /* get ctrl frame */ - return SCPE_OK; /* EOF is ok */ - } /* end block for */ + if ((c = getc (fileref)) == EOF) /* get high byte */ + return SCPE_FMT; /* EOF is error */ + if (!MEM_ADDR_OK (org)) return SCPE_NXM; + M[org] = ((c & 0377) << 8); /* store high */ + if ((c = getc (fileref)) == EOF) /* get low byte */ + return SCPE_FMT; /* EOF is error */ + M[org] = M[org] | (c & 0377); /* store low */ + org = org + 1; /* incr origin */ + if ((c = getc (fileref)) == EOF) /* get ctrl frame */ + return SCPE_OK; /* EOF is ok */ + } /* end block for */ if (!(sim_switches & SWMASK ('C'))) return SCPE_OK; } /* end tape for */ return SCPE_OK; @@ -275,10 +275,10 @@ int32 i, nfirst; for (i = nfirst = 0; fname[i] != NULL; i++) { if (((inst & fop[i].imask) == fop[i].inst) && ((op & fop[i].omask) == fop[i].oper)) { - op = op & ~fop[i].omask; - if (nfirst) fputc (' ', of); - nfirst = 1; - fprintf (of, "%s", fname[i]); } + op = op & ~fop[i].omask; + if (nfirst) fputc (' ', of); + nfirst = 1; + fprintf (of, "%s", fname[i]); } } if (op) fprintf (of, " %o", op); return; @@ -328,64 +328,65 @@ for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */ switch (j) { /* case on class */ case F_V_FO: /* func out */ - fprintf (of, "%s ", opcode[i]); - fprint_op (of, inst, op); - fprintf (of, ",%s", undst[dst]); - break; + fprintf (of, "%s ", opcode[i]); + fprint_op (of, inst, op); + fprintf (of, ",%s", undst[dst]); + break; case F_V_FOI: /* func out impl */ - fprintf (of, "%s ", opcode[i]); - fprint_op (of, inst, op); - break; + fprintf (of, "%s ", opcode[i]); + fprint_op (of, inst, op); + break; case F_V_SF: /* skip func */ - fprintf (of, "%s %s,", opcode[i], unsrc[src]); - fprint_op (of, inst, op); - break; + fprintf (of, "%s %s,", opcode[i], unsrc[src]); + fprint_op (of, inst, op); + break; case F_V_SFI: /* skip func impl */ - fprintf (of, "%s ", opcode[i]); - fprint_op (of, inst, op); - break; + fprintf (of, "%s ", opcode[i]); + fprint_op (of, inst, op); + break; case F_V_RR: /* reg reg */ - if (strcmp (unsrc[src], undst[dst]) == 0) { - if (bop) fprintf (of, "%s %s,%s", opcode[i + 2], - unsrc[src], opname[bop]); - else fprintf (of, "%s %s", opcode[i + 2], unsrc[src]); } - else { if (bop) fprintf (of, "%s %s,%s,%s", opcode[i], - unsrc[src], opname[bop], undst[dst]); - else fprintf (of, "%s %s,%s", opcode[i], - unsrc[src], undst[dst]); } - break; + if (strcmp (unsrc[src], undst[dst]) == 0) { + if (bop) fprintf (of, "%s %s,%s", opcode[i + 2], + unsrc[src], opname[bop]); + else fprintf (of, "%s %s", opcode[i + 2], unsrc[src]); } + else { + if (bop) fprintf (of, "%s %s,%s,%s", opcode[i], + unsrc[src], opname[bop], undst[dst]); + else fprintf (of, "%s %s,%s", opcode[i], + unsrc[src], undst[dst]); } + break; case F_V_ZR: /* zero reg */ - if (bop) fprintf (of, "%s %s,%s", opcode[i], - opname[bop], undst[dst]); - else fprintf (of, "%s %s", opcode[i], undst[dst]); - break; + if (bop) fprintf (of, "%s %s,%s", opcode[i], + opname[bop], undst[dst]); + else fprintf (of, "%s %s", opcode[i], undst[dst]); + break; case F_V_JC: /* jump cond */ - fprintf (of, "%s %s,%s,%o", opcode[i], - unsrc[src], cdname[op >> 1], val[1]); - break; + fprintf (of, "%s %s,%s,%o", opcode[i], + unsrc[src], cdname[op >> 1], val[1]); + break; case F_V_JU: /* jump uncond */ - fprintf (of, "%s %o", opcode[i], val[1]); - break; + fprintf (of, "%s %o", opcode[i], val[1]); + break; case F_V_RM: /* reg mem */ - if (bop) fprintf (of, "%s %s,%s,%o", opcode[i], - unsrc[src], opname[bop], val[1]); - else fprintf (of, "%s %s,%o", opcode[i], unsrc[src], val[1]); - break; + if (bop) fprintf (of, "%s %s,%s,%o", opcode[i], + unsrc[src], opname[bop], val[1]); + else fprintf (of, "%s %s,%o", opcode[i], unsrc[src], val[1]); + break; case F_V_ZM: /* zero mem */ - if (bop) fprintf (of, "%s %s,%o", opcode[i], - opname[bop], val[1]); - else fprintf (of, "%s %o", opcode[i], val[1]); - break; + if (bop) fprintf (of, "%s %s,%o", opcode[i], + opname[bop], val[1]); + else fprintf (of, "%s %o", opcode[i], val[1]); + break; case F_V_MR: /* mem reg */ - if (bop) fprintf (of, "%s %o,%s,%s", opcode[i], - val[1], opname[bop], undst[dst]); - else fprintf (of, "%s %o,%s", opcode[i], val[1], undst[dst]); - break; + if (bop) fprintf (of, "%s %o,%s,%s", opcode[i], + val[1], opname[bop], undst[dst]); + else fprintf (of, "%s %o,%s", opcode[i], val[1], undst[dst]); + break; case F_V_MS: /* mem self */ - if (bop) fprintf (of, "%s %o,%s", opcode[i], - val[1], opname[bop]); - else fprintf (of, "%s %o", opcode[i], val[1]); - break; } /* end case */ + if (bop) fprintf (of, "%s %o,%s", opcode[i], + val[1], opname[bop]); + else fprintf (of, "%s %o", opcode[i], val[1]); + break; } /* end case */ return (j >= F_2WD)? -1: SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; @@ -409,22 +410,22 @@ uint32 inst = val[0]; uint32 fncv = 0, fncm = 0; while (*cptr) { - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - d = get_uint (gbuf, 8, 017, &r); /* octal? */ - if (r == SCPE_OK) { /* ok? */ - if (d & fncm) return NULL; /* already filled? */ - fncv = fncv | d; /* save */ - fncm = fncm | d; } /* field filled */ - else { /* symbol? */ - for (i = 0; fname[i] != NULL; i++) { /* search table */ - if ((strcmp (gbuf, fname[i]) == 0) && /* match for inst? */ - ((inst & fop[i].imask) == fop[i].inst)) { - if (fop[i].oper & fncm) return NULL; /* already filled? */ - fncm = fncm | fop[i].omask; - fncv = fncv | fop[i].oper; - break; } } + cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ + d = get_uint (gbuf, 8, 017, &r); /* octal? */ + if (r == SCPE_OK) { /* ok? */ + if (d & fncm) return NULL; /* already filled? */ + fncv = fncv | d; /* save */ + fncm = fncm | d; } /* field filled */ + else { /* symbol? */ + for (i = 0; fname[i] != NULL; i++) { /* search table */ + if ((strcmp (gbuf, fname[i]) == 0) && /* match for inst? */ + ((inst & fop[i].imask) == fop[i].inst)) { + if (fop[i].oper & fncm) return NULL;/* already filled? */ + fncm = fncm | fop[i].omask; + fncv = fncv | fop[i].oper; + break; } } if (fname[i] == NULL) return NULL; } /* end else */ - } /* end while */ + } /* end while */ val[0] = val[0] | (fncv << I_V_OP); /* store fnc */ return cptr; } @@ -467,8 +468,8 @@ int32 i; tptr = get_glyph (cptr, gbuf, term); /* get glyph */ for (i = 1; i < 4; i++) { /* symbol match? */ if (strcmp (gbuf, opname[i]) == 0) { - val[0] = val[0] | (i << (I_V_OP + 2)); /* or to inst */ - return tptr; } } + val[0] = val[0] | (i << (I_V_OP + 2)); /* or to inst */ + return tptr; } } return cptr; /* original ptr */ } @@ -549,7 +550,7 @@ case F_V_JC: /* jump cond */ if (!cptr) return SCPE_ARG; cptr = get_glyph (cptr, gbuf, ','); /* cond */ for (k = 0; k < 8; k++) { /* symbol? */ - if (strcmp (gbuf, cdname[k]) == 0) break; } + if (strcmp (gbuf, cdname[k]) == 0) break; } if (k >= 8) return SCPE_ARG; val[0] = val[0] | (k << (I_V_OP + 1)); /* or to inst */ case F_V_JU: /* jump uncond */ diff --git a/H316/h316_cpu.c b/H316/h316_cpu.c index f232b25f..e520e329 100644 --- a/H316/h316_cpu.c +++ b/H316/h316_cpu.c @@ -371,8 +371,8 @@ if ((dev_ready & (INT_PENDING | dev_enable)) > INT_PENDING) { /* int req? */ else { if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } + reason = STOP_IBKPT; /* stop simulation */ + break; } Y = PC; /* set mem addr */ MB = Read (Y); /* fetch instr */ PC = NEWA (Y, Y + 1); /* incr PC */ @@ -394,19 +394,19 @@ case 001: case 021: case 041: case 061: /* JMP */ PCQ_ENTRY; /* save PC */ PC = NEWA (PC, Y); /* set new PC */ if (dlog && sim_log) { /* logging? */ - int32 op = I_GETOP (M[PC]) & 017; /* get target */ - if ((op == 014) && (PC == (PCQ_TOP - 2))) { /* jmp .-1 to IO? */ - turnoff = 1; /* yes, stop */ - fprintf (sim_log, "Idle loop detected\n"); } - else turnoff = 0; } /* no, log */ + int32 op = I_GETOP (M[PC]) & 017; /* get target */ + if ((op == 014) && (PC == (PCQ_TOP - 2))) { /* jmp .-1 to IO? */ + turnoff = 1; /* yes, stop */ + fprintf (sim_log, "Idle loop detected\n"); } + else turnoff = 0; } /* no, log */ if (extoff_pending) ext = extoff_pending = 0; /* cond ext off */ break; case 002: case 022: case 042: case 062: /* LDA */ if (reason = Ea (MB, &Y)) break; /* eff addr */ if (dp) { /* double prec? */ - AR = Read (Y & ~1); /* get doubleword */ - BR = Read (Y | 1); - sc = 0; } + AR = Read (Y & ~1); /* get doubleword */ + BR = Read (Y | 1); + sc = 0; } else AR = Read (Y); /* no, get word */ break; case 003: case 023: case 043: case 063: /* ANA */ @@ -416,9 +416,9 @@ case 003: case 023: case 043: case 063: /* ANA */ case 004: case 024: case 044: case 064: /* STA */ if (reason = Ea (MB, &Y)) break; /* eff addr */ if (dp) { /* double prec? */ - if ((Y & 1) == 0) Write (AR, Y); /* if even, store A */ - Write (BR, Y | 1); /* store B */ - sc = 0; } + if ((Y & 1) == 0) Write (AR, Y); /* if even, store A */ + Write (BR, Y | 1); /* store B */ + sc = 0; } else Write (AR, Y); /* no, store word */ break; case 005: case 025: case 045: case 065: /* ERA */ @@ -428,21 +428,21 @@ case 005: case 025: case 045: case 065: /* ERA */ case 006: case 026: case 046: case 066: /* ADD */ if (reason = Ea (MB, &Y)) break; /* eff addr */ if (dp) { /* double prec? */ - t1 = GETDBL_S (AR, BR); /* get A'B */ - t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1)); - t1 = Add31 (t1, t2); /* 31b add */ - PUTDBL_S (t1); - sc = 0; } + t1 = GETDBL_S (AR, BR); /* get A'B */ + t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1)); + t1 = Add31 (t1, t2); /* 31b add */ + PUTDBL_S (t1); + sc = 0; } else AR = Add16 (AR, Read (Y)); /* no, 16b add */ break; case 007: case 027: case 047: case 067: /* SUB */ if (reason = Ea (MB, &Y)) break; /* eff addr */ if (dp) { /* double prec? */ - t1 = GETDBL_S (AR, BR); /* get A'B */ - t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1)); - t1 = Add31 (t1, -t2); /* 31b sub */ - PUTDBL_S (t1); - sc = 0; } + t1 = GETDBL_S (AR, BR); /* get A'B */ + t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1)); + t1 = Add31 (t1, -t2); /* 31b sub */ + PUTDBL_S (t1); + sc = 0; } else AR = Add16 (AR, (-Read (Y)) & DMASK); /* no, 16b sub */ break; @@ -483,25 +483,25 @@ case 035: case 075: /* LDX */ break; case 016: case 036: case 056: case 076: /* MPY */ if (cpu_unit.flags & UNIT_HSA) { /* installed? */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - t1 = SEXT (AR) * SEXT (Read (Y)); - PUTDBL_S (t1); - sc = 0; } + if (reason = Ea (MB, &Y)) break; /* eff addr */ + t1 = SEXT (AR) * SEXT (Read (Y)); + PUTDBL_S (t1); + sc = 0; } else reason = stop_inst; break; case 017: case 037: case 057: case 077: /* DIV */ if (cpu_unit.flags & UNIT_HSA) { /* installed? */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - t2 = SEXT (Read (Y)); /* divr */ - if (t2) { /* divr != 0? */ - t1 = GETDBL_S (AR, BR); /* get A'B */ - BR = (t1 % t2) & DMASK; /* remainder */ - t1 = t1 / t2; /* quotient */ - AR = t1 & DMASK; - if ((t1 > MMASK) || (t1 < (-SIGN))) C = 1; - else C = 0; - sc = 0; } - else C = 1; } + if (reason = Ea (MB, &Y)) break; /* eff addr */ + t2 = SEXT (Read (Y)); /* divr */ + if (t2) { /* divr != 0? */ + t1 = GETDBL_S (AR, BR); /* get A'B */ + BR = (t1 % t2) & DMASK; /* remainder */ + t1 = t1 / t2; /* quotient */ + AR = t1 & DMASK; + if ((t1 > MMASK) || (t1 < (-SIGN))) C = 1; + else C = 0; + sc = 0; } + else C = 1; } else reason = stop_inst; break; @@ -516,67 +516,67 @@ case 034: /* SKS */ t2 = iotab[MB & DEVMASK] (ioSKS, I_GETFNC (MB), AR); reason = t2 >> IOT_V_REASON; if (t2 & IOT_SKIP) { /* skip? */ - PC = NEWA (PC, PC + 1); - turnoff = 0; } + PC = NEWA (PC, PC + 1); + turnoff = 0; } break; case 054: /* INA */ if (MB & INCLRA) AR = 0; t2 = iotab[MB & DEVMASK] (ioINA, I_GETFNC (MB), AR); reason = t2 >> IOT_V_REASON; if (t2 & IOT_SKIP) { /* skip? */ - PC = NEWA (PC, PC + 1); - turnoff = 0; } + PC = NEWA (PC, PC + 1); + turnoff = 0; } AR = t2 & DMASK; /* data */ break; case 074: /* OTA */ t2 = iotab[MB & DEVMASK] (ioOTA, I_GETFNC (MB), AR); reason = t2 >> IOT_V_REASON; if (t2 & IOT_SKIP) { /* skip? */ - PC = NEWA (PC, PC + 1); - turnoff = 0; } + PC = NEWA (PC, PC + 1); + turnoff = 0; } break; /* Control */ case 000: if ((MB & 1) == 0) { /* HLT */ - reason = STOP_HALT; - break; } + reason = STOP_HALT; + break; } if (MB & m14) { /* SGL, DBL */ - if (cpu_unit.flags & UNIT_HSA) dp = (MB & m15)? 1: 0; - else reason = stop_inst; } + if (cpu_unit.flags & UNIT_HSA) dp = (MB & m15)? 1: 0; + else reason = stop_inst; } if (MB & m13) { /* DXA, EXA */ - if (!(cpu_unit.flags & UNIT_EXT)) reason = stop_inst; - else if (MB & m15) { /* EXA */ - ext = 1; - extoff_pending = 0; } /* DXA */ - else extoff_pending = 1; } + if (!(cpu_unit.flags & UNIT_EXT)) reason = stop_inst; + else if (MB & m15) { /* EXA */ + ext = 1; + extoff_pending = 0; } /* DXA */ + else extoff_pending = 1; } if (MB & m12) /* RMP */ - dev_ready = dev_ready & ~INT_MPE; + dev_ready = dev_ready & ~INT_MPE; if (MB & m11) { /* SCA, INK */ - if (MB & m15) /* INK */ - AR = (C << 15) | (dp << 14) | (pme << 13) | (sc & 037); - else if (cpu_unit.flags & UNIT_HSA) /* SCA */ - AR = sc & 037; - else reason = stop_inst; } + if (MB & m15) /* INK */ + AR = (C << 15) | (dp << 14) | (pme << 13) | (sc & 037); + else if (cpu_unit.flags & UNIT_HSA) /* SCA */ + AR = sc & 037; + else reason = stop_inst; } else if (MB & m10) { /* NRM */ - if (cpu_unit.flags & UNIT_HSA) { - for (sc = 0; - (sc <= 32) && ((AR & SIGN) != ((AR << 1) & SIGN)); - sc++) { - AR = (AR & SIGN) | ((AR << 1) & MMASK) | - ((BR >> 14) & 1); - BR = (BR & SIGN) | ((BR << 1) & MMASK); } - sc = sc & 037; } - else reason = stop_inst; } + if (cpu_unit.flags & UNIT_HSA) { + for (sc = 0; + (sc <= 32) && ((AR & SIGN) != ((AR << 1) & SIGN)); + sc++) { + AR = (AR & SIGN) | ((AR << 1) & MMASK) | + ((BR >> 14) & 1); + BR = (BR & SIGN) | ((BR << 1) & MMASK); } + sc = sc & 037; } + else reason = stop_inst; } else if (MB & m9) { /* IAB */ - sc = BR; - BR = AR; - AR = sc; } + sc = BR; + BR = AR; + AR = sc; } if (MB & m8) /* ENB */ - dev_ready = (dev_ready | INT_ON) & ~INT_NODEF; + dev_ready = (dev_ready | INT_ON) & ~INT_NODEF; if (MB & m7) /* INH */ - dev_ready = dev_ready & ~INT_ON; + dev_ready = dev_ready & ~INT_ON; break; /* Shift @@ -607,112 +607,116 @@ case 020: if ((t1 = (-MB) & SHFMASK) == 0) break; /* shift count */ switch (I_GETFNC (MB)) { /* case shift fnc */ case 000: /* LRL */ - if (t1 > 32) ut = 0; /* >32? all 0 */ - else { ut = GETDBL_U (AR, BR); /* get A'B */ - C = (ut >> (t1 - 1)) & 1; /* C = last out */ - ut = ut >> t1; } /* log right */ - PUTDBL_U (ut); /* store A,B */ - break; + if (t1 > 32) ut = 0; /* >32? all 0 */ + else { + ut = GETDBL_U (AR, BR); /* get A'B */ + C = (ut >> (t1 - 1)) & 1; /* C = last out */ + ut = ut >> t1; } /* log right */ + PUTDBL_U (ut); /* store A,B */ + break; case 001: /* LRS */ - if (t1 > 31) t1 = 31; /* limit to 31 */ - t2 = GETDBL_S (SEXT (AR), BR); /* get A'B signed */ - C = (t2 >> (t1 - 1)) & 1; /* C = last out */ - t2 = t2 >> t1; /* arith right */ - PUTDBL_S (t2); /* store A,B */ - break; + if (t1 > 31) t1 = 31; /* limit to 31 */ + t2 = GETDBL_S (SEXT (AR), BR); /* get A'B signed */ + C = (t2 >> (t1 - 1)) & 1; /* C = last out */ + t2 = t2 >> t1; /* arith right */ + PUTDBL_S (t2); /* store A,B */ + break; case 002: /* LRR */ - t2 = t1 % 32; /* mod 32 */ - ut = GETDBL_U (AR, BR); /* get A'B */ - ut = (ut >> t2) | (ut << (32 - t2)); /* rot right */ - C = (ut >> 31) & 1; /* C = A<1> */ - PUTDBL_U (ut); /* store A,B */ - break; + t2 = t1 % 32; /* mod 32 */ + ut = GETDBL_U (AR, BR); /* get A'B */ + ut = (ut >> t2) | (ut << (32 - t2)); /* rot right */ + C = (ut >> 31) & 1; /* C = A<1> */ + PUTDBL_U (ut); /* store A,B */ + break; case 003: /* "long right arot" */ - if (reason = stop_inst) break; /* stop on undef? */ - for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ - C = BR & 1; /* C = last out */ - BR = (BR & SIGN) | ((AR & 1) << 14) | - ((BR & MMASK) >> 1); - AR = ((AR & SIGN) | (C << 15)) | (AR >> 1); } - break; + if (reason = stop_inst) break; /* stop on undef? */ + for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ + C = BR & 1; /* C = last out */ + BR = (BR & SIGN) | ((AR & 1) << 14) | + ((BR & MMASK) >> 1); + AR = ((AR & SIGN) | (C << 15)) | (AR >> 1); } + break; case 004: /* LGR */ - if (t1 > 16) AR = 0; /* > 16? all 0 */ - else { C = (AR >> (t1 - 1)) & 1; /* C = last out */ - AR = (AR >> t1) & DMASK; } /* log right */ - break; + if (t1 > 16) AR = 0; /* > 16? all 0 */ + else { + C = (AR >> (t1 - 1)) & 1; /* C = last out */ + AR = (AR >> t1) & DMASK; } /* log right */ + break; case 005: /* ARS */ - if (t1 > 16) t1 = 16; /* limit to 16 */ - C = ((SEXT (AR)) >> (t1 - 1)) & 1; /* C = last out */ - AR = ((SEXT (AR)) >> t1) & DMASK; /* arith right */ - break; + if (t1 > 16) t1 = 16; /* limit to 16 */ + C = ((SEXT (AR)) >> (t1 - 1)) & 1; /* C = last out */ + AR = ((SEXT (AR)) >> t1) & DMASK; /* arith right */ + break; case 006: /* ARR */ - t2 = t1 % 16; /* mod 16 */ - AR = ((AR >> t2) | (AR << (16 - t2))) & DMASK; - C = (AR >> 15) & 1; /* C = A<1> */ - break; + t2 = t1 % 16; /* mod 16 */ + AR = ((AR >> t2) | (AR << (16 - t2))) & DMASK; + C = (AR >> 15) & 1; /* C = A<1> */ + break; case 007: /* "short right arot" */ - if (reason = stop_inst) break; /* stop on undef? */ - for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ - C = AR & 1; /* C = last out */ - AR = ((AR & SIGN) | (C << 15)) | (AR >> 1); } - break; + if (reason = stop_inst) break; /* stop on undef? */ + for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ + C = AR & 1; /* C = last out */ + AR = ((AR & SIGN) | (C << 15)) | (AR >> 1); } + break; /* Shift, continued */ case 010: /* LLL */ - if (t1 > 32) ut = 0; /* > 32? all 0 */ - else { ut = GETDBL_U (AR, BR); /* get A'B */ - C = (ut >> (32 - t1)) & 1; /* C = last out */ - ut = ut << t1; } /* log left */ - PUTDBL_U (ut); /* store A,B */ - break; + if (t1 > 32) ut = 0; /* > 32? all 0 */ + else { + ut = GETDBL_U (AR, BR); /* get A'B */ + C = (ut >> (32 - t1)) & 1; /* C = last out */ + ut = ut << t1; } /* log left */ + PUTDBL_U (ut); /* store A,B */ + break; case 011: /* LLS */ - if (t1 > 31) t1 = 31; /* limit to 31 */ - t2 = GETDBL_S (SEXT (AR), BR); /* get A'B */ - t3 = t2 << t1; /* "arith" left */ - PUTDBL_S (t3); /* store A'B */ - if ((t2 >> (31 - t1)) != /* shf out = sgn? */ - ((AR & SIGN)? -1: 0)) C = 1; - break; + if (t1 > 31) t1 = 31; /* limit to 31 */ + t2 = GETDBL_S (SEXT (AR), BR); /* get A'B */ + t3 = t2 << t1; /* "arith" left */ + PUTDBL_S (t3); /* store A'B */ + if ((t2 >> (31 - t1)) != /* shf out = sgn? */ + ((AR & SIGN)? -1: 0)) C = 1; + break; case 012: /* LLR */ - t2 = t1 % 32; /* mod 32 */ - ut = GETDBL_U (AR, BR); /* get A'B */ - ut = (ut << t2) | (ut >> (32 - t2)); /* rot left */ - C = ut & 1; /* C = B<16> */ - PUTDBL_U (ut); /* store A,B */ - break; + t2 = t1 % 32; /* mod 32 */ + ut = GETDBL_U (AR, BR); /* get A'B */ + ut = (ut << t2) | (ut >> (32 - t2)); /* rot left */ + C = ut & 1; /* C = B<16> */ + PUTDBL_U (ut); /* store A,B */ + break; case 013: /* "long left arot" */ - if (reason = stop_inst) break; /* stop on undef? */ - for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ - AR = (AR << 1) | ((BR >> 14) & 1); - BR = (BR & SIGN) | ((BR << 1) & MMASK) | - ((AR >> 16) & 1); - if ((AR & SIGN) != ((AR >> 1) & SIGN)) C = 1; - AR = AR & DMASK; } - break; + if (reason = stop_inst) break; /* stop on undef? */ + for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ + AR = (AR << 1) | ((BR >> 14) & 1); + BR = (BR & SIGN) | ((BR << 1) & MMASK) | + ((AR >> 16) & 1); + if ((AR & SIGN) != ((AR >> 1) & SIGN)) C = 1; + AR = AR & DMASK; } + break; case 014: /* LGL */ - if (t1 > 16) AR = 0; /* > 16? all 0 */ - else { C = (AR >> (16 - t1)) & 1; /* C = last out */ - AR = (AR << t1) & DMASK; } /* log left */ - break; + if (t1 > 16) AR = 0; /* > 16? all 0 */ + else { + C = (AR >> (16 - t1)) & 1; /* C = last out */ + AR = (AR << t1) & DMASK; } /* log left */ + break; case 015: /* ALS */ - if (t1 > 16) t1 = 16; /* limit to 16 */ - t2 = SEXT (AR); /* save AR */ - AR = (AR << t1) & DMASK; /* "arith" left */ - if ((t2 >> (16 - t1)) != /* shf out + sgn */ - ((AR & SIGN)? -1: 0)) C = 1; - break; + if (t1 > 16) t1 = 16; /* limit to 16 */ + t2 = SEXT (AR); /* save AR */ + AR = (AR << t1) & DMASK; /* "arith" left */ + if ((t2 >> (16 - t1)) != /* shf out + sgn */ + ((AR & SIGN)? -1: 0)) C = 1; + break; case 016: /* ALR */ - t2 = t1 % 16; /* mod 16 */ - AR = ((AR << t2) | (AR >> (16 - t2))) & DMASK; - C = AR & 1; /* C = A<16> */ - break; + t2 = t1 % 16; /* mod 16 */ + AR = ((AR << t2) | (AR >> (16 - t2))) & DMASK; + C = AR & 1; /* C = A<16> */ + break; case 017: /* "short left arot" */ - if (reason = stop_inst) break; /* stop on undef? */ - for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ - if ((AR & SIGN) != ((AR << 1) & SIGN)) C = 1; - AR = ((AR << 1) | (AR >> 15)) & DMASK; } - break; } /* end case fnc */ + if (reason = stop_inst) break; /* stop on undef? */ + for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ + if ((AR & SIGN) != ((AR << 1) & SIGN)) C = 1; + AR = ((AR << 1) | (AR >> 15)) & DMASK; } + break; } /* end case fnc */ break; /* Skip */ @@ -740,12 +744,12 @@ case 060: else if (MB == 0140100) AR = AR & ~SIGN; /* SSP */ else if (MB == 0140200) C = 0; /* RCB */ else if (MB == 0140320) { /* CSA */ - C = (AR & SIGN) >> 15; - AR = AR & ~SIGN; } + C = (AR & SIGN) >> 15; + AR = AR & ~SIGN; } else if (MB == 0140401) AR = AR ^ DMASK; /* CMA */ else if (MB == 0140407) { /* TCA */ - AR = (-AR) & DMASK; - sc = 0; } + AR = (-AR) & DMASK; + sc = 0; } else if (MB == 0140500) AR = AR | SIGN; /* SSM */ else if (MB == 0140600) C = 1; /* SCB */ else if (MB == 0141044) AR = AR & 0177400; /* CAR */ @@ -755,7 +759,7 @@ case 060: else if (MB == 0141216) AR = Add16 (AR, C); /* ACA */ else if (MB == 0141240) AR = (AR << 8) & DMASK; /* ICR */ else if (MB == 0141340) /* ICA */ - AR = ((AR << 8) | (AR >> 8)) & DMASK; + AR = ((AR << 8) | (AR >> 8)) & DMASK; else if (reason = stop_inst) break; else AR = Operate (MB, AR); /* undefined */ break; @@ -792,14 +796,14 @@ int32 Y = IR & (IA | DISP); /* ind + disp */ if (IR & SC) Y = ((PC - 1) & PAGENO) | Y; /* cur sec? + pageno */ if (ext) { /* extend mode? */ for (i = 0; (i < ind_max) && (Y & IA); i++) { /* resolve ind addr */ - Y = Read (Y & X_AMASK); } /* get ind addr */ + Y = Read (Y & X_AMASK); } /* get ind addr */ if (IR & IDX) Y = Y + XR; /* post-index */ } /* end if ext */ else { /* non-extend */ Y = NEWA (PC, Y + ((IR & IDX)? XR: 0)); /* pre-index */ for (i = 0; (i < ind_max) && (IR & IA); i++) { /* resolve ind addr */ - IR = Read (Y & X_AMASK); /* get ind addr */ - Y = NEWA (Y, IR + ((IR & IDX)? XR: 0)); } /* post-index */ + IR = Read (Y & X_AMASK); /* get ind addr */ + Y = NEWA (Y, IR + ((IR & IDX)? XR: 0)); } /* post-index */ } /* end else */ *addr = Y = Y & X_AMASK; /* return addr */ if (dlog && sim_log && !turnoff) /* cycle log? */ diff --git a/H316/h316_lp.c b/H316/h316_lp.c index efd9e8e8..bf8370e5 100644 --- a/H316/h316_lp.c +++ b/H316/h316_lp.c @@ -127,81 +127,81 @@ switch (inst) { /* case on opcode */ case ioOCP: /* OCP */ switch (fnc) { /* case on fnc */ case 000: case 002: case 004: /* paper adv */ - lpt_svcst = lpt_svcst | LPT_SVCPA; /* set state */ - lpt_svcch = fnc >> 1; /* save channel */ - sim_activate (&lpt_unit, lpt_ptime); - CLR_READY (INT_LPT); /* clear int */ - break; + lpt_svcst = lpt_svcst | LPT_SVCPA; /* set state */ + lpt_svcch = fnc >> 1; /* save channel */ + sim_activate (&lpt_unit, lpt_ptime); + CLR_READY (INT_LPT); /* clear int */ + break; case 007: /* init scan */ - lpt_prdn = 0; /* clear pr done */ - lpt_wdpos = 0; /* init scan pos */ - if (!sim_is_active (&lpt_unit)) lpt_xfer = 1; - CLR_READY (INT_LPT); /* clear int */ - break; + lpt_prdn = 0; /* clear pr done */ + lpt_wdpos = 0; /* init scan pos */ + if (!sim_is_active (&lpt_unit)) lpt_xfer = 1; + CLR_READY (INT_LPT); /* clear int */ + break; default: - return IOBADFNC (dat); } + return IOBADFNC (dat); } break; case ioSKS: /* SKS */ switch (fnc) { /* case on fnc */ case 000: /* if xfer rdy */ - if (lpt_xfer) return IOSKIP (dat); - break; + if (lpt_xfer) return IOSKIP (dat); + break; case 002: /* if !alarm */ - if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat); - break; + if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat); + break; case 003: /* if odd col */ - if (lpt_crpos) return IOSKIP (dat); - break; + if (lpt_crpos) return IOSKIP (dat); + break; case 004: /* if !interrupt */ - if (!TST_INTREQ (INT_LPT)) return IOSKIP (dat); - break; + if (!TST_INTREQ (INT_LPT)) return IOSKIP (dat); + break; case 011: /* if line printed */ - if (lpt_prdn) return IOSKIP (dat); - break; + if (lpt_prdn) return IOSKIP (dat); + break; case 012: /* if !shuttling */ - if (!(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); - break; + if (!(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); + break; case 013: - if (lpt_prdn && !(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); - break; + if (lpt_prdn && !(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); + break; case 014: /* if !advancing */ - if (!(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); - break; + if (!(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); + break; case 015: - if (lpt_prdn && !(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); - break; + if (lpt_prdn && !(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); + break; case 016: - if (!(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) return IOSKIP (dat); - break; + if (!(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) return IOSKIP (dat); + break; case 017: - if (lpt_prdn && !(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) - return IOSKIP (dat); - break; + if (lpt_prdn && !(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) + return IOSKIP (dat); + break; default: - return IOBADFNC (dat); } + return IOBADFNC (dat); } break; case ioOTA: /* OTA */ if (fnc) return IOBADFNC (dat); /* only fnc 0 */ if (lpt_xfer) { /* xfer ready? */ - lpt_xfer = 0; /* clear xfer */ - chr = (dat >> (lpt_crpos? 0: 8)) & 077; /* get 6b char */ - if (chr == lpt_drpos) { /* match drum pos? */ - if (chr < 040) chr = chr | 0100; - lpt_buf[2 * lpt_wdpos + lpt_crpos] = chr; } - lpt_wdpos++; /* adv scan pos */ - if (lpt_wdpos >= LPT_SCAN) { /* end of scan? */ - lpt_wdpos = 0; /* reset scan pos */ - lpt_drpos++; /* adv drum pos */ - if (lpt_drpos >= LPT_DRUM) { /* end of drum? */ - lpt_drpos = 0; /* reset drum pos */ - lpt_crpos = lpt_crpos ^ 1; /* shuttle */ - lpt_svcst = lpt_svcst | LPT_SVCSH; - sim_activate (&lpt_unit, lpt_ptime); - } /* end if shuttle */ - else sim_activate (&lpt_unit, lpt_etime); - } /* end if endscan */ - else sim_activate (&lpt_unit, lpt_xtime); - return IOSKIP (dat); } /* skip return */ + lpt_xfer = 0; /* clear xfer */ + chr = (dat >> (lpt_crpos? 0: 8)) & 077; /* get 6b char */ + if (chr == lpt_drpos) { /* match drum pos? */ + if (chr < 040) chr = chr | 0100; + lpt_buf[2 * lpt_wdpos + lpt_crpos] = chr; } + lpt_wdpos++; /* adv scan pos */ + if (lpt_wdpos >= LPT_SCAN) { /* end of scan? */ + lpt_wdpos = 0; /* reset scan pos */ + lpt_drpos++; /* adv drum pos */ + if (lpt_drpos >= LPT_DRUM) { /* end of drum? */ + lpt_drpos = 0; /* reset drum pos */ + lpt_crpos = lpt_crpos ^ 1; /* shuttle */ + lpt_svcst = lpt_svcst | LPT_SVCSH; + sim_activate (&lpt_unit, lpt_ptime); + } /* end if shuttle */ + else sim_activate (&lpt_unit, lpt_etime); + } /* end if endscan */ + else sim_activate (&lpt_unit, lpt_xtime); + return IOSKIP (dat); } /* skip return */ break; } /* end case op */ return dat; } @@ -226,7 +226,7 @@ if (lpt_svcst & LPT_SVCSH) { /* shuttling */ if (lpt_svcst & LPT_SVCPA) { /* paper advance */ SET_READY (INT_LPT); /* interrupt */ for (i = LPT_WIDTH - 1; i >= 0; i++) { - if (lpt_buf[i] != ' ') break; } + if (lpt_buf[i] != ' ') break; } lpt_buf[i + 1] = 0; fputs (lpt_buf, uptr->fileref); /* output buf */ fputs (lpt_cc[lpt_svcch & 03], uptr->fileref); /* output eol */ diff --git a/H316/h316_stddev.c b/H316/h316_stddev.c index a54cf8e4..b392acf0 100644 --- a/H316/h316_stddev.c +++ b/H316/h316_stddev.c @@ -28,6 +28,7 @@ tty 316/516-33 teleprinter clk/options 316/516-12 real time clocks/internal options + 22-Dec-02 RMS Added break support 01-Nov-02 RMS Added 7b/8b support to terminal 30-May-02 RMS Widened POS to 32b 03-Nov-01 RMS Implemented upper case for console output @@ -199,13 +200,13 @@ case ioSKS: /* SKS */ if (fnc & 013) return IOBADFNC (dat); /* only fnc 0,4 */ if (((fnc == 0) && TST_READY (INT_PTR)) || /* fnc 0? skip rdy */ ((fnc == 4) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */ - return IOSKIP (dat); + return IOSKIP (dat); break; case ioINA: /* INA */ if (fnc & 007) return IOBADFNC (dat); /* only fnc 0,10 */ if (TST_READY (INT_PTR)) { /* ready? */ - CLR_READY (INT_PTR); /* clear ready */ - return IOSKIP (ptr_unit.buf | dat); } /* ret buf, skip */ + CLR_READY (INT_PTR); /* clear ready */ + return IOSKIP (ptr_unit.buf | dat); } /* ret buf, skip */ break; } /* end case op */ return dat; } @@ -220,8 +221,8 @@ if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ptr_stopioe, SCPE_UNATT); if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte */ if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } + if (ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; } else perror ("PTR I/O error"); clearerr (ptr_unit.fileref); return SCPE_IOERR; } @@ -284,28 +285,28 @@ switch (inst) { /* case on opcode */ case ioOCP: /* OCP */ if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ if (fnc) { /* fnc 1? pwr off */ - CLR_READY (INT_PTP); /* not ready */ - ptp_power = 0; /* turn off power */ - sim_cancel (&ptp_unit); } /* stop punch */ + CLR_READY (INT_PTP); /* not ready */ + ptp_power = 0; /* turn off power */ + sim_cancel (&ptp_unit); } /* stop punch */ else if (ptp_power == 0) /* fnc 0? start */ - sim_activate (&ptp_unit, ptp_ptime); + sim_activate (&ptp_unit, ptp_ptime); break; case ioSKS: /* SKS */ if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */ - return IOBADFNC (dat); + return IOBADFNC (dat); if (((fnc == 00) && TST_READY (INT_PTP)) || /* fnc 0? skip rdy */ ((fnc == 01) /* fnc 1? skip ptp on */ && (ptp_power || sim_is_active (&ptp_unit))) || ((fnc == 04) && !TST_INTREQ (INT_PTP))) /* fnc 4? skip !int */ - return IOSKIP (dat); + return IOSKIP (dat); break; case ioOTA: /* OTA */ if (fnc) return IOBADFNC (dat); /* only fnc 0 */ if (TST_READY (INT_PTP)) { /* if ptp ready */ - CLR_READY (INT_PTP); /* clear ready */ - ptp_unit.buf = dat & 0377; /* store byte */ - sim_activate (&ptp_unit, ptp_unit.wait); - return IOSKIP (dat); } /* skip return */ + CLR_READY (INT_PTP); /* clear ready */ + ptp_unit.buf = dat & 0377; /* store byte */ + sim_activate (&ptp_unit, ptp_unit.wait); + return IOSKIP (dat); } /* skip return */ break; } return dat; } @@ -349,11 +350,12 @@ switch (inst) { /* case on opcode */ case ioOCP: /* OCP */ if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ if (fnc && (tty_mode == 0)) { /* input to output? */ - if (!sim_is_active (&tty_unit[TTO])) SET_READY (INT_TTY); - tty_mode = 1; } /* mode is output */ + if (!sim_is_active (&tty_unit[TTO])) /* set ready */ + SET_READY (INT_TTY); + tty_mode = 1; } /* mode is output */ else if ((fnc == 0) && tty_mode) { /* output to input? */ - CLR_READY (INT_TTY); /* clear ready */ - tty_mode = 0; } /* mode is input */ + CLR_READY (INT_TTY); /* clear ready */ + tty_mode = 0; } /* mode is input */ break; case ioSKS: /* SKS */ if (fnc & 012) return IOBADFNC (dat); /* fnc 0,1,4,5 */ @@ -363,26 +365,26 @@ case ioSKS: /* SKS */ ((fnc == 4) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */ ((fnc == 5) && /* fnc 5? skip !xoff */ !tty_mode && ((tty_buf & 0177) == 023))) - return IOSKIP (dat); + return IOSKIP (dat); break; case ioINA: /* INA */ if (fnc & 005) return IOBADFNC (dat); /* only 0,2,10,12 */ if (TST_READY (INT_TTY)) { /* ready? */ - if (tty_mode == 0) CLR_READY (INT_TTY); /* inp? clear rdy */ - return IOSKIP (dat | - (tty_buf & ((fnc & 002)? 077: 0377))); } + if (tty_mode == 0) CLR_READY (INT_TTY); /* inp? clear rdy */ + return IOSKIP (dat | + (tty_buf & ((fnc & 002)? 077: 0377))); } break; case ioOTA: if (fnc & 015) return IOBADFNC (dat); /* only 0,2 */ if (TST_READY (INT_TTY)) { /* ready? */ - tty_buf = dat & 0377; /* store char */ - if (fnc & 002) { /* binary mode? */ - tty_buf = tty_buf | 0100; /* set ch 7 */ - if (tty_buf & 040) tty_buf = tty_buf & 0277; } - if (tty_mode) { - sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); - CLR_READY (INT_TTY); } - return IOSKIP (dat); } + tty_buf = dat & 0377; /* store char */ + if (fnc & 002) { /* binary mode? */ + tty_buf = tty_buf | 0100; /* set ch 7 */ + if (tty_buf & 040) tty_buf = tty_buf & 0277; } + if (tty_mode) { + sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); + CLR_READY (INT_TTY); } + return IOSKIP (dat); } break; } /* end case op */ return dat; } @@ -396,7 +398,8 @@ int32 out, c; sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ out = c & 0177; /* mask echo to 7b */ -if (tty_unit[TTI].flags & UNIT_KSR) { /* KSR? */ +if (c & SCPE_BREAK) c = 0; /* break? */ +else if (tty_unit[TTI].flags & UNIT_KSR) { /* KSR? */ if (islower (out)) out = toupper (out); /* cvt to UC */ c = out | 0200; } /* add TTY bit */ else c = c & ((tty_unit[TTI].flags & UNIT_8B)? 0377: 0177); @@ -404,7 +407,7 @@ if (tty_mode == 0) { /* input mode? */ tty_buf = c; /* put char in buf */ tty_unit[TTI].pos = tty_unit[TTI].pos + 1; SET_READY (INT_TTY); /* set flag */ - sim_putchar (out); } /* echo */ + if (out) sim_putchar (out); } /* echo */ return SCPE_OK; } @@ -452,31 +455,32 @@ case ioOCP: /* OCP */ if (fnc & 015) return IOBADFNC (dat); /* only fnc 0,2 */ CLR_READY (INT_CLK); /* reset ready */ if (fnc) sim_cancel (&clk_unit); /* fnc = 2? stop */ - else { if (!sim_is_active (&clk_unit)) /* fnc = 0? start */ + else { /* fnc = 0? */ + if (!sim_is_active (&clk_unit)) sim_activate (&clk_unit, /* activate */ - sim_rtc_init (clk_unit.wait)); } /* init calibr */ + sim_rtc_init (clk_unit.wait)); } /* init calibr */ break; case ioSKS: /* SKS */ if (fnc == 0) { /* clock skip !int */ - if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); } + if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); } else if ((fnc & 007) == 002) { /* mem parity? */ - if (((fnc == 002) && !TST_READY (INT_MPE)) || - ((fnc == 012) && TST_READY (INT_MPE))) - return IOSKIP (dat); } + if (((fnc == 002) && !TST_READY (INT_MPE)) || + ((fnc == 012) && TST_READY (INT_MPE))) + return IOSKIP (dat); } else return IOBADFNC (dat); /* invalid fnc */ break; case ioOTA: /* OTA */ if (fnc == 000) dev_enable = dat; /* SMK */ else if (fnc == 010) { /* OTK */ - C = (dat >> 15) & 1; /* set C */ - if (cpu_unit.flags & UNIT_HSA) /* HSA included? */ - dp = (dat >> 14) & 1; /* set dp */ - if (cpu_unit.flags & UNIT_EXT) { /* ext opt? */ - if (dat & 020000) { /* ext set? */ - ext = 1; /* yes, set */ - extoff_pending = 0; } - else extoff_pending = 1; } /* no, clr later */ - sc = dat & 037; } /* set sc */ + C = (dat >> 15) & 1; /* set C */ + if (cpu_unit.flags & UNIT_HSA) /* HSA included? */ + dp = (dat >> 14) & 1; /* set dp */ + if (cpu_unit.flags & UNIT_EXT) { /* ext opt? */ + if (dat & 020000) { /* ext set? */ + ext = 1; /* yes, set */ + extoff_pending = 0; } + else extoff_pending = 1; } /* no, clr later */ + sc = dat & 037; } /* set sc */ else return IOBADFNC (dat); break; } return dat; diff --git a/H316/h316_sys.c b/H316/h316_sys.c index 6175d397..283a66e1 100644 --- a/H316/h316_sys.c +++ b/H316/h316_sys.c @@ -187,9 +187,9 @@ int32 i, j; for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ if ((j == class) && (opc_val[i] & inst)) { /* same class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } + inst = inst & ~opc_val[i]; /* mask bit set? */ + fprintf (of, (sp? " %s": "%s"), opcode[i]); + sp = 1; } } return sp; } @@ -232,28 +232,28 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ switch (j) { /* case on class */ case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; + fprintf (of, "%s", opcode[i]); /* opcode */ + break; case I_V_MRF: case I_V_MRX: /* mem ref */ - disp = inst & DISP; /* displacement */ - fprintf (of, "%s ", opcode[i]); /* opcode */ - if (inst & SC) { /* current sector? */ - if (cflag) fprintf (of, "%-o", (addr & PAGENO) | disp); - else fprintf (of, "C %-o", disp); } - else fprintf (of, "%-o", disp); /* sector zero */ - if ((j == I_V_MRF) && (inst & IDX)) fprintf (of, ",1"); - break; + disp = inst & DISP; /* displacement */ + fprintf (of, "%s ", opcode[i]); /* opcode */ + if (inst & SC) { /* current sector? */ + if (cflag) fprintf (of, "%-o", (addr & PAGENO) | disp); + else fprintf (of, "C %-o", disp); } + else fprintf (of, "%-o", disp); /* sector zero */ + if ((j == I_V_MRF) && (inst & IDX)) fprintf (of, ",1"); + break; case I_V_IOT: /* I/O */ - disp = inst & 01777; /* pulse+dev */ - fprintf (of, "%s %o", opcode[i], disp); - break; + disp = inst & 01777; /* pulse+dev */ + fprintf (of, "%s %o", opcode[i], disp); + break; case I_V_SHF: /* shift */ - disp = -inst & SHFMASK; /* shift count */ - fprintf (of, "%s %o", opcode[i], disp); - break; + disp = -inst & SHFMASK; /* shift count */ + fprintf (of, "%s %o", opcode[i], disp); + break; case I_V_SK0: case I_V_SK1: /* skips */ - fprint_opr (of, inst & 0777, j, 0); /* print skips */ - break; } /* end case */ + fprint_opr (of, inst & 0777, j, 0); /* print skips */ + break; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; @@ -315,15 +315,15 @@ case I_V_SHF: /* shift */ case I_V_MRF: case I_V_MRX: /* mem ref */ cptr = get_glyph (cptr, gbuf, ','); /* get next field */ if (k = (strcmp (gbuf, "C") == 0)) { /* C specified? */ - val[0] = val[0] | SC; - cptr = get_glyph (cptr, gbuf, 0); } + val[0] = val[0] | SC; + cptr = get_glyph (cptr, gbuf, 0); } else if (k = (strcmp (gbuf, "Z") == 0)) { /* Z specified? */ - cptr = get_glyph (cptr, gbuf, ','); } + cptr = get_glyph (cptr, gbuf, ','); } d = get_uint (gbuf, 8, X_AMASK, &r); /* construe as addr */ if (r != SCPE_OK) return SCPE_ARG; if (d <= DISP) val[0] = val[0] | d; /* fits? */ else if (cflag && !k && (((addr ^ d) & PAGENO) == 0)) - val[0] = val[0] | (d & DISP) | SC; + val[0] = val[0] | (d & DISP) | SC; else return SCPE_ARG; if ((j == I_V_MRX) || (*cptr == 0)) break; /* indexed? */ cptr = get_glyph (cptr, gbuf, 0); @@ -334,12 +334,12 @@ case I_V_MRF: case I_V_MRX: /* mem ref */ case I_V_SK0: case I_V_SK1: /* skips */ for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && - (strcmp (opcode[i], gbuf) != 0) ; i++) ; - k = opc_val[i] & DMASK; - if ((opcode[i] == NULL) || (((k ^ val[0]) & 0177000) != 0)) - return SCPE_ARG; - val[0] = val[0] | k; } + for (i = 0; (opcode[i] != NULL) && + (strcmp (opcode[i], gbuf) != 0) ; i++) ; + k = opc_val[i] & DMASK; + if ((opcode[i] == NULL) || (((k ^ val[0]) & 0177000) != 0)) + return SCPE_ARG; + val[0] = val[0] | k; } break; } /* end case */ if (*cptr != 0) return SCPE_ARG; /* junk at end? */ return SCPE_OK; diff --git a/HP2100/hp2100_cpu.c b/HP2100/hp2100_cpu.c index f9017369..68e4ebdc 100644 --- a/HP2100/hp2100_cpu.c +++ b/HP2100/hp2100_cpu.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 22-Nov-02 RMS Added 21MX IOP support 24-Oct-02 RMS Fixed bugs in IOP and extended instructions Fixed bugs in memory protection and DMS Added clock calibration @@ -283,8 +284,9 @@ #define UNIT_V_FP (UNIT_V_UF + 3) /* FP */ #define UNIT_V_MPR (UNIT_V_UF + 4) /* mem prot */ #define UNIT_V_DMS (UNIT_V_UF + 5) /* DMS */ -#define UNIT_V_IOP (UNIT_V_UF + 6) /* IOP */ -#define UNIT_V_MSIZE (UNIT_V_UF + 7) /* dummy mask */ +#define UNIT_V_IOP (UNIT_V_UF + 6) /* 2100 IOP */ +#define UNIT_V_IOPX (UNIT_V_UF + 7) /* 21MX IOP */ +#define UNIT_V_MSIZE (UNIT_V_UF + 8) /* dummy mask */ #define UNIT_2100 (1 << UNIT_V_2100) #define UNIT_21MX (1 << UNIT_V_21MX) #define UNIT_EAU (1 << UNIT_V_EAU) @@ -292,6 +294,7 @@ #define UNIT_MPR (1 << UNIT_V_MPR) #define UNIT_DMS (1 << UNIT_V_DMS) #define UNIT_IOP (1 << UNIT_V_IOP) +#define UNIT_IOPX (1 << UNIT_V_IOPX) #define UNIT_MSIZE (1 << UNIT_V_MSIZE) #define MOD_2116 1 @@ -330,6 +333,7 @@ uint32 dms_ump = 0; /* dms user map */ uint32 dms_sr = 0; /* dms status reg */ uint32 dms_vr = 0; /* dms violation reg */ uint32 dms_map[MAP_NUM * MAP_LNT] = { 0 }; /* dms maps */ +uint32 iop_sp = 0; /* iop stack */ uint32 ind_max = 16; /* iadr nest limit */ uint32 stop_inst = 1; /* stop on ill inst */ uint32 stop_dev = 0; /* stop on ill dev */ @@ -347,7 +351,7 @@ static struct opt_table opt_val[] = { { UNIT_FP, MOD_2100 }, { UNIT_MPR, MOD_2100 | MOD_21MX }, { UNIT_DMS, MOD_21MX }, - { UNIT_IOP, MOD_2100 }, + { UNIT_IOP, MOD_2100 | MOD_21MX }, { 0, 0 } }; extern int32 sim_interval; @@ -431,6 +435,7 @@ REG cpu_reg[] = { { ORDATA (DMSSR, dms_sr, 16) }, { ORDATA (DMSVR, dms_vr, 16) }, { BRDATA (DMSMAP, dms_map, 8, PA_N_SIZE, MAP_NUM * MAP_LNT) }, + { ORDATA (IOPSP, iop_sp, 16) }, { FLDATA (STOP_INST, stop_inst, 0) }, { FLDATA (STOP_DEV, stop_dev, 1) }, { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, @@ -448,34 +453,36 @@ REG cpu_reg[] = { { NULL } }; MTAB cpu_mod[] = { - { UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP, + { UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX, 0, NULL, "2116", NULL }, - { UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP, + { UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX, UNIT_2100+UNIT_EAU, NULL, "2100", NULL }, - { UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP, + { UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX, UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS, NULL, "21MX", NULL }, { UNIT_2100+UNIT_21MX, 0, "2116", NULL, NULL }, { UNIT_2100+UNIT_21MX, UNIT_2100, "2100", NULL, NULL }, { UNIT_2100+UNIT_21MX, UNIT_21MX, "21MX", NULL, NULL }, { UNIT_EAU, UNIT_EAU, "EAU", "EAU", &cpu_set_opt, NULL, (void *) UNIT_EAU }, - { UNIT_EAU, 0, "NOEAU", "NOEAU", &cpu_set_opt, + { UNIT_EAU, 0, "no EAU", "NOEAU", &cpu_set_opt, NULL, (void *) UNIT_EAU }, { UNIT_FP, UNIT_FP, "FP", "FP", &cpu_set_opt, NULL, (void *) UNIT_FP }, - { UNIT_FP, 0, "NOFP", "NOFP", &cpu_set_opt, + { UNIT_FP, 0, "no FP", "NOFP", &cpu_set_opt, NULL, (void *) UNIT_FP }, { UNIT_MPR, UNIT_MPR, "MPR", "MPR", &cpu_set_opt, NULL, (void *) UNIT_MPR }, - { UNIT_MPR, 0, "NOMPR", "NOMPR", &cpu_set_opt, + { UNIT_MPR, 0, "no MPR", "NOMPR", &cpu_set_opt, NULL, (void *) UNIT_MPR }, { UNIT_DMS, UNIT_DMS, "DMS", "DMS", &cpu_set_opt, NULL, (void *) UNIT_DMS }, - { UNIT_DMS, 0, "NODMS", "NODMS", &cpu_set_opt, + { UNIT_DMS, 0, "no DMS", "NODMS", &cpu_set_opt, NULL, (void *) UNIT_DMS }, - { UNIT_IOP, UNIT_IOP, "IOP", "IOP", &cpu_set_opt, + { UNIT_MSIZE, 2, NULL, "IOP", &cpu_set_opt, NULL, (void *) UNIT_IOP }, - { UNIT_IOP, 0, "NOIOP", "NOIOP", &cpu_set_opt, + { UNIT_IOP+UNIT_IOPX, UNIT_IOP, "IOP", NULL, NULL }, + { UNIT_IOP+UNIT_IOPX, UNIT_IOPX, "IOP", NULL, NULL }, + { UNIT_IOP+UNIT_IOPX, 0, "no IOP", "NOIOP", &cpu_set_opt, NULL, (void *) UNIT_IOP }, { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, @@ -544,6 +551,7 @@ DEVICE dma1_dev = { #define E_21MX (UNIT_21MX >> (UNIT_V_UF - E_V_FL)) #define E_DMS (UNIT_DMS >> (UNIT_V_UF - E_V_FL)) #define E_IOP (UNIT_IOP >> (UNIT_V_UF - E_V_FL)) +#define E_IOPX (UNIT_IOPX >> (UNIT_V_UF - E_V_FL)) #define E_V_TY 8 /* type */ #define E_M_TY 0xF #define E_NO 0 /* no operands */ @@ -558,7 +566,7 @@ DEVICE dma1_dev = { #define ET_CN (E_CN << E_V_TY) #define ET_AC (E_AC << E_V_TY) #define ET_AZ (E_AZ << E_V_TY) -#define E_V_TYI 12 /* type if IOP */ +#define E_V_TYI 12 /* type if 2100 IOP */ #define E_GETFL(x) (((x) >> E_V_FL) & E_M_FL) #define E_GETTY(f,x) (((x) >> \ ((((f) & E_IOP) && (cpu_unit.flags & UNIT_IOP))? \ @@ -572,6 +580,9 @@ DEVICE dma1_dev = { #define D_NO E_DMS | ET_NO #define D_MR E_DMS | ET_AD #define D_AA E_DMS | ET_AA +#define M_NO E_IOPX | ET_NO +#define M_CN E_IOPX | ET_CN +#define M_AC E_IOPX | ET_AC #define I_NO E_IOP | (ET_NO << (E_V_TYI - E_V_TY)) #define I_CN E_IOP | (ET_CN << (E_V_TYI - E_V_TY)) #define I_AC E_IOP | (ET_AC << (E_V_TYI - E_V_TY)) @@ -591,17 +602,20 @@ static const uint32 e_inst[512] = { 0,0,0,0,0,0,0,0,I_CN,0,0,0,0,0,0,0, /* CRC */ I_CN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* TRSLT */ I_AZ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* WMOVE */ - I_NO,I_NO,I_NO,I_NO,0,0,0,0,0,0,0,0,0,0,0,0, /* READF,PFRIO,PFREI,PFRIO */ - I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,I_NO, /* ENQ,ENPQ */ + I_NO,I_NO,I_NO,I_NO,0,0,0,0,0,0,0,0,0,0,0,0, /* READF,PFRIO,PFREI,PFREX */ + I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,I_NO, /* ENQ,PENQ */ I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* DEQ */ I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SBYTE */ I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* LBYTE */ I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* REST */ 0,0,I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SAVE */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0400 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0420 */ + M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, /* LAI-/SAI- */ + M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, + M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, /* LAI+/SAI+ */ + M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0440 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0460 */ + M_CN,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_CN, /* CRC,REST,READF,INS,ENQ,PENQ,DEQ,TR */ + M_AC,M_NO,M_NO,M_NO,M_NO,0,0,0, /* ILIST,PFREI,PFREX,PFRIO,SAVE */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0500 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0520 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0540 */ @@ -921,8 +935,8 @@ case 0014:case 0015:case 0016:case 0017: t = (t + 1) & DMASK; if (t == 0) E = 1; if (t == SIGN) O = 1; } - if ((IR & 000002) && (t == 0)) skip = 1;/* SZx */ - } /* end if ~RSS */ + if ((IR & 000002) && (t == 0)) skip = 1; /* SZx */ + } /* end if ~RSS */ ABREG[absel] = t; /* store result */ PC = (PC + skip) & VAMASK; /* add in skip */ break; /* end if alter/skip */ @@ -1092,42 +1106,33 @@ case 0203:case 0213: /* MAC1 ext */ /* Floating point instructions */ case 0000: /* IOP ILIST/FAD */ - if (cpu_unit.flags & UNIT_IOP) { /* ILIST (E_AC) */ - do { /* for count */ - WriteW (MA, AR); /* write AR to mem */ - AR = (AR + 1) & DMASK; /* incr AR */ - MA = (MA + 1) & VAMASK; /* incr MA */ - wc = (wc - 1) & DMASK; } /* decr count */ - while (wc != 0); } - else { /* FAD (E_AD) */ - fop = ReadF (MA); /* get fop */ - O = f_as (fop, 0); } /* add, upd ovflo */ + if (cpu_unit.flags & UNIT_IOP) /* ILIST (E_AC) */ + goto IOP_ILIST; + fop = ReadF (MA); /* get fop */ + O = f_as (fop, 0); /* add, upd ovflo */ break; case 0020: /* IOP LAI-/FSB */ if (cpu_unit.flags & UNIT_IOP) /* LAI -20 (I_NO) */ - AR = ReadW ((BR - 020) & VAMASK); /* load AR */ - else { /* FSB (E_AD) */ - fop = ReadF (MA); /* get fop */ - O = f_as (fop, 1); } /* sub, upd ovflo */ + goto IOP_LAIM; + fop = ReadF (MA); /* get fop */ + O = f_as (fop, 1); /* sub, upd ovflo */ break; case 0040: /* IOP LAI+/FMP */ if (cpu_unit.flags & UNIT_IOP) /* LAI 0 (I_NO) */ - AR = ReadW (BR & VAMASK); /* load AR */ - else { /* FMP (E_AD) */ - fop = ReadF (MA); /* get fop */ - O = f_mul (fop); } /* mul, upd ovflo */ + goto IOP_LAIP; + fop = ReadF (MA); /* get fop */ + O = f_mul (fop); /* mul, upd ovflo */ break; case 0060: /* IOP SAI-/FDV */ if (cpu_unit.flags & UNIT_IOP) /* SAI -20 (I_NO) */ - WriteW ((BR - 020) & VAMASK, AR); /* store AR */ - else { /* FDV (E_AD) */ - fop = ReadF (MA); /* get fop */ - O = f_div (fop); } /* div, upd ovflo */ + goto IOP_SAIM; + fop = ReadF (MA); /* get fop */ + O = f_div (fop); /* div, upd ovflo */ break; case 0100: /* IOP SAI+/FIX */ if (cpu_unit.flags & UNIT_IOP) /* SAI 0 (I_NO) */ - WriteW (BR & VAMASK, AR); /* store AR */ - else O = f_fix (); /* FIX (E_NO) */ + goto IOP_SAIP; + O = f_fix (); /* FIX (E_NO) */ break; case 0120: /* IOP MBYTE/FLT */ if (cpu_unit.flags & UNIT_IOP) /* MBYTE (I_AZ) */ @@ -1135,30 +1140,30 @@ case 0203:case 0213: /* MAC1 ext */ O = f_flt (); /* FLT (E_NO) */ break; -/* IOP instructions */ +/* 2100 (and 21MX) IOP instructions */ - case 0021: case 0022: case 0023: /* IOP LAI- (I_NO) */ + IOP_LAIM: case 0021: case 0022: case 0023: /* IOP LAI- (I_NO) */ case 0024: case 0025: case 0026: case 0027: case 0030: case 0031: case 0032: case 0033: case 0034: case 0035: case 0036: case 0037: MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */ AR = ReadW (MA); /* load AR */ break; - case 0041: case 0042: case 0043: /* IOP LAI+ (I_NO) */ + IOP_LAIP: case 0041: case 0042: case 0043: /* IOP LAI+ (I_NO) */ case 0044: case 0045: case 0046: case 0047: case 0050: case 0051: case 0052: case 0053: case 0054: case 0055: case 0056: case 0057: MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */ AR = ReadW (MA); /* load AR */ break; - case 0061: case 0062: case 0063: /* IOP SAI- (I_NO) */ + IOP_SAIM: case 0061: case 0062: case 0063: /* IOP SAI- (I_NO) */ case 0064: case 0065: case 0066: case 0067: case 0070: case 0071: case 0072: case 0073: case 0074: case 0075: case 0076: case 0077: MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */ WriteW (MA, AR); /* store AR */ break; - case 0101: case 0102: case 0103: /* IOP SAI+ (I_NO) */ + IOP_SAIP: case 0101: case 0102: case 0103: /* IOP SAI+ (I_NO) */ case 0104: case 0105: case 0106: case 0107: case 0110: case 0111: case 0112: case 0113: case 0114: case 0115: case 0116: case 0117: @@ -1166,6 +1171,7 @@ case 0203:case 0213: /* MAC1 ext */ WriteW (MA, AR); /* store AR */ break; case 0150: /* IOP CRC (I_CN) */ + case 0460: /* IOPX CRC (I_CN) */ t = (AR & 0xFF) ^ wc; /* start CRC */ for (i = 0; i < 8; i++) { /* apply polynomial */ t = (t >> 1) | ((t & 1) << 15); /* rotate right */ @@ -1173,6 +1179,7 @@ case 0203:case 0213: /* MAC1 ext */ WriteW (awc, t); /* rewrite CRC */ break; case 0160: /* IOP TRSLT (I_CN) */ + case 0467: /* IOPX TRSLT (I_CN) */ if (wc & SIGN) break; /* cnt < 0? */ while (wc != 0) { /* loop */ MA = (AR + AR + ReadB (BR)) & VAMASK; @@ -1180,19 +1187,25 @@ case 0203:case 0213: /* MAC1 ext */ WriteB (BR, t); /* store char */ BR = (BR + 1) & DMASK; /* incr ptr */ wc = (wc - 1) & DMASK; /* decr cnt */ - WriteW (awc, wc); } + WriteW (awc, wc); + if (wc && intrq) { /* more and intr? */ + PC = err_PC; /* stop for now */ + break; } } break; case 0220: /* IOP READF (I_NO) */ - AR = mp_fence; /* copy mp_fence */ + case 0462: /* IOPX READF (I_NO) */ + AR = iop_sp; /* copy stk ptr */ break; case 0221: /* IOP PRFIO (I_NO) */ + case 0473: /* IOPX PFRIO (I_NO) */ IR = ReadW (PC); /* get IO instr */ PC = (PC + 1) & VAMASK; WriteW (PC, 1); /* set flag */ PC = (PC + 1) & VAMASK; reason = iogrp (IR, 0); /* execute instr */ break; - case 0222: /* IOP PRFIE (I_NO) */ + case 0222: /* IOP PRFEI (I_NO) */ + case 0471: /* IOPX PFREI (I_NO) */ IR = ReadW (PC); /* get IO instr */ PC = (PC + 1) & VAMASK; WriteW (PC, 1); /* set flag */ @@ -1200,12 +1213,14 @@ case 0203:case 0213: /* MAC1 ext */ reason = iogrp (IR, 0); /* execute instr */ /* fall through */ case 0223: /* IOP PRFEX (I_NO) */ + case 0472: /* IOPX PFREX (I_NO) */ MA = ReadW (PC); /* exit addr */ PCQ_ENTRY; PC = ReadW (MA) & VAMASK; /* jump indirect */ WriteW (MA, 0); /* clear exit */ break; case 0240: /* IOP ENQ (I_NO) */ + case 0464: /* IOPX ENQ (I_NO) */ hp = ReadW (AR & VAMASK); /* addr of head */ tp = ReadW ((AR + 1) & VAMASK); /* addr of tail */ WriteW ((BR - 1) & VAMASK, 0); /* entry link */ @@ -1213,7 +1228,8 @@ case 0203:case 0213: /* MAC1 ext */ WriteW ((AR + 1) & VAMASK, BR); /* queue tail */ if (hp != 0) PC = (PC + 1) & VAMASK; /* q not empty? skip */ break; - case 0257: /* IOP ENQP (I_NO) */ + case 0257: /* IOP PENQ (I_NO) */ + case 0465: /* IOPX PENQ (I_NO) */ hp = ReadW (AR & VAMASK); /* addr of head */ WriteW ((BR - 1) & VAMASK, hp); /* becomes entry link */ WriteW (AR & VAMASK, BR); /* queue head */ @@ -1222,6 +1238,7 @@ case 0203:case 0213: /* MAC1 ext */ else PC = (PC + 1) & VAMASK; /* skip */ break; case 0260: /* IOP DEQ (I_NO) */ + case 0466: /* IOPX DEQ (I_NO) */ BR = ReadW (AR & VAMASK); /* addr of head */ if (BR) { /* queue not empty? */ hp = ReadW ((BR - 1) & VAMASK); /* read hd entry link */ @@ -1239,23 +1256,56 @@ case 0203:case 0213: /* MAC1 ext */ BR = (BR + 1) & DMASK; /* incr ptr */ break; case 0340: /* IOP REST (I_NO) */ - mp_fence = (mp_fence - 1) & VAMASK; /* pop E/~O,BR,AR */ - t = ReadW (mp_fence); + case 0461: /* IOPX REST (I_NO) */ + iop_sp = (iop_sp - 1) & VAMASK; /* pop E/~O,BR,AR */ + t = ReadW (iop_sp); O = ((t >> 1) ^ 1) & 1; E = t & 1; - mp_fence = (mp_fence - 1) & VAMASK; - BR = ReadW (mp_fence); - mp_fence = (mp_fence - 1) & VAMASK; - AR = ReadW (mp_fence); + iop_sp = (iop_sp - 1) & VAMASK; + BR = ReadW (iop_sp); + iop_sp = (iop_sp - 1) & VAMASK; + AR = ReadW (iop_sp); + if (cpu_unit.flags & UNIT_2100) mp_fence = iop_sp; break; case 0362: /* IOP SAVE (I_NO) */ - WriteW (mp_fence, AR); /* push AR,BR,E/~O */ - mp_fence = (mp_fence + 1) & VAMASK; - WriteW (mp_fence, BR); - mp_fence = (mp_fence + 1) & VAMASK; + case 0474: /* IOPX SAVE (I_NO) */ + WriteW (iop_sp, AR); /* push AR,BR,E/~O */ + iop_sp = (iop_sp + 1) & VAMASK; + WriteW (iop_sp, BR); + iop_sp = (iop_sp + 1) & VAMASK; t = ((O ^ 1) << 1) | E; - WriteW (mp_fence, t); - mp_fence = (mp_fence + 1) & VAMASK; + WriteW (iop_sp, t); + iop_sp = (iop_sp + 1) & VAMASK; + if (cpu_unit.flags & UNIT_2100) mp_fence = iop_sp; + break; + + case 0400: case 0401: case 0402: case 0403: /* IOPX LAI-/SAI- (I_NO) */ + case 0404: case 0405: case 0406: case 0407: + case 0410: case 0411: case 0412: case 0413: + case 0414: case 0415: case 0416: case 0417: + MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */ + if (IR & I_AB) AR = ReadW (MA); /* AB = 1? LAI */ + else WriteW (MA, AR); /* AB = 0? SAI */ + break; + case 0420: case 0421: case 0422: case 0423: /* IOPX LAI+/SAI+ (I_NO) */ + case 0424: case 0425: case 0426: case 0427: + case 0430: case 0431: case 0432: case 0433: + case 0434: case 0435: case 0436: case 0437: + MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */ + if (IR & I_AB) AR = ReadW (MA); /* AB = 1? LAI */ + else WriteW (MA, AR); /* AB = 0? SAI */ + break; + case 0463: /* IOPX INS (I_NO) */ + iop_sp = AR; /* init stk ptr */ + break; + case 0470: /* IOPX ILIST (I_CN) */ + IOP_ILIST: + do { /* for count */ + WriteW (MA, AR); /* write AR to mem */ + AR = (AR + 1) & DMASK; /* incr AR */ + MA = (MA + 1) & VAMASK; /* incr MA */ + wc = (wc - 1) & DMASK; } /* decr count */ + while (wc != 0); break; /* DMS instructions, move alternate - interruptible @@ -2220,6 +2270,7 @@ case ioLIX: /* load */ break; case ioOTX: /* output */ mp_fence = dat & VAMASK; + if (cpu_unit.flags & UNIT_2100) iop_sp = mp_fence; break; case ioCTL: /* control clear/set */ if ((IR & I_CTL) == 0) { /* STC */ @@ -2420,6 +2471,8 @@ else M[addr] = val & DMASK; return SCPE_OK; } +/* Memory size validation */ + t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 mc = 0; @@ -2515,11 +2568,14 @@ mod = MOD_2116; if (uptr->flags & UNIT_2100) mod = MOD_2100; else if (uptr->flags & UNIT_21MX) mod = MOD_21MX; for (i = 0; opt_val[i].optf != 0; i++) { - if ((val == opt_val[i].optf) && (mod & opt_val[i].cpuf)) { - if (mod == MOD_2100) { - if (val == UNIT_FP) uptr->flags = uptr->flags & ~UNIT_IOP; - if (val == UNIT_IOP) uptr->flags = uptr->flags & ~UNIT_FP; } - if (val == UNIT_DMS) uptr->flags = uptr->flags | UNIT_MPR; + if ((opt == opt_val[i].optf) && (mod & opt_val[i].cpuf)) { + if ((mod == MOD_2100) && (val == UNIT_FP)) + uptr->flags = uptr->flags & ~UNIT_IOP; + if ((opt == UNIT_IOP) && val) { + if (mod == MOD_2100) uptr->flags = + (uptr->flags & ~UNIT_FP) | UNIT_IOP | UNIT_MPR; + if (mod == MOD_21MX) uptr->flags |= UNIT_IOPX | UNIT_MPR; } + if (val == UNIT_DMS) uptr->flags |= UNIT_MPR; return SCPE_OK; } } return SCPE_NOFNC; } diff --git a/HP2100/hp2100_defs.h b/HP2100/hp2100_defs.h index b820de8c..660a0a18 100644 --- a/HP2100/hp2100_defs.h +++ b/HP2100/hp2100_defs.h @@ -45,6 +45,7 @@ #define STOP_IBKPT 4 /* breakpoint */ #define STOP_IND 5 /* indirect loop */ #define STOP_INDINT 6 /* indirect intr */ +#define STOP_NOCONN 7 /* no connection */ #define ABORT_PRO 1 /* protection abort */ @@ -207,6 +208,8 @@ struct DMA { /* DMA channel */ #define DRC 027 /* 12610A control */ #define MSD 030 /* 13181A data */ #define MSC 031 /* 13181A control */ +#define IPLI 032 /* 12556B link in */ +#define IPLO 033 /* 12556B link out */ #define MUXL 040 /* 12920A lower data */ #define MUXU 041 /* 12920A upper data */ #define MUXC 042 /* 12920A control */ diff --git a/HP2100/hp2100_diag.txt b/HP2100/hp2100_diag.txt index ac9e03e7..18abb79a 100644 --- a/HP2100/hp2100_diag.txt +++ b/HP2100/hp2100_diag.txt @@ -1,3 +1,5 @@ +HP2100 Diagnostics + CPU status writeup sources 24315 Memory reference group passed in 21MX CE no @@ -32,7 +34,27 @@ CPU status writeup sources - prints diagnostic name - prints END OF PASS 1 and halts -13206 IOP for 2100 group passed 13206 manual no +13206 IOP for 2100 passed 13206 manual no + - load diagnostic via configurator + - D S 0 + - SET CPU 2100 + - SET CPU IOP + - RUN 2000 + - prints diagnostic name + - prints section names, PASS 000001, and halts + - note: will not pass interruptibility tests + +13207 IOP for 21MX passed 13207 manual no + - load diagnostic via configurator + - D S 13 + - SET CPU 21MX + - SET CPU IOP + - RUN 100 + - HLT 74, PC = 2425 + - D S 0 + - CON + - prints diagnostic name + - prints section names, PASS 000001, and halts 24320 Floating point passed in 21MX CE no - load diagnostic via configurator diff --git a/HP2100/hp2100_doc.txt b/HP2100/hp2100_doc.txt index 5f4d75c4..58b77bb2 100644 --- a/HP2100/hp2100_doc.txt +++ b/HP2100/hp2100_doc.txt @@ -51,6 +51,7 @@ sim/hp2100/ hp2100_defs.h hp2100_dp.c hp2100_dq.c hp2100_dr.c + hp2100_ipl.c hp2100_lps.c hp2100_lpt.c hp2100_mt.c @@ -85,6 +86,8 @@ DR 12606B fixed head disk controller with 2770/2771 disks MT 12559C magnetic tape controller with one 3030 drive MS 13181A magnetic tape controller with four 7970B drives 13183A magnetic tape controller with four 7970E drives +IPLI 12556B interprocessor link, input side +IPLO 12556B interprocessor link, output side The HP2100 simulator implements several unique stop conditions: @@ -107,8 +110,8 @@ CPU options include choice of instruction set and memory size. SET CPU NOEAU no EAU instructions (2116 only) SET CPU FP FP instructions (2100 only) SET CPU NOFP no FP instructions (2100 only) - SET CPU IOP IOP instructions (2100 only) - SET CPU NOIOP no IOP instructions (2100 only) + SET CPU IOP IOP instructions (2100, 21MX only) + SET CPU NOIOP no IOP instructions (2100, 21MX only) SET CPU DMS DMS instructions (21MX only) SET CPU NODMS no DMS instructions (21MX only) SET CPU 4K set memory size = 4K @@ -505,6 +508,62 @@ The modem control (MUXM) implements these registers: The terminal multiplexor does not support save and restore. All open connections are lost when the simulator shuts down or MUXU is detached. +2.4.8 Interprocessor Link (IPLI, IPLO) + +The interprocessor link is a pair of 12556B parallel interfaces that +are cross coupled to provide interprocessor communications to a second +copy of the HP2100 simulator. The IPL is intended to support simulation +of a two system HP TimeShared Basic configuration. The links are actually +bidirectional half-duplex; TimeShared Basic uses them unidirectionally. +The IPL is disabled by default. + +To operate, the IPL devices must be enabled and then connected to the IPL +devices in another copy of the simulator. The IPLI device in the first +simulator is connected to the IPLO device in the second, and vice versa. +Connections are established with the ATTACH command. One copy of the +simulator listens for connections on a specified port (ATTACH -L); the +other establishes connections to an IP address and port (ATTACH -C). +Either copy may perform either operation, but the operations must be +done in matched pairs: + + simulator #1 simulator #2 + + sim> set ipli ena sim> set ipli ena + (also enables iplo) (also enables iplo) + sim> att -lw ipli 4000 + Listening on port 4000 + Waiting for connection + sim> att -c iplo 4000 + Connection established Connected to 127.0.0.1 port 4000 + sim> att -lw iplo 4000 + Listening on port 4001 + Waiting for connection + sim> att -c ipli 4001 + Connection established Connected to 127.0.0.1 port 4000 + +Both forms of ATTACH take a modifier -W (wait); if specified, the command +will wait up to 30 seconds for the connection process to complete. ATTACH +-C can specify both an IP address and a port, in the form aa.bb.cc.dd:port; +if the IP address is omitted, it defaults to 127.0.0.1 (local system). + +Both IPLI and IPLO implement the BOOT command. BOOT loads the HP Access +Basic Block Loader for the IOP into the top 64 words of memory and starts +it running. + +Both IPLI and IPLO implement these registers: + + name size comments + + BUF 16 buffer + HOLD 8 holding buffer + CMD 1 device enable + CTL 1 device/interrupt enable + FLG 1 device ready + FBF 1 device ready buffer + TIME 24 polling interval for input + STOP_IOE 1 stop on I/O error + + 2.5 12557A Disk Controller (DPC, DPD) with 2781 Drives 13210A Disk Controller (DPC, DPD) with 7900 Drives diff --git a/HP2100/hp2100_dp.c b/HP2100/hp2100_dp.c index deebad73..5187f9f3 100644 --- a/HP2100/hp2100_dp.c +++ b/HP2100/hp2100_dp.c @@ -119,8 +119,8 @@ #define STA_MBZ13 (STA_ATN + STA_RWU + STA_SKI) /* zero in 13210 */ extern uint16 *M; -extern int32 PC, SR; -extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; +extern uint32 PC, SR; +extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; extern int32 sim_switches; extern UNIT cpu_unit; @@ -702,8 +702,8 @@ return SCPE_OK; /* 7900/7901 bootstrap routine (HP 12992F ROM) */ +#define LDR_BASE 077 #define CHANGE_DEV (1 << 24) -#define CHANGE_ADDR (1 << 23) static const int32 dboot[IBL_LNT] = { 0106700+CHANGE_DEV, /*ST CLC DC ; clr dch */ @@ -766,7 +766,7 @@ static const int32 dboot[IBL_LNT] = { 0027700, /* JMP ST ; no, retry */ 0117751, /*XT JSB ADDR2,I ; start program */ 0120000+CHANGE_DEV, /*DMACW 120000+DC */ - CHANGE_ADDR }; /* -ST */ + 0000000 }; /* -ST */ t_stat dpc_boot (int32 unitno, DEVICE *dptr) { @@ -778,11 +778,10 @@ PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ SR = IBL_DP + (dev << IBL_V_DEV); /* set SR */ if (sim_switches & SWMASK ('F')) SR = SR | IBL_FIX; /* boot from fixed? */ for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ - if (dboot[i] & CHANGE_ADDR) /* memory limit? */ - M[PC + i] = (-PC) & DMASK; - else if (dboot[i] & CHANGE_DEV) /* IO instr? */ + if (dboot[i] & CHANGE_DEV) /* IO instr? */ M[PC + i] = (dboot[i] + dev) & DMASK; - else M[PC + i] = dboot[i]; } + else M[PC + i] = dboot[i]; } +M[PC + LDR_BASE] = (~PC + 1) & DMASK; return SCPE_OK; } diff --git a/HP2100/hp2100_dq.c b/HP2100/hp2100_dq.c index a1c36051..b40e54cd 100644 --- a/HP2100/hp2100_dq.c +++ b/HP2100/hp2100_dq.c @@ -104,8 +104,8 @@ #define STA_ALLERR (STA_NRDY + STA_EOC + STA_AER + STA_FLG + STA_DTE) extern uint16 *M; -extern int32 PC, SR; -extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; +extern uint32 PC, SR; +extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; extern int32 sim_switches; extern UNIT cpu_unit; @@ -654,8 +654,8 @@ return SCPE_OK; /* 2883/2884 bootstrap routine (subset HP 12992A ROM) */ +#define LDR_BASE 077 #define CHANGE_DEV (1 << 24) -#define CHANGE_ADDR (1 << 23) static const int32 dboot[IBL_LNT] = { 0106700+CHANGE_DEV, /*ST CLC DC ; clr dch */ @@ -698,7 +698,7 @@ static const int32 dboot[IBL_LNT] = { 0164000, /*CNT -6144. */ 0117773, /*XT JSB ADDR2,I ; start program */ 0120000+CHANGE_DEV, /*DMACW 120000+DC */ - CHANGE_ADDR }; /* -ST */ + 0000000 }; /* -ST */ t_stat dqc_boot (int32 unitno, DEVICE *dptr) { @@ -709,10 +709,9 @@ dev = dqd_dib.devno; /* get data chan dev */ PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ SR = IBL_DQ + (dev << IBL_V_DEV); /* set SR */ for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ - if (dboot[i] & CHANGE_ADDR) /* memory limit? */ - M[PC + i] = (-PC) & DMASK; - else if (dboot[i] & CHANGE_DEV) /* IO instr? */ + if (dboot[i] & CHANGE_DEV) /* IO instr? */ M[PC + i] = (dboot[i] + dev) & DMASK; else M[PC + i] = dboot[i]; } +M[PC + LDR_BASE] = (~PC + 1) & DMASK; return SCPE_OK; } diff --git a/HP2100/hp2100_dr.c b/HP2100/hp2100_dr.c index cefb6655..c472f00a 100644 --- a/HP2100/hp2100_dr.c +++ b/HP2100/hp2100_dr.c @@ -94,8 +94,8 @@ extern UNIT cpu_unit; extern uint16 *M; -extern int32 PC; -extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; +extern uint32 PC; +extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; int32 drc_cw = 0; /* fnc, addr */ int32 drc_sta = 0; /* status */ diff --git a/HP2100/hp2100_ipl.c b/HP2100/hp2100_ipl.c new file mode 100644 index 00000000..a1fbfa43 --- /dev/null +++ b/HP2100/hp2100_ipl.c @@ -0,0 +1,465 @@ +/* hp2100_ipl.c: HP 2000 interprocessor link simulator + + Copyright (c) 2002, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + ipli, iplo 12556B interprocessor link pair +*/ + +#include "hp2100_defs.h" +#include "sim_sock.h" +#include "sim_tmxr.h" + +#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */ +#define UNIT_V_ACTV (UNIT_V_UF + 1) /* making connection */ +#define UNIT_V_ESTB (UNIT_V_UF + 2) /* connection established */ +#define UNIT_DIAG (1 << UNIT_V_DIAG) +#define UNIT_ACTV (1 << UNIT_V_ACTV) +#define UNIT_ESTB (1 << UNIT_V_ESTB) +#define DSOCKET u3 /* data socket */ +#define LSOCKET u4 /* listening socket */ +#define HOLD wait /* holding byte */ +#define IPL_HOLD 0100000 + +extern uint32 PC; +extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; +extern FILE *sim_log; +int32 ipl_ptime = 400; /* polling interval */ +int32 ipl_stopioe = 0; /* stop on error */ + +DEVICE ipli_dev, iplo_dev; +int32 ipliio (int32 inst, int32 IR, int32 dat); +int32 iploio (int32 inst, int32 IR, int32 dat); +int32 iplio (UNIT *uptr, int32 inst, int32 IR, int32 dat); +t_stat ipl_svc (UNIT *uptr); +t_stat ipl_reset (DEVICE *dptr); +t_stat ipl_attach (UNIT *uptr, char *cptr); +t_stat ipl_detach (UNIT *uptr); +t_stat ipl_boot (int32 unitno, DEVICE *dptr); +t_stat ipl_dscln (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat ipl_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc); +t_bool ipl_check_conn (UNIT *uptr); + +/* IPLI data structures + + ipli_dev IPLI device descriptor + ipli_unit IPLI unit descriptor + ipli_reg IPLI register list +*/ + +DIB ipl_dib[] = { + { IPLI, 0, 0, 0, 0, &ipliio }, + { IPLO, 0, 0, 0, 0, &iploio } }; + +#define ipli_dib ipl_dib[0] +#define iplo_dib ipl_dib[1] + +UNIT ipl_unit[] = { + { UDATA (&ipl_svc, UNIT_ATTABLE, 0) }, + { UDATA (&ipl_svc, UNIT_ATTABLE, 0) } }; + +#define ipli_unit ipl_unit[0] +#define iplo_unit ipl_unit[1] + +REG ipli_reg[] = { + { ORDATA (BUF, ipli_unit.buf, 16) }, + { FLDATA (CMD, ipli_dib.cmd, 0) }, + { FLDATA (CTL, ipli_dib.ctl, 0) }, + { FLDATA (FLG, ipli_dib.flg, 0) }, + { FLDATA (FBF, ipli_dib.fbf, 0) }, + { ORDATA (HOLD, ipli_unit.HOLD, 16) }, + { DRDATA (TIME, ipl_ptime, 24), PV_LEFT }, + { FLDATA (STOP_IOE, ipl_stopioe, 0) }, + { ORDATA (DEVNO, ipli_dib.devno, 6), REG_HRO }, + { NULL } }; + +MTAB ipl_mod[] = { + { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", &ipl_setdiag }, + { UNIT_DIAG, 0, "link mode", "LINK", &ipl_setdiag }, + { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", + &ipl_dscln, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", + &hp_setdev, &hp_showdev, &ipli_dev }, + { 0 } }; + +DEVICE ipli_dev = { + "IPLI", &ipli_unit, ipli_reg, ipl_mod, + 1, 10, 31, 1, 16, 16, + &tmxr_ex, &tmxr_dep, &ipl_reset, + &ipl_boot, &ipl_attach, &ipl_detach, + &ipli_dib, DEV_DISABLE | DEV_DIS }; + +/* IPLO data structures + + iplo_dev IPLO device descriptor + iplo_unit IPLO unit descriptor + iplo_reg IPLO register list +*/ + +REG iplo_reg[] = { + { ORDATA (BUF, iplo_unit.buf, 16) }, + { FLDATA (CMD, iplo_dib.cmd, 0) }, + { FLDATA (CTL, iplo_dib.ctl, 0) }, + { FLDATA (FLG, iplo_dib.flg, 0) }, + { FLDATA (FBF, iplo_dib.fbf, 0) }, + { ORDATA (HOLD, iplo_unit.HOLD, 16) }, + { DRDATA (TIME, ipl_ptime, 24), PV_LEFT }, + { ORDATA (DEVNO, iplo_dib.devno, 6), REG_HRO }, + { NULL } }; + +DEVICE iplo_dev = { + "IPLO", &iplo_unit, iplo_reg, ipl_mod, + 1, 10, 31, 1, 16, 16, + &tmxr_ex, &tmxr_dep, &ipl_reset, + &ipl_boot, &ipl_attach, &ipl_detach, + &iplo_dib, DEV_DISABLE | DEV_DIS }; + +/* Interprocessor link I/O routines */ + +int32 ipliio (int32 inst, int32 IR, int32 dat) +{ +return iplio (&ipli_unit, inst, IR, dat); +} + +int32 iploio (int32 inst, int32 IR, int32 dat) +{ +return iplio (&iplo_unit, inst, IR, dat); +} + +int32 iplio (UNIT *uptr, int32 inst, int32 IR, int32 dat) +{ +uint32 u, dev, odev; +int32 sta; +int8 msg[2]; + +dev = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ +case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ + break; +case ioSFC: /* skip flag clear */ + if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + return dat; +case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + return dat; +case ioOTX: /* output */ + uptr->buf = dat; + break; +case ioLIX: /* load */ + dat = uptr->buf; /* return val */ + break; +case ioMIX: /* merge */ + dat = dat | uptr->buf; /* get return data */ + break; +case ioCTL: /* control clear/set */ + if (IR & I_CTL) { /* CLC */ + clrCMD (dev); /* clear ctl, cmd */ + clrCTL (dev); } + else { /* STC */ + setCMD (dev); /* set ctl, cmd */ + setCTL (dev); + if (uptr->flags & UNIT_ATT) { /* attached? */ + if ((uptr->flags & UNIT_ESTB) == 0) { /* established? */ + if (!ipl_check_conn (uptr)) /* not established? */ + return STOP_NOCONN; /* lose */ + uptr->flags = uptr->flags | UNIT_ESTB; } + msg[0] = (uptr->buf >> 8) & 0377; + msg[1] = uptr->buf & 0377; + sta = sim_write_sock (uptr->DSOCKET, msg, 2); + if (sta == SOCKET_ERROR) { + printf ("IPL: socket write error\n"); + return SCPE_IOERR; } + sim_os_sleep (0); } + else if (uptr->flags & UNIT_DIAG) { /* diagnostic mode? */ + u = (uptr - ipl_unit) ^ 1; /* find other device */ + ipl_unit[u].buf = uptr->buf; /* output to other */ + odev = ipl_dib[u].devno; /* other device no */ + setFLG (odev); } /* set other flag */ + else return SCPE_UNATT; } /* lose */ + break; +default: + break; } +if (IR & I_HC) { clrFLG (dev); } /* H/C option */ +return dat; +} + +/* Unit service - poll for input */ + +t_stat ipl_svc (UNIT *uptr) +{ +int32 u, nb, dev; +int8 msg[2]; + +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* not attached? */ +sim_activate (uptr, ipl_ptime); /* reactivate */ +if ((uptr->flags & UNIT_ESTB) == 0) { /* not established? */ + if (!ipl_check_conn (uptr)) return SCPE_OK; /* check for conn */ + uptr->flags = uptr->flags | UNIT_ESTB; } +nb = sim_read_sock (uptr->DSOCKET, msg, uptr->HOLD? 1: 2); +if (nb < 0) { /* connection closed? */ + printf ("IPL: socket read error\n"); + return SCPE_IOERR; } +if (nb == 0) return SCPE_OK; /* no data? */ +if (uptr->HOLD) { /* holdover byte? */ + uptr->buf = ((uptr->HOLD & 0377) << 8) | (((int32) msg[0]) & 0377); + uptr->HOLD = 0; } +else if (nb == 1) uptr->HOLD = (((int32) msg[0]) & 0377) | IPL_HOLD; +else uptr->buf = ((((int32) msg[0]) & 0377) << 8) | + (((int32) msg[1]) & 0377); +u = uptr - ipl_unit; /* get link number */ +dev = ipl_dib[u].devno; /* get device number */ +clrCMD (dev); /* clr cmd, set flag */ +setFLG (dev); +return SCPE_OK; +} + +t_bool ipl_check_conn (UNIT *uptr) +{ +SOCKET sock; + +if (uptr->flags & UNIT_ESTB) return TRUE; /* established? */ +if (uptr->flags & UNIT_ACTV) { /* active connect? */ + if (sim_check_conn (uptr->DSOCKET, 0) <= 0) return FALSE; } +else { sock = sim_accept_conn (uptr->LSOCKET, NULL); /* poll connect */ + if (sock == INVALID_SOCKET) return FALSE; /* got a live one? */ + uptr->DSOCKET = sock; } /* save data socket */ +uptr->flags = uptr->flags | UNIT_ESTB; /* conn established */ +return TRUE; +} + +/* Reset routine */ + +t_stat ipl_reset (DEVICE *dptr) +{ +DIB *dibp = (DIB *) dptr->ctxt; +UNIT *uptr = dptr->units; + +hp_enbdis_pair (&ipli_dev, &iplo_dev); /* make pair cons */ +dibp->cmd = dibp->ctl = 0; /* clear cmd, ctl */ +dibp->flg = dibp->fbf = 1; /* set flg, fbf */ +uptr->buf = uptr->HOLD = 0; +if (uptr->flags & UNIT_ATT) sim_activate (uptr, ipl_ptime); +else sim_cancel (uptr); /* deactivate unit */ +return SCPE_OK; +} + +/* Attach routine + + attach -l - listen for connection on port + attach -c - connect to ip address and port +*/ + +t_stat ipl_attach (UNIT *uptr, char *cptr) +{ +extern int32 sim_switches; +SOCKET newsock; +uint32 i, t, ipa, ipp, oldf; +char *tptr; +t_stat r; + +r = get_ipaddr (cptr, &ipa, &ipp); +if ((r != SCPE_OK) || (ipp == 0)) return SCPE_ARG; +oldf = uptr->flags; +if (oldf & UNIT_ATT) ipl_detach (uptr); +if ((sim_switches & SWMASK ('C')) || + ((sim_switches & SIM_SW_REST) && (oldf & UNIT_ACTV))) { + if (ipa == 0) ipa = 0x7F000001; + newsock = sim_connect_sock (ipa, ipp); + if (newsock == INVALID_SOCKET) return SCPE_IOERR; + printf ("Connecting to IP address %d.%d.%d.%d, port %d\n", + (ipa >> 24) & 0xff, (ipa >> 16) & 0xff, + (ipa >> 8) & 0xff, ipa & 0xff, ipp); + if (sim_log) fprintf (sim_log, + "Connecting to IP address %d.%d.%d.%d, port %d\n", + (ipa >> 24) & 0xff, (ipa >> 16) & 0xff, + (ipa >> 8) & 0xff, ipa & 0xff, ipp); + uptr->flags = uptr->flags | UNIT_ACTV; + uptr->LSOCKET = 0; + uptr->DSOCKET = newsock; } +else { if (ipa != 0) return SCPE_ARG; + newsock = sim_master_sock (ipp); + if (newsock == INVALID_SOCKET) return SCPE_IOERR; + printf ("Listening on port %d\n", ipp); + if (sim_log) fprintf (sim_log, "Listening on port %d\n", ipp); + uptr->flags = uptr->flags & ~UNIT_ACTV; + uptr->LSOCKET = newsock; + uptr->DSOCKET = 0; } +uptr->buf = uptr->HOLD = 0; +uptr->flags = (uptr->flags | UNIT_ATT) & ~UNIT_ESTB; /* no more errors */ +tptr = malloc (strlen (cptr) + 1); /* get string buf */ +if (tptr == NULL) { /* no memory? */ + ipl_detach (uptr); /* close sockets */ + return SCPE_MEM; } +strcpy (tptr, cptr); /* copy ipaddr:port */ +uptr->filename = tptr; /* save */ +sim_activate (uptr, ipl_ptime); /* activate poll */ +if (sim_switches & SWMASK ('W')) { /* wait? */ + for (i = 0; i < 30; i++) { /* check for 30 sec */ + if (t = ipl_check_conn (uptr)) break; /* established? */ + if ((i % 10) == 0) /* status every 10 sec */ + printf ("Waiting for connnection\n"); + sim_os_sleep (1); } /* sleep 1 sec */ + if (t) printf ("Connection established\n"); } +return SCPE_OK; +} + +/* Detach routine */ + +t_stat ipl_detach (UNIT *uptr) +{ +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +if (uptr->flags & UNIT_ACTV) sim_close_sock (uptr->DSOCKET, 1); +else { if (uptr->flags & UNIT_ESTB) /* if established, */ + sim_close_sock (uptr->DSOCKET, 0); /* close data socket */ + sim_close_sock (uptr->LSOCKET, 1); } /* closen listen socket */ +free (uptr->filename); /* free string */ +uptr->filename = NULL; +uptr->LSOCKET = 0; +uptr->DSOCKET = 0; +uptr->flags = uptr->flags & ~(UNIT_ATT | UNIT_ACTV | UNIT_ESTB); +sim_cancel (uptr); /* don't poll */ +return SCPE_OK; +} + +/* Disconnect routine */ + +t_stat ipl_dscln (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (cptr) return SCPE_ARG; +if (((uptr->flags & UNIT_ATT) == 0) || (uptr->flags & UNIT_ACTV) || + ((uptr->flags & UNIT_ESTB) == 0)) return SCPE_NOFNC; +sim_close_sock (uptr->DSOCKET, 0); +uptr->DSOCKET = 0; +uptr->flags = uptr->flags & ~UNIT_ESTB; +return SCPE_OK; +} + +/* Diagnostic/normal mode routine */ + +t_stat ipl_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (val) { + ipli_unit.flags = ipli_unit.flags | UNIT_DIAG; + iplo_unit.flags = iplo_unit.flags | UNIT_DIAG; } +else { ipli_unit.flags = ipli_unit.flags & ~UNIT_DIAG; + iplo_unit.flags = iplo_unit.flags & ~UNIT_DIAG; } +return SCPE_OK; +} + +/* Interprocessor link bootstrap routine (HP Access Manual) */ + +#define LDR_BASE 073 +#define IPL_PNTR 074 +#define PTR_PNTR 075 +#define IPL_DEVA 076 +#define PTR_DEVA 077 + +static const int32 pboot[IBL_LNT] = { + 0163774, /*BBL LDA ICK,I ; IPL sel code */ + 0027751, /* JMP CFG ; go configure */ + 0107700, /*ST CLC 0,C ; intr off */ + 0002702, /* CLA,CCE,SZA ; skip in */ + 0063772, /*CN LDA M26 ; feed frame */ + 0002307, /*EOC CCE,INA,SZA,RSS ; end of file? */ + 0027760, /* JMP EOT ; yes */ + 0017736, /* JSB READ ; get #char */ + 0007307, /* CMB,CCE,INB,SZB,RSS ; 2's comp; null? */ + 0027705, /* JMP EOC ; read next */ + 0077770, /* STB WC ; word in rec */ + 0017736, /* JSB READ ; get feed frame */ + 0017736, /* JSB READ ; get address */ + 0074000, /* STB 0 ; init csum */ + 0077771, /* STB AD ; save addr */ + 0067771, /*CK LDB AD ; check addr */ + 0047773, /* ADB MAXAD ; below loader */ + 0002040, /* SEZ ; E =0 => OK */ + 0102055, /* HLT 55 */ + 0017736, /* JSB READ ; get word */ + 0040001, /* ADA 1 ; cont checksum */ + 0177771, /* STB AD,I ; store word */ + 0037771, /* ISZ AD */ + 0000040, /* CLE ; force wd read */ + 0037770, /* ISZ WC ; block done? */ + 0027717, /* JMP CK ; no */ + 0017736, /* JSB READ ; get checksum */ + 0054000, /* CPB 0 ; ok? */ + 0027704, /* JMP CN ; next block */ + 0102011, /* HLT 11 ; bad csum */ + 0000000, /*RD 0 */ + 0006600, /* CLB,CME ; E reg byte ptr */ + 0103700, /*IO1 STC RDR,C ; start reader */ + 0102300, /*IO2 SFS RDR ; wait */ + 0027741, /* JMP *-1 */ + 0106400, /*IO3 MIB RDR ; get byte */ + 0002041, /* SEZ,RSS ; E set? */ + 0127736, /* JMP RD,I ; no, done */ + 0005767, /* BLF,CLE,BLF ; shift byte */ + 0027740, /* JMP IO1 ; again */ + 0163775, /* LDA PTR,I ; get ptr code */ + 0043765, /*CFG ADA SFS ; config IO */ + 0073741, /* STA IO2 */ + 0043766, /* ADA STC */ + 0073740, /* STA IO1 */ + 0043767, /* ADA MIB */ + 0073743, /* STA IO3 */ + 0027702, /* JMP ST */ + 0063777, /*EOT LDA PSC ; put select codes */ + 0067776, /* LDB ISC ; where xloader wants */ + 0102077, /* HLT 77 */ + 0027702, /* JMP ST */ + 0000000, /* NOP */ + 0102300, /*SFS SFS 0 */ + 0001400, /*STC 1400 */ + 0002500, /*MIB 2500 */ + 0000000, /*WC 0 */ + 0000000, /*AD 0 */ + 0177746, /*M26 -26 */ + 0000000, /*MAX -BBL */ + 0007776, /*ICK ISC */ + 0007777, /*PTR IPT */ + 0000000, /*ISC 0 */ + 0000000 /*IPT 0 */ +}; + +t_stat ipl_boot (int32 unitno, DEVICE *dptr) +{ +int32 i, devi, devp; +extern DIB ptr_dib; +extern UNIT cpu_unit; +extern uint32 SR; +extern uint16 *M; + +devi = ipli_dib.devno; /* get device no */ +devp = ptr_dib.devno; +PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ +SR = (devi << IBL_V_DEV) | devp; /* set SR */ +for (i = 0; i < IBL_LNT; i++) M[PC + i] = pboot[i]; /* copy bootstrap */ +M[PC + LDR_BASE] = (~PC + 1) & DMASK; /* fix ups */ +M[PC + IPL_PNTR] = M[PC + IPL_PNTR] | PC; +M[PC + PTR_PNTR] = M[PC + PTR_PNTR] | PC; +M[PC + IPL_DEVA] = devi; +M[PC + PTR_DEVA] = devp; +return SCPE_OK; +} + diff --git a/HP2100/hp2100_lps.c b/HP2100/hp2100_lps.c index ec034c4e..7820981b 100644 --- a/HP2100/hp2100_lps.c +++ b/HP2100/hp2100_lps.c @@ -42,8 +42,8 @@ #define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */ #define UNIT_DIAG (1 << UNIT_V_DIAG) -extern int32 PC; -extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; +extern uint32 PC; +extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; int32 lps_ctime = 1000; /* char time */ int32 lps_stopioe = 0; /* stop on error */ int32 lps_sta = 0; @@ -80,8 +80,8 @@ REG lps_reg[] = { { NULL } }; MTAB lps_mod[] = { - { UNIT_DIAG, UNIT_DIAG, "DIAG", "DIAG", NULL }, - { UNIT_DIAG, 0, "PRINTER", "PRINTER", NULL }, + { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL }, + { UNIT_DIAG, 0, "printer mode", "PRINTER", NULL }, { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &lps_dev }, { 0 } }; @@ -117,23 +117,24 @@ case ioLIX: /* load */ dat = 0; /* default sta = 0 */ case ioMIX: /* merge */ if ((lps_unit.flags & UNIT_DIAG) == 0) { /* real lpt? */ - lps_sta = 0; /* create status */ - if ((lps_unit.flags & UNIT_ATT) == 0) - lps_sta = lps_sta | LPS_BUSY | LPS_NRDY; - else if (sim_is_active (&lps_unit)) - lps_sta = lps_sta | LPS_BUSY; } + lps_sta = 0; /* create status */ + if ((lps_unit.flags & UNIT_ATT) == 0) + lps_sta = lps_sta | LPS_BUSY | LPS_NRDY; + else if (sim_is_active (&lps_unit)) + lps_sta = lps_sta | LPS_BUSY; } dat = dat | lps_sta; /* diag, rtn status */ break; case ioCTL: /* control clear/set */ if (IR & I_CTL) { /* CLC */ - clrCMD (dev); /* clear ctl, cmd */ - clrCTL (dev); } - else { setCMD (dev); /* STC */ - setCTL (dev); /* set ctl, cmd */ - if (lps_unit.flags & UNIT_DIAG) /* diagnostic? */ - sim_activate (&lps_unit, 1); /* loop back */ - else sim_activate (&lps_unit, /* real lpt, sched */ - (lps_unit.buf < 040)? lps_unit.wait: lps_ctime); } + clrCMD (dev); /* clear ctl, cmd */ + clrCTL (dev); } + else { /* STC */ + setCMD (dev); /* set ctl, cmd */ + setCTL (dev); + if (lps_unit.flags & UNIT_DIAG) /* diagnostic? */ + sim_activate (&lps_unit, 1); /* loop back */ + else sim_activate (&lps_unit, /* real lpt, sched */ + (lps_unit.buf < 040)? lps_unit.wait: lps_ctime); } break; default: break; } diff --git a/HP2100/hp2100_lpt.c b/HP2100/hp2100_lpt.c index bd09d145..e75087b8 100644 --- a/HP2100/hp2100_lpt.c +++ b/HP2100/hp2100_lpt.c @@ -41,8 +41,8 @@ #define LPT_SKIPM 0000077 /* line count mask */ #define LPT_CHANM 0000007 /* channel mask */ -extern int32 PC; -extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; +extern uint32 PC; +extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; int32 lpt_ctime = 1000; /* char time */ int32 lpt_stopioe = 0; /* stop on error */ int32 lpt_lcnt = 0; /* line count */ @@ -117,19 +117,20 @@ case ioLIX: /* load */ dat = 0; /* default sta = 0 */ case ioMIX: /* merge */ if (lpt_unit.flags & UNIT_ATT) { - dat = dat | LPT_RDY; - if (!sim_is_active (&lpt_unit)) - dat = dat | LPT_NBSY; } + dat = dat | LPT_RDY; + if (!sim_is_active (&lpt_unit)) + dat = dat | LPT_NBSY; } else dat = dat | LPT_PAPO; break; case ioCTL: /* control clear/set */ if (IR & I_CTL) { /* CLC */ - clrCMD (dev); /* clear ctl, cmd */ - clrCTL (dev); } - else { setCMD (dev); /* STC */ - setCTL (dev); /* set ctl, cmd */ - sim_activate (&lpt_unit, /* schedule op */ - (lpt_unit.buf & LPT_CTL)? lpt_unit.wait: lpt_ctime); } + clrCMD (dev); /* clear ctl, cmd */ + clrCTL (dev); } + else { /* STC */ + setCMD (dev); /* set ctl, cmd */ + setCTL (dev); + sim_activate (&lpt_unit, /* schedule op */ + (lpt_unit.buf & LPT_CTL)? lpt_unit.wait: lpt_ctime); } break; default: break; } diff --git a/HP2100/hp2100_ms.c b/HP2100/hp2100_ms.c index 976499d7..61cdf279 100644 --- a/HP2100/hp2100_ms.c +++ b/HP2100/hp2100_ms.c @@ -111,8 +111,8 @@ #define STA_DYN (STA_PE|STA_SEL|STA_TBSY|STA_WLK|STA_LOCAL) extern uint16 *M; -extern int32 PC, SR; -extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; +extern uint32 PC, SR; +extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; extern int32 sim_switches; extern UNIT cpu_unit; diff --git a/HP2100/hp2100_mt.c b/HP2100/hp2100_mt.c index 440765ca..6b2e2d6a 100644 --- a/HP2100/hp2100_mt.c +++ b/HP2100/hp2100_mt.c @@ -88,8 +88,8 @@ #define STA_PAR 0002 /* parity error */ #define STA_BUSY 0001 /* busy (d) */ -extern int32 PC; -extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; +extern uint32 PC; +extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; int32 mtc_fnc = 0; /* function */ int32 mtc_sta = 0; /* status register */ int32 mtc_dtf = 0; /* data xfer flop */ diff --git a/HP2100/hp2100_mux.c b/HP2100/hp2100_mux.c index 8e267fee..887f2ba1 100644 --- a/HP2100/hp2100_mux.c +++ b/HP2100/hp2100_mux.c @@ -87,7 +87,7 @@ #define LIU_SEEK 0100000 /* seeking NI */ #define LIU_DG 0000010 /* diagnose */ -#define LIU_BRK 0000004 /* break NI */ +#define LIU_BRK 0000004 /* break */ #define LIU_LOST 0000002 /* char lost */ #define LIU_TR 0000001 /* trans/rcv */ @@ -129,8 +129,8 @@ ((muxc_ota[ch] & (OTC_ES2|OTC_ES1)) >> OTC_V_ES)) \ << LIC_V_I) -extern int32 PC; -extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; +extern uint32 PC; +extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; uint16 mux_sta[MUX_LINES]; /* line status */ uint16 mux_rpar[MUX_LINES + MUX_ILINES]; /* rcv param */ @@ -482,19 +482,26 @@ tmxr_poll_rx (&mux_desc); /* poll for input */ for (ln = 0; ln < MUX_LINES; ln++) { /* loop thru lines */ if (mux_ldsc[ln].conn) { /* connected? */ if (c = tmxr_getc_ln (&mux_ldsc[ln])) { /* get char */ - if (mux_rchp[ln]) mux_sta[ln] = mux_sta[ln] | LIU_LOST; - if (muxl_unit[ln].flags & UNIT_UC) { /* cvt to UC? */ - c = c & 0177; - if (islower (c)) c = toupper (c); } - else c = c & ((muxl_unit[ln].flags & UNIT_8B)? 0377: 0177); - if (mux_rpar[ln] & OTL_ECHO) { /* echo? */ - TMLN *lp = &mux_ldsc[ln]; /* get line */ - tmxr_putc_ln (lp, c); /* output char */ - tmxr_poll_tx (&mux_desc); } /* poll xmt */ + if (c & SCPE_BREAK) { /* break? */ + mux_sta[ln] = mux_sta[ln] | LIU_BRK; + mux_rbuf[ln] = 0; } /* no char */ + else { /* normal */ + if (mux_rchp[ln]) mux_sta[ln] = mux_sta[ln] | LIU_LOST; + if (muxl_unit[ln].flags & UNIT_UC) { /* cvt to UC? */ + c = c & 0177; + if (islower (c)) c = toupper (c); } + else c = c & ((muxl_unit[ln].flags & UNIT_8B)? 0377: 0177); + if (mux_rpar[ln] & OTL_ECHO) { /* echo? */ + TMLN *lp = &mux_ldsc[ln]; /* get line */ + tmxr_putc_ln (lp, c); /* output char */ + tmxr_poll_tx (&mux_desc); } /* poll xmt */ + mux_rbuf[ln] = c; /* save char */ + mux_rchp[ln] = 1; } /* char pending */ if (mux_rpar[ln] & OTL_DIAG) mux_diag (c); /* rcv diag? */ - mux_rbuf[ln] = c; /* save char */ - mux_rchp[ln] = 1; } } /* char pending */ - else muxc_lia[ln] = 0; } /* disconnected */ /* end for */ + } /* end if char */ + } /* end if connected */ + else muxc_lia[ln] = 0; /* disconnected */ + } /* end for */ if (!FLG (muxl_dib.devno)) mux_data_int (); /* scan for data int */ if (!FLG (muxc_dib.devno)) mux_ctrl_int (); /* scan modem */ return SCPE_OK; @@ -584,9 +591,13 @@ void mux_diag (int32 c) int32 i; for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) { - if (mux_rchp[i]) mux_sta[i] = mux_sta[i] | LIU_LOST; - mux_rchp[i] = 1; - mux_rbuf[i] = c; } + if (c & SCPE_BREAK) { /* break? */ + mux_sta[i] = mux_sta[i] | LIU_BRK; + mux_rbuf[i] = 0; } /* no char */ + else { + if (mux_rchp[i]) mux_sta[i] = mux_sta[i] | LIU_LOST; + mux_rchp[i] = 1; + mux_rbuf[i] = c; } } return; } diff --git a/HP2100/hp2100_stddev.c b/HP2100/hp2100_stddev.c index 4c1762c1..e687a86c 100644 --- a/HP2100/hp2100_stddev.c +++ b/HP2100/hp2100_stddev.c @@ -28,6 +28,7 @@ tty 12531C buffered teleprinter interface clk 12539C time base generator + 22-Dec-02 RMS Added break support 01-Nov-02 RMS Revised BOOT command for IBL ROMs Fixed bug in TTY reset, TTY starts in input mode Fixed bug in TTY mode OTA, stores data as well @@ -77,8 +78,8 @@ #define CLK_ERROR (1 << CLK_V_ERROR) extern uint16 *M; -extern int32 PC, SR; -extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; +extern uint32 PC, SR; +extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2]; extern UNIT cpu_unit; int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ @@ -263,8 +264,8 @@ REG clk_reg[] = { { NULL } }; MTAB clk_mod[] = { - { UNIT_DIAG, UNIT_DIAG, "DIAG", "DIAG", NULL }, - { UNIT_DIAG, 0, "CALIBRATED", "CALIBRATED", NULL }, + { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL }, + { UNIT_DIAG, 0, "calibrated", "CALIBRATED", NULL }, { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &clk_dev }, { 0 } }; @@ -350,8 +351,8 @@ return SCPE_OK; /* Paper tape reader bootstrap routine (HP 12992K ROM) */ +#define LDR_BASE 077 #define CHANGE_DEV (1 << 24) -#define CHANGE_ADDR (1 << 23) static const int32 pboot[IBL_LNT] = { 0107700, /*ST CLC 0,C ; intr off */ @@ -403,7 +404,7 @@ static const int32 pboot[IBL_LNT] = { 0177765, /*M11 -11 ; feed count */ 0, 0, 0, 0, 0, 0, 0, 0, /* unused */ 0, 0, 0, 0, 0, 0, 0, /* unused */ - CHANGE_ADDR }; /*MAXAD -ST ; max addr */ + 0000000 }; /*MAXAD -ST ; max addr */ t_stat ptr_boot (int32 unitno, DEVICE *dptr) { @@ -413,11 +414,10 @@ dev = ptr_dib.devno; /* get device no */ PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ SR = IBL_PTR + (dev << IBL_V_DEV); /* set SR */ for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ - if (pboot[i] & CHANGE_ADDR) /* memory limit? */ - M[PC + i] = (-PC) & DMASK; - else if (pboot[i] & CHANGE_DEV) /* IO instr? */ + if (pboot[i] & CHANGE_DEV) /* IO instr? */ M[PC + i] = (pboot[i] + dev) & DMASK; - else M[PC + i] = pboot[i]; } + else M[PC + i] = pboot[i]; } +M[PC + LDR_BASE] = (~PC + 1) & DMASK; return SCPE_OK; } @@ -564,7 +564,8 @@ int32 c, dev; dev = tty_dib.devno; /* get device no */ sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (tty_unit[TTI].flags & UNIT_UC) { /* UC only? */ +if (c & SCPE_BREAK) c = 0; /* break? */ +else if (tty_unit[TTI].flags & UNIT_UC) { /* UC only? */ c = c & 0177; if (islower (c)) c = toupper (c); } else c = c & ((tty_unit[TTI].flags & UNIT_8B)? 0377: 0177); @@ -572,7 +573,7 @@ if (tty_mode & TM_KBD) { /* keyboard enabled? */ tty_buf = c; /* put char in buf */ tty_unit[TTI].pos = tty_unit[TTI].pos + 1; setFLG (dev); /* set flag */ - return tto_out (c); } /* echo or punch? */ + if (c) return tto_out (c); } /* echo or punch? */ return SCPE_OK; } diff --git a/HP2100/hp2100_sys.c b/HP2100/hp2100_sys.c index 5b335e80..cebf7d88 100644 --- a/HP2100/hp2100_sys.c +++ b/HP2100/hp2100_sys.c @@ -51,6 +51,7 @@ extern DEVICE dpd_dev, dpc_dev; extern DEVICE dqd_dev, dqc_dev; extern DEVICE drd_dev, drc_dev; extern DEVICE muxl_dev, muxu_dev, muxc_dev; +extern DEVICE ipli_dev, iplo_dev; extern REG cpu_reg[]; extern uint16 *M; @@ -86,6 +87,7 @@ DEVICE *sim_devices[] = { &mtd_dev, &mtc_dev, &msd_dev, &msc_dev, &muxl_dev, &muxu_dev, &muxc_dev, + &ipli_dev, &iplo_dev, NULL }; const char *sim_stop_messages[] = { @@ -95,7 +97,8 @@ const char *sim_stop_messages[] = { "HALT instruction", "Breakpoint", "Indirect address loop", - "Indirect address interrupt (should not happen!)" }; + "Indirect address interrupt (should not happen!)", + "No connection on interprocessor link" }; /* Binary loader diff --git a/I1401/i1401_cpu.c b/I1401/i1401_cpu.c index c3fb6890..efead22f 100644 --- a/I1401/i1401_cpu.c +++ b/I1401/i1401_cpu.c @@ -521,7 +521,7 @@ unit = (t == BCD_ZERO)? 0: t; /* save char as unit */ xa = (AS >> V_INDEX) & M_INDEX; /* get index reg */ if (xa && (D != BCD_PERCNT) && (cpu_unit.flags & XSA)) { /* indexed? */ AS = AS + hun_table[M[xa] & CHAR] + ten_table[M[xa + 1] & CHAR] + - one_table[M[xa + 2] & CHAR]; + one_table[M[xa + 2] & CHAR]; AS = (AS & INDEXMASK) % MAXMEMSIZE; } if (!(flags & MLS)) BS = AS; /* not MLS? B = A */ PP (IS); @@ -544,8 +544,8 @@ if ((t = M[IS]) & WM) { /* WM? 6 char inst */ BS = BS + one_table[t]; /* finish B addr */ xa = (BS >> V_INDEX) & M_INDEX; /* get index reg */ if (xa && (cpu_unit.flags & XSA)) { /* indexed? */ - BS = BS + hun_table[M[xa] & CHAR] + ten_table[M[xa + 1] & CHAR] - + one_table[M[xa + 2] & CHAR]; + BS = BS + hun_table[M[xa] & CHAR] + ten_table[M[xa + 1] & CHAR] + + one_table[M[xa + 2] & CHAR]; BS = (BS & INDEXMASK) % MAXMEMSIZE; } PP (IS); @@ -580,55 +580,65 @@ switch (op) { /* case on opcode */ case OP_MCW: /* move char */ if (ilnt >= 8) { /* I/O form? */ - reason = iodisp (dev, unit, MD_NORM, D); - break; } + reason = iodisp (dev, unit, MD_NORM, D); + break; } if (ADDR_ERR (AS)) { /* check A addr */ - reason = STOP_INVA; - break; } - do { M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */ - wm = M[AS] | M[BS]; - MM (AS); MM (BS); } /* decr pointers */ + reason = STOP_INVA; + break; } + do { + M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */ + wm = M[AS] | M[BS]; + MM (AS); MM (BS); } /* decr pointers */ while ((wm & WM) == 0); /* stop on A,B WM */ break; + case OP_LCA: /* load char */ if (ilnt >= 8) { /* I/O form? */ - reason = iodisp (dev, unit, MD_WM, D); - break; } + reason = iodisp (dev, unit, MD_WM, D); + break; } if (ADDR_ERR (AS)) { /* check A addr */ - reason = STOP_INVA; - break; } - do { wm = M[BS] = M[AS]; /* move char + wmark */ - MM (AS); MM (BS); } /* decr pointers */ + reason = STOP_INVA; + break; } + do { + wm = M[BS] = M[AS]; /* move char + wmark */ + MM (AS); MM (BS); } /* decr pointers */ while ((wm & WM) == 0); /* stop on A WM */ break; + case OP_MCM: /* move to rec/group */ - do { M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */ - t = M[AS]; - PP (AS); PP (BS); } /* incr pointers */ + do { + M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */ + t = M[AS]; + PP (AS); PP (BS); } /* incr pointers */ while (((t & CHAR) != BCD_RECMRK) && (t != (BCD_GRPMRK + WM))); break; + case OP_MSZ: /* move suppress zero */ bsave = BS; /* save B start */ qzero = 1; /* set suppress */ - do { M[BS] = M[AS] & ((BS != bsave)? CHAR: DIGIT); /* copy char */ - wm = M[AS]; - MM (AS); MM (BS); } /* decr pointers */ + do { + M[BS] = M[AS] & ((BS != bsave)? CHAR: DIGIT); /* copy char */ + wm = M[AS]; + MM (AS); MM (BS); } /* decr pointers */ while ((wm & WM) == 0); /* stop on A WM */ if (reason) break; /* addr err? stop */ - do { PP (BS); /* adv B */ - t = M[BS]; /* get B, cant be WM */ - if ((t == BCD_ZERO) || (t == BCD_COMMA)) { - if (qzero) M[BS] = 0; } - else if ((t == BCD_BLANK) || (t == BCD_MINUS)) ; - else if (((t == BCD_DECIMAL) && (cpu_unit.flags & EPE)) || - (t <= BCD_NINE)) qzero = 0; - else qzero = 1; } + do { + PP (BS); /* adv B */ + t = M[BS]; /* get B, cant be WM */ + if ((t == BCD_ZERO) || (t == BCD_COMMA)) { + if (qzero) M[BS] = 0; } + else if ((t == BCD_BLANK) || (t == BCD_MINUS)) ; + else if (((t == BCD_DECIMAL) && (cpu_unit.flags & EPE)) || + (t <= BCD_NINE)) qzero = 0; + else qzero = 1; } while (BS <= bsave); break; + case OP_MN: /* move numeric */ M[BS] = (M[BS] & ~DIGIT) | (M[AS] & DIGIT); /* move digit */ MM (AS); MM (BS); /* decr pointers */ break; + case OP_MZ: /* move zone */ M[BS] = (M[BS] & ~ZONE) | (M[AS] & ZONE); /* move high bits */ MM (AS); MM (BS); /* decr pointers */ @@ -641,23 +651,24 @@ case OP_MZ: /* move zone */ case OP_C: /* compare */ if (ilnt != 1) { /* if not chained */ - ind[IN_EQU] = 1; /* clear indicators */ - ind[IN_UNQ] = ind[IN_HGH] = ind[IN_LOW] = 0; } - do { a = M[AS]; /* get characters */ - b = M[BS]; - wm = a | b; /* get word marks */ - if ((a & CHAR) != (b & CHAR)) { /* unequal? */ - ind[IN_EQU] = 0; /* set indicators */ - ind[IN_UNQ] = 1; - ind[IN_HGH] = col_table[b & CHAR] > col_table [a & CHAR]; - ind[IN_LOW] = ind[IN_HGH] ^ 1; } - MM (AS); MM (BS); } /* decr pointers */ + ind[IN_EQU] = 1; /* clear indicators */ + ind[IN_UNQ] = ind[IN_HGH] = ind[IN_LOW] = 0; } + do { + a = M[AS]; /* get characters */ + b = M[BS]; + wm = a | b; /* get word marks */ + if ((a & CHAR) != (b & CHAR)) { /* unequal? */ + ind[IN_EQU] = 0; /* set indicators */ + ind[IN_UNQ] = 1; + ind[IN_HGH] = col_table[b & CHAR] > col_table [a & CHAR]; + ind[IN_LOW] = ind[IN_HGH] ^ 1; } + MM (AS); MM (BS); } /* decr pointers */ while ((wm & WM) == 0); /* stop on A, B WM */ if ((a & WM) && !(b & WM)) { /* short A field? */ - ind[IN_EQU] = ind[IN_LOW] = 0; - ind[IN_UNQ] = ind[IN_HGH] = 1; } + ind[IN_EQU] = ind[IN_LOW] = 0; + ind[IN_UNQ] = ind[IN_HGH] = 1; } if (!(cpu_unit.flags & HLE)) /* no HLE? */ - ind[IN_EQU] = ind[IN_LOW] = ind[IN_HGH] = 0; + ind[IN_EQU] = ind[IN_LOW] = ind[IN_HGH] = 0; break; /* Branch instructions A check B check @@ -673,23 +684,26 @@ case OP_C: /* compare */ case OP_B: /* branch */ if (ilnt == 4) { BRANCH; } /* uncond branch? */ else if (ilnt == 5) { /* branch on ind? */ - if (ind[D]) { BRANCH; } /* test indicator */ - if (ind_table[D]) ind[D] = 0; } /* reset if needed */ - else { if (ADDR_ERR (BS)) { /* branch char eq */ - reason = STOP_INVB; /* validate B addr */ - break; } - if ((M[BS] & CHAR) == D) { BRANCH; } /* char equal? */ - else { MM (BS); } } + if (ind[D]) { BRANCH; } /* test indicator */ + if (ind_table[D]) ind[D] = 0; } /* reset if needed */ + else { + if (ADDR_ERR (BS)) { /* branch char eq */ + reason = STOP_INVB; /* validate B addr */ + break; } + if ((M[BS] & CHAR) == D) { BRANCH; } /* char equal? */ + else { MM (BS); } } break; + case OP_BWZ: /* branch wm or zone */ if (((D & 1) && (M[BS] & WM)) || /* d1? test wm */ ((D & 2) && ((M[BS] & ZONE) == (D & ZONE)))) /* d2? test zone */ { BRANCH; } - else { MM (BS); } /* decr pointer */ + else { MM (BS); } /* decr pointer */ break; + case OP_BBE: /* branch if bit eq */ if (M[BS] & D & CHAR) { BRANCH; } /* any bits set? */ - else { MM (BS); } /* decr pointer */ + else { MM (BS); } /* decr pointer */ break; /* Arithmetic instructions A check B check @@ -704,16 +718,19 @@ case OP_BBE: /* branch if bit eq */ case OP_ZA: case OP_ZS: /* zero and add/sub */ a = i = 0; /* clear flags */ - do { if (a & WM) wm = M[BS] = (M[BS] & WM) | BCD_ZERO; - else { a = M[AS]; /* get A char */ - t = (a & CHAR)? bin_to_bcd[a & DIGIT]: 0; - wm = M[BS] = (M[BS] & WM) | t; /* move digit */ - MM (AS); } - if (i == 0) i = M[BS] = M[BS] | - ((((a & ZONE) == BBIT) ^ (op == OP_ZS))? BBIT: ZONE); - MM (BS); } + do { + if (a & WM) wm = M[BS] = (M[BS] & WM) | BCD_ZERO; + else { + a = M[AS]; /* get A char */ + t = (a & CHAR)? bin_to_bcd[a & DIGIT]: 0; + wm = M[BS] = (M[BS] & WM) | t; /* move digit */ + MM (AS); } + if (i == 0) i = M[BS] = M[BS] | + ((((a & ZONE) == BBIT) ^ (op == OP_ZS))? BBIT: ZONE); + MM (BS); } while ((wm & WM) == 0); /* stop on B WM */ break; + case OP_A: case OP_S: /* add/sub */ bsave = BS; /* save sign pos */ a = M[AS]; /* get A digit/sign */ @@ -728,30 +745,32 @@ case OP_A: case OP_S: /* add/sub */ M[BS] = b; /* store result */ MM (BS); if (b & WM) { /* b wm? done */ - if (qsign && (carry == 0)) M[bsave] = /* compl, no carry? */ - WM + ((b & ZONE) ^ ABIT) + sum_table[10 - t]; - break; } - do { if (a & WM) a = WM; /* A WM? char = 0 */ - else { a = M[AS]; /* else get A */ - MM (AS); } - b = M[BS]; /* get B */ - t = bcd_to_bin[a & DIGIT]; /* get A binary */ - t = bcd_to_bin[b & DIGIT] + (qsign? 9 - t: t) + carry; - carry = (t >= 10); /* get carry */ - if ((b & WM) && (qsign == 0)) { /* last, no recomp? */ - M[BS] = WM + sum_table[t] + /* zone add */ - (((a & ZONE) + b + (carry? ABIT: 0)) & ZONE); - ind[IN_OVF] = carry; } /* ovflo if carry */ - else M[BS] = (b & WM) + sum_table[t]; /* normal add */ - MM (BS); } + if (qsign && (carry == 0)) M[bsave] = /* compl, no carry? */ + WM + ((b & ZONE) ^ ABIT) + sum_table[10 - t]; + break; } + do { + if (a & WM) a = WM; /* A WM? char = 0 */ + else { + a = M[AS]; /* else get A */ + MM (AS); } + b = M[BS]; /* get B */ + t = bcd_to_bin[a & DIGIT]; /* get A binary */ + t = bcd_to_bin[b & DIGIT] + (qsign? 9 - t: t) + carry; + carry = (t >= 10); /* get carry */ + if ((b & WM) && (qsign == 0)) { /* last, no recomp? */ + M[BS] = WM + sum_table[t] + /* zone add */ + (((a & ZONE) + b + (carry? ABIT: 0)) & ZONE); + ind[IN_OVF] = carry; } /* ovflo if carry */ + else M[BS] = (b & WM) + sum_table[t]; /* normal add */ + MM (BS); } while ((b & WM) == 0); /* stop on B WM */ if (reason) break; /* address err? */ if (qsign && (carry == 0)) { /* recompl, no carry? */ - M[bsave] = M[bsave] ^ ABIT; /* XOR sign */ - for (carry = 1; bsave != BS; --bsave) { /* rescan */ - t = 9 - bcd_to_bin[M[bsave] & DIGIT] + carry; - carry = (t >= 10); - M[bsave] = (M[bsave] & ~DIGIT) | sum_table[t]; } } + M[bsave] = M[bsave] ^ ABIT; /* XOR sign */ + for (carry = 1; bsave != BS; --bsave) { /* rescan */ + t = 9 - bcd_to_bin[M[bsave] & DIGIT] + carry; + carry = (t >= 10); + M[bsave] = (M[bsave] & ~DIGIT) | sum_table[t]; } } break; /* I/O instructions A check B check @@ -776,18 +795,21 @@ case OP_R: /* read */ BS = CDR_BUF + CDR_WIDTH; if (ilnt >= 4) { BRANCH; } /* check for branch */ break; + case OP_W: /* write */ if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ reason = write_line (ilnt, D); /* print line */ BS = LPT_BUF + LPT_WIDTH; if (ilnt >= 4) { BRANCH; } /* check for branch */ break; + case OP_P: /* punch */ if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */ reason = punch_card (ilnt, D); /* punch card */ BS = CDP_BUF + CDP_WIDTH; if (ilnt >= 4) { BRANCH; } /* check for branch */ break; + case OP_WR: /* write and read */ if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ reason = write_line (ilnt, D); /* print line */ @@ -796,6 +818,7 @@ case OP_WR: /* write and read */ if (ilnt >= 4) { BRANCH; } /* check for branch */ if (reason == SCPE_OK) reason = r1; /* merge errors */ break; + case OP_WP: /* write and punch */ if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ reason = write_line (ilnt, D); /* print line */ @@ -804,6 +827,7 @@ case OP_WP: /* write and punch */ if (ilnt >= 4) { BRANCH; } /* check for branch */ if (reason == SCPE_OK) reason = r1; /* merge errors */ break; + case OP_RP: /* read and punch */ if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */ reason = read_card (ilnt, D); /* read card */ @@ -812,6 +836,7 @@ case OP_RP: /* read and punch */ if (ilnt >= 4) { BRANCH; } /* check for branch */ if (reason == SCPE_OK) reason = r1; /* merge errors */ break; + case OP_WRP: /* write, read, punch */ if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ reason = write_line (ilnt, D); /* print line */ @@ -821,19 +846,23 @@ case OP_WRP: /* write, read, punch */ if (ilnt >= 4) { BRANCH; } /* check for branch */ if (reason == SCPE_OK) reason = (r1 == SCPE_OK)? r2: r1; break; + case OP_SS: /* select stacker */ if (reason = iomod (ilnt, D, ss_mod)) break; /* valid modifier? */ if (reason = select_stack (D)) break; /* sel stack, error? */ if (ilnt >= 4) { BRANCH; } /* check for branch */ break; + case OP_CC: /* carriage control */ if (reason = carriage_control (D)) break; /* car ctrl, error? */ if (ilnt >= 4) { BRANCH; } /* check for branch */ break; + case OP_MTF: /* magtape function */ if (reason = iomod (ilnt, D, mtf_mod)) break; /* valid modifier? */ if (reason = mt_func (unit, D)) break; /* mt func, error? */ break; /* can't branch */ + case OP_RF: case OP_PF: /* read, punch feed */ break; /* nop's */ @@ -864,11 +893,11 @@ case OP_MCE: /* edit */ a = M[AS]; /* get A char */ b = M[BS]; /* get B char */ if (a & WM) { /* one char A field? */ - reason = STOP_MCE1; - break; } + reason = STOP_MCE1; + break; } if (b & WM) { /* one char B field? */ - reason = STOP_MCE2; - break; } + reason = STOP_MCE2; + break; } t = a & DIGIT; MM (AS); /* get A digit */ qsign = ((a & ZONE) == BBIT); /* get A field sign */ qawm = qzero = qbody = 0; /* clear other flags */ @@ -886,78 +915,81 @@ case OP_MCE: /* edit */ & blank B */ - do { b = M[BS]; /* get B char */ - M[BS] = M[BS] & ~WM; /* clr WM */ - switch (b & CHAR) { /* case on B char */ - case BCD_ASTER: /* * */ - if (!qbody || qdollar || !(cpu_unit.flags & EPE)) break; - qaster = 1; /* flag */ - goto A_CYCLE; /* take A cycle */ - case BCD_DOLLAR: /* $ */ - if (!qbody || qaster || !(cpu_unit.flags & EPE)) break; - qdollar = 1; /* flag */ - goto A_CYCLE; /* take A cycle */ - case BCD_ZERO: /* 0 */ - if (qawm && !qzero && !(b & WM)) { - M[BS] = BCD_ZERO + WM; /* mark with WM */ - qzero = 1; /* flag supress */ - break; } - if (!qzero) t = t | WM; /* first? set WM */ - qzero = 1; /* flag supress */ + do { + b = M[BS]; /* get B char */ + M[BS] = M[BS] & ~WM; /* clr WM */ + switch (b & CHAR) { /* case on B char */ + case BCD_ASTER: /* * */ + if (!qbody || qdollar || !(cpu_unit.flags & EPE)) break; + qaster = 1; /* flag */ + goto A_CYCLE; /* take A cycle */ + case BCD_DOLLAR: /* $ */ + if (!qbody || qaster || !(cpu_unit.flags & EPE)) break; + qdollar = 1; /* flag */ + goto A_CYCLE; /* take A cycle */ + case BCD_ZERO: /* 0 */ + if (qawm && !qzero && !(b & WM)) { + M[BS] = BCD_ZERO + WM; /* mark with WM */ + qzero = 1; /* flag supress */ + break; } + if (!qzero) t = t | WM; /* first? set WM */ + qzero = 1; /* flag supress */ /* fall through */ - case BCD_BLANK: /* blank */ - if (qawm) break; /* any A left? */ - A_CYCLE: - M[BS] = t; /* copy char */ - if (a & WM) { /* end of A field? */ - qbody = 0; /* end body */ - qawm = 1; } - else { qbody = 1; /* in body */ - a = M[AS]; MM (AS); /* next A */ - t = a & CHAR; } - break; - case BCD_C: case BCD_R: case BCD_MINUS: /* C, R, - */ - if (!qsign && !qbody) M[BS] = BCD_BLANK; - break; - case BCD_COMMA: /* , */ - if (!qbody) M[BS] = BCD_BLANK; /* bl if status */ - break; - case BCD_AMPER: /* & */ - M[BS] = BCD_BLANK; /* blank B field */ - break; } /* end switch */ - MM (BS); } /* decr B pointer */ + case BCD_BLANK: /* blank */ + if (qawm) break; /* any A left? */ + A_CYCLE: + M[BS] = t; /* copy char */ + if (a & WM) { /* end of A field? */ + qbody = 0; /* end body */ + qawm = 1; } + else { + qbody = 1; /* in body */ + a = M[AS]; MM (AS); /* next A */ + t = a & CHAR; } + break; + case BCD_C: case BCD_R: case BCD_MINUS: /* C, R, - */ + if (!qsign && !qbody) M[BS] = BCD_BLANK; + break; + case BCD_COMMA: /* , */ + if (!qbody) M[BS] = BCD_BLANK; /* bl if status */ + break; + case BCD_AMPER: /* & */ + M[BS] = BCD_BLANK; /* blank B field */ + break; } /* end switch */ + MM (BS); } /* decr B pointer */ while ((b & WM) == 0); /* stop on B WM */ if (reason) break; /* address err? */ if (!qawm || !qzero) { /* rescan? */ - if (qdollar) reason = STOP_MCE3; /* error if $ */ - break; } + if (qdollar) reason = STOP_MCE3; /* error if $ */ + break; } /* Edit pass 2 - from left to right, supressing zeroes */ - do { b = M[++BS]; /* get B char */ - switch (b & CHAR) { /* case on B char */ - case BCD_ONE: case BCD_TWO: case BCD_THREE: - case BCD_FOUR: case BCD_FIVE: case BCD_SIX: - case BCD_SEVEN: case BCD_EIGHT: case BCD_NINE: - qzero = 0; /* turn off supr */ - break; - case BCD_ZERO: case BCD_COMMA: /* 0 or , */ - if (qzero && !qdecimal) /* if supr, blank */ - M[BS] = qaster? BCD_ASTER: BCD_BLANK; - break; - case BCD_BLANK: /* blank */ - if (qaster) M[BS] = BCD_ASTER; /* if EPE *, repl */ - break; - case BCD_DECIMAL: /* . */ - if (qzero && (cpu_unit.flags & EPE)) - qdecimal = 1; /* flag for EPE */ - case BCD_PERCNT: case BCD_WM: case BCD_BS: - case BCD_TS: case BCD_MINUS: - break; /* ignore */ - default: /* other */ - qzero = 1; /* restart supr */ - break; } } /* end case, do */ + do { + b = M[++BS]; /* get B char */ + switch (b & CHAR) { /* case on B char */ + case BCD_ONE: case BCD_TWO: case BCD_THREE: + case BCD_FOUR: case BCD_FIVE: case BCD_SIX: + case BCD_SEVEN: case BCD_EIGHT: case BCD_NINE: + qzero = 0; /* turn off supr */ + break; + case BCD_ZERO: case BCD_COMMA: /* 0 or , */ + if (qzero && !qdecimal) /* if supr, blank */ + M[BS] = qaster? BCD_ASTER: BCD_BLANK; + break; + case BCD_BLANK: /* blank */ + if (qaster) M[BS] = BCD_ASTER; /* if EPE *, repl */ + break; + case BCD_DECIMAL: /* . */ + if (qzero && (cpu_unit.flags & EPE)) + qdecimal = 1; /* flag for EPE */ + case BCD_PERCNT: case BCD_WM: case BCD_BS: + case BCD_TS: case BCD_MINUS: + break; /* ignore */ + default: /* other */ + qzero = 1; /* restart supr */ + break; } } /* end case, do */ while ((b & WM) == 0); M[BS] = M[BS] & ~WM; /* clear B WM */ @@ -967,16 +999,16 @@ case OP_MCE: /* edit */ /* Edit pass 3 (extended print only) - from right to left */ for (;; ) { /* until chars */ - b = M[BS]; /* get B char */ - if ((b == BCD_BLANK) && qdollar) { /* blank & flt $? */ - M[BS] = BCD_DOLLAR; /* insert $ */ - break; } /* exit for */ - if (b == BCD_DECIMAL) { /* decimal? */ - M[BS] = qaster? BCD_ASTER: BCD_BLANK; - break; } /* exit for */ - if ((b == BCD_ZERO) && !qdollar) /* 0 & ~flt $ */ - M[BS] = qaster? BCD_ASTER: BCD_BLANK; - BS--; } /* end for */ + b = M[BS]; /* get B char */ + if ((b == BCD_BLANK) && qdollar) { /* blank & flt $? */ + M[BS] = BCD_DOLLAR; /* insert $ */ + break; } /* exit for */ + if (b == BCD_DECIMAL) { /* decimal? */ + M[BS] = qaster? BCD_ASTER: BCD_BLANK; + break; } /* exit for */ + if ((b == BCD_ZERO) && !qdollar) /* 0 & ~flt $ */ + M[BS] = qaster? BCD_ASTER: BCD_BLANK; + BS--; } /* end for */ break; /* done at last! */ /* Multiply. Comments from the PDP-10 based simulator by Len Fehskens. @@ -995,9 +1027,10 @@ case OP_MCE: /* edit */ case OP_MUL: asave = AS; bsave = lowprd = BS; /* save AS, BS */ - do { a = M[AS]; /* get mpcd char */ - M[BS] = BCD_ZERO; /* zero prod */ - MM (AS); MM (BS); } /* decr pointers */ + do { + a = M[AS]; /* get mpcd char */ + M[BS] = BCD_ZERO; /* zero prod */ + MM (AS); MM (BS); } /* decr pointers */ while ((a & WM) == 0); /* until A WM */ if (reason) break; /* address err? */ M[BS] = BCD_ZERO; /* zero hi prod */ @@ -1009,23 +1042,25 @@ case OP_MUL: AS and ps cannot produce an address error. */ - do { ps = bsave; /* ptr to prod */ - AS = asave; /* ptr to mpcd */ - carry = 0; /* init carry */ - b = M[BS]; /* get mpyr char */ - do { a = M[AS]; /* get mpcd char */ - t = (bcd_to_bin[a & DIGIT] * /* mpyr * mpcd */ - bcd_to_bin[b & DIGIT]) + /* + c + partial prod */ - carry + bcd_to_bin[M[ps] & DIGIT]; - carry = cry_table[t]; - M[ps] = (M[ps] & WM) | sum_table[t]; - MM (AS); ps--; } - while ((a & WM) == 0); /* until mpcd done */ - M[BS] = (M[BS] & WM) | BCD_ZERO; /* zero mpyr just used */ - t = bcd_to_bin[M[ps] & DIGIT] + carry; /* add carry to prod */ - M[ps] = (M[ps] & WM) | sum_table[t]; /* store */ - bsave--; /* adv prod ptr */ - MM (BS); } /* adv mpyr ptr */ + do { + ps = bsave; /* ptr to prod */ + AS = asave; /* ptr to mpcd */ + carry = 0; /* init carry */ + b = M[BS]; /* get mpyr char */ + do { + a = M[AS]; /* get mpcd char */ + t = (bcd_to_bin[a & DIGIT] * /* mpyr * mpcd */ + bcd_to_bin[b & DIGIT]) + /* + c + partial prod */ + carry + bcd_to_bin[M[ps] & DIGIT]; + carry = cry_table[t]; + M[ps] = (M[ps] & WM) | sum_table[t]; + MM (AS); ps--; } + while ((a & WM) == 0); /* until mpcd done */ + M[BS] = (M[BS] & WM) | BCD_ZERO; /* zero mpyr just used */ + t = bcd_to_bin[M[ps] & DIGIT] + carry; /* add carry to prod */ + M[ps] = (M[ps] & WM) | sum_table[t]; /* store */ + bsave--; /* adv prod ptr */ + MM (BS); } /* adv mpyr ptr */ while ((b & WM) == 0); /* until mpyr done */ M[lowprd] = M[lowprd] | ZONE; /* assume + */ if (sign) M[lowprd] = M[lowprd] & ~ABIT; /* if minus, B only */ @@ -1058,24 +1093,26 @@ case OP_MUL: case OP_DIV: asave = AS; ahigh = -1; - do { a = M[AS]; /* get dvr char */ - if ((a & CHAR) != BCD_ZERO) ahigh = AS; /* mark non-zero */ - MM (AS); } + do { + a = M[AS]; /* get dvr char */ + if ((a & CHAR) != BCD_ZERO) ahigh = AS; /* mark non-zero */ + MM (AS); } while ((a & WM) == 0); if (reason) break; /* address err? */ if (ahigh < 0) { /* div? by zero */ - ind[IN_OVF] = 1; /* set ovf indic */ - qs = bsave = BS; /* quo, dividend */ - do { b = M[bsave]; /* find end divd */ - PP (bsave); } /* marked by zone */ - while ((b & ZONE) == 0); - if (reason) break; /* address err? */ - if (ADDR_ERR (qs)) { /* address err? */ - reason = STOP_WRAP; /* address wrap? */ - break; } - div_sign (M[asave], b, qs - 1, bsave - 1); /* set signs */ - BS = (BS - 2) - (asave - (AS + 1)); /* final bs */ - break; } + ind[IN_OVF] = 1; /* set ovf indic */ + qs = bsave = BS; /* quo, dividend */ + do { + b = M[bsave]; /* find end divd */ + PP (bsave); } /* marked by zone */ + while ((b & ZONE) == 0); + if (reason) break; /* address err? */ + if (ADDR_ERR (qs)) { /* address err? */ + reason = STOP_WRAP; /* address wrap? */ + break; } + div_sign (M[asave], b, qs - 1, bsave - 1); /* set signs */ + BS = (BS - 2) - (asave - (AS + 1)); /* final bs */ + break; } bsave = BS + (asave - ahigh); /* end subdivd */ qs = (BS - 2) - (ahigh - (AS + 1)); /* quo start */ @@ -1087,17 +1124,19 @@ case OP_DIV: qs = current quotient digit */ - do { quo = 0; /* clear quo digit */ - if (ADDR_ERR (qs) || ADDR_ERR (bsave)) { - reason = STOP_WRAP; /* address wrap? */ - break; } - b = M[bsave]; /* save low divd */ - do { t = div_sub (asave, bsave, ahigh); /* subtract */ - quo++; } /* incr quo digit */ - while (t == 0); /* until borrow */ - div_add (asave, bsave, ahigh); quo--; /* restore */ - M[qs] = (M[qs] & WM) | sum_table[quo]; /* store quo digit */ - bsave++; qs++; } /* adv divd, quo */ + do { + quo = 0; /* clear quo digit */ + if (ADDR_ERR (qs) || ADDR_ERR (bsave)) { + reason = STOP_WRAP; /* address wrap? */ + break; } + b = M[bsave]; /* save low divd */ + do { + t = div_sub (asave, bsave, ahigh); /* subtract */ + quo++; } /* incr quo digit */ + while (t == 0); /* until borrow */ + div_add (asave, bsave, ahigh); quo--; /* restore */ + M[qs] = (M[qs] & WM) | sum_table[quo]; /* store quo digit */ + bsave++; qs++; } /* adv divd, quo */ while ((b & ZONE) == 0); /* until B sign */ if (reason) break; /* address err? */ @@ -1131,17 +1170,20 @@ case OP_SWM: /* set word mark */ M[AS] = M[AS] | WM; /* set B field mark */ MM (AS); MM (BS); /* decr pointers */ break; + case OP_CWM: /* clear word mark */ M[BS] = M[BS] & ~WM; /* clear A field mark */ M[AS] = M[AS] & ~WM; /* clear B field mark */ MM (AS); MM (BS); /* decr pointers */ break; + case OP_CS: /* clear storage */ t = (BS / 100) * 100; /* lower bound */ while (BS >= t) M[BS--] = 0; /* clear region */ if (BS < 0) BS = BS + MEMSIZE; /* wrap if needed */ if (ilnt >= 7) { BRANCH; } /* branch variant? */ break; + case OP_MA: /* modify address */ a = one_table[M[AS] & CHAR]; MM (AS); /* get A address */ a = a + ten_table[M[AS] & CHAR]; MM (AS); @@ -1155,18 +1197,22 @@ case OP_MA: /* modify address */ M[BS + 1] = (M[BS + 1] & WM) | store_addr_h (t); if (((a % 4000) + (b % 4000)) >= 4000) BS = BS + 2; /* carry? */ break; + case OP_SAR: case OP_SBR: /* store A, B reg */ M[AS] = (M[AS] & WM) | store_addr_u (BS); MM (AS); M[AS] = (M[AS] & WM) | store_addr_t (BS); MM (AS); M[AS] = (M[AS] & WM) | store_addr_h (BS); MM (AS); break; + case OP_NOP: /* nop */ break; + case OP_H: /* halt */ if (ilnt >= 4) { BRANCH; } /* branch if called */ reason = STOP_HALT; /* stop simulator */ saved_IS = IS; /* commit instruction */ break; + default: reason = STOP_NXI; /* unimplemented */ break; } /* end switch */ diff --git a/I1401/i1401_dp.c b/I1401/i1401_dp.c index 26dd6a50..760fbcd2 100644 --- a/I1401/i1401_dp.c +++ b/I1401/i1401_dp.c @@ -203,12 +203,12 @@ if ((fnc == FNC_SEEK) && /* seek and */ if (diff < 0) return STOP_INVDSC; /* error? */ diff = diff >> 1; /* diff is *2 */ if ((M[dcf + DCF_DIR + DCF_DIR_LEN - 1] & ZONE) == BBIT) - diff = -diff; /* get sign */ + diff = -diff; /* get sign */ uptr->CYL = uptr->CYL + diff; /* bound seek */ if (uptr->CYL < 0) uptr->CYL = 0; else if (uptr->CYL >= DP_NUMCY) { /* too big? */ - uptr->CYL = 0; /* system hangs */ - return STOP_INVDCY; } + uptr->CYL = 0; /* system hangs */ + return STOP_INVDCY; } sim_activate (&dp_unit[0], dp_time); /* set ctlr busy */ return SCPE_OK; } /* done! */ @@ -217,7 +217,7 @@ if ((sec < 0) || (sec >= (DP_NUMDR * DP_TOTSC))) /* bad sector? */ return STOP_INVDSC; if (fnc == FNC_SEEK) { /* seek? */ uptr->CYL = (sec / (DP_NUMSF * DP_NUMSC)) % /* set cyl # */ - DP_NUMCY; + DP_NUMCY; sim_activate (&dp_unit[0], dp_time); /* set ctlr busy */ return SCPE_OK; } /* done! */ @@ -229,10 +229,11 @@ if (cnt < 0) return STOP_INVDCN; /* bad count? */ if (fnc >= FNC_WOFF) return STOP_INVDFN; /* invalid func */ if (mod == BCD_W) { /* write? */ if (fnc == FNC_CHECK) { /* write check? */ - qwc = 1; /* special read */ - fnc = dp_lastf; } /* use last func */ - else { dp_lastf = fnc; /* save func */ - fnc = fnc + FNC_WOFF; } } /* change to write */ + qwc = 1; /* special read */ + fnc = dp_lastf; } /* use last func */ + else { + dp_lastf = fnc; /* save func */ + fnc = fnc + FNC_WOFF; } } /* change to write */ else if (mod == BCD_R) dp_lastf = fnc; /* read? save func */ else return STOP_INVM; /* other? error */ @@ -311,8 +312,8 @@ if (r == SCPE_OK) { /* normal so far? */ BS++; /* advance BS */ if (ADDR_ERR (BS)) return STOP_WRAP; /* address error? */ if (M[BS - 1] != (WM + BCD_GRPMRK)) { /* GM + WM at end? */ - ind[IN_LNG] = ind[IN_DSK] = 1; /* no, error */ - r = STOP_INVDLN; } } + ind[IN_LNG] = ind[IN_DSK] = 1; /* no, error */ + r = STOP_INVDLN; } } CRETIOE (iochk || !ind[IN_DSK], r); /* return status */ } @@ -330,18 +331,18 @@ static const int32 dec_tab[DP_ADDR] = /* powers of 10 */ for (i = 0; i < DP_ADDR; i++) { /* copy address */ if (M[BS] == (WM | BCD_GRPMRK)) { /* premature GWM? */ - ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ - return STOP_INVDLN; } + ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ + return STOP_INVDLN; } if (zad) { /* addr zero? */ - ac = sec / dec_tab[i]; /* get addr digit */ - sec = sec % dec_tab[i]; /* get remainder */ - ac = bcd_to_bin[ac]; } /* cvt to BCD */ + ac = sec / dec_tab[i]; /* get addr digit */ + sec = sec % dec_tab[i]; /* get remainder */ + ac = bcd_to_bin[ac]; } /* cvt to BCD */ else ac = *ap; /* addr char */ if (qwc) { /* wr chk? skip if zad */ - if (!zad && (flg? (M[BS] != ac): /* L? cmp with WM */ - ((M[BS] & CHAR) != (ac & CHAR)))) { /* M? cmp w/o WM */ - ind[IN_DPW] = ind[IN_DSK] = 1; - return STOP_WRCHKE; } } + if (!zad && (flg? (M[BS] != ac): /* L? cmp with WM */ + ((M[BS] & CHAR) != (ac & CHAR)))) { /* M? cmp w/o WM */ + ind[IN_DPW] = ind[IN_DSK] = 1; + return STOP_WRCHKE; } } else if (flg) M[BS] = ac & CHAR; /* load mode */ else M[BS] = (M[BS] & WM) | (ac & CHAR); /* move mode */ ap++; BS++; /* adv ptrs */ @@ -360,13 +361,13 @@ uint8 *ap = ((uint8 *) uptr->filebuf) + da + DP_ADDR; /* buf ptr */ lim = flg? (DP_DATA - 10): DP_DATA; /* load vs move */ for (i = 0; i < lim; i++) { /* copy data */ if (M[BS] == (WM | BCD_GRPMRK)) { /* premature GWM? */ - ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ - return STOP_INVDLN; } + ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ + return STOP_INVDLN; } if (qwc) { /* write check? */ - if (flg? (M[BS] != *ap): /* load mode cmp */ - ((M[BS] & CHAR) != (*ap & CHAR))) { /* move mode cmp */ - ind[IN_DPW] = ind[IN_DSK] = 1; /* error */ - return STOP_WRCHKE; } } + if (flg? (M[BS] != *ap): /* load mode cmp */ + ((M[BS] & CHAR) != (*ap & CHAR))) { /* move mode cmp */ + ind[IN_DPW] = ind[IN_DSK] = 1; /* error */ + return STOP_WRCHKE; } } else if (flg) M[BS] = *ap & (WM | CHAR); /* load mode */ else M[BS] = (M[BS] & WM) | (*ap & CHAR); /* word mode */ ap++; BS++; /* adv ptrs */ @@ -384,9 +385,9 @@ uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ for (i = 0; i < DP_ADDR; i++) { /* copy address */ if (M[BS] == (WM | BCD_GRPMRK)) { /* premature GWM? */ - dp_fill (uptr, da, DP_NUMCH - i); /* fill, set err */ - ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ - return STOP_INVDLN; } + dp_fill (uptr, da, DP_NUMCH - i); /* fill, set err */ + ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ + return STOP_INVDLN; } if (flg) *ap = M[BS] & (WM | CHAR); /* L? copy WM */ else *ap = M[BS] & CHAR; /* M? strip WM */ if (da >= uptr->hwmark) uptr->hwmark = da + 1; @@ -406,9 +407,9 @@ uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ lim = flg? (DP_DATA - 10): DP_DATA; /* load vs move */ for (i = 0; i < lim; i++) { /* copy data */ if (M[BS] == (WM | BCD_GRPMRK)) { /* premature GWM? */ - dp_fill (uptr, da, DP_DATA - i); /* fill, set err */ - ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ - return STOP_INVDLN; } + dp_fill (uptr, da, DP_DATA - i); /* fill, set err */ + ind[IN_LNG] = ind[IN_DSK] = 1; /* error */ + return STOP_INVDLN; } if (flg) *ap = M[BS] & (WM | CHAR); /* load, copy WM */ else *ap = M[BS] & CHAR; /* move, strip WM */ if (da >= uptr->hwmark) uptr->hwmark = da + 1; @@ -475,7 +476,7 @@ uint8 c; for (i = 0; i < DP_ADDR; i++, ap++) { /* loop thru addr */ c = M[dcf + DCF_SEC + i]; /* sector addr char */ if ((c & CHAR) != (*ap & CHAR)) /* cmp w/o WM */ - return FALSE; } + return FALSE; } return TRUE; /* compare ok */ } diff --git a/I1401/i1401_iq.c b/I1401/i1401_iq.c index b12556bc..6866dd7d 100644 --- a/I1401/i1401_iq.c +++ b/I1401/i1401_iq.c @@ -25,6 +25,7 @@ inq 1407 inquiry terminal + 22-Dec-02 RMS Added break support 07-Sep-01 RMS Moved function prototypes 14-Apr-99 RMS Changed t_addr to unsigned */ @@ -82,39 +83,41 @@ case BCD_R: /* input */ ind[IN_INR] = 0; /* clear req */ puts_tty ("[Enter]\r\n"); /* prompt */ for (i = 0; M[BS] != (BCD_GRPMRK + WM); i++) { /* until GM + WM */ - while ((t = sim_poll_kbd ()) == SCPE_OK) - if (stop_cpu) return SCPE_STOP; /* interrupt? */ - if (t < SCPE_KFLAG) return t; /* if not char, err */ - t = t & 0177; - if ((t == '\r') || (t == '\n')) break; - if (t == inq_char) { /* cancel? */ - ind[IN_INC] = 1; /* set indicator */ - puts_tty ("\r\n[Canceled]\r\n"); - return SCPE_OK; } - if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); - sim_putchar (t); /* echo */ - if (flag == MD_WM) { /* word mark mode? */ - if ((t == '~') && (wm_seen == 0)) wm_seen = WM; - else { M[BS] = wm_seen | ascii_to_bcd[t]; - wm_seen = 0; } } - else M[BS] = (M[BS] & WM) | ascii_to_bcd[t]; - if (!wm_seen) BS++; - if (ADDR_ERR (BS)) { - BS = BA | (BS % MAXMEMSIZE); - return STOP_NXM; } } + while (((t = sim_poll_kbd ()) == SCPE_OK) || + (t & SCPE_BREAK)) { + if (stop_cpu) return SCPE_STOP; } /* interrupt? */ + if (t < SCPE_KFLAG) return t; /* if not char, err */ + t = t & 0177; + if ((t == '\r') || (t == '\n')) break; + if (t == inq_char) { /* cancel? */ + ind[IN_INC] = 1; /* set indicator */ + puts_tty ("\r\n[Canceled]\r\n"); + return SCPE_OK; } + if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); + sim_putchar (t); /* echo */ + if (flag == MD_WM) { /* word mark mode? */ + if ((t == '~') && (wm_seen == 0)) wm_seen = WM; + else { + M[BS] = wm_seen | ascii_to_bcd[t]; + wm_seen = 0; } } + else M[BS] = (M[BS] & WM) | ascii_to_bcd[t]; + if (!wm_seen) BS++; + if (ADDR_ERR (BS)) { + BS = BA | (BS % MAXMEMSIZE); + return STOP_NXM; } } puts_tty ("\r\n"); M[BS++] = BCD_GRPMRK + WM; return SCPE_OK; case BCD_W: /* output */ for (i = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); i++) { - if ((flag == MD_WM) && (t & WM)) { - if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); - sim_putchar ('~'); } + if ((flag == MD_WM) && (t & WM)) { if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); - sim_putchar (bcd_to_ascii[t & CHAR]); - if (ADDR_ERR (BS)) { - BS = BA | (BS % MAXMEMSIZE); - return STOP_NXM; } } + sim_putchar ('~'); } + if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); + sim_putchar (bcd_to_ascii[t & CHAR]); + if (ADDR_ERR (BS)) { + BS = BA | (BS % MAXMEMSIZE); + return STOP_NXM; } } puts_tty ("\r\n"); return SCPE_OK; default: diff --git a/I1401/i1401_lp.c b/I1401/i1401_lp.c index c93e21f2..f7eaac41 100644 --- a/I1401/i1401_lp.c +++ b/I1401/i1401_lp.c @@ -164,14 +164,14 @@ switch (action) { case 0: /* to channel now */ if ((mod == 0) || (mod > 12) || CHP (mod, cct[cctptr])) return SCPE_OK; for (i = 1; i < cctlnt + 1; i++) { /* sweep thru cct */ - if (CHP (mod, cct[(cctptr + i) % cctlnt])) - return space (i, TRUE); } + if (CHP (mod, cct[(cctptr + i) % cctlnt])) + return space (i, TRUE); } return STOP_CCT; /* runaway channel */ case 1: /* space after */ if (mod <= 3) { - lines = mod; /* save # lines */ - lflag = FALSE; /* flag spacing */ - ind[IN_CC9] = ind[IN_CC12] = 0; } + lines = mod; /* save # lines */ + lflag = FALSE; /* flag spacing */ + ind[IN_CC9] = ind[IN_CC12] = 0; } return SCPE_OK; case 2: /* space now */ if (mod <= 3) return space (mod, FALSE); @@ -180,10 +180,10 @@ case 3: /* to channel after */ if ((mod == 0) || (mod > 12)) return SCPE_OK; /* check channel */ ind[IN_CC9] = ind[IN_CC12] = 0; for (i = 1; i < cctlnt + 1; i++) { /* sweep thru cct */ - if (CHP (mod, cct[(cctptr + i) % cctlnt])) { - lines = i; /* save # lines */ - lflag = TRUE; /* flag skipping */ - return SCPE_OK; } } + if (CHP (mod, cct[(cctptr + i) % cctlnt])) { + lines = i; /* save # lines */ + lflag = TRUE; /* flag skipping */ + return SCPE_OK; } } return STOP_CCT; } /* runaway channel */ return SCPE_OK; } @@ -203,7 +203,8 @@ if ((lpt_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; cctptr = (cctptr + count) % cctlnt; /* adv cct, mod lnt */ if (sflag && CHP (0, cct[cctptr])) /* skip, top of form? */ fputs ("\n\f", lpt_unit.fileref); /* nl, ff */ -else { for (i = 0; i < count; i++) fputc ('\n', lpt_unit.fileref); } +else { for (i = 0; i < count; i++) + fputc ('\n', lpt_unit.fileref); } lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ ind[IN_CC9] = CHP (9, cct[cctptr]) != 0; /* set indicators */ ind[IN_CC12] = CHP (12, cct[cctptr]) != 0; diff --git a/I1401/i1401_mt.c b/I1401/i1401_mt.c index 980d63ff..6e3b97dc 100644 --- a/I1401/i1401_mt.c +++ b/I1401/i1401_mt.c @@ -147,16 +147,15 @@ switch (mod) { /* case on modifier */ case BCD_B: /* backspace */ ind[IN_END] = 0; /* clear end of reel */ if (pnu || (uptr->pos < sizeof (t_mtrlnt))) /* bot or pnu? */ - return SCPE_OK; - fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), - SEEK_SET); + return SCPE_OK; + fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET); fxread (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref); if ((err = ferror (uptr->fileref)) || /* err or eof? */ feof (uptr->fileref)) break; if ((tbc == MTR_TMK) || (tbc == MTR_EOM)) /* tmk or eom? */ - uptr->pos = uptr->pos - sizeof (t_mtrlnt); + uptr->pos = uptr->pos - sizeof (t_mtrlnt); else uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) - - (2 * sizeof (t_mtrlnt)); + (2 * sizeof (t_mtrlnt)); break; /* end case */ case BCD_E: /* erase = nop */ @@ -218,13 +217,13 @@ case BCD_R: /* read */ fxread (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref); if (err = ferror (uptr->fileref)) break; /* error? */ if (feof (uptr->fileref) || (tbc == MTR_EOM)) { /* eom or eof? */ - ind[IN_TAP] = 1; /* pretend error */ - MT_SET_PNU (uptr); /* pos not upd */ - break; } + ind[IN_TAP] = 1; /* pretend error */ + MT_SET_PNU (uptr); /* pos not upd */ + break; } if (tbc == MTR_TMK) { /* tape mark? */ - ind[IN_END] = 1; /* set end mark */ - uptr->pos = uptr->pos + sizeof (t_mtrlnt); - break; } + ind[IN_END] = 1; /* set end mark */ + uptr->pos = uptr->pos + sizeof (t_mtrlnt); + break; } if (MTRF (tbc)) ind[IN_TAP] = 1; /* error? set flag */ tbc = MTRL (tbc); /* clear error flag */ if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */ @@ -232,31 +231,32 @@ case BCD_R: /* read */ if (err = ferror (uptr->fileref)) break; /* I/O error? */ for ( ; i < tbc; i++) dbuf[i] = 0; /* fill with 0's */ uptr->pos = uptr->pos + ((tbc + 1) & ~1) + - (2 * sizeof (t_mtrlnt)); + (2 * sizeof (t_mtrlnt)); for (i = 0; i < tbc; i++) { /* loop thru buf */ - if (M[BS] == (BCD_GRPMRK + WM)) { /* GWM in memory? */ - BS++; /* incr BS */ - if (ADDR_ERR (BS)) { /* test for wrap */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } - return SCPE_OK; } /* done */ - t = dbuf[i]; /* get char */ - if ((flag != MD_BIN) && (t == BCD_ALT)) t = BCD_BLANK; - if (flag == MD_WM) { /* word mk mode? */ - if ((t == BCD_WM) && (wm_seen == 0)) wm_seen = WM; - else { M[BS] = wm_seen | (t & CHAR); - wm_seen = 0; } } - else M[BS] = (M[BS] & WM) | (t & CHAR); - if (!wm_seen) BS++; - if (ADDR_ERR (BS)) { /* check next BS */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } } + if (M[BS] == (BCD_GRPMRK + WM)) { /* GWM in memory? */ + BS++; /* incr BS */ + if (ADDR_ERR (BS)) { /* test for wrap */ + BS = BA | (BS % MAXMEMSIZE); + return STOP_WRAP; } + return SCPE_OK; } /* done */ + t = dbuf[i]; /* get char */ + if ((flag != MD_BIN) && (t == BCD_ALT)) t = BCD_BLANK; + if (flag == MD_WM) { /* word mk mode? */ + if ((t == BCD_WM) && (wm_seen == 0)) wm_seen = WM; + else { + M[BS] = wm_seen | (t & CHAR); + wm_seen = 0; } } + else M[BS] = (M[BS] & WM) | (t & CHAR); + if (!wm_seen) BS++; + if (ADDR_ERR (BS)) { /* check next BS */ + BS = BA | (BS % MAXMEMSIZE); + return STOP_WRAP; } } if (flag == MD_WM) M[BS] = WM | BCD_GRPMRK; /* load? set WM */ else M[BS] = (M[BS] & WM) | BCD_GRPMRK; /* move? save WM */ BS++; /* adv BS */ if (ADDR_ERR (BS)) { /* check final BS */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } + BS = BA | (BS % MAXMEMSIZE); + return STOP_WRAP; } break; case BCD_W: @@ -264,13 +264,13 @@ case BCD_W: if (M[BS] == (BCD_GRPMRK + WM)) return STOP_MTZ; /* eor? */ ind[IN_TAP] = ind[IN_END] = 0; /* clear error */ for (tbc = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); ) { - if ((t & WM) && (flag == MD_WM)) dbuf[tbc++] = BCD_WM; - if (((t & CHAR) == BCD_BLANK) && (flag != MD_BIN)) - dbuf[tbc++] = BCD_ALT; - else dbuf[tbc++] = t & CHAR; - if (ADDR_ERR (BS)) { /* check next BS */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } } + if ((t & WM) && (flag == MD_WM)) dbuf[tbc++] = BCD_WM; + if (((t & CHAR) == BCD_BLANK) && (flag != MD_BIN)) + dbuf[tbc++] = BCD_ALT; + else dbuf[tbc++] = t & CHAR; + if (ADDR_ERR (BS)) { /* check next BS */ + BS = BA | (BS % MAXMEMSIZE); + return STOP_WRAP; } } ebc = (tbc + 1) & ~1; /* force even */ fseek (uptr->fileref, uptr->pos, SEEK_SET); fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref); @@ -279,8 +279,8 @@ case BCD_W: if (err = ferror (uptr->fileref)) break; /* I/O error? */ uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); if (ADDR_ERR (BS)) { /* check final BS */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } + BS = BA | (BS % MAXMEMSIZE); + return STOP_WRAP; } break; default: return STOP_INVM; } diff --git a/I1401/i1401_sys.c b/I1401/i1401_sys.c index 6ad4cf84..c9cf3c8e 100644 --- a/I1401/i1401_sys.c +++ b/I1401/i1401_sys.c @@ -133,18 +133,18 @@ ptr = 0; for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */ mask = 0; if (*cptr == '(') { /* repeat count? */ - cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */ - rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */ - if (r != SCPE_OK) return SCPE_FMT; } + cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */ + rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */ + if (r != SCPE_OK) return SCPE_FMT; } else rpt = 1; while (*cptr != 0) { /* get col no's */ - cptr = get_glyph (cptr, gbuf, ','); /* get next field */ - col = get_uint (gbuf, 10, 12, &r); /* column number */ - if (r != SCPE_OK) return SCPE_FMT; - mask = mask | (1 << col); } /* set bit */ + cptr = get_glyph (cptr, gbuf, ','); /* get next field */ + col = get_uint (gbuf, 10, 12, &r); /* column number */ + if (r != SCPE_OK) return SCPE_FMT; + mask = mask | (1 << col); } /* set bit */ for ( ; rpt > 0; rpt--) { /* store vals */ - if (ptr >= CCT_LNT) return SCPE_FMT; - cctbuf[ptr++] = mask; } } + if (ptr >= CCT_LNT) return SCPE_FMT; + cctbuf[ptr++] = mask; } } if (ptr == 0) return SCPE_FMT; cctlnt = ptr; cctptr = 0; @@ -203,7 +203,7 @@ extern int32 op_table[64], len_table[9]; if (sw & SWMASK ('C')) { /* character? */ t = val[0]; if (uptr->flags & UNIT_BCD) - fprintf (of, (t & WM)? "~%c": "%c", bcd_to_ascii[t & CHAR]); + fprintf (of, (t & WM)? "~%c": "%c", bcd_to_ascii[t & CHAR]); else fprintf (of, FMTASC (t & 0177)); return SCPE_OK; } if ((uptr != NULL) && (uptr != &cpu_unit)) return SCPE_ARG; /* CPU? */ @@ -214,8 +214,9 @@ if (sw & SWMASK ('D')) { /* dump? */ return -(i - 1); } if (sw & SWMASK ('S')) { /* string? */ i = 0; - do { t = val[i++]; - fprintf (of, (t & WM)? "~%c": "%c", bcd_to_ascii[t & CHAR]); } + do { + t = val[i++]; + fprintf (of, (t & WM)? "~%c": "%c", bcd_to_ascii[t & CHAR]); } while ((i < LINE_LNT) && ((val[i] & WM) == 0)); return -(i - 1); } if ((sw & SWMASK ('M')) == 0) return SCPE_ARG; @@ -300,13 +301,13 @@ if ((sw & SWMASK ('C')) || (sw & SWMASK ('S')) || (*cptr == '~') || ((*cptr == '\'') && cptr++) || ((*cptr == '"') && cptr++)) { wm_seen = 0; for (i = 0; (i < sim_emax) && (*cptr != 0); ) { - t = *cptr++; /* get character */ - if (cflag && (wm_seen == 0) && (t == '~')) wm_seen = WM; - else if (uptr->flags & UNIT_BCD) { - if (t < 040) return SCPE_ARG; - val[i++] = ascii_to_bcd[t] | wm_seen; - wm_seen = 0; } - else val[i++] = t; } + t = *cptr++; /* get character */ + if (cflag && (wm_seen == 0) && (t == '~')) wm_seen = WM; + else if (uptr->flags & UNIT_BCD) { + if (t < 040) return SCPE_ARG; + val[i++] = ascii_to_bcd[t] | wm_seen; + wm_seen = 0; } + else val[i++] = t; } if ((i == 0) || wm_seen) return SCPE_ARG; return -(i-1); } @@ -321,14 +322,14 @@ if (((op_table[op] && IO) && (get_io (gbuf, &val[1]) == SCPE_OK)) || (get_addr (gbuf, &val[1]) == SCPE_OK)) { cptr = get_glyph (cptr, gbuf, 0); /* get addr or d */ if (get_addr (gbuf, &val[4]) == SCPE_OK) { - cptr = get_glyph (cptr, gbuf, ','); /* get d */ - ilnt = 7; } /* a and b addresses */ + cptr = get_glyph (cptr, gbuf, ','); /* get d */ + ilnt = 7; } /* a and b addresses */ else ilnt = 4; } /* a address */ else ilnt = 1; /* no addresses */ if ((gbuf[0] == '\'') || (gbuf[0] == '"')) { /* d character? */ t = gbuf[1]; if ((gbuf[2] != 0) || (*cptr != 0) || (t < 040)) - return SCPE_ARG; /* end and legal? */ + return SCPE_ARG; /* end and legal? */ val[ilnt] = ascii_to_bcd[t]; /* save D char */ ilnt = ilnt + 1; } else if (gbuf[0] != 0) return SCPE_ARG; /* not done? */ diff --git a/I1620/i1620_cd.c b/I1620/i1620_cd.c index 43990d8a..6305ea7e 100644 --- a/I1620/i1620_cd.c +++ b/I1620/i1620_cd.c @@ -222,26 +222,26 @@ case OP_RN: /* read numeric */ r = cdr_read (); /* fill reader buf */ if (r != SCPE_OK) return r; /* error? */ for (i = 0; i < CD_LEN; i++) { /* transfer to mem */ - cdc = cdr_to_num[cdr_buf[i]]; /* translate */ - if (cdc < 0) { /* invalid? */ - ind[IN_RDCHK] = 1; /* set read check */ - inv = STOP_INVCHR; /* set return status */ - cdc = 0; } - M[pa] = cdc; /* store digit */ - PP (pa); } /* incr mem addr */ + cdc = cdr_to_num[cdr_buf[i]]; /* translate */ + if (cdc < 0) { /* invalid? */ + ind[IN_RDCHK] = 1; /* set read check */ + inv = STOP_INVCHR; /* set return status */ + cdc = 0; } + M[pa] = cdc; /* store digit */ + PP (pa); } /* incr mem addr */ break; case OP_RA: /* read alphameric */ r = cdr_read (); /* fill reader buf */ if (r != SCPE_OK) return r; /* error? */ for (i = 0; i < CD_LEN; i++) { /* transfer to mem */ - cdc = cdr_to_alp[cdr_buf[i]]; /* translate */ - if (cdc < 0) { /* invalid? */ - ind[IN_RDCHK] = 1; /* set read check */ - inv = STOP_INVCHR; /* set return status */ - cdc = 0; }; - M[pa] = (M[pa] & FLAG) | (cdc & DIGIT); /* store 2 digits */ - M[pa - 1] = (M[pa - 1] & FLAG) | ((cdc >> 4) & DIGIT); - pa = ADDR_A (pa, 2); } /* incr mem addr */ + cdc = cdr_to_alp[cdr_buf[i]]; /* translate */ + if (cdc < 0) { /* invalid? */ + ind[IN_RDCHK] = 1; /* set read check */ + inv = STOP_INVCHR; /* set return status */ + cdc = 0; }; + M[pa] = (M[pa] & FLAG) | (cdc & DIGIT); /* store 2 digits */ + M[pa - 1] = (M[pa - 1] & FLAG) | ((cdc >> 4) & DIGIT); + pa = ADDR_A (pa, 2); } /* incr mem addr */ break; default: /* invalid function */ return STOP_INVFNC; } @@ -333,14 +333,14 @@ case OP_WN: return cdp_num (pa, CD_LEN, FALSE); /* write numeric */ case OP_WA: for (i = 0; i < CD_LEN; i++) { /* one card */ - d = M[pa] & DIGIT; /* get digit pair */ - z = M[pa - 1] & DIGIT; - cdc = alp_to_cdp[(z << 4) | d]; /* translate */ - if (cdc < 0) { /* bad char? */ - ind[IN_WRCHK] = 1; /* set write check */ - CRETIOE (io_stop, STOP_INVCHR); } - cdp_buf[i] = cdc; /* store in buf */ - pa = ADDR_A (pa, 2); } /* incr mem addr */ + d = M[pa] & DIGIT; /* get digit pair */ + z = M[pa - 1] & DIGIT; + cdc = alp_to_cdp[(z << 4) | d]; /* translate */ + if (cdc < 0) { /* bad char? */ + ind[IN_WRCHK] = 1; /* set write check */ + CRETIOE (io_stop, STOP_INVCHR); } + cdp_buf[i] = cdc; /* store in buf */ + pa = ADDR_A (pa, 2); } /* incr mem addr */ return cdp_write (CD_LEN); /* punch buffer */ default: /* invalid function */ return STOP_INVFNC; } diff --git a/I1620/i1620_cpu.c b/I1620/i1620_cpu.c index b9b88287..f0e4a7e9 100644 --- a/I1620/i1620_cpu.c +++ b/I1620/i1620_cpu.c @@ -561,7 +561,7 @@ case OP_BB: PR1 = 1; } /* invalidate */ else if (IR2 != 1) { /* IR2 valid? */ BRANCH (IR2); /* return to IR2 */ - IR2 = 1; } /* invalidate */ + IR2 = 1; } /* invalidate */ else reason = STOP_INVRTN; /* MAR check */ break; @@ -770,23 +770,23 @@ case OP_BS: t = M[ADDR_A (saved_PC, I_SEL)] & DIGIT; /* get select */ switch (t) { /* case on select */ case 0: - idxe = idxb = 0; /* indexing off */ - break; + idxe = idxb = 0; /* indexing off */ + break; case 1: - idxe = 1; idxb = 0; /* index band A */ - break; + idxe = 1; idxb = 0; /* index band A */ + break; case 2: - idxe = idxb = 1; /* index band B */ - break; + idxe = idxb = 1; /* index band B */ + break; case 8: - iae = 0; /* indirect off */ - break; + iae = 0; /* indirect off */ + break; case 9: - iae = 1; /* indirect on */ - break; + iae = 1; /* indirect on */ + break; default: - reason = STOP_INVSEL; /* undefined */ - break; } + reason = STOP_INVSEL; /* undefined */ + break; } BRANCH (PAR); break; @@ -1683,9 +1683,10 @@ do { sd = M[s] & DIGIT; /* src digit */ MM (s); /* decr src addr */ MM (tbl); /* skip 1st tbl dig */ tblc = 0; /* count */ - do { tf = M[tbl] & FLAG; /* get next */ - MM (tbl); /* decr ptr */ - if (tblc++ > MEMSIZE) return STOP_FWRAP; } + do { + tf = M[tbl] & FLAG; /* get next */ + MM (tbl); /* decr ptr */ + if (tblc++ > MEMSIZE) return STOP_FWRAP; } while (tf == 0); /* until flag */ if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ while (sf == 0); diff --git a/I1620/i1620_lp.c b/I1620/i1620_lp.c index f120a2dc..e2320204 100644 --- a/I1620/i1620_lp.c +++ b/I1620/i1620_lp.c @@ -160,18 +160,18 @@ case OP_WN: return lpt_num (pa, 0, f1); /* write numeric */ case OP_WA: for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */ - d = M[pa] & DIGIT; /* get digit */ - z = M[pa - 1] & DIGIT; /* get zone */ - if ((d & REC_MARK) == REC_MARK) break; /* 8-2 char? */ - lpc = alp_to_lpt[(z << 4) | d]; /* translate pair */ - if (lpc < 0) { /* bad char? */ - ind[IN_WRCHK] = ind[IN_PRCHK] = 1; /* wr chk */ - inv = STOP_INVCHR; } /* set return status */ - lpt_buf[lpt_bptr] = lpc & 0x7F; /* fill buffer */ - pa = ADDR_A (pa, 2); } /* incr mem addr */ + d = M[pa] & DIGIT; /* get digit */ + z = M[pa - 1] & DIGIT; /* get zone */ + if ((d & REC_MARK) == REC_MARK) break; /* 8-2 char? */ + lpc = alp_to_lpt[(z << 4) | d]; /* translate pair */ + if (lpc < 0) { /* bad char? */ + ind[IN_WRCHK] = ind[IN_PRCHK] = 1; /* wr chk */ + inv = STOP_INVCHR; } /* set return status */ + lpt_buf[lpt_bptr] = lpc & 0x7F; /* fill buffer */ + pa = ADDR_A (pa, 2); } /* incr mem addr */ if ((f1 & 1) == 0) { ; /* print now? */ - r = lpt_print (); /* print line */ - if (r != SCPE_OK) return r; } + r = lpt_print (); /* print line */ + if (r != SCPE_OK) return r; } CRETIOE (io_stop, inv); default: /* invalid function */ return STOP_INVFNC; } @@ -191,11 +191,11 @@ end = pa + len; for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */ d = M[pa]; /* get digit */ if (len? (pa >= end): /* end reached? */ - ((d & REC_MARK) == REC_MARK)) break; + ((d & REC_MARK) == REC_MARK)) break; lpc = num_to_lpt[d]; /* translate */ if (lpc < 0) { /* bad char? */ - ind[IN_WRCHK] = ind[IN_PRCHK] = 1; /* wr chk */ - inv = STOP_INVCHR; } /* set return status */ + ind[IN_WRCHK] = ind[IN_PRCHK] = 1; /* wr chk */ + inv = STOP_INVCHR; } /* set return status */ lpt_buf[lpt_bptr++] = lpc & 0x7F; /* fill buffer */ PP (pa); } /* incr mem addr */ if ((f1 & 1) == 0) { /* print now? */ @@ -226,10 +226,10 @@ if (lpt_bptr) { /* any line? */ lpt_unit.pos = ftell (lpt_unit.fileref); /* update pos */ lpt_buf_init (); /* reinit buf */ if (ferror (lpt_unit.fileref)) { /* error? */ - ind[IN_PRCHK] = ind[IN_WRCHK] = 1; /* wr, pri check */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } } + ind[IN_PRCHK] = ind[IN_WRCHK] = 1; /* wr, pri check */ + perror ("LPT I/O error"); + clearerr (lpt_unit.fileref); + return SCPE_IOERR; } } lpt_savctrl = 0x61; /* reset ctrl */ if ((ctrl & K_LIN) == ((ctrl & K_IMM)? 0: K_LIN)) /* space lines? */ diff --git a/I1620/i1620_pt.c b/I1620/i1620_pt.c index 40b9a7e3..251d2e9b 100644 --- a/I1620/i1620_pt.c +++ b/I1620/i1620_pt.c @@ -205,34 +205,34 @@ t_stat r, inv = SCPE_OK; switch (op) { /* case on op */ case OP_RN: /* read numeric */ for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */ - r = ptr_read (&ptc, TRUE); /* read frame */ - if (r != SCPE_OK) return r; /* error? */ - if (ptc & PT_EL) { /* end record? */ - M[pa] = REC_MARK; /* store rec mark */ - CRETIOE (io_stop, inv); } /* done */ - if (bad_par[ptc]) { /* bad parity? */ - ind[IN_RDCHK] = 1; /* set read check */ - inv = STOP_INVCHR; /* set return status */ - M[pa] = 0; } /* store zero */ - else M[pa] = ptr_to_num[ptc]; /* translate, store */ - PP (pa); } /* incr mem addr */ + r = ptr_read (&ptc, TRUE); /* read frame */ + if (r != SCPE_OK) return r; /* error? */ + if (ptc & PT_EL) { /* end record? */ + M[pa] = REC_MARK; /* store rec mark */ + CRETIOE (io_stop, inv); } /* done */ + if (bad_par[ptc]) { /* bad parity? */ + ind[IN_RDCHK] = 1; /* set read check */ + inv = STOP_INVCHR; /* set return status */ + M[pa] = 0; } /* store zero */ + else M[pa] = ptr_to_num[ptc]; /* translate, store */ + PP (pa); } /* incr mem addr */ break; case OP_RA: /* read alphameric */ for (i = 0; i < MEMSIZE; i = i + 2) { /* (stop runaway) */ - r = ptr_read (&ptc, TRUE); /* read frame */ - if (r != SCPE_OK) return r; /* error? */ - if (ptc & PT_EL) { /* end record? */ - M[pa] = REC_MARK; /* store rec mark */ - M[pa - 1] = 0; - CRETIOE (io_stop, inv); } /* done */ - mc = ptr_to_alp[ptc]; /* translate */ - if (bad_par[ptc] || (mc < 0)) { /* bad par or char? */ - ind[IN_RDCHK] = 1; /* set read check */ - inv = STOP_INVCHR; /* set return status */ - mc = 0; } /* store blank */ - M[pa] = (M[pa] & FLAG) | (mc & DIGIT); /* store 2 digits */ - M[pa - 1] = (M[pa - 1] & FLAG) | ((mc >> 4) & DIGIT); - pa = ADDR_A (pa, 2); } /* incr mem addr */ + r = ptr_read (&ptc, TRUE); /* read frame */ + if (r != SCPE_OK) return r; /* error? */ + if (ptc & PT_EL) { /* end record? */ + M[pa] = REC_MARK; /* store rec mark */ + M[pa - 1] = 0; + CRETIOE (io_stop, inv); } /* done */ + mc = ptr_to_alp[ptc]; /* translate */ + if (bad_par[ptc] || (mc < 0)) { /* bad par or char? */ + ind[IN_RDCHK] = 1; /* set read check */ + inv = STOP_INVCHR; /* set return status */ + mc = 0; } /* store blank */ + M[pa] = (M[pa] & FLAG) | (mc & DIGIT); /* store 2 digits */ + M[pa - 1] = (M[pa - 1] & FLAG) | ((mc >> 4) & DIGIT); + pa = ADDR_A (pa, 2); } /* incr mem addr */ break; default: /* invalid function */ return STOP_INVFNC; } @@ -251,19 +251,19 @@ if ((cpu_unit.flags & IF_BIN) == 0) return STOP_INVIO; switch (op) { /* case on op */ case OP_RA: /* read alphameric */ for (i = 0; i < MEMSIZE; i = i + 2) { /* (stop runaway) */ - r = ptr_read (&ptc, FALSE); /* read frame */ - if (r != SCPE_OK) return r; /* error? */ - if (ptc & PT_EL) { /* end record? */ - M[pa] = REC_MARK; /* store rec mark */ - M[pa - 1] = 0; - CRETIOE (io_stop, inv); } /* done */ - if (bad_par[ptc]) { /* bad parity? */ - ind[IN_RDCHK] = 1; /* set read check */ - inv = STOP_INVCHR; } /* set return status */ - M[pa] = (M[pa] & FLAG) | (ptc & 07); /* store 2 digits */ - M[pa - 1] = (M[pa - 1] & FLAG) | - (((ptc >> 5) & 06) | ((ptc >> 3) & 1)); - pa = ADDR_A (pa, 2); } /* incr mem addr */ + r = ptr_read (&ptc, FALSE); /* read frame */ + if (r != SCPE_OK) return r; /* error? */ + if (ptc & PT_EL) { /* end record? */ + M[pa] = REC_MARK; /* store rec mark */ + M[pa - 1] = 0; + CRETIOE (io_stop, inv); } /* done */ + if (bad_par[ptc]) { /* bad parity? */ + ind[IN_RDCHK] = 1; /* set read check */ + inv = STOP_INVCHR; } /* set return status */ + M[pa] = (M[pa] & FLAG) | (ptc & 07); /* store 2 digits */ + M[pa - 1] = (M[pa - 1] & FLAG) | + (((ptc >> 5) & 06) | ((ptc >> 3) & 1)); + pa = ADDR_A (pa, 2); } /* incr mem addr */ break; default: /* invalid function */ return STOP_INVFNC; } @@ -281,12 +281,12 @@ if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ return SCPE_UNATT; } do { if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read char */ - ind[IN_RDCHK] = 1; /* err, rd chk */ - if (feof (ptr_unit.fileref)) - printf ("PTR end of file\n"); - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } + ind[IN_RDCHK] = 1; /* err, rd chk */ + if (feof (ptr_unit.fileref)) + printf ("PTR end of file\n"); + else perror ("PTR I/O error"); + clearerr (ptr_unit.fileref); + return SCPE_IOERR; } *c = temp & 0377; /* save char */ ptr_unit.pos = ptr_unit.pos + 1; } /* incr file addr */ while (ignfeed && (*c == PT_FD)); /* until not feed */ @@ -345,17 +345,17 @@ case OP_WN: return ptp_num (pa, 0); /* punch numeric */ case OP_WA: for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */ - d = M[pa] & DIGIT; /* get digit */ - z = M[pa - 1] & DIGIT; /* get zone */ - if ((d & REC_MARK) == REC_MARK) /* 8-2 char? */ - return ptp_write (PT_EL); /* end record */ - ptc = alp_to_ptp[(z << 4) | d]; /* translate pair */ - if (ptc < 0) { /* bad char? */ - ind[IN_WRCHK] = 1; /* write check */ - CRETIOE (io_stop, STOP_INVCHR); } - r = ptp_write (ptc); /* write char */ - if (r != SCPE_OK) return r; /* error? */ - pa = ADDR_A (pa, 2); } /* incr mem addr */ + d = M[pa] & DIGIT; /* get digit */ + z = M[pa - 1] & DIGIT; /* get zone */ + if ((d & REC_MARK) == REC_MARK) /* 8-2 char? */ + return ptp_write (PT_EL); /* end record */ + ptc = alp_to_ptp[(z << 4) | d]; /* translate pair */ + if (ptc < 0) { /* bad char? */ + ind[IN_WRCHK] = 1; /* write check */ + CRETIOE (io_stop, STOP_INVCHR); } + r = ptp_write (ptc); /* write char */ + if (r != SCPE_OK) return r; /* error? */ + pa = ADDR_A (pa, 2); } /* incr mem addr */ break; default: /* invalid function */ return STOP_INVFNC; } @@ -374,15 +374,15 @@ if ((cpu_unit.flags & IF_BIN) == 0) return STOP_INVIO; switch (op) { /* decode op */ case OP_WA: for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */ - d = M[pa] & DIGIT; /* get digit */ - z = M[pa - 1] & DIGIT; /* get zone */ - if ((d & REC_MARK) == REC_MARK) /* 8-2 char? */ - return ptp_write (PT_EL); /* end record */ - ptc = ((z & 06) << 5) | ((z & 01) << 3) | (d & 07); - if (bad_par[ptc]) ptc = ptc | PT_C; /* set parity */ - r = ptp_write (ptc); /* write char */ - if (r != SCPE_OK) return r; /* error? */ - pa = ADDR_A (pa, 2); } /* incr mem addr */ + d = M[pa] & DIGIT; /* get digit */ + z = M[pa - 1] & DIGIT; /* get zone */ + if ((d & REC_MARK) == REC_MARK) /* 8-2 char? */ + return ptp_write (PT_EL); /* end record */ + ptc = ((z & 06) << 5) | ((z & 01) << 3) | (d & 07); + if (bad_par[ptc]) ptc = ptc | PT_C; /* set parity */ + r = ptp_write (ptc); /* write char */ + if (r != SCPE_OK) return r; /* error? */ + pa = ADDR_A (pa, 2); } /* incr mem addr */ break; default: /* invalid function */ return STOP_INVFNC; } @@ -402,7 +402,7 @@ for (i = 0; i < MEMSIZE; i++) { /* stop runaway */ d = M[pa] & (FLAG | DIGIT); /* get char */ if (len? (pa >= end): /* dump: end reached? */ ((d & REC_MARK) == REC_MARK)) /* write: rec mark? */ - return ptp_write (PT_EL); /* end record */ + return ptp_write (PT_EL); /* end record */ r = ptp_write (num_to_ptp[d]); /* write */ if (r != SCPE_OK) return r; /* error? */ PP (pa); } /* incr mem addr */ diff --git a/I1620/i1620_tty.c b/I1620/i1620_tty.c index 5520968a..a268e1c0 100644 --- a/I1620/i1620_tty.c +++ b/I1620/i1620_tty.c @@ -24,6 +24,8 @@ in this Software without prior written authorization from Robert M Supnik. tty console typewriter + + 22-Dec-02 RMS Added break test */ #include "i1620_defs.h" @@ -153,43 +155,43 @@ switch (op) { /* case on op */ case OP_K: /* control */ switch (f1) { /* case on control */ case 1: /* space */ - tto_write (' '); - break; + tto_write (' '); + break; case 2: /* return */ - tto_write ('\r'); - break; + tto_write ('\r'); + break; case 3: /* backspace */ - if ((cpu_unit.flags & IF_MII) == 0) return STOP_INVFNC; - tto_write ('\b'); - break; + if ((cpu_unit.flags & IF_MII) == 0) return STOP_INVFNC; + tto_write ('\b'); + break; case 4: /* index */ - if ((cpu_unit.flags & IF_MII) == 0) return STOP_INVFNC; - tto_write ('\n'); - break; + if ((cpu_unit.flags & IF_MII) == 0) return STOP_INVFNC; + tto_write ('\n'); + break; case 8: /* tab */ - tto_write ('\t'); - break; + tto_write ('\t'); + break; default: - return STOP_INVFNC; } + return STOP_INVFNC; } return SCPE_OK; case OP_RN: /* read numeric */ tti_unlock (); /* unlock keyboard */ for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */ - r = tti_rnum (&ttc); /* read char */ - if (r != SCPE_OK) return r; /* error? */ - if (ttc == 0x7F) return SCPE_OK; /* end record? */ - M[pa] = ttc & (FLAG | DIGIT); /* store char */ - PP (pa); } /* incr mem addr */ + r = tti_rnum (&ttc); /* read char */ + if (r != SCPE_OK) return r; /* error? */ + if (ttc == 0x7F) return SCPE_OK; /* end record? */ + M[pa] = ttc & (FLAG | DIGIT); /* store char */ + PP (pa); } /* incr mem addr */ break; case OP_RA: /* read alphameric */ tti_unlock (); for (i = 0; i < MEMSIZE; i = i + 2) { /* (stop runaway) */ - r = tti_ralp (&ttc); /* read char */ - if (r != SCPE_OK) return r; /* error? */ - if (ttc == 0x7F) return SCPE_OK; /* end record? */ - M[pa] = (M[pa] & FLAG) | (ttc & DIGIT); /* store 2 digits */ - M[pa - 1] = (M[pa - 1] & FLAG) | ((ttc >> 4) & DIGIT); - pa = ADDR_A (pa, 2); } /* incr mem addr */ + r = tti_ralp (&ttc); /* read char */ + if (r != SCPE_OK) return r; /* error? */ + if (ttc == 0x7F) return SCPE_OK; /* end record? */ + M[pa] = (M[pa] & FLAG) | (ttc & DIGIT); /* store 2 digits */ + M[pa - 1] = (M[pa - 1] & FLAG) | ((ttc >> 4) & DIGIT); + pa = ADDR_A (pa, 2); } /* incr mem addr */ break; case OP_DN: return tto_num (pa, 20000 - (pa % 20000)); /* dump numeric */ @@ -197,16 +199,16 @@ case OP_WN: return tto_num (pa, 0); /* type numeric */ case OP_WA: for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */ - d = M[pa] & DIGIT; /* get digit */ - if ((d & 0xA) == REC_MARK) /* 8-2 char? */ - CRETIOE (io_stop, inv); /* end record */ - d = ((M[pa - 1] & DIGIT) << 4) | d; /* get digit pair */ - ttc = alp_to_tto[d]; /* translate */ - if (ttc < 0) { /* bad char? */ - ind[IN_WRCHK] = 1; /* set write check */ - inv = STOP_INVCHR; } /* set return status */ - tto_write (ttc & 0x7F); /* write */ - pa = ADDR_A (pa, 2); } /* incr mem addr */ + d = M[pa] & DIGIT; /* get digit */ + if ((d & 0xA) == REC_MARK) /* 8-2 char? */ + CRETIOE (io_stop, inv); /* end record */ + d = ((M[pa - 1] & DIGIT) << 4) | d; /* get digit pair */ + ttc = alp_to_tto[d]; /* translate */ + if (ttc < 0) { /* bad char? */ + ind[IN_WRCHK] = 1; /* set write check */ + inv = STOP_INVCHR; } /* set return status */ + tto_write (ttc & 0x7F); /* write */ + pa = ADDR_A (pa, 2); } /* incr mem addr */ break; default: /* invalid function */ return STOP_INVFNC; } @@ -260,7 +262,7 @@ t_stat tti_read (int8 *c) int32 t; do { t = sim_poll_kbd (); } /* get character */ -while (t == SCPE_OK); +while ((t == SCPE_OK) || (t & SCPE_BREAK)); /* ignore break */ if (t < SCPE_KFLAG) return t; /* error? */ *c = t & 0177; /* store character */ return SCPE_OK; @@ -279,7 +281,7 @@ for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */ d = M[pa]; /* get char */ if (len? (pa >= end): /* dump: end reached? */ ((d & REC_MARK) == REC_MARK)) /* write: rec mark? */ - return SCPE_OK; /* end operation */ + return SCPE_OK; /* end operation */ if (d & FLAG) tto_write ('~'); /* flag? */ r = tto_write (num_to_tto[d & DIGIT]); /* write */ if (r != SCPE_OK) return r; /* error? */ diff --git a/Ibm1130/ibm1130_cpu.c b/Ibm1130/ibm1130_cpu.c index a41001a1..bf5b09e7 100644 --- a/Ibm1130/ibm1130_cpu.c +++ b/Ibm1130/ibm1130_cpu.c @@ -190,7 +190,7 @@ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_reset (DEVICE *dptr); t_stat cpu_svc (UNIT *uptr); -t_stat cpu_set_size (UNIT *uptr, int32 value); +t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc); void calc_ints (void); extern t_stat ts_wr (int32 data, int32 addr, int32 access); @@ -1182,7 +1182,7 @@ t_stat cpu_svc (UNIT *uptr) * Memory allocation * ------------------------------------------------------------------------ */ -t_stat cpu_set_size (UNIT *uptr, int32 value) +t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc) { t_bool used; int32 i; diff --git a/Ibm1130/ibm1130_cr.c b/Ibm1130/ibm1130_cr.c index 9223b85f..72167626 100644 --- a/Ibm1130/ibm1130_cr.c +++ b/Ibm1130/ibm1130_cr.c @@ -149,12 +149,12 @@ extern int32 sim_switches; static t_stat cr_svc (UNIT *uptr); static t_stat cr_reset (DEVICE *dptr); -static t_stat cr_set_code (UNIT *uptr, int32 match); +static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc); static t_stat cr_attach (UNIT *uptr, char *cptr); static t_stat cr_detach (UNIT *uptr); static t_stat cp_reset (DEVICE *dptr); -static t_stat cp_set_code (UNIT *uptr, int32 match); +static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc); static t_stat cp_detach (UNIT *uptr); static int16 cr_dsw = 0; /* device status word */ @@ -497,12 +497,12 @@ t_stat set_active_cr_code (int match) return SCPE_OK; } -t_stat cr_set_code (UNIT *uptr, int32 match) +t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) { return set_active_cr_code(match); } -t_stat cp_set_code (UNIT *uptr, int32 match) +t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) { CPCODE *code; int ncode; @@ -550,7 +550,7 @@ t_stat load_cr_boot (int drvno) return SCPE_OK; } -t_stat cr_boot (int unitno) +t_stat cr_boot (int unitno, DEVICE *dptr) { t_stat rval; short buf[80]; @@ -917,7 +917,7 @@ static t_bool nextdeck (void) static t_stat cr_reset (DEVICE *dptr) { - cr_set_code(&cr_unit, active_cr_code & UNIT_CODE); /* reset to specified code table */ + cr_set_code(&cr_unit, active_cr_code & UNIT_CODE, NULL, NULL); /* reset to specified code table */ readstate = STATION_EMPTY; @@ -948,7 +948,7 @@ static t_stat cr_reset (DEVICE *dptr) static t_stat cp_reset (DEVICE *dptr) { - cp_set_code(&cp_unit, cp_unit.flags & UNIT_CODE); + cp_set_code(&cp_unit, cp_unit.flags & UNIT_CODE, NULL, NULL); punchstate = STATION_EMPTY; cp_unit.COLUMN = -1; diff --git a/Ibm1130/ibm1130_defs.h b/Ibm1130/ibm1130_defs.h index c317f7d9..513bddfe 100644 --- a/Ibm1130/ibm1130_defs.h +++ b/Ibm1130/ibm1130_defs.h @@ -259,7 +259,7 @@ void xio_error (char *msg); void bail (char *msg); t_stat load_cr_boot (int drv); -t_stat cr_boot (int unitno); +t_stat cr_boot (int unitno, DEVICE *dptr); void calc_ints (void); /* recalculate interrupt bitmask */ void trace_io (char *fmt, ...); /* debugging printout */ void scp_panic (char *msg); /* bail out of simulator */ diff --git a/Ibm1130/ibm1130_disk.c b/Ibm1130/ibm1130_disk.c index 23c56fd0..6e517e91 100644 --- a/Ibm1130/ibm1130_disk.c +++ b/Ibm1130/ibm1130_disk.c @@ -80,7 +80,7 @@ static t_stat dsk_svc (UNIT *uptr); static t_stat dsk_reset (DEVICE *dptr); static t_stat dsk_attach (UNIT *uptr, char *cptr); static t_stat dsk_detach (UNIT *uptr); -static t_stat dsk_boot (int unitno); +static t_stat dsk_boot (int unitno, DEVICE *dptr); static void diskfail (UNIT *uptr, int errflag); @@ -511,7 +511,7 @@ static t_stat dsk_detach (UNIT *uptr) // boot routine - if they type BOOT DSK, load the standard boot card. -static t_stat dsk_boot (int unitno) +static t_stat dsk_boot (int unitno, DEVICE *dptr) { t_stat rval; diff --git a/Ibm1130/ibm1130_gui.c b/Ibm1130/ibm1130_gui.c index 7266d469..ecad18c0 100644 --- a/Ibm1130/ibm1130_gui.c +++ b/Ibm1130/ibm1130_gui.c @@ -984,7 +984,7 @@ void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam) if (! running) { /* if card reader is attached to a file, do cold start read of one card */ IAR = 0; /* reset IAR */ // stuff_cmd("boot cr"); - if (cr_boot(0) != SCPE_OK) /* load boot card */ + if (cr_boot(0, NULL) != SCPE_OK) /* load boot card */ remark_cmd("IPL failed"); } break; diff --git a/Ibm1130/asm1130.c b/Ibm1130/utils/asm1130.c similarity index 96% rename from Ibm1130/asm1130.c rename to Ibm1130/utils/asm1130.c index 4c35dee2..b1643e91 100644 --- a/Ibm1130/asm1130.c +++ b/Ibm1130/utils/asm1130.c @@ -13,6 +13,7 @@ // ASM1130 - IBM 1130 Cross Assembler // // Version +// 1.07 - 2003Jan05 - Filenames are now left in lower case. SYMBOLS.SYS stays all upper case // 1.06 - 2002May02 - Fixed bug in ebdic constants (data goes into low byte) // First stab at adding ISS level # info, this is iffy // 1.05 - 2002Apr24 - Made negative BSS size a warning not an error, as it @@ -155,7 +156,7 @@ #define TRUE 1 #define FALSE 0 -#define VERSION "ASM1130 CROSS ASSEMBLER V1.06" +#define VERSION "ASM1130 CROSS ASSEMBLER V1.07" #define ISTV 0x33 // magic number from DMS R2V12 monitorm symbol @ISTV @@ -1880,9 +1881,10 @@ void proc (char *fname) else strcpy(curfn, fname); // otherwise use extension specified -#if (defined(WIN32) || defined(VMS)) - upcase(curfn); // only force uppercase of name on Windows and VMS -#endif +// let's leave filename case alone even if it doesn't matter +//#if (defined(WIN32) || defined(VMS)) +// upcase(curfn); // only force uppercase of name on Windows and VMS +//#endif if (progname[0] == '\0') { // pick up primary filename if ((c = strrchr(curfn, '\\')) == NULL) diff --git a/Ibm1130/asm1130.mak b/Ibm1130/utils/asm1130.mak similarity index 100% rename from Ibm1130/asm1130.mak rename to Ibm1130/utils/asm1130.mak diff --git a/Ibm1130/bindump.c b/Ibm1130/utils/bindump.c similarity index 100% rename from Ibm1130/bindump.c rename to Ibm1130/utils/bindump.c diff --git a/Ibm1130/bindump.mak b/Ibm1130/utils/bindump.mak similarity index 100% rename from Ibm1130/bindump.mak rename to Ibm1130/utils/bindump.mak diff --git a/Ibm1130/checkdisk.c b/Ibm1130/utils/checkdisk.c similarity index 100% rename from Ibm1130/checkdisk.c rename to Ibm1130/utils/checkdisk.c diff --git a/Ibm1130/checkdisk.mak b/Ibm1130/utils/checkdisk.mak similarity index 100% rename from Ibm1130/checkdisk.mak rename to Ibm1130/utils/checkdisk.mak diff --git a/Ibm1130/diskview.c b/Ibm1130/utils/diskview.c similarity index 100% rename from Ibm1130/diskview.c rename to Ibm1130/utils/diskview.c diff --git a/Ibm1130/diskview.mak b/Ibm1130/utils/diskview.mak similarity index 100% rename from Ibm1130/diskview.mak rename to Ibm1130/utils/diskview.mak diff --git a/Ibm1130/mkboot.c b/Ibm1130/utils/mkboot.c similarity index 100% rename from Ibm1130/mkboot.c rename to Ibm1130/utils/mkboot.c diff --git a/Ibm1130/mkboot.mak b/Ibm1130/utils/mkboot.mak similarity index 100% rename from Ibm1130/mkboot.mak rename to Ibm1130/utils/mkboot.mak diff --git a/Ibm1130/viewdeck.c b/Ibm1130/utils/viewdeck.c similarity index 100% rename from Ibm1130/viewdeck.c rename to Ibm1130/utils/viewdeck.c diff --git a/Ibm1130/viewdeck.mak b/Ibm1130/utils/viewdeck.mak similarity index 100% rename from Ibm1130/viewdeck.mak rename to Ibm1130/utils/viewdeck.mak diff --git a/Interdata/id16_cpu.c b/Interdata/id16_cpu.c new file mode 100644 index 00000000..dfd4c606 --- /dev/null +++ b/Interdata/id16_cpu.c @@ -0,0 +1,1718 @@ +/* id16_cpu.c: Interdata 16b CPU simulator + + Copyright (c) 2000-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + The register state for the Interdata 16b CPU is: + + R[0:F]<0:15> general registers + F[0:7]<0:31> single precision floating point registers + D[0:7]<0:63> double precision floating point registers + PSW<0:31> processor status word, including + STAT<0:11> status flags + CC<0:3> condition codes + PC<0:15> program counter + int_req[8]<0:31> interrupt requests + int_enb[8]<0:31> interrupt enables + + The Interdata 16b systems have four instruction formats: register to + register, short format, register to memory, and register to storage. + The formats are: + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | R2 | register-register + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | N | short format + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | RX | register-memory + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | address | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | RX | register-storage + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | address | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + For register-memory and register-storage instructions, an effective + address is calculated as follows: + + effective addr = address + RX (if RX > 0) + + Register-memory instructions can access an address space of 64K bytes. + + The Interdata 16b product line had many different models, with varying + instruction sets: + + instruction group model = 3 4 5 70 80 716 816 816E + base group (61) y y y y y y y y + AL, LM, STM (3) - y y y y y y y + single prec fp (13) - y y y y y y y + model 5 group (36) - - y y y y y y + double prec fp (17) - - - - - - y y + memory extension (4) - - - - - - - y + + This allows the most common CPU options to be covered by just five + model selections: I3, I4, I5/70/80/716, I816, and I816E. Variations + within a model (e.g., 816 with no floating point or just single + precision floating point) are not implemented. + + The I3 kept its general registers in memory; this is not simulated. + Single precision (only) floating point was implemented in microcode, + did not have a guard digit, and kept the floating point registers in + memory. Double precision floating point was implemented in hardware, + provided a guard digit for single precision (but not double), and + kept the floating point registers in hardware. +*/ + +/* This routine is the instruction decode routine for the Interdata CPU. + It is called from the simulator control program to execute + instructions in simulated memory, starting at the simulated PC. + It runs until 'reason' is set non-zero. + + General notes: + + 1. Reasons to stop. The simulator can be stopped by: + + HALT instruction + breakpoint encountered + wait state and no I/O outstanding + invalid instruction + I/O error in I/O simulator + + 2. Interrupts. Each device has an interrupt armed flag, an interrupt + request flag, and an interrupt enabled flag. To facilitate evaluation, + all interrupt requests are kept in int_req, and all enables in int_enb. + Interrupt armed flags are local to devices. If external interrupts are + enabled in the PSW, and a request is pending, an interrupt occurs. + + 3. Non-existent memory. On the Interdata 16b, reads to non-existent + memory return zero, and writes are ignored. In the simulator, the + largest possible memory is instantiated and initialized to zero. + Thus, only writes need be checked against actual memory size. + + 4. Adding I/O devices. These modules must be modified: + + id_defs.h add device interrupt definitions + id16_sys.c add sim_devices table entry +*/ + +#include "id_defs.h" + +#define PCQ_SIZE 64 /* must be 2**n */ +#define PCQ_MASK (PCQ_SIZE - 1) +#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = oPC +#define VAMASK VAMASK16 +#define VA_S1 0x8000 /* S0/S1 flag */ + +#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */ +#define UNIT_V_ID4 (UNIT_V_UF + 1) +#define UNIT_V_716 (UNIT_V_UF + 2) +#define UNIT_V_816 (UNIT_V_UF + 3) +#define UNIT_V_816E (UNIT_V_UF + 4) +#define UNIT_MSIZE (1 << UNIT_V_MSIZE) +#define UNIT_ID4 (1 << UNIT_V_ID4) +#define UNIT_716 (1 << UNIT_V_716) +#define UNIT_816 (1 << UNIT_V_816) +#define UNIT_816E (1 << UNIT_V_816E) +#define UNIT_TYPE (UNIT_ID4 | UNIT_716 | UNIT_816 | UNIT_816E) + +#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | 0xFFFF8000)): \ + ((int32) ((x) & 0x7FFF))) +#define CC_GL_16(x) if ((x) & SIGN16) cc = CC_L; \ + else if (x) cc = CC_G; \ + else cc = 0 +#define CC_GL_32(x) if ((x) & SIGN32) cc = CC_L; \ + else if (x) cc = CC_G; \ + else cc = 0 +#define BUILD_PSW(x) (((PSW & ~CC_MASK) | (x)) & psw_mask) +#define CPU_x16 (cpu_unit.flags & (UNIT_716 | UNIT_816 | UNIT_816E)) + +uint32 GREG[16] = { 0 }; /* general registers */ +uint16 *M = NULL; /* memory */ +uint32 *R = &GREG[0]; /* register set ptr */ +uint32 F[8] = { 0 }; /* sp fp registers */ +dpr_t D[8] = { 0 }; /* dp fp registers */ +uint32 PSW = 0; /* processor status word */ +uint32 psw_mask = PSW_x16; /* PSW mask */ +uint32 PC = 0; /* program counter */ +uint32 SR = 0; /* switch register */ +uint32 DR = 0; /* display register */ +uint32 DRX = 0; /* display extension */ +uint32 drmod = 0; /* mode */ +uint32 srpos = 0; /* switch register pos */ +uint32 drpos = 0; /* display register pos */ +uint32 s0_rel = 0; /* S0 relocation */ +uint32 s1_rel = 0; /* S1 relocation */ +uint32 int_req[INTSZ] = { 0 }; /* interrupt requests */ +uint32 int_enb[INTSZ] = { 0 }; /* interrupt enables */ +int32 blkiop = -1; /* block I/O in prog */ +uint32 qevent = 0; /* events */ +uint32 stop_inst = 0; /* stop on ill inst */ +uint32 stop_wait = 0; /* stop on wait */ +uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ +int32 pcq_p = 0; /* PC queue ptr */ +REG *pcq_r = NULL; /* PC queue reg ptr */ +uint32 dec_flgs = 0; /* decode flags */ +uint32 fp_in_hwre = 0; /* ucode/hwre fp */ +uint32 pawidth = PAWIDTH16; /* phys addr mask */ +uint32 cpu_log = 0; /* debug logging */ +struct BlockIO blk_io; /* block I/O status */ +uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL }; + +extern int32 sim_interval; +extern int32 sim_int_char; +extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +extern UNIT pic_unit, lfc_unit, pas_unit; /* timers */ + +uint32 ReadB (uint32 loc); +uint32 ReadH (uint32 loc); +void WriteB (uint32 loc, uint32 val); +void WriteH (uint32 loc, uint32 val); +uint32 int_auto (uint32 dev, uint32 cc); +uint32 addtoq (uint32 ea, uint32 val, uint32 flg); +uint32 remfmq (uint32 ea, uint32 r1, uint32 flg); +uint32 newPSW (uint32 val); +uint32 swap_psw (uint32 loc, uint32 cc); +uint32 testsysq (uint32); +uint32 display (uint32 dev, uint32 op, uint32 dat); +t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); +t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); +t_stat cpu_reset (DEVICE *dptr); +t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc); + +extern t_bool devtab_init (void); +extern void int_eval (void); +extern uint32 int_getdev (void); +extern t_bool sch_blk (uint32 dev); +extern uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea); +extern uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea); +extern uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea); +extern uint32 f_m (uint32 op, uint32 r1, uint32 r2, uint32 ea); +extern uint32 f_d (uint32 op, uint32 r1, uint32 r2, uint32 ea); +extern uint32 f_fix (uint32 op, uint32 r1, uint32 r2); +extern uint32 f_flt (uint32 op, uint32 r1, uint32 r2); + +/* Instruction decoding table - flags are first implementation */ + +const uint16 decrom[256] = { + 0, /* 00 */ + OP_RR, /* BALR */ + OP_RR, /* BTCR */ + OP_RR, /* BFCR */ + OP_RR, /* NHR */ + OP_RR, /* CLHR */ + OP_RR, /* OHR */ + OP_RR, /* XHR */ + OP_RR, /* LHR */ + OP_RR | OP_716, /* CHR */ + OP_RR, /* AHR */ + OP_RR, /* SHR */ + OP_RR, /* MHR */ + OP_RR, /* DHR */ + OP_RR, /* ACHR */ + OP_RR, /* SCHR */ + 0, 0, 0, /* 10:12 */ + OP_RR | OP_816E | OP_PRV, /* SETMR */ + 0, 0, 0, 0, /* 14:1F */ + 0, 0, 0, 0, 0, 0, 0, 0, + OP_NO | OP_716, /* BTBS */ + OP_NO | OP_716, /* BTFS */ + OP_NO | OP_716, /* BFBS */ + OP_NO | OP_716, /* BFFS */ + OP_NO | OP_716, /* LIS */ + OP_NO | OP_716, /* LCS */ + OP_NO | OP_716, /* AIS */ + OP_NO | OP_716, /* SIS */ + OP_NO | OP_ID4, /* LER */ + OP_NO | OP_ID4, /* CER */ + OP_NO | OP_ID4, /* AER */ + OP_NO | OP_ID4, /* SER */ + OP_NO | OP_ID4, /* MER */ + OP_NO | OP_ID4, /* DER */ + OP_NO | OP_816, /* FXR */ + OP_NO | OP_816, /* FLR */ + 0, 0, 0, /* 30:32 */ + OP_RR | OP_816E | OP_PRV, /* LPSR */ + 0, 0, 0, 0, /* 34:37 */ + OP_NO | OP_816 | OP_DPF, /* LDR */ + OP_NO | OP_816 | OP_DPF, /* CDR */ + OP_NO | OP_816 | OP_DPF, /* ADR */ + OP_NO | OP_816 | OP_DPF, /* SDR */ + OP_NO | OP_816 | OP_DPF, /* MDR */ + OP_NO | OP_816 | OP_DPF, /* DDR */ + OP_NO | OP_816 | OP_DPF, /* FXDR */ + OP_NO | OP_816 | OP_DPF, /* FLDR */ + OP_RX, /* STH */ + OP_RX, /* BAL */ + OP_RX, /* BTC */ + OP_RX, /* BFC */ + OP_RXH, /* NH */ + OP_RXH, /* CLH */ + OP_RXH, /* OH */ + OP_RXH, /* XH */ + OP_RXH, /* LH */ + OP_RXH | OP_716, /* CH */ + OP_RXH, /* AH */ + OP_RXH, /* SH */ + OP_RXH, /* MH */ + OP_RXH, /* DH */ + OP_RXH, /* ACH */ + OP_RXH, /* SCH */ + 0, 0, 0, /* 50:52 */ + OP_RXH | OP_816E | OP_PRV, /* SETM */ + 0, 0, 0, 0, /* 54:5F */ + 0, 0, 0, 0, 0, 0, 0, 0, + OP_RX | OP_ID4, /* STE */ + OP_RXH | OP_716, /* AHM */ + 0, 0, /* 62:63 */ + OP_RX | OP_716, /* ATL */ + OP_RX | OP_716, /* ABL */ + OP_RX | OP_716, /* RTL */ + OP_RX | OP_716, /* RBL */ + OP_RX | OP_ID4, /* LE */ + OP_RX | OP_ID4, /* CE */ + OP_RX | OP_ID4, /* AE */ + OP_RX | OP_ID4, /* SE */ + OP_RX | OP_ID4, /* ME */ + OP_RX | OP_ID4, /* DE */ + 0, 0, /* 6E:6F */ + OP_RX | OP_816 | OP_DPF, /* STD */ + OP_RX | OP_816, /* SME */ + OP_RX | OP_816, /* LME */ + OP_RXH | OP_816E | OP_PRV, /* LPS */ + 0, 0, 0, 0, /* 74:7F */ + OP_RX | OP_816 | OP_DPF, /* LD */ + OP_RX | OP_816 | OP_DPF, /* CD */ + OP_RX | OP_816 | OP_DPF, /* AD */ + OP_RX | OP_816 | OP_DPF, /* SD */ + OP_RX | OP_816 | OP_DPF, /* MD */ + OP_RX | OP_816 | OP_DPF, /* DD */ + OP_RX | OP_816 | OP_DPF, /* STMD */ + OP_RX | OP_816 | OP_DPF, /* LMD */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 80:8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + OP_NO | OP_716, /* SRLS */ + OP_NO | OP_716, /* SLLS */ + OP_NO, /* STBR */ + OP_NO, /* LDBR */ + OP_NO | OP_716, /* EXBR */ + OP_NO | OP_716 | OP_PRV, /* EPSR */ + OP_RR | OP_PRV, /* WBR */ + OP_RR | OP_PRV, /* RBR */ + OP_RR | OP_716 | OP_PRV, /* WHR */ + OP_RR | OP_716 | OP_PRV, /* RHR */ + OP_RR | OP_PRV, /* WDR */ + OP_RR | OP_PRV, /* RDR */ + OP_RR | OP_716, /* MHUR */ + OP_RR | OP_PRV, /* SSR */ + OP_RR | OP_PRV, /* OCR */ + OP_RR | OP_PRV, /* AIR */ + 0, 0, 0, 0, 0, 0, 0, 0, /* A0:AF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* B0:BF */ + 0, 0, 0, 0, 0, 0, 0, 0, + OP_RX, /* BXH */ + OP_RX, /* BXLE */ + OP_RX | OP_PRV, /* LPSW */ + OP_RS | OP_716, /* THI */ + OP_RS, /* NHI */ + OP_RS, /* CLHI */ + OP_RS, /* OHI */ + OP_RS, /* XHI */ + OP_RS, /* LHI */ + OP_RS | OP_716, /* CHI */ + OP_RS, /* AHI */ + OP_RS, /* SHI */ + OP_RS, /* SRHL */ + OP_RS, /* SLHL */ + OP_RS, /* SRHA */ + OP_RS, /* SLHA */ + OP_RX | OP_ID4, /* STM */ + OP_RX | OP_ID4, /* LM */ + OP_RX, /* STB */ + OP_RX, /* LDB */ + OP_RX | OP_716, /* CLB */ + OP_RX | OP_ID4 | OP_PRV, /* AL */ + OP_RXH | OP_PRV, /* WB */ + OP_RXH | OP_PRV, /* RB */ + OP_RX | OP_716 | OP_PRV, /* WH */ + OP_RX | OP_716 | OP_PRV, /* RH */ + OP_RX | OP_PRV, /* WD */ + OP_RX | OP_PRV, /* RD */ + OP_RXH | OP_716, /* MHU */ + OP_RX | OP_PRV, /* SS */ + OP_RX | OP_PRV, /* OC */ + OP_RX | OP_PRV, /* AI */ + 0, /* E0 */ + OP_RX | OP_716, /* SVC */ + OP_RS | OP_716 | OP_PRV, /* SINT */ + 0, 0, 0, 0, 0, 0, 0, /* E3:E9 */ + OP_RS | OP_716, /* RRL */ + OP_RS | OP_716, /* RLL */ + OP_RS | OP_716, /* SRL */ + OP_RS | OP_716, /* SLL */ + OP_RS | OP_716, /* SRA */ + OP_RS | OP_716, /* SLA */ + 0, 0, 0, 0, 0, 0, 0, 0, /* F0:FF */ + 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* 8/16E relocation constants for S0 and S1, indexed by PSW<8:11> */ + +static uint32 s0_rel_const[16] = { /* addr 0-7FFF */ + 0x00000, 0x00000, 0x00000, 0x00000, /* 0 = no reloc */ + 0x00000, 0x00000, 0x00000, 0x08000, /* 8000 = rel to S1 */ + 0x08000, 0x08000, 0x08000, 0x08000, + 0x08000, 0x08000, 0x08000, 0x00000 }; + +static uint32 s1_rel_const[16] = { /* addr 8000-FFFF */ + 0x00000, 0x08000, 0x10000, 0x18000, /* reloc const must */ + 0x20000, 0x28000, 0x30000, 0xFFF8000, /* "sub" base addr */ + 0x00000, 0x08000, 0x10000, 0x18000, + 0x20000, 0x28000, 0x30000, 0x00000 }; + +/* CPU data structures + + cpu_dev CPU device descriptor + cpu_unit CPU unit descriptor + cpu_reg CPU register list + cpu_mod CPU modifiers list +*/ + +DIB cpu_dib = { d_DS, -1, v_DS, NULL, &display, NULL }; + +UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_716, + MAXMEMSIZE16) }; + +REG cpu_reg[] = { + { HRDATA (PC, PC, 16) }, + { HRDATA (R0, GREG[0], 16) }, + { HRDATA (R1, GREG[1], 16) }, + { HRDATA (R2, GREG[2], 16) }, + { HRDATA (R3, GREG[3], 16) }, + { HRDATA (R4, GREG[4], 16) }, + { HRDATA (R5, GREG[5], 16) }, + { HRDATA (R6, GREG[6], 16) }, + { HRDATA (R7, GREG[7], 16) }, + { HRDATA (R8, GREG[8], 16) }, + { HRDATA (R9, GREG[9], 16) }, + { HRDATA (R10, GREG[10], 16) }, + { HRDATA (R11, GREG[11], 16) }, + { HRDATA (R12, GREG[12], 16) }, + { HRDATA (R13, GREG[13], 16) }, + { HRDATA (R14, GREG[14], 16) }, + { HRDATA (R15, GREG[15], 16) }, + { HRDATA (FR0, F[0], 32) }, + { HRDATA (FR2, F[1], 32) }, + { HRDATA (FR4, F[2], 32) }, + { HRDATA (FR6, F[3], 32) }, + { HRDATA (FR8, F[4], 32) }, + { HRDATA (FR10, F[5], 32) }, + { HRDATA (FR12, F[6], 32) }, + { HRDATA (FR14, F[7], 32) }, + { HRDATA (D0H, D[0].h, 32) }, + { HRDATA (D0L, D[0].l, 32) }, + { HRDATA (D2H, D[1].h, 32) }, + { HRDATA (D2L, D[1].l, 32) }, + { HRDATA (D4H, D[2].h, 32) }, + { HRDATA (D4L, D[2].l, 32) }, + { HRDATA (D6H, D[3].h, 32) }, + { HRDATA (D6L, D[3].l, 32) }, + { HRDATA (D8H, D[4].h, 32) }, + { HRDATA (D8L, D[4].l, 32) }, + { HRDATA (D10H, D[5].h, 32) }, + { HRDATA (D10L, D[5].l, 32) }, + { HRDATA (D12L, D[6].l, 32) }, + { HRDATA (D12H, D[6].h, 32) }, + { HRDATA (D14H, D[7].h, 32) }, + { HRDATA (D14L, D[7].l, 32) }, + { HRDATA (PSW, PSW, 16) }, + { HRDATA (CC, PSW, 4) }, + { HRDATA (SR, SR, 16) }, + { HRDATA (DR, DR, 32) }, + { HRDATA (DRX, DRX, 8) }, + { FLDATA (DRMOD, drmod, 0) }, + { FLDATA (SRPOS, srpos, 0) }, + { HRDATA (DRPOS, drpos, 3) }, + { BRDATA (IRQ, int_req, 16, 32, 8) }, + { BRDATA (IEN, int_enb, 16, 32, 8) }, + { HRDATA (QEVENT, qevent, 4), REG_HRO }, + { FLDATA (STOP_INST, stop_inst, 0) }, + { FLDATA (STOP_WAIT, stop_inst, 0) }, + { BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO+REG_CIRC }, + { HRDATA (PCQP, pcq_p, 6), REG_HRO }, + { HRDATA (WRU, sim_int_char, 8) }, + { HRDATA (DBGLOG, cpu_log, 16), REG_HIDDEN }, + { HRDATA (BLKIOD, blk_io.dfl, 16), REG_HRO }, + { HRDATA (BLKIOC, blk_io.cur, 16), REG_HRO }, + { HRDATA (BLKIOE, blk_io.end, 16), REG_HRO }, + { NULL } }; + +MTAB cpu_mod[] = { + { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, + { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, + { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, + { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, + { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size }, + { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, + { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size }, + { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size }, + { UNIT_TYPE, 0, "I3", "I3", &cpu_set_model }, + { UNIT_TYPE, UNIT_ID4, "I4", "I4", &cpu_set_model }, + { UNIT_TYPE, UNIT_716, "7/16", "716", &cpu_set_model }, + { UNIT_TYPE, UNIT_816, "8/16", "816", &cpu_set_model }, + { UNIT_TYPE, UNIT_816E, "8/16E", "816E", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT", + &cpu_set_consint, NULL, NULL }, + { 0 } }; + +DEVICE cpu_dev = { + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 16, 18, 1, 16, 8, + &cpu_ex, &cpu_dep, &cpu_reset, + NULL, NULL, NULL, + &cpu_dib, 0 }; + +t_stat sim_instr (void) +{ +uint32 cc; +t_stat reason; + +/* Restore register state */ + +if (devtab_init ()) return SCPE_STOP; /* check conflicts */ +pawidth = PAWIDTH16; /* default width */ +if (cpu_unit.flags & UNIT_816E) { /* 8/16E? */ + dec_flgs = 0; /* all instr ok */ + fp_in_hwre = 1; /* fp in hwre */ + pawidth = PAWIDTH16E; /* 18b phys addr */ + psw_mask = PSW_816E; } /* mem ext bits */ +else if (cpu_unit.flags & UNIT_816) { /* 8/16? */ + dec_flgs = OP_816E; + fp_in_hwre = 1; + pawidth = PAWIDTH16; + psw_mask = PSW_x16; } +else if (cpu_unit.flags & UNIT_716) { /* I5, 70, 80, 7/16? */ + dec_flgs = OP_816 | OP_816E; + fp_in_hwre = 0; + pawidth = PAWIDTH16; + psw_mask = PSW_x16; } +else if (cpu_unit.flags & UNIT_ID4) { /* I4? */ + dec_flgs = OP_716 | OP_816 | OP_816E; + fp_in_hwre = 0; + pawidth = PAWIDTH16; + psw_mask = PSW_ID4; } +else { dec_flgs = OP_ID4 | OP_716 | OP_816 | OP_816E; /* I3 */ + fp_in_hwre = 0; + pawidth = PAWIDTH16; + psw_mask = PSW_ID4; } +int_eval (); /* eval interrupts */ +cc = newPSW (PSW & psw_mask); /* split PSW, eval wait */ +sim_rtcn_init (lfc_unit.wait, TMR_LFC); /* init clock */ +sim_rtcn_init (pic_unit.wait, TMR_PIC); /* init timer */ +sim_rtcn_init (pas_unit.wait, TMR_PAS); /* init pas */ +reason = 0; + +/* Process events */ + +while (reason == 0) { /* loop until halted */ +uint32 dev, drom, inc, lim, opnd; +uint32 op, r1, r1p1, r2, ea, oPC; +uint32 rslt, t, map; +int32 sr, st; + +if (sim_interval <= 0) { /* check clock queue */ + if (reason = sim_process_event ()) break; + int_eval (); } + +if (qevent) { /* any events? */ + if (qevent & EV_BLK) { /* block I/O in prog? */ + dev = blk_io.dfl & DEV_MAX; /* get device */ + cc = dev_tab[dev] (dev, IO_SS, 0) & 0xF; /* sense status */ + if (cc == STA_BSY) { /* just busy? */ + sim_interval = 0; /* force I/O event */ + continue; } + else if (cc == 0) { /* ready? */ + if (blk_io.dfl & BL_RD) { /* read? */ + t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ + if ((t == 0) && (blk_io.dfl & BL_LZ)) continue; + blk_io.dfl = blk_io.dfl & ~BL_LZ; /* non-zero seen */ + WriteB (blk_io.cur, t); } /* write mem */ + else { /* write */ + t = ReadB (blk_io.cur); /* read mem */ + dev_tab[dev] (dev, IO_WD, t); } /* put byte */ + if (blk_io.cur != blk_io.end) { /* more to do? */ + blk_io.cur = (blk_io.cur + 1) & VAMASK; /* incr addr */ + continue; } } + qevent = qevent & ~EV_BLK; /* clr block I/O flg */ + int_eval (); /* re-eval intr */ + continue; } + + if ((qevent & EV_INT) && (PSW & PSW_EXI)) { /* interrupt? */ + if (PSW & PSW_AIO) { /* auto enabled? */ + dev = int_getdev (); /* get int dev */ + cc = int_auto (dev, cc); /* do auto intr */ + int_eval (); } /* re-eval intr */ + else cc = swap_psw (EXIPSW, cc); /* old type, swap */ + continue; } + + if (PSW & PSW_WAIT) { /* wait state? */ + t = sim_qcount (); /* events in queue */ + if ((t == 0) || ((t == 1) && stop_wait)) /* empty, or kbd only? */ + reason = STOP_WAIT; /* then stop */ + else sim_interval = 0; /* force check */ + continue; } + + qevent = 0; } /* no events */ + +/* Fetch and decode instruction */ + +if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ + reason = STOP_IBKPT; /* stop simulation */ + break; } + +sim_interval = sim_interval - 1; + +t = ReadH (oPC = PC); /* fetch instr */ +op = (t >> 8) & 0xFF; /* isolate op, R1, R2 */ +r1 = (t >> 4) & 0xF; +r2 = t & 0xF; +drom = decrom[op]; +if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */ + if (stop_inst) reason = STOP_RSRV; /* stop or */ + else cc = swap_psw (ILOPSW, cc); /* swap PSW */ + continue; } +if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */ + cc = swap_psw (ILOPSW, cc); /* swap PSW */ + continue; } +switch (drom & OP_MASK) { /* decode instruction */ +case OP_NO: /* no operand */ + opnd = r2; /* assume short */ + break; +case OP_RR: /* reg-reg */ + opnd = R[r2]; /* operand is R2 */ + break; +case OP_RS: /* reg-storage */ +case OP_RX: /* reg-mem */ + PC = (PC + 2) & VAMASK; /* increment PC */ + ea = ReadH (PC); /* fetch address */ + if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */ + opnd = ea; /* operand is ea */ + break; +case OP_RXH: /* reg-mem read */ + PC = (PC + 2) & VAMASK; /* increment PC */ + ea = ReadH (PC); /* fetch address */ + if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */ + opnd = ReadH (ea); /* fetch operand */ + break; } +PC = (PC + 2) & VAMASK; /* increment PC */ +switch (op) { /* case on opcode */ + +/* Load/store instructions */ + +case 0x08: /* LHR - RR */ +case 0x24: /* LIS - NO */ +case 0x48: /* LH - RXH */ +case 0xC8: /* LHI - RS */ + R[r1] = opnd; /* load operand */ + CC_GL_16 (R[r1]); /* set G,L */ + break; + +case 0x25: /* LCS - NO */ + R[r1] = (~opnd + 1) & DMASK16; /* load complement */ + CC_GL_16 (R[r1]); /* set G,L */ + break; + +case 0x40: /* STH - RX */ + WriteH (ea, R[r1]); /* store register */ + break; + +case 0xD1: /* LM - RX */ + for ( ; r1 <= 0xF; r1++) { /* loop thru reg */ + R[r1] = ReadH (ea); /* load register */ + ea = (ea + 2) & VAMASK; } /* incr mem addr */ + break; + +case 0xD0: /* STM - RX */ + for ( ; r1 <= 0xF; r1++) { /* loop thru reg */ + WriteH (ea, R[r1]); /* store register */ + ea = (ea + 2) & VAMASK; } /* incr mem addr */ + break; + +case 0x93: /* LDBR - NO */ + R[r1] = R[r2] & DMASK8; /* load byte */ + break; +case 0xD3: /* LDB - RX */ + R[r1] = ReadB (ea); /* load byte */ + break; + +case 0x92: /* STBR - NO */ + R[r2] = (R[r2] & ~DMASK8) | (R[r1] & DMASK8); /* store byte */ + break; +case 0xD2: /* STB - RX */ + WriteB (ea, R[r1] & DMASK8); /* store byte */ + break; + +case 0x94: /* EXBR - NO */ + R[r1] = (R[r2] >> 8) | ((R[r2] & DMASK8) << 8); + break; + +/* Control instructions */ + +case 0x01: /* BALR - RR */ +case 0x41: /* BAL - RX */ + PCQ_ENTRY; /* save old PC */ + R[r1] = PC; /* save cur PC */ + PC = opnd; /* branch */ + break; + +case 0x02: /* BTCR - RR */ +case 0x42: /* BTC - RX */ + if (cc & r1) { /* test CC's */ + PCQ_ENTRY; /* branch if true */ + PC = opnd; } + break; + +case 0x20: /* BTBS - NO */ + if (cc & r1) { /* test CC's */ + PCQ_ENTRY; /* branch if true */ + PC = (oPC - r2 - r2) & VAMASK; } + break; + +case 0x21: /* BTFS - NO */ + if (cc & r1) { /* test CC's */ + PCQ_ENTRY; /* branch if true */ + PC = (oPC + r2 + r2) & VAMASK; } + break; + +case 0x03: /* BFCR - RR */ +case 0x43: /* BFC - RX */ + if ((cc & r1) == 0) { /* test CC's */ + PCQ_ENTRY; /* branch if false */ + PC = opnd; } + break; + +case 0x22: /* BFBS - NO */ + if ((cc & r1) == 0) { /* test CC's */ + PCQ_ENTRY; /* branch if false */ + PC = (oPC - r2 - r2) & VAMASK; } + break; + +case 0x23: /* BFFS - NO */ + if ((cc & r1) == 0) { /* test CC's */ + PCQ_ENTRY; /* branch if false */ + PC = (oPC + r2 + r2) & VAMASK; } + break; + +case 0xC0: /* BXH - RX */ + inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */ + lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */ + R[r1] = (R[r1] + inc) & DMASK16; /* R1 = R1 + inc */ + if (R[r1] > lim) { /* if R1 > lim */ + PCQ_ENTRY; /* branch */ + PC = opnd; } + break; + +case 0xC1: /* BXLE - RX */ + inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */ + lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */ + R[r1] = (R[r1] + inc) & DMASK16; /* R1 = R1 + inc */ + if (R[r1] <= lim) { /* if R1 <= lim */ + PCQ_ENTRY; /* branch */ + PC = opnd; } + break; + +/* Logical instructions */ + +case 0x04: /* NHR - RR */ +case 0x44: /* NH - RXH */ +case 0xC4: /* NHI - RS */ + R[r1] = R[r1] & opnd; /* result */ + CC_GL_16 (R[r1]); /* set G,L */ + break; + +case 0x06: /* OHR - RR */ +case 0x46: /* OH - RXH */ +case 0xC6: /* OHI - RS */ + R[r1] = R[r1] | opnd; /* result */ + CC_GL_16 (R[r1]); /* set G,L */ + break; + +case 0x07: /* XHR - RR */ +case 0x47: /* XH - RXH */ +case 0xC7: /* XHI - RS */ + R[r1] = R[r1] ^ opnd; /* result */ + CC_GL_16 (R[r1]); /* set G,L */ + break; + +case 0xC3: /* THI - RS */ + rslt = R[r1] & opnd; /* result */ + CC_GL_16 (rslt); /* set G, L */ + break; + +case 0x05: /* CLHR - RR */ +case 0x45: /* CLH - RXH */ +case 0xC5: /* CLHI - RS */ + rslt = (R[r1] - opnd) & DMASK16; /* result */ + CC_GL_16 (rslt); /* set G,L */ + if (R[r1] < opnd) cc = cc | CC_C; /* set C if borrow */ + if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) cc = cc | CC_V; + break; + +case 0xD4: /* CLB - RX */ + opnd = ReadB (ea); /* get operand */ + t = R[r1] & DMASK8; + rslt = (t - opnd) & DMASK16; /* result */ + CC_GL_16 (rslt); /* set G,L */ + if (t < opnd) cc = cc | CC_C; /* set C if borrow */ + break; + +/* Shift instructions */ + +case 0xCC: /* SRHL - RS */ + opnd = opnd & 0xF; /* shift count */ +case 0x90: /* SRLS - NO */ + rslt = R[r1] >> opnd; /* result */ + CC_GL_16 (rslt); /* set G,L */ + if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C; + R[r1] = rslt; /* store result */ + break; + +case 0xCD: /* SLHL - RS */ + opnd = opnd & 0xF; /* shift count */ +case 0x91: /* SLLS - NO */ + rslt = R[r1] << opnd; /* raw result */ + R[r1] = rslt & DMASK16; /* masked result */ + CC_GL_16 (R[r1]); /* set G,L */ + if (opnd && (rslt & 0x10000)) cc = cc | CC_C; /* set C if shft out */ + break; + +case 0xCE: /* SRHA - RS */ + opnd = opnd & 0xF; /* shift count */ + rslt = (SEXT16 (R[r1]) >> opnd) & DMASK16; /* result */ + CC_GL_16 (rslt); /* set G,L */ + if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C; + R[r1] = rslt; /* store result */ + break; + +case 0xCF: /* SLHA - RS */ + opnd = opnd & 0xF; /* shift count */ + rslt = R[r1] << opnd; /* raw result */ + R[r1] = (R[r1] & SIGN16) | (rslt & MMASK16); /* arith result */ + CC_GL_16 (R[r1]); /* set G,L */ + if (opnd && (rslt & SIGN16)) cc = cc | CC_C; /* set C if shft out */ + break; + +case 0xEA: /* RRL - RS */ + r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ + opnd = opnd & 0x1F; /* shift count */ + t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ + if (opnd) rslt = (t >> opnd) | (t << (32 - opnd)); /* result */ + else rslt = t; /* no shift */ + CC_GL_32 (rslt); /* set G,L 32b */ + R[r1] = (rslt >> 16) & DMASK16; /* hi result */ + R[r1p1] = rslt & DMASK16; /* lo result */ + break; + +case 0xEB: /* RLL - RS */ + r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ + opnd = opnd & 0x1F; /* shift count */ + t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ + if (opnd) rslt = (t << opnd) | (t >> (32 - opnd)); /* result */ + else rslt = t; /* no shift */ + CC_GL_32 (rslt); /* set G,L 32b */ + R[r1] = (rslt >> 16) & DMASK16; /* hi result */ + R[r1p1] = rslt & DMASK16; /* lo result */ + break; + +case 0xEC: /* SRL - RS */ + r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ + opnd = opnd & 0x1F; /* shift count */ + t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ + rslt = t >> opnd; /* result */ + CC_GL_32 (rslt); /* set G,L 32b */ + if (opnd && ((t >> (opnd - 1)) & 1)) cc = cc | CC_C; + R[r1] = (rslt >> 16) & DMASK16; /* hi result */ + R[r1p1] = rslt & DMASK16; /* lo result */ + break; + +case 0xED: /* SLL - RS */ + r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ + opnd = opnd & 0x1F; /* shift count */ + t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ + rslt = t << opnd; /* result */ + CC_GL_32 (rslt); /* set G,L 32b */ + if (opnd && ((t << (opnd - 1)) & SIGN32)) cc = cc | CC_C; + R[r1] = (rslt >> 16) & DMASK16; /* hi result */ + R[r1p1] = rslt & DMASK16; /* lo result */ + break; + +case 0xEE: /* SRA - RS */ + r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ + opnd = opnd & 0x1F; /* shift count */ + t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ + rslt = ((int32) t) >> opnd; /* signed result */ + CC_GL_32 (rslt); /* set G,L 32b */ + if (opnd && ((t >> (opnd - 1)) & 1)) cc = cc | CC_C; + R[r1] = (rslt >> 16) & DMASK16; /* hi result */ + R[r1p1] = rslt & DMASK16; /* lo result */ + break; + +case 0xEF: /* SLA - RS */ + r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ + opnd = opnd & 0x1F; /* shift count */ + t = (R[r1] << 16) | R[r1p1]; /* form 32b op */ + rslt = (t & SIGN32) | ((t << opnd) & MMASK32); /* signed result */ + CC_GL_32 (rslt); /* set G,L 32b */ + if (opnd && ((t << opnd) & SIGN32)) cc = cc | CC_C; + R[r1] = (rslt >> 16) & DMASK16; /* hi result */ + R[r1p1] = rslt & DMASK16; /* lo result */ + break; + +/* Arithmetic instructions */ + +case 0x0A: /* AHR - RR */ +case 0x26: /* AIS - NO */ +case 0x4A: /* AH - RXH */ +case 0xCA: /* AHI - RS */ + rslt = (R[r1] + opnd) & DMASK16; /* result */ + CC_GL_16 (rslt); /* set G,L */ + if (rslt < opnd) cc = cc | CC_C; /* set C if carry */ + if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) cc = cc | CC_V; + R[r1] = rslt; + break; + +case 0x61: /* AHM - RXH */ + rslt = (R[r1] + opnd) & DMASK16; /* result */ + CC_GL_16 (rslt); /* set G,L */ + if (rslt < opnd) cc = cc | CC_C; /* set C if carry */ + if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) cc = cc | CC_V; + WriteH (ea, rslt); /* store in memory */ + break; + +case 0x0B: /* SHR - RR */ +case 0x27: /* SIS - NO */ +case 0x4B: /* SH - RXH */ +case 0xCB: /* SHI - RS */ + rslt = (R[r1] - opnd) & DMASK16; /* result */ + CC_GL_16 (rslt); /* set G,L */ + if (R[r1] < opnd) cc = cc | CC_C; /* set C if borrow */ + if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) cc = cc | CC_V; + R[r1] = rslt; + break; + +case 0x09: /* CHR - RR */ +case 0x49: /* CH - RXH */ +case 0xC9: /* CHI - RS */ + sr = SEXT16 (R[r1]); /* sign ext */ + st = SEXT16 (opnd); + if (sr < st) cc = CC_C | CC_L; /* < sets C, L */ + else if (sr > st) cc = CC_G; /* > sets G */ + else cc = 0; + if (((R[r1] ^ opnd) & (~opnd ^ (sr - st))) & SIGN16) + cc = cc | CC_V; + break; + +case 0x0C: /* MHR - RR */ +case 0x4C: /* MH - RXH */ + r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ + rslt = SEXT16 (R[r1p1]) * SEXT16 (opnd); /* multiply */ + R[r1] = (rslt >> 16) & DMASK16; /* hi result */ + R[r1p1] = rslt & DMASK16; /* lo result */ + break; + +case 0x9C: /* MHUR - RR */ +case 0xDC: /* MHU - RXH */ + r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ + rslt = R[r1p1] * opnd; /* multiply, unsigned */ + R[r1] = (rslt >> 16) & DMASK16; /* hi result */ + R[r1p1] = rslt & DMASK16; /* lo result */ + break; + +case 0x0D: /* DHR - RR */ +case 0x4D: /* DH - RXH */ + r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ + sr = (R[r1] << 16) | R[r1p1]; /* signed 32b divd */ + if (opnd) { /* if divisor != 0 */ + st = sr / SEXT16 (opnd); /* signed quotient */ + sr = sr % SEXT16 (opnd); } /* remainder */ + if (opnd && (st < 0x8000) && (st >= -0x8000)) { /* if quo fits */ + R[r1] = sr & DMASK16; /* store remainder */ + R[r1p1] = st & DMASK16; } /* store quotient */ + else if (PSW & PSW_AFI) /* div fault enabled? */ + cc = swap_psw (AFIPSW, cc); /* swap PSW */ + break; + +case 0x0E: /* ACHR - RR */ +case 0x4E: /* ACH - RXH */ + t = R[r1] + opnd + ((cc & CC_C) != 0); /* raw result */ + rslt = t & DMASK16; /* masked result */ + CC_GL_16 (rslt); /* set G,L */ + if (t > DMASK16) cc = cc | CC_C; /* set C if carry */ + if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) cc = cc | CC_V; + R[r1] = rslt; /* store result */ + break; + +case 0x0F: /* SCHR - RR */ +case 0x4F: /* SCH - RXH */ + t = R[r1] - opnd - ((cc & CC_C) != 0); /* raw result */ + rslt = t & DMASK16; /* masked result */ + CC_GL_16 (rslt); /* set G,L */ + if (t > DMASK16) cc = cc | CC_C; /* set C if borrow */ + if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) cc = cc | CC_V; + R[r1] = rslt; /* store result */ + break; + +/* Floating point instructions */ + +case 0x28: /* LER - NO */ +case 0x38: /* LDR - NO */ +case 0x68: /* LE - RX */ +case 0x78: /* LD - RX */ + cc = f_l (op, r1, r2, ea); /* load */ + if ((cc & CC_V) && (PSW & PSW_FPF) && CPU_x16) /* V set, x/16? */ + cc = swap_psw (FPFPSW, cc); + break; + +case 0x29: /* CER - NO */ +case 0x39: /* CDR - NO */ +case 0x69: /* CE - RX */ +case 0x79: /* CD - RX */ + cc = f_c (op, r1, r2, ea); /* compare */ + break; + +case 0x2A: /* AER - NO */ +case 0x2B: /* SER - NO */ +case 0x3A: /* ADR - NO */ +case 0x3B: /* SDR - NO */ +case 0x6A: /* AE - RX */ +case 0x6B: /* SE - RX */ +case 0x7A: /* AD - RX */ +case 0x7B: /* SD - RX */ + cc = f_as (op, r1, r2, ea); /* add/sub */ + if ((cc & CC_V) && (PSW & PSW_FPF) && CPU_x16) /* V set, x/16? */ + cc = swap_psw (FPFPSW, cc); + break; + +case 0x2C: /* MER - NO */ +case 0x3C: /* MDR - NO */ +case 0x6C: /* ME - RX */ +case 0x7C: /* MD - RX */ + cc = f_m (op, r1, r2, ea); /* multiply */ + if ((cc & CC_V) && (PSW & PSW_FPF) && CPU_x16) /* V set, x/16? */ + cc = swap_psw (FPFPSW, cc); + break; + +case 0x2D: /* DER - NO */ +case 0x3D: /* DDR - NO */ +case 0x6D: /* DE - RX */ +case 0x7D: /* DD - RX */ + cc = f_d (op, r1, r2, ea); /* perform divide */ + if ((cc & CC_V) && ((cc & CC_C) || /* V set, x/16 or */ + ((PSW & PSW_FPF) && CPU_x16))) /* V & C set? */ + cc = swap_psw (FPFPSW, cc); + break; + +case 0x2E: /* FXR - NO */ +case 0x3E: /* FXDR - NO */ + cc = f_fix (op, r1, r2); /* cvt to integer */ + break; + +case 0x2F: /* FLR - NO */ +case 0x3F: /* FLDR - NO */ + cc = f_flt (op, r1, r2); /* cvt to floating */ + break; + +case 0x60: /* STE - RX */ + t = ReadFReg (r1); /* get fp reg */ + WriteF (ea, t, P); /* write */ + break; + +case 0x70: /* STD - RX */ + WriteF (ea, D[r1 >> 1].h, P); /* write hi */ + WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, P); /* write lo */ + break; + +case 0x71: /* STME - RX */ + for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ + t = ReadFReg (r1); /* get fp reg */ + WriteF (ea, t, P); /* write */ + ea = (ea + 4) & VAMASK; } /* incr mem addr */ + break; + +case 0x72: /* LME - RX */ + for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ + t = ReadF (ea, P); /* get value */ + WriteFReg (r1, t); /* write reg */ + ea = (ea + 4) & VAMASK; } /* incr mem addr */ + break; + +case 0x7E: /* STMD - RX */ + for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ + WriteF (ea, D[r1 >> 1].h, P); /* write register */ + WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, P); + ea = (ea + 8) & VAMASK; } /* incr mem addr */ + break; + +case 0x7F: /* LMD - RX */ + for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ + D[r1 >> 1].h = ReadF (ea, P); /* load register */ + D[r1 >> 1].l = ReadF ((ea + 4) & VAMASK, P); + ea = (ea + 8) & VAMASK; } /* incr mem addr */ + break; + +/* Miscellaneous */ + +case 0xE1: /* SVC - RX */ + PCQ_ENTRY; /* save PC */ + WriteH (SVCAP, ea); /* save opnd */ + WriteH (SVOPS, BUILD_PSW (cc)); /* save PS */ + WriteH (SVOPC, PC); /* save PC */ + PC = ReadH (SVNPC + r1 + r1); /* new PC */ + cc = newPSW (ReadH (SVNPS)); /* new PS */ + break; + +case 0xE2: /* SINT - RS */ + dev = opnd & DEV_MAX; /* get dev */ + cc = int_auto (dev, cc); /* auto intr */ + int_eval (); /* re-eval intr */ + break; + +case 0xC2: /* LPSW - RX */ + PCQ_ENTRY; /* effective branch */ + PC = ReadH ((ea + 2) & VAMASK); /* read PC */ + cc = newPSW (ReadH (ea)); /* read PSW */ + if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ + break; + +case 0x95: /* EPSR - RR */ + R[r1] = BUILD_PSW (cc); /* save PSW */ +case 0x33: /* LPSR - NO */ + cc = newPSW (R[r2]); /* load new PSW */ + if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ + break; + +case 0x73: /* LPS - RXH */ + cc = newPSW (opnd); /* load new PSW */ + if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ + break; + +case 0x64: /* ATL - RX */ +case 0x65: /* ABL - RX */ + cc = addtoq (ea, R[r1], op & 1); /* add to q */ + break; + +case 0x66: /* RTL - RX */ +case 0x67: /* RBL - RX */ + cc = remfmq (ea, r1, op & 1); /* remove from q */ + break; + +case 0x13: /* SETMR - RR */ +case 0x53: /* SETM - RXH */ + t = BUILD_PSW (cc); /* old PSW */ + map = PSW_GETMAP (opnd); /* get new map */ + switch (map) { /* case on map */ + case 0x7: + map = 0; /* use 1:1 map */ + R[r1] = R[r1] ^ SIGN16; /* flip sign */ + break; + case 0x8: case 0x9: case 0xA: case 0xB: + case 0xC: case 0xD: case 0xE: + if (R[r1] & SIGN16) map = map & ~0x8; /* S1? clr map<0> */ + else { + map = 0; /* else 1:1 map */ + R[r1] = R[r1] | SIGN16; } /* set sign */ + break; + default: + break; } + t = (t & ~PSW_MAP) | (map << PSW_V_MAP); /* insert map */ + newPSW (t); /* load new PSW */ + CC_GL_16 (rslt); /* set G,L */ + break; + +/* I/O instructions */ + +case 0xDE: /* OC - RX */ + opnd = ReadB (ea); /* fetch operand */ +case 0x9E: /* OCR - RR */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { + dev_tab[dev] (dev, IO_ADR, 0); /* select */ + dev_tab[dev] (dev, IO_OC, opnd & DMASK8); /* send command */ + int_eval (); /* re-eval intr */ + cc = 0; } + else cc = CC_V; + break; + +case 0xDA: /* WD - RX */ + opnd = ReadB (ea); /* fetch operand */ +case 0x9A: /* WDR - RR */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { + dev_tab[dev] (dev, IO_ADR, 0); /* select */ + dev_tab[dev] (dev, IO_WD, opnd & DMASK8); /* send data */ + int_eval (); /* re-eval intr */ + cc = 0; } + else cc = CC_V; + break; + +case 0xD8: /* WH - RX */ + opnd = ReadH (ea); /* fetch operand */ +case 0x98: /* WHR - RR */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { + if (dev_tab[dev] (dev, IO_ADR, 0)) /* select; hw ok? */ + dev_tab[dev] (dev, IO_WH, opnd); /* send data */ + else { /* byte only */ + dev_tab[dev] (dev, IO_WD, opnd >> 8); /* send hi byte */ + dev_tab[dev] (dev, IO_WD, opnd & DMASK8); } /* send lo byte */ + int_eval (); /* re-eval intr */ + cc = 0; } + else cc = CC_V; + break; + +case 0x9B: /* RDR - RR */ +case 0xDB: /* RD - RX */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { /* dev exist? */ + dev_tab[dev] (dev, IO_ADR, 0); /* select */ + t = dev_tab[dev] (dev, IO_RD, 0); /* get data */ + cc = 0; } + else { /* no */ + t = 0; /* read zero */ + cc = CC_V; } /* set V */ + if (OP_TYPE (op) != OP_RR) WriteB (ea, t); /* RX or RR? */ + else R[r2] = t & DMASK8; + int_eval (); /* re-eval intr */ + break; + +case 0x99: /* RHR - RR */ +case 0xD9: /* RH - RX */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { /* dev exist? */ + if (dev_tab[dev] (dev, IO_ADR, 0)) /* select, hw ok? */ + t = dev_tab[dev] (dev, IO_RH, 0); /* get data */ + else { /* byte only */ + rslt = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ + t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ + t = (rslt << 8) | t; } /* merge */ + cc = 0; } + else { /* no */ + t = 0; /* read zero */ + cc = CC_V; } /* set V */ + if (OP_TYPE (op) != OP_RR) WriteH (ea, t); /* RX or RR? */ + else R[r2] = t; + int_eval (); /* re-eval intr */ + break; + +case 0x9F: /* AIR - RR */ +case 0xDF: /* AI - RX */ + R[r1] = int_getdev (); /* get int dev */ + /* fall through */ +case 0x9D: /* SSR - RR */ +case 0xDD: /* SS - RX */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { /* dev exist? */ + dev_tab[dev] (dev, IO_ADR, 0); /* select */ + t = dev_tab[dev] (dev, IO_SS, 0); } /* get status */ + else t = STA_EX; /* no */ + if (OP_TYPE (op) != OP_RR) WriteB (ea, t); /* RR or RX? */ + else R[r2] = t & DMASK8; + cc = t & 0xF; + int_eval (); /* re-eval intr */ + break; + +/* Block I/O instructions + + On a real Interdata system, the block I/O instructions can't be + interrupted or stopped. To model this behavior, while allowing + the instructions to go back through fetch for I/O processing and + WRU testing, the simulator implements a 'block I/O in progress' + flag and status block. If a block I/O is in progress, normal + interrupts and fetches are suppressed until the block I/O is done. +*/ + +case 0x96: /* WBR - RR */ +case 0xD6: /* WB - RXH */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { /* dev exist? */ + if (OP_TYPE (op) != OP_RR) + lim = ReadH ((ea + 2) & VAMASK); + else lim = R[(r2 + 1) & 0xF]; + if (opnd > lim) cc = 0; /* start > end? */ + else { /* no, start I/O */ + dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ + blk_io.dfl = dev; /* set status block */ + blk_io.cur = opnd; + blk_io.end = lim; + qevent = qevent | EV_BLK; } } /* I/O in prog */ + else cc = CC_V; /* nx dev */ + break; + +case 0x97: /* RBR - RR */ +case 0xD7: /* RB - RXH */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { /* dev exist? */ + if (OP_TYPE (op) != OP_RR) + lim = ReadH ((ea + 2) & VAMASK); + else lim = R[(r2 + 1) & 0xF]; + if (opnd > lim) cc = 0; /* start > end? */ + else { /* no, start I/O */ + dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ + blk_io.dfl = dev | BL_RD; /* set status block */ + blk_io.cur = opnd; + blk_io.end = lim; + qevent = qevent | EV_BLK; } } /* I/O in prog */ + else cc = CC_V; /* nx dev */ + break; + +case 0xD5: /* AL - RX */ + dev = ReadB (AL_DEV); /* get device */ + t = ReadB (AL_IOC); /* get command */ + if (DEV_ACC (dev)) { /* dev exist? */ + if (AL_BUF > ea) cc = 0; /* start > end? */ + else { /* no, start I/O */ + dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ + dev_tab[dev] (dev, IO_OC, t); /* start dev */ + blk_io.dfl = dev | BL_RD | BL_LZ; /* set status block */ + blk_io.cur = AL_BUF; + blk_io.end = ea; + qevent = qevent | EV_BLK; } } /* I/O in prog */ + else cc = CC_V; /* nx dev */ + break; } /* end switch */ + } /* end while */ + +/* Simulation halted */ + +PSW = BUILD_PSW (cc); +PC = PC & VAMASK; +pcq_r->qptr = pcq_p; /* update pc q ptr */ +return reason; +} + +/* Load new PSW and memory map */ + +uint32 newPSW (uint32 val) +{ +PSW = val & psw_mask; /* store PSW */ +int_eval (); /* update intreq */ +if (PSW & PSW_WAIT) qevent = qevent | EV_WAIT; /* wait state? */ +else qevent = qevent & ~EV_WAIT; +if (cpu_unit.flags & UNIT_816E) { /* mapping enabled? */ + uint32 map = PSW_GETMAP (PSW); /* get new map */ + s0_rel = s0_rel_const[map]; /* set relocation */ + s1_rel = s1_rel_const[map]; } /* constants */ +else s0_rel = s1_rel = 0; /* no relocation */ +if (PSW & PSW_AIO) SET_ENB (v_DS); /* PSW<4> controls */ +else CLR_ENB (v_DS); /* DS interrupts */ +return PSW & CC_MASK; +} + +/* Swap PSW */ + +uint32 swap_psw (uint32 loc, uint32 cc) +{ +WriteH (loc, BUILD_PSW (cc)); /* write PSW, PC */ +WriteH (loc + 2, PC); +cc = newPSW (ReadH (loc + 4)); /* read PSW, PC */ +PC = ReadH (loc + 6); +if (PSW & PSW_SQI) cc = testsysq (cc); /* sys q int enb? */ +return cc; /* return CC */ +} + +/* Test for queue interrupts */ + +uint32 testsysq (uint32 cc) +{ +int32 qb = ReadH (SQP); /* get sys q addr */ +int32 usd = ReadB (qb + Q16_USD); /* get use count */ + +if (usd) { /* any entries? */ + WriteH (SQIPSW, BUILD_PSW (cc)); /* swap PSW */ + WriteH (SQIPSW + 2, PC); + cc = newPSW (ReadH (SQIPSW + 4)); + PC = ReadH (SQIPSW + 6); } +return cc; +} + +/* Add to head of queue */ + +uint32 addtoq (uint32 ea, uint32 val, uint32 flg) +{ +uint32 slt, usd, wra, t; + +t = ReadH (ea); /* slots/used */ +slt = (t >> 8) & DMASK8; /* # slots */ +usd = t & DMASK8; /* # used */ +if (usd >= slt) return CC_V; /* list full? */ +usd = usd + 1; /* inc # used */ +WriteB (ea + Q16_USD, usd); /* rewrite */ +if (flg) { /* ABL? */ + wra = ReadB ((ea + Q16_BOT) & VAMASK); /* get bottom */ + t = wra + 1; /* adv bottom */ + if (t >= slt) t = 0; /* wrap if necc */ + WriteB ((ea + Q16_BOT) & VAMASK, t); } /* rewrite bottom */ +else { /* ATL */ + wra = ReadB ((ea + Q16_TOP) & VAMASK); /* get top */ + if (wra == 0) wra = (slt - 1) & DMASK8; /* wrap if necc */ + else wra = wra - 1; /* dec top */ + WriteB ((ea + Q16_TOP) & VAMASK, wra); } /* rewrite top */ +WriteH ((ea + Q16_BASE + (wra * Q16_SLNT)) & VAMASK, val); /* write slot */ +return 0; +} + +uint32 remfmq (uint32 ea, uint32 r1, uint32 flg) +{ +uint32 slt, usd, rda, t; + +t = ReadH (ea); /* get slots/used */ +slt = (t >> 8) & DMASK8; /* # slots */ +usd = t & DMASK8; /* # used */ +if (usd == 0) return CC_V; /* empty? */ +usd = usd - 1; /* dec used */ +WriteB (ea + Q16_USD, usd); /* rewrite */ +if (flg) { /* RBL? */ + rda = ReadB ((ea + Q16_BOT) & VAMASK); /* get bottom */ + if (rda == 0) rda = (slt - 1) & DMASK8; /* wrap if necc */ + else rda = rda - 1; /* dec bottom */ + WriteB ((ea + Q16_BOT) & VAMASK, rda); } /* rewrite bottom */ +else { rda = ReadB ((ea + Q16_TOP) & VAMASK); /* RTL, get top */ + t = rda + 1; /* adv top */ + if (t >= slt) t = 0; /* wrap if necc */ + WriteB ((ea + Q16_TOP) & VAMASK, t); } /* rewrite top */ +R[r1] = ReadH ((ea + Q16_BASE + (rda * Q16_SLNT)) & VAMASK); /* read slot */ +if (usd) return CC_G; /* set cc's */ +else return 0; +} + +/* Automatic interrupt processing */ + +#define CCW16_ERR(x) (((x)|CCW16_INIT|CCW16_NOP|CCW16_Q) & \ + ~(CCW16_CHN|CCW16_CON|CCW16_HI)) + +uint32 int_auto (uint32 dev, uint32 cc) +{ +int32 ba, ea, by, vec, ccw, bpi, fnc, trm, st, i, t; +t_bool sysqe = FALSE; +t_bool rpt = FALSE; + +do { + vec = ReadH (INTSVT + dev + dev); /* get vector */ + if ((vec & 1) == 0) { /* immed int? */ + WriteH (vec, BUILD_PSW (cc)); /* write PSW, PC */ + WriteH ((vec + 2) & VAMASK, PC); + cc = newPSW (ReadH ((vec + 4) & VAMASK)); /* read PSW */ + PC = (vec + 6) & VAMASK; /* set new PC */ + return cc; } + vec = vec & ~1; /* get CCW addr */ + ccw = ReadH (vec); /* read CCW */ + if (DEV_ACC (dev)) dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ + if (ccw & CCW16_NOP) break; /* NOP? exit */ + if (ccw & CCW16_INIT) { /* init set? */ + ccw = ccw & ~CCW16_INIT; /* clr init */ + WriteH (vec, ccw); /* rewrite */ + if (ccw & CCW16_OC) { /* OC set? */ + if (DEV_ACC (dev)) { /* dev exist? */ + by = ReadB ((vec + CCB16_IOC) & VAMASK);/* read OC byte */ + dev_tab[dev] (dev, IO_OC, by); } /* send to dev */ + break; } } /* and exit */ + fnc = CCW16_FNC (ccw); /* get func */ + st = 0; /* default status */ + if (fnc == CCW16_DMT) { /* DMT */ + ba = ReadH ((vec + CCB16_STR) & VAMASK); /* get cnt wd */ + ba = (ba - 1) & DMASK16; /* decr */ + WriteH ((vec + CCB16_STR) & VAMASK, ba); /* rewrite */ + if (ba) break; /* nz? exit */ + } /* end if dmt */ + else if (fnc != CCW16_NUL) { /* rd or wr? */ + if (DEV_ACC (dev)) /* dev exist? */ + st = dev_tab[dev] (dev, IO_SS, 0); /* sense status */ + else st = CC_V; /* else timeout */ + if (st & 0xF) { /* error? */ + ccw = CCW16_ERR (ccw); /* neuter CCW */ + WriteH (vec, ccw); } /* rewrite CCW */ + else { /* ok, do xfer */ + bpi = CCW16_BPI (ccw); /* get bytes/int */ + if (bpi == 0) bpi = 16; /* max 16B */ + ba = ReadH ((vec + CCB16_STR) & VAMASK); /* get start */ + for (i = 0; i < bpi; i++) { /* do # bytes */ + if (fnc == CCW16_RD) { /* chan read? */ + by = dev_tab[dev] (dev, IO_RD, 0); /* read byte */ + WriteB (ba, by); } /* store */ + else { /* chan write */ + by = ReadB (ba); /* fetch */ + dev_tab[dev] (dev, IO_WD, by); } /* write byte */ + ba = (ba + 1) & VAMASK; } /* incr addr */ + WriteH ((vec + CCB16_STR) & VAMASK, ba); /* rewrite */ + ea = ReadH ((vec + CCB16_END) & VAMASK); /* get end */ + trm = ReadB ((vec + CCB16_TRM) & VAMASK); /* get term chr */ + if ((ba <= ea) && /* not at end? */ + (((ccw & CCW16_TRM) == 0) || /* not term chr? */ + (by != trm))) break; /* exit */ + ccw = ccw | CCW16_NOP; /* nop CCW */ + WriteH (vec, ccw); /* rewrite CCW */ + } /* end else sta */ + } /* end if r/w */ + +/* Termination phase */ + + t = (dev << 8) | (st & DMASK8); /* form dev/sta */ + WriteH ((vec + CCB16_DEV) & VAMASK, t); /* write dev/sta */ + if (ccw & CCW16_Q) { /* q request? */ + t = ReadH (SQP); /* get sys q addr */ + if (addtoq (t, vec, ccw & CCW16_HI)) { /* add to sys q */ + WriteH (SQOP, vec); /* write to ovflo */ + return swap_psw (SQVPSW, cc); } /* take exception */ + else sysqe = TRUE; } /* made an entry */ + if (ccw & CCW16_CHN) { /* chain */ + t = ReadH ((vec + CCB16_CHN) & VAMASK); /* get chain wd */ + WriteH (INTSVT + dev + dev, t); /* wr int svc tab */ + if (ccw & CCW16_CON) rpt = TRUE; } /* cont? */ + } while (rpt); + +/* Common exit */ + +if (sysqe && (PSW & PSW_SQI)) /* sys q ent & enb? */ + return swap_psw (SQIPSW, cc); /* take sys q int */ +return cc; +} + +/* Display register device */ + +uint32 display (uint32 dev, uint32 op, uint32 dat) +{ +int t; + +switch (op) { +case IO_ADR: /* select */ + if (!drmod) drpos = srpos = 0; /* norm mode? clr */ + return BY; /* byte only */ +case IO_OC: /* command */ + op = op & 0xC0; + if (op == 0x40) { /* x40 = inc */ + drmod = 1; + drpos = srpos = 0; } /* init cntrs */ + else if (op == 0x80) drmod = 0; /* x80 = norm */ + break; +case IO_WD: /* write */ + if (drpos < 4) + DR = (DR & ~(DMASK8 << (drpos * 8))) | (dat << (drpos * 8)); + else if (drpos == 4) DRX = dat; + drpos = (drpos + 1) & + ((cpu_unit.flags & (UNIT_716 | UNIT_816))? 7: 3); + break; +case IO_RD: /* read */ + t = (SR >> (srpos * 8)) & DMASK8; + srpos = srpos ^ 1; + return t; +case IO_SS: /* status */ + return 0x80; } +return 0; +} + +/* Memory interface routines + + ReadB read byte (processor) + ReadH read halfword (processor) + ReadF read fullword (processor) + WriteB write byte (processor) + WriteH write halfword (processor) + WriteF write fullword (processor) + IOReadB read byte (IO) + IOWriteB write byte (IO) + IOReadH read halfword (IO) + IOWriteH write halfword (IO) +*/ + +uint32 ReadB (uint32 loc) +{ +uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; + +return ((M[pa >> 1] >> ((pa & 1)? 0: 8)) & DMASK8); +} + +uint32 ReadH (uint32 loc) +{ +uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; + +return M[pa >> 1]; +} + +uint32 ReadF (uint32 loc, uint32 rel) +{ +uint32 pa, pa1; +uint32 loc1 = (loc + 2) & VAMASK; + +loc = loc & VAMASK; /* FP doesn't mask */ +if (rel) { + pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; + pa1 = (loc1 + ((loc1 & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; } +else { pa = loc; + pa1 = loc1; } + +return (((uint32) M[pa >> 1]) << 16) | + ((uint32) M[pa1 >> 1]); +} + +void WriteB (uint32 loc, uint32 val) +{ +uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; + +val = val & DMASK8; +if (MEM_ADDR_OK (pa)) M[pa >> 1] = ((pa & 1)? + ((M[pa >> 1] & ~DMASK8) | val): + ((M[pa >> 1] & DMASK8) | (val << 8))); +return; +} + +void WriteH (uint32 loc, uint32 val) +{ +uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; + +if (MEM_ADDR_OK (pa)) M[pa >> 1] = val & DMASK16; +return; +} + +void WriteF (uint32 loc, uint32 val, uint32 rel) +{ +uint32 pa, pa1; +uint32 loc1 = (loc + 2) & VAMASK; + +loc = loc & VAMASK; /* FP doesn't mask */ +if (rel) { + pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; + pa1 = (loc1 + ((loc1 & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; } +else { pa = loc; + pa1 = loc1; } +if (MEM_ADDR_OK (pa)) M[pa >> 1] = (val >> 16) & DMASK16; +if (MEM_ADDR_OK (pa1)) M[pa1 >> 1] = val & DMASK16; +return; +} + +uint32 IOReadB (uint32 loc) +{ +return ((M[loc >> 1] >> ((loc & 1)? 0: 8)) & DMASK8); +} + +void IOWriteB (uint32 loc, uint32 val) +{ +val = val & DMASK8; +M[loc >> 1] = ((loc & 1)? + ((M[loc >> 1] & ~DMASK8) | val): + ((M[loc >> 1] & DMASK8) | (val << 8))); +return; +} + +/* Reset routine */ + +t_stat cpu_reset (DEVICE *dptr) +{ +qevent = 0; /* no events */ +newPSW (0); /* PSW = 0 */ +DR = 0; /* clr display */ +drmod = 0; +blk_io.dfl = blk_io.cur = blk_io.end = 0; /* no block IO */ +sim_brk_types = sim_brk_dflt = SWMASK ('E'); /* init bkpts */ +if (M == NULL) M = calloc (MAXMEMSIZE16E >> 1, sizeof (uint16)); +if (M == NULL) return SCPE_MEM; +pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */ +if (pcq_r) pcq_r->qptr = 0; +else return SCPE_IERR; +return SCPE_OK; +} + +/* Memory examine */ + +t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) +{ +if (sw & SWMASK ('V')) { + if (addr > VAMASK) return SCPE_NXM; + addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; } +if (addr >= MEMSIZE) return SCPE_NXM; +if (vptr != NULL) *vptr = IOReadB (addr); +return SCPE_OK; +} + +/* Memory deposit */ + +t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) +{ +if (sw & SWMASK ('V')) { + if (addr > VAMASK) return SCPE_NXM; + addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; } +if (addr >= MEMSIZE) return SCPE_NXM; +IOWriteB (addr, val & 0xFF); +return SCPE_OK; +} + +/* Change memory size */ + +t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 mc = 0; +t_addr i; + +if ((val <= 0) || ((val & 0xFFF) != 0) || + (((uint32) val) > ((uptr->flags & UNIT_816E)? MAXMEMSIZE16E: MAXMEMSIZE16))) + return SCPE_ARG; +for (i = val; i < MEMSIZE; i = i + 2) mc = mc | M[i >> 1]; +if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) + return SCPE_OK; +MEMSIZE = val; +for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2) M[i >> 1] = 0; +return SCPE_OK; +} + +/* Change CPU model */ + +t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +t_addr i; + +if (!(val & UNIT_816E) && (MEMSIZE > MAXMEMSIZE16)) { + MEMSIZE = MAXMEMSIZE16; + for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2) M[i >> 1] = 0; + printf ("Reducing memory to 64KB\n"); } +return SCPE_OK; +} + +/* Set console interrupt */ + +t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if ((uptr->flags & (UNIT_716 | UNIT_816 | UNIT_816E)) == 0) + return SCPE_NOFNC; +if (PSW & PSW_AIO) SET_INT (v_DS); +return SCPE_OK; +} diff --git a/Interdata/id16_dboot.c b/Interdata/id16_dboot.c new file mode 100644 index 00000000..3ee2e86c --- /dev/null +++ b/Interdata/id16_dboot.c @@ -0,0 +1,346 @@ +/* id16_dboot.c: Interdata 16b simulator disk bootstrap + + Copyright (c) 2000-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. +*/ + +#include "id_defs.h" + +#define DBOOT_BEG 0x1000 +#define DBOOT_START 0x100e +#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8)) + +/* Boot ROM: transcription of OS/16 MT2 ALO Direct Access Loader */ + +static uint8 dboot_rom[] = { + 0xca, 0xf0, 0x00, 0x30, + 0xc5, 0xf0, 0x00, 0x3a, + 0x02, 0x8e, + 0x26, 0xf7, + 0x03, 0x0e, + 0xd1, 0xc0, 0x00, 0x78, + 0xd0, 0xc0, 0x13, 0xf6, + 0x07, 0xdd, + 0xc8, 0x10, 0x10, 0x00, + 0xd3, 0xf0, 0x00, 0x7e, + 0xc4, 0xf0, 0x00, 0x0f, + 0x01, 0xe1, + 0xd2, 0xf0, 0x12, 0xe2, + 0xd3, 0xf0, 0x00, 0x7f, + 0x90, 0xf4, + 0x01, 0xe1, + 0xd2, 0xf0, 0x12, 0xe3, + 0xd3, 0xf0, 0x00, 0x7f, + 0xc4, 0xf0, 0x00, 0x0f, + 0x01, 0xe1, + 0xd2, 0xf0, 0x12, 0xe4, + 0xd3, 0x20, 0x00, 0x7d, + 0xd3, 0x30, 0x00, 0x7c, + 0xd3, 0x40, 0x00, 0x7a, + 0xd3, 0x50, 0x00, 0x7b, + 0xc8, 0x70, 0x12, 0xf6, + 0xc8, 0x80, 0x13, 0xf5, + 0x07, 0xaa, + 0x07, 0xcc, + 0x41, 0xe0, 0x11, 0x88, + 0x48, 0xa0, 0x12, 0xfe, + 0x48, 0xc0, 0x13, 0x00, + 0x43, 0x00, 0x10, 0x98, + 0xc8, 0x70, 0x12, 0xf6, + 0x41, 0xe0, 0x11, 0x88, + 0xc8, 0xe0, 0x12, 0xfa, + 0x24, 0x15, + 0xd3, 0x0e, 0x00, 0x24, + 0xc3, 0x00, 0x00, 0x10, + 0x21, 0x3f, + 0xca, 0xe0, 0x00, 0x30, + 0x27, 0x11, + 0x20, 0x38, + 0x48, 0xa0, 0x12, 0xf6, + 0x48, 0xc0, 0x12, 0xf8, + 0x42, 0x30, 0x10, 0x70, + 0x08, 0xaa, + 0x20, 0x33, + 0x43, 0x00, 0x12, 0xb2, + 0x90, 0x05, + 0x42, 0x30, 0x10, 0x88, + 0xc8, 0x60, 0x4f, 0x53, + 0x45, 0x63, 0x00, 0x00, + 0x20, 0x36, + 0xc8, 0x60, 0x31, 0x36, + 0x45, 0x6e, 0x00, 0x02, + 0x20, 0x3b, + 0x48, 0x6e, 0x00, 0x08, + 0x45, 0x60, 0x12, 0xe2, + 0x20, 0x35, + 0xd3, 0x6e, 0x00, 0x0a, + 0xd4, 0x60, 0x12, 0xe4, + 0x20, 0x3a, + 0x08, 0x0e, + 0x07, 0x66, + 0xca, 0x60, 0x20, 0x00, + 0x23, 0x36, + 0x40, 0x06, 0x00, 0x00, + 0x45, 0x06, 0x00, 0x00, + 0x22, 0x37, + 0x48, 0xae, 0x00, 0x0c, + 0x48, 0xce, 0x00, 0x0e, + 0x48, 0x0e, 0x00, 0x10, + 0x48, 0x1e, 0x00, 0x12, + 0x0b, 0x1c, + 0x0f, 0x0a, 0x07, 0xff, + 0x26, 0x11, + 0x0e, 0x0f, + 0xed, 0x00, 0x00, 0x08, + 0xcb, 0x60, 0x02, 0xbe, + 0x08, 0x00, + 0x23, 0x34, + 0x08, 0x86, + 0x08, 0x16, + 0x23, 0x04, + 0x05, 0x16, + 0x22, 0x84, + 0x08, 0x81, + 0x07, 0x77, + 0x27, 0x81, + 0xc8, 0xd1, 0xee, 0xc0, + 0xc8, 0xf0, 0x11, 0x40, + 0x48, 0x0f, 0x00, 0x00, + 0x40, 0x01, 0x00, 0x00, + 0x26, 0xf2, + 0x26, 0x12, + 0xc5, 0xf0, 0x13, 0xfe, + 0x20, 0x88, + 0x0a, 0xed, + 0x40, 0xed, 0x12, 0xf4, + 0x43, 0x0d, 0x11, 0x40, + 0x41, 0xed, 0x11, 0x88, + 0xd1, 0xed, 0x13, 0xf6, + 0xd0, 0xe0, 0x00, 0x78, + 0xd1, 0xed, 0x13, 0xfa, + 0xd0, 0xe0, 0x00, 0x7c, + 0x48, 0x10, 0x00, 0x62, + 0x48, 0x6d, 0x12, 0xf4, + 0xd1, 0xa6, 0x00, 0x00, + 0xd0, 0xa1, 0x00, 0x30, + 0xd1, 0xe6, 0x00, 0x0c, + 0xd0, 0xe1, 0x00, 0x28, + 0x43, 0x00, 0x00, 0x60, + 0x07, 0x00, + 0x07, 0xbb, + 0x0b, 0xcf, + 0x0f, 0xab, + 0x21, 0x13, + 0x26, 0x01, + 0x22, 0x04, + 0x0a, 0xcf, + 0x0e, 0xab, + 0x08, 0xac, + 0x08, 0xc0, + 0x03, 0x0e, + 0xde, 0x2d, 0x12, 0x1e, + 0xc5, 0x50, 0x00, 0x33, + 0x42, 0x2d, 0x11, 0xec, + 0xde, 0x3d, 0x12, 0x1e, + 0x9d, 0x3f, + 0x22, 0x21, + 0x9d, 0x4f, + 0x42, 0x1d, 0x12, 0xb8, + 0xc3, 0xf0, 0x00, 0x10, + 0x20, 0x35, + 0xd0, 0xad, 0x13, 0xea, + 0xc8, 0xf0, 0x00, 0x30, + 0x41, 0xed, 0x11, 0x70, + 0x08, 0x9c, + 0x08, 0xba, + 0x48, 0xad, 0x13, 0xea, + 0x48, 0xcd, 0x13, 0xee, + 0xd1, 0xed, 0x13, 0xf2, + 0xc5, 0xb0, 0x00, 0x18, + 0x21, 0x82, + 0x26, 0xb8, + 0x98, 0x49, + 0xde, 0x4d, 0x12, 0xe7, + 0x9d, 0x3f, + 0x22, 0x21, + 0x9d, 0x4f, + 0x42, 0x7d, 0x12, 0xb8, + 0x20, 0x83, + 0x98, 0x27, + 0x98, 0x28, + 0x98, 0x49, + 0x9a, 0x3b, + 0x41, 0x6d, 0x12, 0x7a, + 0x22, 0x0f, + 0x9d, 0x4f, + 0xc3, 0xf0, 0x00, 0x19, + 0x42, 0x3d, 0x12, 0xb8, + 0xd0, 0xad, 0x13, 0xea, + 0xc8, 0xf5, 0xff, 0xcc, + 0x0a, 0xff, + 0x48, 0xff, 0x12, 0xec, + 0x41, 0xed, 0x11, 0x70, + 0x08, 0x9c, + 0x08, 0xca, + 0x07, 0xaa, + 0xc8, 0xf5, 0xff, 0xcc, + 0xd3, 0xff, 0x12, 0xe8, + 0x41, 0xed, 0x11, 0x70, + 0x40, 0xcd, 0x12, 0xf2, + 0x08, 0xba, + 0x48, 0xad, 0x13, 0xea, + 0x48, 0xcd, 0x13, 0xee, + 0xd1, 0xed, 0x13, 0xf2, + 0xde, 0x4d, 0x12, 0x6e, + 0x9d, 0x3f, + 0x22, 0x21, + 0x98, 0x49, + 0xde, 0x4d, 0x12, 0xd0, + 0x9d, 0x3f, + 0x22, 0x21, + 0xde, 0x4d, 0x12, 0xa2, + 0x9d, 0x3f, + 0x22, 0x21, + 0xd8, 0x4d, 0x12, 0xf2, + 0xde, 0x4d, 0x12, 0xd1, + 0x9d, 0x3f, + 0x22, 0x21, + 0xde, 0x4d, 0x12, 0xe7, + 0x9d, 0x3f, + 0x22, 0x21, + 0x9d, 0x4f, + 0x20, 0x81, + 0xc3, 0xf0, 0x00, 0x53, + 0x42, 0x3d, 0x12, 0xb8, + 0x48, 0xfd, 0x12, 0xf2, + 0x91, 0xfa, + 0x06, 0xf9, + 0xc8, 0x6d, 0x12, 0x2c, + 0x98, 0x27, + 0x98, 0x28, + 0x9a, 0x3b, + 0x98, 0x3f, + 0xde, 0x3d, 0x12, 0xe6, + 0xde, 0x2d, 0x11, 0xaf, + 0x9d, 0x2f, + 0x20, 0x81, + 0xde, 0x2d, 0x12, 0x1e, + 0x99, 0x20, + 0xde, 0x2d, 0x12, 0x1e, + 0x9d, 0x3f, + 0x22, 0x21, + 0x42, 0x1d, 0x12, 0xbc, + 0xc3, 0xf0, 0x00, 0x10, + 0x03, 0x3e, + 0x0b, 0x07, + 0x26, 0x02, + 0xc4, 0x00, 0xff, 0x00, + 0x0a, 0x70, + 0x26, 0x91, + 0x07, 0xbb, + 0x40, 0xbd, 0x12, 0xf2, + 0x03, 0x06, + 0x24, 0xf1, + 0x24, 0x10, + 0x23, 0x04, + 0x08, 0x14, + 0x23, 0x02, + 0x08, 0x13, + 0x24, 0x01, + 0xde, 0x0d, 0x10, 0xdc, + 0x9a, 0x0f, + 0x9a, 0x01, + 0xde, 0x0d, 0x12, 0xe5, + 0xd1, 0xed, 0x13, 0xf6, + 0xd0, 0xe0, 0x00, 0x78, + 0xd1, 0xed, 0x13, 0xfa, + 0xd0, 0xe0, 0x00, 0x7c, + 0x91, 0x0f, + 0x95, 0x10, + 0x22, 0x01, + 0x00, 0x00, 0x00, + 0x80, + 0xc1, + 0xc2, + 0x14, 0x40, 0x40, 0x00, + 0x01, 0x90, + 0x01, 0x40, + 0x04, 0xc0, + 0x00, 0x00, + 0x00, 0x00 +}; + +/* Lower memory setup + + 78 = binary input device address + 79 = binary device input command + 7A = disk device number + 7B = device code + 7C = disk controller address + 7D = selector channel address + 7E:7F = operating system extension (user specified) +*/ + +struct dboot_id { + char *name; + uint32 cap; + uint32 dtype; + uint32 offset; +}; + +static struct dboot_id dboot_tab[] = { + { "DP", 2, 0x31, o_DP0 }, + { "DP", 9, 0x33, o_DP0 }, + { "DM", 64, 0x35, o_ID0 }, + { "DM", 244, 0x36, o_ID0 }, + { NULL } }; + +t_stat id_dboot (int32 u, DEVICE *dptr) +{ +extern DIB pt_dib, sch_dib; +extern uint32 PC; +uint32 i, typ, ctlno, off, cap, sch_dev; +UNIT *uptr; + +DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */ +ctlno = ddib->dno; /* get ctrl devno */ +sch_dev = sch_dib.dno + ddib->sch; /* sch dev # */ +uptr = dptr->units + u; /* get capacity */ +cap = uptr->capac >> 20; +for (i = typ = 0; dboot_tab[i].name != NULL; i++) { + if ((strcmp (dboot_tab[i].name, dptr->name) == 0) && + (dboot_tab[i].cap == cap)) { + typ = dboot_tab[i].dtype; + off = dboot_tab[i].offset; } } +if (typ == 0) return SCPE_NOFNC; + +IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */ +IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */ +IOWriteB (AL_IOC, 0x99); +IOWriteB (AL_DSKU, ctlno + ((u + 1) * off)); /* disk param */ +IOWriteB (AL_DSKT, typ); +IOWriteB (AL_DSKC, ctlno); +IOWriteB (AL_SCH, sch_dev); +PC = DBOOT_START; +return SCPE_OK; +} diff --git a/Interdata/id16_sys.c b/Interdata/id16_sys.c new file mode 100644 index 00000000..37e357c2 --- /dev/null +++ b/Interdata/id16_sys.c @@ -0,0 +1,521 @@ +/* id16_sys.c: Interdata 16b simulator interface + + Copyright (c) 2000-2003, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. +*/ + +#include "id_defs.h" +#include + +#define MSK_SBF 0x0100 + +extern DEVICE cpu_dev; +extern DEVICE sch_dev; +extern DEVICE pt_dev; +extern DEVICE tt_dev, ttp_dev; +extern DEVICE pas_dev, pasl_dev; +extern DEVICE lpt_dev; +extern DEVICE pic_dev, lfc_dev; +extern DEVICE dp_dev, idc_dev; +extern DEVICE fd_dev, mt_dev; +extern UNIT cpu_unit; +extern REG cpu_reg[]; +extern uint16 *M; + +t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val); +t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val); +extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam); +extern pt_dump (FILE *of, char *cptr, char *fnam); + +/* SCP data structures and interface routines + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages + sim_load binary loader +*/ + +char sim_name[] = "Interdata 16b"; + +REG *sim_PC = &cpu_reg[0]; + +int32 sim_emax = 8; + +DEVICE *sim_devices[] = { + &cpu_dev, + &sch_dev, + &pt_dev, + &tt_dev, + &ttp_dev, + &pas_dev, + &pasl_dev, + &pic_dev, + &lfc_dev, + &lpt_dev, + &dp_dev, + &idc_dev, + &fd_dev, + &mt_dev, + NULL }; + +const char *sim_stop_messages[] = { + "Unknown error", + "Reserved instruction", + "HALT instruction", + "Breakpoint", + "Wait state", + "Runaway VFU" }; + +/* Binary loader -- load carriage control tape + Binary dump -- paper tape dump */ + +t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +{ +if (flag) return pt_dump (fileref, cptr, fnam); +return lp_load (fileref, cptr, fnam); +} + +/* Symbol tables */ + +#define I_V_FL 16 /* class bits */ +#define I_M_FL 0xF /* class mask */ +#define I_V_MR 0x0 /* mask-register */ +#define I_V_RR 0x1 /* register-register */ +#define I_V_R 0x2 /* register */ +#define I_V_MX 0x3 /* mask-memory */ +#define I_V_RX 0x4 /* register-memory */ +#define I_V_X 0x5 /* memory */ +#define I_V_FF 0x6 /* float reg-reg */ +#define I_V_FX 0x7 /* float reg-mem */ +#define I_V_SI 0x8 /* short immed */ +#define I_V_SB 0x9 /* short branch */ +#define I_V_SX 0xA /* short ext branch */ +#define I_MR (I_V_MR << I_V_FL) +#define I_RR (I_V_RR << I_V_FL) +#define I_R (I_V_R << I_V_FL) +#define I_MX (I_V_MX << I_V_FL) +#define I_RX (I_V_RX << I_V_FL) +#define I_X (I_V_X << I_V_FL) +#define I_FF (I_V_FF << I_V_FL) +#define I_FX (I_V_FX << I_V_FL) +#define I_SI (I_V_SI << I_V_FL) +#define I_SB (I_V_SB << I_V_FL) +#define I_SX (I_V_SX << I_V_FL) + +#define R_X 0 /* no reg */ +#define R_M 1 /* reg mask */ +#define R_R 2 /* reg int reg */ +#define R_F 3 /* reg flt reg */ + +static const int32 masks[] = { + 0xFF00, 0xFF00, 0xFFF0, 0xFF00, + 0xFF00, 0xFFF0, 0xFF00, 0xFF00, + 0xFF00, 0xFE00, 0xFEF0 }; + +static const uint32 r1_type[] = { + R_M, R_R, R_X, R_M, + R_R, R_X, R_F, R_F, + R_R, R_M, R_X }; + +static const uint32 r2_type[] = { + R_X, R_R, R_R, R_X, + R_X, R_X, R_F, R_X, + R_M, R_X, R_X }; + +static const char *opcode[] = { +"BER", "BNER","BZR", "BNZR", +"BPR", "BNPR","BLR", "BNLR", +"BMR", "BNMR","BOR", "BNOR", +"BCR", "BNCR","BR", +"BES", "BNES","BZS", "BNZS", +"BPS", "BNPS","BLS", "BNLS", +"BMS", "BNMS","BOS", "BNOS", +"BCS", "BNCS","BS", +"BE", "BNE", "BZ", "BNZ", +"BP", "BNP", "BL", "BNL", +"BM", "BNM", "BO", "BNO", +"BC", "BNC", "B", + "BALR","BTCR","BFCR", +"NHR", "CLHR","OHR", "XHR", +"LHR", "CHR", "AHR", "SHR", +"MHR", "DHR", "ACHR","SCHR", + "SETMR", +"BTBS","BTFS","BFBS","BFFS", +"LIS", "LCS", "AIS", "SIS", +"LER", "CER", "AER", "SER", +"MER", "DER", "FXR", "FLR", + "LPSR", +"LDR", "CDR", "ADR", "SDR", +"MDR", "DDR", "FXDR","FLDR", +"STH", "BAL", "BTC", "BFC", +"NH", "CLH", "OH", "XH", +"LH", "CH", "AH", "SH", +"MH", "DH", "ACH", "SCH", + "SETM", +"STE", "AHM", +"ATL", "ABL", "RTL", "RBL", +"LE", "CE", "AE", "SE", +"ME", "DE", +"STD", "STME","LME", "LPS", +"LD", "CD", "AD", "SD", +"MD", "DD", "STMD","LMD", +"SRLS","SLLS","STBR","LBR", +"EXBR","EPSR","WBR", "RBR", +"WHR", "RHR", "WDR", "RDR", +"MHUR","SSR", "OCR", "AIR", +"BXH", "BXLE","LPSW","THI", +"NHI", "CLHI","OHI", "XHI", +"LHI", "CHI", "AHI", "SHI", +"SRHL","SLHL","SRHA","SLHA", +"STM", "LM", "STB", "LB", +"CLB", "AL", "WB", "RB", +"WH", "RH", "WD", "RD", +"MHU", "SS", "OC", "AI", + "SVC", "SINT", + "RRL", "RLL", +"SRL", "SLL", "SRA", "SLA", +NULL }; + +static const uint32 opc_val[] = { +0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R, +0x0220+I_R, 0x0320+I_R, 0x0280+I_R, 0x0380+I_R, +0x0210+I_R, 0x0310+I_R, 0x0240+I_R, 0x0340+I_R, +0x0280+I_R, 0x0380+I_R, 0x0300+I_R, +0x2230+I_SX, 0x2030+I_SX, 0x2230+I_SX, 0x2030+I_SX, +0x2020+I_SX, 0x2220+I_SX, 0x2080+I_SX, 0x2280+I_SX, +0x2010+I_SX, 0x2210+I_SX, 0x2040+I_SX, 0x2240+I_SX, +0x2080+I_SX, 0x2280+I_SX, 0x2200+I_SX, +0x4330+I_X, 0x4230+I_X, 0x4330+I_X, 0x4230+I_X, +0x4220+I_X, 0x4320+I_X, 0x4280+I_X, 0x4380+I_X, +0x4210+I_X, 0x4310+I_X, 0x4240+I_X, 0x4340+I_X, +0x4280+I_X, 0x4380+I_X, 0x4300+I_X, + 0x0100+I_RR, 0x0200+I_MR, 0x0300+I_MR, +0x0400+I_RR, 0x0500+I_RR, 0x0600+I_RR, 0x0700+I_RR, +0x0800+I_RR, 0x0900+I_RR, 0x0A00+I_RR, 0x0B00+I_RR, +0x0C00+I_RR, 0x0D00+I_RR, 0x0E00+I_RR, 0x0F00+I_RR, + 0x1300+I_RR, +0x2000+I_SB, 0x2100+I_SB, 0x2200+I_SB, 0x2300+I_SB, +0x2400+I_SI, 0x2500+I_SI, 0x2600+I_SI, 0x2700+I_SI, +0x2800+I_FF, 0x2900+I_FF, 0x2A00+I_FF, 0x2B00+I_FF, +0x2C00+I_FF, 0x2D00+I_FF, 0x2E00+I_RR, 0x2F00+I_RR, + 0x3300+I_R, +0x3800+I_FF, 0x3900+I_FF, 0x3A00+I_FF, 0x3B00+I_FF, +0x3C00+I_FF, 0x3D00+I_FF, 0x3E00+I_RR, 0x3F00+I_RR, +0x4000+I_RX, 0x4100+I_RX, 0x4200+I_MX, 0x4300+I_MX, +0x4400+I_RX, 0x4500+I_RX, 0x4600+I_RX, 0x4700+I_RX, +0x4800+I_RX, 0x4900+I_RX, 0x4A00+I_RX, 0x4B00+I_RX, +0x4C00+I_RX, 0x4D00+I_RX, 0x4E00+I_RX, 0x4F00+I_RX, + 0x5300+I_RX, +0x6000+I_RX, 0x6100+I_RX, +0x6400+I_RX, 0x6500+I_RX, 0x6600+I_RX, 0x6700+I_RX, +0x6800+I_FX, 0x6900+I_FX, 0x6A00+I_FX, 0x6B00+I_FX, +0x6C00+I_FX, 0x6D00+I_FX, +0x7000+I_FX, 0x7100+I_FX, 0x7200+I_FX, 0x7300+I_X, +0x7800+I_FX, 0x7900+I_FX, 0x7A00+I_FX, 0x7B00+I_FX, +0x7C00+I_FX, 0x7D00+I_FX, 0x7E00+I_FX, 0x7F00+I_FX, +0x9000+I_SI, 0x9100+I_SI, 0x9200+I_RR, 0x9300+I_RR, +0x9400+I_RR, 0x9500+I_RR, 0x9600+I_RR, 0x9700+I_RR, +0x9800+I_RR, 0x9900+I_RR, 0x9A00+I_RR, 0x9B00+I_RR, +0x9C00+I_RR, 0x9D00+I_RR, 0x9E00+I_RR, 0x9F00+I_RR, +0xC000+I_RX, 0xC100+I_RX, 0xC200+I_X, 0xC300+I_RX, +0xC400+I_RX, 0xC500+I_RX, 0xC600+I_RX, 0xC700+I_RX, +0xC800+I_RX, 0xC900+I_RX, 0xCA00+I_RX, 0xCB00+I_RX, +0xCC00+I_RX, 0xCD00+I_RX, 0xCE00+I_RX, 0xCF00+I_RX, +0xD000+I_RX, 0xD100+I_RX, 0xD200+I_RX, 0xD300+I_RX, +0xD400+I_RX, 0xD500+I_X, 0xD600+I_RX, 0xD700+I_RX, +0xD800+I_RX, 0xD900+I_RX, 0xDA00+I_RX, 0xDB00+I_RX, +0xDC00+I_RX, 0xDD00+I_RX, 0xDE00+I_RX, 0xDF00+I_RX, + 0xE100+I_RX, 0xE200+I_RX, + 0xEA00+I_RX, 0xEB00+I_RX, +0xEC00+I_RX, 0xED00+I_RX, 0xEE00+I_RX, 0xEF00+I_RX, +0xFFFF }; + +#define GETNUM(d,n) for (k = d = 0; k < n; k++) \ + d = (d << 8) | (((uint32) val[vp++]) & 0xFF) + +/* Symbolic decode + + Inputs: + *of = output stream + addr = current PC + *val = values to decode + *uptr = pointer to unit + sw = switches + Outputs: + return = if >= 0, error code + if < 0, number of extra bytes retired +*/ + +t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, + UNIT *uptr, int32 sw) +{ +int32 c, k, num, rdx, vp, lnt; +t_stat r; +DEVICE *dptr; + +if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +dptr = find_dev_from_unit (uptr); /* find dev */ +if (dptr == NULL) return SCPE_IERR; +if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ +if (sw & SWMASK ('B')) lnt = 1; /* get length */ +else if (sw & SWMASK ('W')) lnt = 2; +else if (sw & SWMASK ('F')) lnt = 4; +else lnt = (uptr == &cpu_unit)? 2: 1; +if (sw & SWMASK ('D')) rdx = 10; /* get radix */ +else if (sw & SWMASK ('O')) rdx = 8; +else if (sw & SWMASK ('H')) rdx = 16; +else rdx = dptr->dradix; +vp = 0; /* init ptr */ +if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ + if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ + if ((val[0] & 0x7F) == 0) return SCPE_ARG; + while (vp < lnt) { /* print string */ + if ((c = (uint32) val[vp++] & 0x7F) == 0) break; + fprintf (of, (c < 0x20)? "<%02X>": "%c", c); } + return -(vp - 1); } /* return # chars */ + +if (sw & SWMASK ('M')) { /* inst format? */ + r = fprint_sym_m (of, addr, val); /* decode inst */ + if (r <= 0) return r; } + +GETNUM (num, lnt); /* get number */ +fprint_val (of, num, rdx, lnt * 8, PV_RZRO); +return -(vp - 1); +} + +/* Symbolic decode for -m + + Inputs: + of = output stream + addr = current PC + *val = values to decode + Outputs: + return = if >= 0, error code + if < 0, number of extra bytes retired +*/ + +t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val) +{ +uint32 i, j, k, inst, r1, r2, ea, tgt, vp; + +vp = 0; +GETNUM (inst, 2); /* first 16b */ +GETNUM (ea, 2); /* second 16b */ +for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */ + j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ + if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */ + r1 = (inst >> 4) & 0xF; + r2 = inst & 0xF; + switch (j) { /* case on class */ + case I_V_MR: /* mask-register */ + fprintf (of, "%s %-X,R%d", opcode[i], r1, r2); + return -1; + case I_V_RR: /* register-register */ + case I_V_FF: /* floating-floating */ + fprintf (of, "%s R%d,R%d", opcode[i], r1, r2); + return -1; + case I_V_SI: /* short immediate */ + fprintf (of, "%s R%d,%-X", opcode[i], r1, r2); + return -1; + case I_V_SB: /* short branch */ + if (inst & MSK_SBF) tgt = addr + r2 + r2; + else tgt = addr - r2 - r2; + fprintf (of, "%s %-X,%-X", opcode[i], r1, tgt); + return -1; + case I_V_SX: /* ext short branch */ + if (inst & MSK_SBF) tgt = addr + r2 + r2; + else tgt = addr - r2 - r2; + fprintf (of, "%s %-X", opcode[i], tgt); + return -1; + case I_V_R: /* register */ + fprintf (of, "%s R%d", opcode[i], r2); + return -1; + case I_V_MX: /* mask-memory */ + fprintf (of, "%s %-X,%-X", opcode[i], r1, ea); + break; + case I_V_RX: /* register-memory */ + case I_V_FX: /* floating-memory */ + fprintf (of, "%s R%d,%-X", opcode[i], r1, ea); + break; + case I_V_X: /* memory */ + fprintf (of, "%s %-X", opcode[i], ea); + break; } /* end case */ + if (r2) fprintf (of, "(R%d)", r2); + return -3; } /* end if */ + } /* end for */ +return SCPE_ARG; /* no match */ +} + +/* Register number + + Inputs: + *cptr = pointer to input string + **optr = pointer to pointer to next char + rtype = mask, integer, or float + Outputs: + rnum = output register number, -1 if error +*/ + +int32 get_reg (char *cptr, char **optr, int32 rtype) +{ +int32 reg; + +if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */ + cptr++; /* skip */ + if (rtype == R_M) return -1; } /* cant be mask */ +if ((*cptr >= '0') && (*cptr <= '9')) { + reg = *cptr++ - '0'; + if ((*cptr >= '0') && (*cptr <= '9')) + reg = (reg * 10) + (*cptr - '0'); + else --cptr; + if (reg > 0xF) return -1; } +else if ((*cptr >= 'a') && (*cptr <= 'f')) reg = (*cptr - 'a') + 10; +else if ((*cptr >= 'A') && (*cptr <= 'F')) reg = (*cptr - 'A') + 10; +else return -1; +if ((rtype == R_F) && (reg & 1)) return -1; +*optr = cptr + 1; +return reg; +} + +#define PUTNUM(d,n) for (k = n; k > 0; k--) \ + val[vp++] = (d >> ((k - 1) * 8)) & 0xFF + +/* Symbolic input */ + +t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) +{ +int32 k, rdx, lnt, num, vp; +t_stat r; +DEVICE *dptr; +static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF }; + +if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +dptr = find_dev_from_unit (uptr); /* find dev */ +if (dptr == NULL) return SCPE_IERR; +if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ +if (sw & SWMASK ('B')) lnt = 1; /* get length */ +else if (sw & SWMASK ('W')) lnt = 2; +else if (sw & SWMASK ('F')) lnt = 4; +else lnt = (uptr == &cpu_unit)? 2: 1; +if (sw & SWMASK ('D')) rdx = 10; /* get radix */ +else if (sw & SWMASK ('O')) rdx = 8; +else if (sw & SWMASK ('H')) rdx = 16; +else rdx = dptr->dradix; +vp = 0; +if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ + if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ + if (*cptr == 0) return SCPE_ARG; + while ((vp < lnt) && *cptr) { /* get chars */ + val[vp++] = *cptr++; } + return -(vp - 1); } /* return # chars */ + +if (uptr == &cpu_unit) { /* cpu only */ + r = parse_sym_m (cptr, addr, val); /* try to parse inst */ + if (r <= 0) return r; } + +num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */ +if (r != SCPE_OK) return r; +PUTNUM (num, lnt); /* store */ +return -(lnt - 1); +} + +/* Symbolic input for -m + + Inputs: + *cptr = pointer to input string + addr = current PC + *val = pointer to output values + Outputs: + status = > 0 error code + <= 0 -number of extra words +*/ + +t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val) +{ +uint32 i, j, k, t, df, db, inst, ea, vp; +int32 r1, r2; +t_stat r; +char *tptr, gbuf[CBUFSIZE]; + +vp = 0; +cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; +if (opcode[i] == NULL) return SCPE_ARG; +inst = opc_val[i] & 0xFFFF; /* get value */ +j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ +if (r1_type[j]) { /* any R1 field? */ + cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */ + if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0) + return SCPE_ARG; + if (*tptr != 0) return SCPE_ARG; /* all done? */ + inst = inst | (r1 << 4); } /* or in R1 */ + +cptr = get_glyph (cptr, gbuf, 0); /* get operand */ +if (*cptr) return SCPE_ARG; /* should be end */ +switch (j) { /* case on class */ + +case I_V_FF: case I_V_SI: /* flt-flt, sh imm */ +case I_V_MR: case I_V_RR: /* mask/reg-reg */ +case I_V_R: /* register */ + if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0) + return SCPE_ARG; + if (*tptr != 0) return SCPE_ARG; /* all done? */ + inst = inst | r2; /* or in R2 */ + break; + +case I_V_FX: /* float-memory */ +case I_V_MX: case I_V_RX: /* mask/reg-mem */ +case I_V_X: /* memory */ + errno = 0; + ea = strtoul (gbuf, &tptr, 16); /* get address */ + if (errno || (gbuf == tptr)) return SCPE_ARG; /* error? */ + if (*tptr == '(') { /* index? */ + if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0) + return SCPE_ARG; + if (*tptr++ != ')') return SCPE_ARG; + inst = inst | r2; } /* or in R2 */ + if (*tptr != 0) return SCPE_ARG; + PUTNUM (inst, 2); + PUTNUM (ea, 2); + return -3; + +case I_V_SB: case I_V_SX: /* short branches */ + t = get_uint (gbuf, 16, DMASK16, &r); /* get addr */ + if ((r != SCPE_OK) || (t & 1)) return r; /* error if odd */ + db = (addr - t) & 0x1F; /* back displ */ + df = (t - addr) & 0x1F; /* fwd displ */ + if ((t == ((addr - db) & VAMASK16)) && /* back work and */ + ((j == I_V_SX) || !(inst & MSK_SBF))) { /* ext or back br? */ + inst = inst | (db >> 1); /* or in back displ */ + break; } + if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */ + ((j == I_V_SX) || (inst & MSK_SBF))) { /* ext or fwd br? */ + inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */ + break; } + return SCPE_ARG; } /* end case */ + +PUTNUM (inst, 2); +return -1; +} diff --git a/Interdata/id32_cpu.c b/Interdata/id32_cpu.c new file mode 100644 index 00000000..3a0b204d --- /dev/null +++ b/Interdata/id32_cpu.c @@ -0,0 +1,2025 @@ +/* id32_cpu.c: Interdata 32b CPU simulator + + Copyright (c) 2000-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + The register state for an Interdata 32b CPU is: + + REG[0:F][2]<0:31> general register sets + F[0:7]<0:31> single precision floating point registers + D[0:7]<0:63> double precision floating point registers + PSW<0:63> processor status word, including + STAT<0:11> status flags + CC<0:3> condition codes + PC<0:31> program counter + int_req[n]<0:31> interrupt requests + int_enb[n]<0:31> interrupt enables + + The Interdata 32b systems have seven instruction formats: register to + register, short format, register and memory (three formats), and register + and immediate (two formats). The formats are: + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | R2 | register-register + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | N | short format + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | RX | register-memory 1 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ (absolute 14b) + | 0| 0| address | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | RX | register-memory 2 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ (relative) + | 1| address | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | RX | register-memory 3 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ (double index) + | 0| 1| 0| 0| RX2 | address hi | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | address lo | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | RX | register-immediate 1 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | immediate | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | R1 | RX | register-immediate 2 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | immediate hi | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | immediate lo | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + For register-memory 1 and register-immediate 1 and 2 an instructions, an + effective address is calculated as follows: + + effective addr = address + RX (if RX > 0) + + For register-memory 2, an effective address is calculated as follows: + + effective addr = address + PC + RX (if RX > 0) + + For register-memory 3, an effective address is calculated as follows: + + effective addr = address + RX (if RX > 0) + RX2 (if RX2 > 0) + + Register-memory instructions can access an address space of 16M bytes. +*/ + +/* This routine is the instruction decode routine for the Interdata CPU. + It is called from the simulator control program to execute + instructions in simulated memory, starting at the simulated PC. + It runs until 'reason' is set non-zero. + + General notes: + + 1. Reasons to stop. The simulator can be stopped by: + + HALT instruction + breakpoint encountered + wait state and no I/O outstanding + invalid instruction + I/O error in I/O simulator + + 2. Interrupts. Each device has an interrupt armed flag, an interrupt + request flag, and an interrupt enabled flag. To facilitate evaluation, + all interrupt requests are kept in int_req, and all enables in int_enb. + Interrupt armed flags are local to devices. If external interrupts are + enabled in the PSW, and a request is pending, an interrupt occurs. + + 3. Non-existent memory. On the Interdata 32b, reads to non-existent + memory return zero, and writes are ignored. In the simulator, the + largest possible memory is instantiated and initialized to zero. + Thus, only writes need be checked against actual memory size. + + 4. Adding I/O devices. These modules must be modified: + + id_defs.h add device interrupt definitions + id32_sys.c add sim_devices table entry +*/ + +#include "id_defs.h" +#include + +#define PCQ_SIZE 64 /* must be 2**n */ +#define PCQ_MASK (PCQ_SIZE - 1) +#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = oPC +#define VAMASK VAMASK32 +#define NRSETS 2 /* 2 gen reg sets */ +#define PSW_MASK PSW_x32 +#define ABORT(val) longjmp (save_env, (val)) +#define MPRO (-1) + +#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */ +#define UNIT_V_DPFP (UNIT_V_UF + 1) +#define UNIT_V_832 (UNIT_V_UF + 2) +#define UNIT_MSIZE (1 << UNIT_V_MSIZE) +#define UNIT_DPFP (1 << UNIT_V_DPFP) +#define UNIT_832 (1 << UNIT_V_832) +#define UNIT_TYPE (UNIT_DPFP | UNIT_832) + +#define SEXT32(x) (((x) & SIGN32)? ((int32) ((x) | ~0x7FFFFFFF)): \ + ((int32) ((x) & 0x7FFFFFFF))) +#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | ~0x7FFF)): \ + ((int32) ((x) & 0x7FFF))) +#define SEXT15(x) (((x) & 0x4000)? ((int32) ((x) | ~0x3FFF)): \ + ((int32) ((x) & 0x3FFF))) +#define CC_GL_16(x) if ((x) & SIGN16) cc = CC_L; \ + else if (x) cc = CC_G; \ + else cc = 0 +#define CC_GL_32(x) if ((x) & SIGN32) cc = CC_L; \ + else if (x) cc = CC_G; \ + else cc = 0 +#define BUILD_PSW(x) (((PSW & ~CC_MASK) | (x)) & PSW_MASK) +#define NEG(x) ((~(x) + 1) & DMASK32) +#define ABS(x) (((x) & SIGN32)? NEG (x): (x)) +#define DNEG(x,y) y = NEG (y); \ + x = (~(x) + (y == 0)) & DMASK32 + +uint32 GREG[16 * NRSETS] = { 0 }; /* general registers */ +uint32 *M = NULL; /* memory */ +uint32 *R = &GREG[0]; /* working reg set */ +uint32 F[8] = { 0 }; /* sp fp registers */ +dpr_t D[8] = { 0 }; /* dp fp registers */ +uint32 PSW = 0; /* processor status word */ +uint32 PC = 0; /* program counter */ +uint32 oPC = 0; /* PC at inst start */ +uint32 SR = 0; /* switch register */ +uint32 DR = 0; /* display register */ +uint32 DRX = 0; /* display extension */ +uint32 drmod = 0; /* mode */ +uint32 srpos = 0; /* switch register pos */ +uint32 drpos = 0; /* display register pos */ +uint32 mac_reg[MAC_LNT] = { 0 }; /* mac registers */ +uint32 mac_sta = 0; /* mac status */ +uint32 int_req[INTSZ] = { 0 }; /* interrupt requests */ +uint32 int_enb[INTSZ] = { 0 }; /* interrupt enables */ +uint32 qevent = 0; /* events */ +uint32 stop_inst = 0; /* stop on ill inst */ +uint32 stop_wait = 0; /* stop on wait */ +uint32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ +int32 pcq_p = 0; /* PC queue ptr */ +REG *pcq_r = NULL; /* PC queue reg ptr */ +uint32 dec_flgs = 0; /* decode flags */ +uint32 fp_in_hwre = 0; /* ucode vs hwre fp */ +uint32 pawidth = PAWIDTH32; /* addr mask */ +uint32 cpu_log = 0; /* debug logging */ +jmp_buf save_env; /* abort handler */ +struct BlockIO blk_io; /* block I/O status */ +uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL }; + +extern int32 sim_interval; +extern int32 sim_int_char; +extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +extern UNIT pic_unit, lfc_unit, pas_unit; /* timers */ +extern FILE *sim_log; + +uint32 ReadB (uint32 loc, uint32 rel); +uint32 ReadH (uint32 loc, uint32 rel); +void WriteB (uint32 loc, uint32 val, uint32 rel); +void WriteH (uint32 loc, uint32 val, uint32 rel); +uint32 RelocT (uint32 va, uint32 base, uint32 rel, uint32 *pa); +uint32 int_auto (uint32 dev, uint32 cc); +uint32 addtoq (uint32 ea, uint32 val, uint32 flg); +uint32 remfmq (uint32 ea, uint32 r1, uint32 flg); +uint32 exception (uint32 loc, uint32 cc, uint32 flg); +uint32 newPSW (uint32 val); +uint32 testsysq (uint32 cc); +uint32 display (uint32 dev, uint32 op, uint32 dat); +t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); +t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); +t_stat cpu_reset (DEVICE *dptr); +t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc); +void set_r_display (uint32 *rbase); + +extern t_bool devtab_init (void); +extern void int_eval (void); +extern uint32 int_getdev (void); +extern void sch_cycle (uint32 ch); +extern t_bool sch_blk (uint32 dev); +extern uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea); +extern uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea); +extern uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea); +extern uint32 f_m (uint32 op, uint32 r1, uint32 r2, uint32 ea); +extern uint32 f_d (uint32 op, uint32 r1, uint32 r2, uint32 ea); +extern uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2); +extern uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2); + +/* Instruction decoding table */ + +const uint16 decrom[256] = { + 0, /* 00 */ + OP_RR, /* BALR */ + OP_RR, /* BTCR */ + OP_RR, /* BFCR */ + OP_RR, /* NR */ + OP_RR, /* CLR */ + OP_RR, /* OR */ + OP_RR, /* XR */ + OP_RR, /* LR */ + OP_RR, /* CR */ + OP_RR, /* AR */ + OP_RR, /* SR */ + OP_RR, /* MHR */ + OP_RR, /* DHR */ + 0, 0, /* 0E:0F */ + OP_NO, /* SRLS */ + OP_NO, /* SLLS */ + OP_RR, /* CHVR */ + 0, 0, 0, 0, 0, /* 13:17 */ + OP_RR | OP_PRV, /* LPSWR */ + 0, 0, 0, /* 19:1B */ + OP_RR, /* MR */ + OP_RR, /* DR */ + 0, 0, /* 1E:1F */ + OP_NO, /* BTBS */ + OP_NO, /* BTFS */ + OP_NO, /* BFBS */ + OP_NO, /* BFFS */ + OP_NO, /* LIS */ + OP_NO, /* LCS */ + OP_NO, /* AIS */ + OP_NO, /* SIS */ + OP_NO, /* LER */ + OP_NO, /* CER */ + OP_NO, /* AER */ + OP_NO, /* SER */ + OP_NO, /* MER */ + OP_NO, /* DER */ + OP_NO, /* FXR */ + OP_NO, /* FLR */ + 0, /* MPBSR - 8/32C */ + 0, /* 31 */ + 0, /* PBR - 8/32C */ + 0, /* 33 */ + OP_RR, /* EXHR */ + 0, 0, 0, /* 35:37 */ + OP_NO | OP_DPF, /* LDR */ + OP_NO | OP_DPF, /* CDR */ + OP_NO | OP_DPF, /* ADR */ + OP_NO | OP_DPF, /* SDR */ + OP_NO | OP_DPF, /* MDR */ + OP_NO | OP_DPF, /* DDR */ + OP_NO | OP_DPF, /* FXDR */ + OP_NO | OP_DPF, /* FLDR */ + OP_RX, /* STH */ + OP_RX, /* BAL */ + OP_RX, /* BTC */ + OP_RX, /* BFC */ + OP_RXH, /* NH */ + OP_RXH, /* CLH */ + OP_RXH, /* OH */ + OP_RXH, /* XH */ + OP_RXH, /* LH */ + OP_RXH, /* CH */ + OP_RXH, /* AH */ + OP_RXH, /* SH */ + OP_RXH, /* MH */ + OP_RXH, /* DH */ + 0, 0, /* 4E:4F */ + OP_RX, /* ST */ + OP_RXF, /* AM */ + 0, 0, /* 52:53 */ + OP_RXF, /* N */ + OP_RXF, /* CL */ + OP_RXF, /* O */ + OP_RXF, /* X */ + OP_RXF, /* L */ + OP_RXF, /* C */ + OP_RXF, /* A */ + OP_RXF, /* S */ + OP_RXF, /* M */ + OP_RXF, /* D */ + OP_RX, /* CRC12 */ + OP_RX, /* CRC16 */ + OP_RX, /* STE */ + OP_RXH, /* AHM */ + 0, /* PB - 8/32C */ + OP_RX, /* LRA */ + OP_RX, /* ATL */ + OP_RX, /* ABL */ + OP_RX, /* RTL */ + OP_RX, /* RBL */ + OP_RX, /* LE */ + OP_RX, /* CE */ + OP_RX, /* AE */ + OP_RX, /* SE */ + OP_RX, /* ME */ + OP_RX, /* DE */ + 0, 0, /* 6E:6F */ + OP_RX | OP_DPF, /* STD */ + OP_RX, /* SME */ + OP_RX, /* LME */ + OP_RX, /* LHL */ + OP_RX, /* TBT */ + OP_RX, /* SBT */ + OP_RX, /* RBT */ + OP_RX, /* CBT */ + OP_RX | OP_DPF, /* LD */ + OP_RX | OP_DPF, /* CD */ + OP_RX | OP_DPF, /* AD */ + OP_RX | OP_DPF, /* SD */ + OP_RX | OP_DPF, /* MD */ + OP_RX | OP_DPF, /* DD */ + OP_RX | OP_DPF, /* STMD */ + OP_RX | OP_DPF, /* LMD */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 80:8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + OP_NO, /* SRHLS */ + OP_NO, /* SLHLS */ + OP_NO, /* STBR */ + OP_NO, /* LDBR */ + OP_NO, /* EXBR */ + OP_NO | OP_PRV, /* EPSR */ + OP_RR | OP_PRV, /* WBR */ + OP_RR | OP_PRV, /* RBR */ + OP_RR | OP_PRV, /* WHR */ + OP_RR | OP_PRV, /* RHR */ + OP_RR | OP_PRV, /* WDR */ + OP_RR | OP_PRV, /* RDR */ + 0, /* 9C */ + OP_RR | OP_PRV, /* SSR */ + OP_RR | OP_PRV, /* OCR */ + 0, /* 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* A0:AF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* B0:BF */ + 0, 0, 0, 0, 0, 0, 0, 0, + OP_RX, /* BXH */ + OP_RX, /* BXLE */ + OP_RXF | OP_PRV, /* LPSW */ + OP_RI1, /* THI */ + OP_RI1, /* NHI */ + OP_RI1, /* CLHI */ + OP_RI1, /* OHI */ + OP_RI1, /* XHI */ + OP_RI1, /* LHI */ + OP_RI1, /* CHI */ + OP_RI1, /* AHI */ + OP_RI1, /* SHI */ + OP_RI1, /* SRHL */ + OP_RI1, /* SLHL */ + OP_RI1, /* SRHA */ + OP_RI1, /* SLHA */ + OP_RX, /* STM */ + OP_RX, /* LM */ + OP_RX, /* STB */ + OP_RX, /* LDB */ + OP_RX, /* CLB */ + OP_RX | OP_PRV, /* AL */ + OP_RXF | OP_PRV, /* WB */ + OP_RXF | OP_PRV, /* RB */ + OP_RX | OP_PRV, /* WH */ + OP_RX | OP_PRV, /* RH */ + OP_RX | OP_PRV, /* WD */ + OP_RX | OP_PRV, /* RD */ + 0, /* DC */ + OP_RX | OP_PRV, /* SS */ + OP_RX | OP_PRV, /* OC */ + 0, /* DF */ + OP_RXH, /* TS */ + OP_RX, /* SVC */ + OP_RI1 | OP_PRV, /* SINT */ + OP_RX | OP_PRV, /* SCP */ + 0, 0, /* E4:E5 */ + OP_RX, /* LA */ + OP_RXF, /* TLATE */ + 0, 0, /* E8:E9 */ + OP_RI1, /* RRL */ + OP_RI1, /* RLL */ + OP_RI1, /* SRL */ + OP_RI1, /* SLL */ + OP_RI1, /* SRA */ + OP_RI1, /* SLA */ + 0, 0, 0, /* F0:F2 */ + OP_RI2, /* TI */ + OP_RI2, /* NI */ + OP_RI2, /* CLI */ + OP_RI2, /* OI */ + OP_RI2, /* XI */ + OP_RI2, /* LI */ + OP_RI2, /* CI */ + OP_RI2, /* AI */ + OP_RI2, /* SI */ + 0, 0, 0, 0 }; /* FC:FF */ + +/* CPU data structures + + cpu_dev CPU device descriptor + cpu_unit CPU unit descriptor + cpu_reg CPU register list + cpu_mod CPU modifiers list +*/ + +DIB cpu_dib = { d_DS, -1, v_DS, NULL, &display }; + +UNIT cpu_unit = { UDATA (NULL, UNIT_FIX | UNIT_BINK, MAXMEMSIZE32) }; + +REG cpu_reg[] = { + { HRDATA (PC, PC, 20) }, + { HRDATA (OPC, oPC, 20), REG_HRO }, + { HRDATA (R0, GREG[0], 32) }, + { HRDATA (R1, GREG[1], 32) }, + { HRDATA (R2, GREG[2], 32) }, + { HRDATA (R3, GREG[3], 32) }, + { HRDATA (R4, GREG[4], 32) }, + { HRDATA (R5, GREG[5], 32) }, + { HRDATA (R6, GREG[6], 32) }, + { HRDATA (R7, GREG[7], 32) }, + { HRDATA (R8, GREG[8], 32) }, + { HRDATA (R9, GREG[9], 32) }, + { HRDATA (R10, GREG[10], 32) }, + { HRDATA (R11, GREG[11], 32) }, + { HRDATA (R12, GREG[12], 32) }, + { HRDATA (R13, GREG[13], 32) }, + { HRDATA (R14, GREG[14], 32) }, + { HRDATA (R15, GREG[15], 32) }, + { HRDATA (FR0, F[0], 32) }, + { HRDATA (FR2, F[1], 32) }, + { HRDATA (FR4, F[2], 32) }, + { HRDATA (FR6, F[3], 32) }, + { HRDATA (FR8, F[4], 32) }, + { HRDATA (FR10, F[5], 32) }, + { HRDATA (FR12, F[6], 32) }, + { HRDATA (FR14, F[7], 32) }, + { HRDATA (D0H, D[0].h, 32) }, + { HRDATA (D0L, D[0].l, 32) }, + { HRDATA (D2H, D[1].h, 32) }, + { HRDATA (D2L, D[1].l, 32) }, + { HRDATA (D4H, D[2].h, 32) }, + { HRDATA (D4L, D[2].l, 32) }, + { HRDATA (D6H, D[3].h, 32) }, + { HRDATA (D6L, D[3].l, 32) }, + { HRDATA (D8H, D[4].h, 32) }, + { HRDATA (D8L, D[4].l, 32) }, + { HRDATA (D10H, D[5].h, 32) }, + { HRDATA (D10L, D[5].l, 32) }, + { HRDATA (D12L, D[6].l, 32) }, + { HRDATA (D12H, D[6].h, 32) }, + { HRDATA (D14H, D[7].h, 32) }, + { HRDATA (D14L, D[7].l, 32) }, + { HRDATA (PSW, PSW, 16) }, + { HRDATA (CC, PSW, 4) }, + { HRDATA (SR, SR, 32) }, + { HRDATA (DR, DR, 32) }, + { HRDATA (DRX, DRX, 8) }, + { FLDATA (DRMOD, drmod, 0) }, + { FLDATA (SRPOS, srpos, 0) }, + { HRDATA (DRPOS, drpos, 3) }, + { BRDATA (IRQ, int_req, 16, 32, INTSZ) }, + { BRDATA (IEN, int_enb, 16, 32, INTSZ) }, + { BRDATA (MACREG, mac_reg, 16, 32, MAC_LNT) }, + { HRDATA (MACSTA, mac_sta, 5) }, + { HRDATA (QEVENT, qevent, 4), REG_HRO }, + { FLDATA (STOP_INST, stop_inst, 0) }, + { FLDATA (STOP_WAIT, stop_wait, 0) }, + { BRDATA (PCQ, pcq, 16, 20, PCQ_SIZE), REG_RO+REG_CIRC }, + { HRDATA (PCQP, pcq_p, 6), REG_HRO }, + { HRDATA (WRU, sim_int_char, 8) }, + { HRDATA (DBGLOG, cpu_log, 16), REG_HIDDEN }, + { HRDATA (BLKIOD, blk_io.dfl, 16), REG_HRO }, + { HRDATA (BLKIOC, blk_io.cur, 20), REG_HRO }, + { HRDATA (BLKIOE, blk_io.end, 20), REG_HRO }, + { BRDATA (GREG, GREG, 16, 32, 16 * NRSETS) }, + { NULL } }; + +MTAB cpu_mod[] = { + { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, + { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size }, + { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size }, + { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size }, + { UNIT_MSIZE, 1048756, NULL, "1M", &cpu_set_size }, + { UNIT_TYPE, 0, "7/32, single precision fp", "732", NULL }, + { UNIT_DPFP, UNIT_DPFP, NULL, "DPFP", NULL }, + { UNIT_TYPE, UNIT_DPFP, "7/32, double precision fp", NULL, NULL }, + { UNIT_TYPE, UNIT_DPFP | UNIT_832, "8/32", "832", NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT", + &cpu_set_consint, NULL, NULL }, + { 0 } }; + +DEVICE cpu_dev = { + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 16, 20, 1, 16, 8, + &cpu_ex, &cpu_dep, &cpu_reset, + NULL, NULL, NULL, + &cpu_dib, 0 }; + +t_stat sim_instr (void) +{ +volatile uint32 cc; /* set before setjmp */ +t_stat reason; /* set after setjmp */ +int abortval; + +/* Restore register state */ + +if (devtab_init ()) return SCPE_STOP; /* check conflicts */ +if (cpu_unit.flags & (UNIT_DPFP | UNIT_832)) { + fp_in_hwre = 1; /* fp in hwre */ + dec_flgs = 0; } /* all instr ok */ +else { fp_in_hwre = 0; /* fp in ucode */ + dec_flgs = OP_DPF; } /* sp only */ +int_eval (); /* eval interrupts */ +cc = newPSW (PSW & PSW_MASK); /* split PSW, eval wait */ +sim_rtcn_init (lfc_unit.wait, TMR_LFC); /* init clock */ +sim_rtcn_init (pic_unit.wait, TMR_PIC); /* init timer */ +sim_rtcn_init (pas_unit.wait, TMR_PAS); /* init pas */ +reason = 0; + +/* Abort handling + + If an abort occurs in memory protection, the relocation routine + executes a longjmp to this area OUTSIDE the main simulation loop. + Memory protection errors are the only sources of aborts in the + Interdata 32b systems. All referenced variables must be globals, + and all sim_instr scoped automatic variables must be volatile or + set after the call on setjmp. +*/ + +abortval = setjmp (save_env); /* set abort hdlr */ +if (abortval != 0) { /* mem mgt abort? */ + qevent = qevent | EV_MAC; /* set MAC intr */ + if (cpu_unit.flags & UNIT_832) PC = oPC; } /* 832? restore PC */ + +/* Event handling */ + +while (reason == 0) { /* loop until halted */ +uint32 dev, drom, opnd, inc, lim, bufa; +uint32 op, r1, r1p1, r2, rx2, ea; +uint32 mpy, mpc, dvr; +uint32 i, rslt, rlo, t; +int32 sr, st; + +if (sim_interval <= 0) { /* check clock queue */ + if (reason = sim_process_event ()) break; + int_eval (); } + +if (qevent) { /* any events? */ + if (qevent & EV_MAC) { /* MAC interrupt? */ + qevent = 0; /* clr all events */ + cc = exception (MPRPSW, cc, 0); /* take exception */ + int_eval (); /* re-eval intr */ + continue; } + + if (qevent & EV_BLK) { /* block I/O in prog? */ + dev = blk_io.dfl & DEV_MAX; /* get device */ + cc = dev_tab[dev] (dev, IO_SS, 0) & 0xF; /* sense status */ + if (cc == STA_BSY) { /* just busy? */ + sim_interval = 0; /* force I/O event */ + continue; } + else if (cc == 0) { /* ready, no err? */ + if (blk_io.dfl & BL_RD) { /* read? */ + t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ + if ((t == 0) && (blk_io.dfl & BL_LZ)) continue; + blk_io.dfl = blk_io.dfl & ~BL_LZ; /* non-zero seen */ + WriteB (blk_io.cur, t, VW); } /* write mem */ + else { /* write */ + t = ReadB (blk_io.cur, VR); /* read mem */ + dev_tab[dev] (dev, IO_WD, t); } /* put byte */ + if (blk_io.cur != blk_io.end) { /* more to do? */ + blk_io.cur = (blk_io.cur + 1) & VAMASK; /* incr addr */ + continue; } } + qevent = qevent & ~EV_BLK; /* clr blk I/O flag */ + int_eval (); /* re-eval intr */ + continue; } + + if ((qevent & EV_INT) && (PSW & PSW_EXI)) { /* interrupt? */ + dev = int_getdev (); /* get int dev */ + cc = int_auto (dev, cc); /* do auto intr */ + int_eval (); /* re-eval intr */ + continue; } + + if (PSW & PSW_WAIT) { /* wait state? */ + t = sim_qcount (); /* events in queue */ + if ((t == 0) || ((t == 1) && stop_wait)) /* empty, or kbd only? */ + reason = STOP_WAIT; /* then stop */ + else sim_interval = 0; /* force check */ + continue; } + + qevent = 0; } /* no events */ + +/* Instruction fetch and decode */ + +if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ + reason = STOP_IBKPT; /* stop simulation */ + break; } + +sim_interval = sim_interval - 1; + +t = ReadH (oPC = PC, VE); /* fetch instr */ +op = (t >> 8) & 0xFF; /* extract op,R1,R2 */ +r1 = (t >> 4) & 0xF; +r2 = t & 0xF; +drom = decrom[op]; /* get decode flags */ +if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */ + if (stop_inst) reason = STOP_RSRV; /* stop or */ + else cc = exception (ILOPSW, cc, 0); /* exception */ + continue; } +if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */ + cc = exception (ILOPSW, cc, 0); /* exception */ + continue; } + +switch (drom & OP_MASK) { /* decode instruction */ +case OP_NO: /* no operand */ + opnd = r2; /* assume short */ + PC = (PC + 2) & VAMASK; /* increment PC */ + break; +case OP_RR: /* reg-reg */ + ea = opnd = R[r2]; /* operand is R2 */ + PC = (PC + 2) & VAMASK; /* increment PC */ + break; +case OP_RI1: /* reg-imm 1 */ + t = ReadH ((PC + 2) & VAMASK, VE); /* fetch immed */ + opnd = SEXT16 (t); /* sign extend */ + if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */ + PC = (PC + 4) & VAMASK; /* increment PC */ + break; +case OP_RI2: /* reg-imm 2 */ + t = ReadH ((PC + 2) & VAMASK, VE); /* fetch imm hi */ + opnd = t << 16; /* shift to place */ + t = ReadH ((PC + 4) & VAMASK, VE); /* fetch imm lo */ + opnd = opnd | t; /* complete imm */ + if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */ + PC = (PC + 6) & VAMASK; /* increment PC */ + break; +case OP_RX: case OP_RXH: case OP_RXF: /* reg-mem */ + t = ReadH ((PC + 2) & VAMASK, VE); /* fetch addr */ + if ((t & 0xC000) == 0) { /* displacement? */ + PC = (PC + 4) & VAMASK; /* increment PC */ + ea = t; } /* abs 14b displ */ + else if (t & 0x8000) { /* relative? */ + PC = (PC + 4) & VAMASK; /* increment PC */ + ea = PC + SEXT15 (t); } /* add to incr PC */ + else { /* absolute */ + rx2 = (t >> 8) & 0xF; /* get second index */ + ea = (t & 0xFF) << 16; /* shift to place */ + t = ReadH ((PC + 4) & VAMASK, VE); /* fetch addr lo */ + ea = ea | t; /* finish addr */ + if (rx2) ea = ea + R[rx2]; /* index calc 2 */ + PC = (PC + 6) & VAMASK; } /* increment PC */ + if (r2) ea = ea + R[r2]; /* index calculation */ + ea = ea & VAMASK; + if ((drom & OP_MASK) == OP_RXF) /* get fw operand? */ + opnd = ReadF (ea, VR); /* read fullword */ + else if ((drom & OP_MASK) == OP_RXH) { /* get hw operand? */ + t = ReadH (ea, VR); /* read halfword */ + opnd = SEXT16 (t); } /* sign extend */ + else opnd = ea; /* for sloppy code */ + break; +case OP_UNDEF: + return SCPE_IERR; } +if (qevent & EV_MAC) continue; /* MAC abort on fetch? */ +switch (op) { /* case on opcode */ + +/* Load/store instructions */ + +case 0x08: /* LR - RR */ +case 0x24: /* LIS - NO */ +case 0x48: /* LH - RXH */ +case 0x58: /* L - RXF */ +case 0xC8: /* LHI - RI1 */ +case 0xF8: /* LI - RI2 */ + R[r1] = opnd; /* load operand */ + CC_GL_32 (R[r1]); /* set G,L */ + break; + +case 0x73: /* LHL - RX */ + R[r1] = ReadH (ea, VR); /* get op, zero ext */ + CC_GL_32 (R[r1]); /* set G, L */ + break; + +case 0x25: /* LCS - NO */ + R[r1] = NEG (opnd); /* load complement */ + CC_GL_32 (R[r1]); /* set G,L */ + break; + +case 0xE6: /* LA - RX */ + R[r1] = ea; /* load addr */ + break; + +case 0x63: /* LRA - RX */ + cc = RelocT (R[r1] & VAMASK, ea, VR, &R[r1]); /* test reloc */ + break; + +case 0x40: /* STH - RX */ + WriteH (ea, R[r1] & DMASK16, VW); /* store register */ + break; + +case 0x50: /* ST - RX */ + WriteF (ea, R[r1], VW); /* store register */ + break; + +case 0xD1: /* LM - RX */ + for ( ; r1 <= 0xF; r1++) { /* loop thru reg */ + R[r1] = ReadF (ea, VR); /* load register */ + ea = (ea + 4) & VAMASK; } /* incr mem addr */ + break; + +case 0xD0: /* STM - RX */ + for ( ; r1 <= 0xF; r1++) { /* loop thru reg */ + WriteF (ea, R[r1], VW); /* store register */ + ea = (ea + 4) & VAMASK; } /* incr mem addr */ + break; + +case 0xE0: /* TS - RXH */ + CC_GL_16 (opnd); /* set cc's */ + WriteH (ea, opnd | SIGN16, VW); /* set MSB */ + break; + +case 0x93: /* LDBR - NO */ + R[r1] = R[r2] & DMASK8; /* load byte */ + break; +case 0xD3: /* LDB - RX */ + R[r1] = ReadB (ea, VR); /* load byte */ + break; + +case 0x92: /* STBR - NO */ + R[r2] = (R[r2] & ~DMASK8) | (R[r1] & DMASK8); /* store byte */ + break; +case 0xD2: /* STB - RX */ + WriteB (ea, R[r1] & DMASK8, VW); /* store byte */ + break; + +case 0x34: /* EXHR - NO */ + R[r1] = ((R[r2] >> 16) & DMASK16) | ((R[r2] & DMASK16) << 16); + break; + +case 0x94: /* EXBR - NO */ + R[r1] = (R[r1] & ~DMASK16) | + ((R[r2] >> 8) & DMASK8) | ((R[r2] & DMASK8) << 8); + break; + +/* Control instructions */ + +case 0x01: /* BALR - RR */ +case 0x41: /* BAL - RX */ + PCQ_ENTRY; /* save old PC */ + R[r1] = PC; /* save cur PC */ + PC = ea; /* branch */ + break; + +case 0x02: /* BTCR - RR */ +case 0x42: /* BTC - RX */ + if (cc & r1) { /* test CC's */ + PCQ_ENTRY; /* branch if true */ + PC = ea; } + break; + +case 0x20: /* BTBS - NO */ + if (cc & r1) { /* test CC's */ + PCQ_ENTRY; /* branch if true */ + PC = (oPC - r2 - r2) & VAMASK; } + break; + +case 0x21: /* BTFS - NO */ + if (cc & r1) { /* test CC's */ + PCQ_ENTRY; /* branch if true */ + PC = (oPC + r2 + r2) & VAMASK; } + break; + +case 0x03: /* BFCR - RR */ +case 0x43: /* BFC - RX */ + if ((cc & r1) == 0) { /* test CC's */ + PCQ_ENTRY; /* branch if false */ + PC = ea; } + break; + +case 0x22: /* BFBS - NO */ + if ((cc & r1) == 0) { /* test CC's */ + PCQ_ENTRY; /* branch if false */ + PC = (oPC - r2 - r2) & VAMASK; } + break; + +case 0x23: /* BFFS - NO */ + if ((cc & r1) == 0) { /* test CC's */ + PCQ_ENTRY; /* branch if false */ + PC = (oPC + r2 + r2) & VAMASK; } + break; + +case 0xC0: /* BXH - RX */ + inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */ + lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */ + R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */ + if (R[r1] > lim) { /* if R1 > lim */ + PCQ_ENTRY; /* branch */ + PC = ea; } + break; + +case 0xC1: /* BXLE - RS */ + inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */ + lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */ + R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */ + if (R[r1] <= lim) { /* if R1 <= lim */ + PCQ_ENTRY; /* branch */ + PC = ea; } + break; + +/* Logical instructions */ + +case 0x04: /* NR - RR */ +case 0x44: /* NH - RXH */ +case 0x54: /* N - RXF */ +case 0xC4: /* NHI - RI1 */ +case 0xF4: /* NI - RI2 */ + R[r1] = R[r1] & opnd; /* result */ + CC_GL_32 (R[r1]); /* set G,L */ + break; + +case 0x06: /* OR - RR */ +case 0x46: /* OH - RXH */ +case 0x56: /* O - RXF */ +case 0xC6: /* OHI - RI1 */ +case 0xF6: /* OI - RI2 */ + R[r1] = R[r1] | opnd; /* result */ + CC_GL_32 (R[r1]); /* set G,L */ + break; + +case 0x07: /* XR - RR */ +case 0x47: /* XH - RXH */ +case 0x57: /* X - RXF */ +case 0xC7: /* XHI - RI1 */ +case 0xF7: /* XI - RI2 */ + R[r1] = R[r1] ^ opnd; /* result */ + CC_GL_32 (R[r1]); /* set G,L */ + break; + +case 0xC3: /* THI - RI1 */ +case 0xF3: /* TI - RI2 */ + rslt = R[r1] & opnd; /* result */ + CC_GL_32 (rslt); /* set G, L */ + break; + +case 0x05: /* CLR - RR */ +case 0x45: /* CLH - RXH */ +case 0x55: /* CL - RXF */ +case 0xC5: /* CLHI - RI1 */ +case 0xF5: /* CI - RI2 */ + rslt = (R[r1] - opnd) & DMASK32; /* result */ + CC_GL_32 (rslt); /* set G,L */ + if (R[r1] < opnd) cc = cc | CC_C; /* set C if borrow */ + if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) cc = cc | CC_V; + break; + +case 0xD4: /* CLB - RX */ + opnd = ReadB (ea, VR); /* get operand */ + t = R[r1] & DMASK8; + rslt = (t - opnd) & DMASK16; /* result */ + CC_GL_16 (rslt); /* set G,L 16b */ + if (t < opnd) cc = cc | CC_C; /* set C if borrow */ + break; + +case 0x12: /* CHVR - RR */ + t = cc & CC_C; /* save C */ + R[r1] = (SEXT16 (opnd & DMASK16)) & DMASK32; /* result */ + CC_GL_32 (R[r1]); /* set G, L */ + if (R[r1] != opnd) cc = cc | CC_V; /* wont fit? set V */ + cc = cc | t; /* restore C */ + break; + +/* Shift instructions */ + +case 0xCC: /* SRHL - RI1 */ + opnd = opnd & 0xF; /* shift count */ +case 0x90: /* SRHLS - NO */ + rslt = (R[r1] & DMASK16) >> opnd; /* result */ + CC_GL_16 (rslt); /* set G,L 16b */ + if (opnd && (((R[r1] & DMASK16) >> (opnd - 1)) & 1)) cc = cc | CC_C; + R[r1] = (R[r1] & ~DMASK16) | rslt; /* store result */ + break; + +case 0xCD: /* SLHL - RI1 */ + opnd = opnd & 0xF; /* shift count */ +case 0x91: /* SLHLS - NO */ + rslt = R[r1] << opnd; /* result */ + CC_GL_16 (rslt & DMASK16); /* set G,L 16b */ + if (opnd && (rslt & 0x10000)) cc = cc | CC_C; /* set C if shft out */ + R[r1] = (R[r1] & ~DMASK16) | (rslt & DMASK16); /* store result */ + break; + +case 0xCE: /* SRHA - RI1 */ + opnd = opnd & 0xF; /* shift count */ + rslt = (SEXT16 (R[r1]) >> opnd) & DMASK16; /* result */ + CC_GL_16 (rslt); /* set G,L 16b */ + if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C; + R[r1] = (R[r1] & ~DMASK16) | rslt; /* store result */ + break; + +case 0xCF: /* SLHA - RI1 */ + opnd = opnd & 0xF; /* shift count */ + rslt = R[r1] << opnd; /* raw result */ + R[r1] = (R[r1] & ~MMASK16) | (rslt & MMASK16); + CC_GL_16 (R[r1] & DMASK16); /* set G,L 16b */ + if (opnd && (rslt & SIGN16)) cc = cc | CC_C; /* set C if shft out */ + break; + +case 0xEC: /* SRL - RI1 */ + opnd = opnd & 0x1F; /* shift count */ +case 0x10: /* SRLS - NO */ + rslt = R[r1] >> opnd; /* result */ + CC_GL_32 (rslt); /* set G,L */ + if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C; + R[r1] = rslt; /* store result */ + break; + +case 0xED: /* SLL - RI1 */ + opnd = opnd & 0x1F; /* shift count */ +case 0x11: /* SLLS - NO */ + rslt = (R[r1] << opnd) & DMASK32; /* result */ + CC_GL_32 (rslt); /* set G,L */ + if (opnd && ((R[r1] << (opnd - 1)) & SIGN32)) cc = cc | CC_C; + R[r1] = rslt; /* store result */ + break; + +case 0xEE: /* SRA - RI1 */ + opnd = opnd & 0x1F; /* shift count */ + rslt = (SEXT32 (R[r1]) >> opnd) & DMASK32; /* result */ + CC_GL_32 (rslt); /* set G,L */ + if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C; + R[r1] = rslt; /* store result */ + break; + +case 0xEF: /* SLA - RI1 */ + opnd = opnd & 0x1F; /* shift count */ + rslt = (R[r1] << opnd) & DMASK32; /* raw result */ + R[r1] = (R[r1] & SIGN32) | (rslt & MMASK32); /* arith result */ + CC_GL_32 (R[r1]); /* set G,L */ + if (opnd && (rslt & SIGN32)) cc = cc | CC_C; /* set C if shft out */ + break; + +case 0xEA: /* RRL - RI1 */ + opnd = opnd & 0x1F; /* shift count */ + if (opnd) R[r1] = (R[r1] >> opnd) | /* if cnt > 0 */ + ((R[r1] << (32 - opnd)) & DMASK32); /* rotate */ + CC_GL_32 (R[r1]); /* set G,L */ + break; + +case 0xEB: /* RLL - RI1 */ + opnd = opnd & 0x1F; /* shift count */ + if (opnd) R[r1] = ((R[r1] << opnd) & DMASK32) | /* if cnt > 0 */ + (R[r1] >> (32 - opnd)); /* rotate */ + CC_GL_32 (R[r1]); /* set G,L */ + break; + +/* Bit instructions */ + +case 0x74: /* TBT - RX */ + t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */ + ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */ + opnd = ReadH (ea, VR); /* read HW */ + if (opnd & t) cc = CC_G; /* test bit */ + else cc = 0; + break; + +case 0x75: /* SBT - RX */ + t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */ + ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */ + opnd = ReadH (ea, VR); /* read HW */ + WriteH (ea, opnd | t, VW); /* set bit, rewr */ + if (opnd & t) cc = CC_G; /* test bit */ + else cc = 0; + break; + +case 0x76: /* RBT - RX */ + t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */ + ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */ + opnd = ReadH (ea, VR); /* read HW */ + WriteH (ea, opnd & ~t, VW); /* clr bit, rewr */ + if (opnd & t) cc = CC_G; /* test bit */ + else cc = 0; + break; + +case 0x77: /* CBT - RX */ + t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */ + ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */ + opnd = ReadH (ea, VR); /* read HW */ + WriteH (ea, opnd ^ t, VW); /* com bit, rewr */ + if (opnd & t) cc = CC_G; /* test bit */ + else cc = 0; + break; + +/* Arithmetic instructions */ + +case 0x0A: /* AR - RR */ +case 0x26: /* AIS - NO */ +case 0x4A: /* AH - RXH */ +case 0x5A: /* A - RXF */ +case 0xCA: /* AHI - RI1 */ +case 0xFA: /* AI - RI2 */ + rslt = (R[r1] + opnd) & DMASK32; /* result */ + CC_GL_32 (rslt); /* set G,L */ + if (rslt < opnd) cc = cc | CC_C; /* set C if carry */ + if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN32) cc = cc | CC_V; + R[r1] = rslt; + break; + +case 0x51: /* AM - RXF */ + rslt = (R[r1] + opnd) & DMASK32; /* result */ + WriteF (ea, rslt, VW); /* write result */ + CC_GL_32 (rslt); /* set G,L */ + if (rslt < opnd) cc = cc | CC_C; /* set C if carry */ + if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN32) cc = cc | CC_V; + break; + +case 0x61: /* AHM - RXH */ + rslt = (R[r1] + opnd) & DMASK16; /* result */ + WriteH (ea, rslt, VW); /* write result */ + CC_GL_16 (rslt); /* set G,L 16b */ + if (rslt < (opnd & DMASK16)) cc = cc | CC_C; /* set C if carry */ + if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) cc = cc | CC_V; + break; + +case 0x0B: /* SR - RR */ +case 0x27: /* SIS - NO */ +case 0x4B: /* SH - RXH */ +case 0x5B: /* S - RXF */ +case 0xCB: /* SHI - RI1 */ +case 0xFB: /* SI - RI2 */ + rslt = (R[r1] - opnd) & DMASK32; /* result */ + CC_GL_32 (rslt); /* set G,L */ + if (R[r1] < opnd) cc = cc | CC_C; /* set C if borrow */ + if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) cc = cc | CC_V; + R[r1] = rslt; + break; + +case 0x09: /* CR - RR */ +case 0x49: /* CH - RXH */ +case 0x59: /* C - RXF */ +case 0xC9: /* CHI - RI1 */ +case 0xF9: /* CI - RI2 */ + if (R[r1] == opnd) cc = 0; /* =? */ + else if ((R[r1] ^ opnd) & SIGN32) /* unlike signs? */ + cc = (R[r1] & SIGN32)? (CC_C | CC_L): CC_G; + else cc = (R[r1] > opnd)? CC_G: (CC_C | CC_L); /* like signs */ + if (((R[r1] ^ opnd) & (~opnd ^ (R[r1] - opnd))) & SIGN32) + cc = cc | CC_V; + break; + +case 0x0C: /* MHR - RR */ +case 0x4C: /* MH - RXH */ + R[r1] = (SEXT16 (R[r1]) * SEXT16 (opnd)) & DMASK32; /* multiply */ + break; + +case 0x1C: /* MR - RR */ +case 0x5C: /* M - RXF */ + r1p1 = (r1 + 1) & 0xF; + mpc = ABS (opnd); /* |mpcnd| */ + mpy = ABS (R[r1p1]); /* |mplyr| */ + rslt = rlo = 0; /* clr result */ + for (i = 0; i < 32; i++) { /* develop 32b */ + t = 0; /* no cout */ + if (mpy & 1) { /* cond add */ + rslt = (rslt + mpc) & DMASK32; + if (rslt < mpc) t = SIGN32; } + rlo = (rlo >> 1) | ((rslt & 1) << 31); /* shift result */ + rslt = (rslt >> 1) | t; + mpy = mpy >> 1; } /* shift mpylr */ + if ((opnd ^ R[r1p1]) & SIGN32) { + DNEG (rslt, rlo); } + R[r1] = rslt; /* store result */ + R[r1p1] = rlo; + break; + +case 0x0D: /* DHR - RR */ +case 0x4D: /* DH - RXH */ + r1p1 = (r1 + 1) & 0xF; + opnd = opnd & DMASK16; /* force HW opnd */ + if (opnd) { /* if divisor != 0 */ + st = SEXT32 (R[r1]) / SEXT16 (opnd); /* quotient */ + sr = SEXT32 (R[r1]) % SEXT16 (opnd); } /* remainder */ + if (opnd && (st < 0x8000) && (st >= -0x8000)) { /* if quo fits */ + R[r1] = sr & DMASK32; /* store remainder */ + R[r1p1] = st & DMASK32; } /* store quotient */ + else if (PSW & PSW_AFI) /* div fault enabled? */ + cc = exception (AFIPSW, cc, 0); /* exception */ + break; + +case 0x1D: /* DR - RR */ +case 0x5D: /* D - RXF */ + r1p1 = (r1 + 1) & 0xF; + rslt = R[r1]; /* get dividend */ + rlo = R[r1p1]; + if (R[r1] & SIGN32) { DNEG (rslt, rlo); } /* |divd| */ + dvr = ABS (opnd); /* |divr| */ + if (rslt < dvr) { /* will div work? */ + uint32 quos = R[r1] ^ opnd; /* expected sign */ + for (i = t = 0; i < 32; i++) { /* 32 iterations */ + rslt = ((rslt << 1) & DMASK32) | /* shift divd */ + ((rlo >> 31) & 1); + rlo = (rlo << 1) & DMASK32; + t = (t << 1) & DMASK32; /* shift quo */ + if (rslt >= dvr) { /* subtract work? */ + rslt = rslt - dvr; /* divd -= divr */ + t = t | 1; } } /* set quo bit */ + if (quos & SIGN32) t = NEG (t); /* res -? neg quo */ + if (R[r1] & SIGN32) rslt = NEG (rslt); /* adj rem sign */ + if (t && ((t ^ quos) & SIGN32)) { /* res sign wrong? */ + if (PSW & PSW_AFI) /* if enabled, */ + cc = exception (AFIPSW, cc, 0); /* exception */ + break; } + R[r1] = rslt; /* store rem */ + R[r1p1] = t; } /* store quo */ + else if (PSW & PSW_AFI) /* div fault enabled? */ + cc = exception (AFIPSW, cc, 0); /* exception */ + break; + +/* Floating point instructions */ + +case 0x28: /* LER - NO */ +case 0x38: /* LDR - NO */ +case 0x68: /* LE - RX */ +case 0x78: /* LD - RX */ + cc = f_l (op, r1, r2, ea); /* load */ + if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */ + cc = exception (AFIPSW, cc, 1); + break; + +case 0x29: /* CER - NO */ +case 0x39: /* CDR - NO */ +case 0x69: /* CE - RX */ +case 0x79: /* CD - RX */ + cc = f_c (op, r1, r2, ea); /* compare */ + break; + +case 0x2A: /* AER - NO */ +case 0x2B: /* SER - NO */ +case 0x3A: /* ADR - NO */ +case 0x3B: /* SDR - NO */ +case 0x6A: /* AE - RX */ +case 0x6B: /* SE - RX */ +case 0x7A: /* AD - RX */ +case 0x7B: /* SD - RX */ + cc = f_as (op, r1, r2, ea); /* add/sub */ + if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */ + cc = exception (AFIPSW, cc, 1); + break; + +case 0x2C: /* MER - NO */ +case 0x3C: /* MDR - NO */ +case 0x6C: /* ME - RX */ +case 0x7C: /* MD - RX */ + cc = f_m (op, r1, r2, ea); /* multiply */ + if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */ + cc = exception (AFIPSW, cc, 1); + break; + +case 0x2D: /* DER - NO */ +case 0x3D: /* DDR - NO */ +case 0x6D: /* DE - RX */ +case 0x7D: /* DD - RX */ + cc = f_d (op, r1, r2, ea); /* perform divide */ + if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */ + cc = exception (AFIPSW, cc, 1); + break; + +case 0x2E: /* FXR - NO */ +case 0x3E: /* FXDR - NO */ + cc = f_fix32 (op, r1, r2); /* cvt to integer */ + break; + +case 0x2F: /* FLR - NO */ +case 0x3F: /* FLDR - NO */ + cc = f_flt32 (op, r1, r2); /* cvt to floating */ + break; + +case 0x60: /* STE - RX */ + t = ReadFReg (r1); /* get sp reg */ + WriteF (ea, t, VW); /* write */ + break; + +case 0x70: /* STD - RX */ + WriteF (ea, D[r1 >> 1].h, VW); /* write hi */ + WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, VW); /* write lo */ + break; + +case 0x71: /* STME - RX */ + for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ + t = ReadFReg (r1); /* get sp reg */ + WriteF (ea, t, VW); /* write */ + ea = (ea + 4) & VAMASK; } /* incr mem addr */ + break; + +case 0x72: /* LME - RX */ + for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ + t = ReadF (ea, VR); /* get value */ + WriteFReg (r1, t); /* write reg */ + ea = (ea + 4) & VAMASK; } /* incr mem addr */ + break; + +case 0x7E: /* STMD - RX */ + for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ + WriteF (ea, D[r1 >> 1].h, VW); /* write register */ + WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, VW); + ea = (ea + 8) & VAMASK; } /* incr mem addr */ + break; + +case 0x7F: /* LMD - RX */ + for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */ + D[r1 >> 1].h = ReadF (ea, VR); /* load register */ + D[r1 >> 1].l = ReadF ((ea + 4) & VAMASK, VR); + ea = (ea + 8) & VAMASK; } /* incr mem addr */ + break; + +/* Miscellaneous */ + +case 0xE1: /* SVC - RX */ + PCQ_ENTRY; /* effective branch */ + t = BUILD_PSW (cc); /* save PSW */ + cc = newPSW (ReadF (SVNPS32, P)); /* get new PSW */ + R[13] = ea & 0xFFFFFF; /* parameter */ + R[14] = t; /* old PSW */ + R[15] = PC; /* old PC */ + PC = ReadH (SVNPC + r1 + r1, P); /* new PC */ + if (DBG_LOG (LOG_CPU_C)) fprintf (sim_log, + ">>SVC: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", + pcq[pcq_p], t, PC, PSW); + break; + +case 0xE2: /* SINT - RI1 */ + dev = opnd & DEV_MAX; /* get dev */ + cc = int_auto (dev, cc); /* auto int */ + int_eval (); + break; + +case 0xE3: /* SCP - RX */ + opnd = ReadH (ea, VR); /* zero ext operand */ + if (opnd & CCW32_B1) t = ea + CCB32_B1C; /* point to buf */ + else t = ea + CCB32_B0C; + sr = ReadH (t & VAMASK, VR); /* get count */ + sr = SEXT16 (sr); /* sign extend */ + if (sr <= 0) { /* <= 0? */ + bufa = ReadF ((t + 2) & VAMASK, VR); /* get buf end */ + if (opnd & CCW32_WR) /* write? */ + R[r1] = ReadB ((bufa + sr) & VAMASK, VR); /* R1 gets mem */ + else WriteB ((bufa + sr) & VAMASK, R[r1], VW); /* read, R1 to mem */ + sr = sr + 1; /* inc count */ + CC_GL_32 (sr & DMASK32); /* set cc's */ + WriteH (t & VAMASK, sr & DMASK16, VW); /* rewrite */ + if ((sr > 0) && !(opnd & CCW32_FST)) /* buf switch? */ + WriteH (ea, opnd ^ CCW32_B1, VW); /* flip CCW bit */ + } /* end if */ + else cc = CC_V; + break; + +case 0x18: /* LPSWR - RR */ + PCQ_ENTRY; /* effective branch */ + PC = R[(r2 + 1) & 0xF] & VAMASK; /* new PC (old reg set) */ + if (DBG_LOG (LOG_CPU_C)) fprintf (sim_log, + ">>LPSWR: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", + pcq[pcq_p], BUILD_PSW (cc), PC, opnd); + cc = newPSW (opnd); /* new PSW */ + if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ + break; + +case 0xC2: /* LPSW - RXF */ + PCQ_ENTRY; /* effective branch */ + PC = ReadF ((ea + 4) & VAMASK, VR) & VAMASK; /* new PC */ + if (DBG_LOG (LOG_CPU_C)) fprintf (sim_log, + ">>LPSW: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", + pcq[pcq_p], BUILD_PSW (cc), PC, opnd); + cc = newPSW (opnd); /* new PSW */ + if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ + break; + +case 0x95: /* EPSR - NO */ + R[r1] = BUILD_PSW (cc); /* save PSW */ + cc = newPSW (R[r2]); /* load new PSW */ + if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ + break; + +case 0x64: /* ATL - RX */ +case 0x65: /* ABL - RX */ + cc = addtoq (ea, R[r1], op & 1); /* add to q */ + break; + +case 0x66: /* RTL - RX */ +case 0x67: /* RBL - RX */ + cc = remfmq (ea, r1, op & 1); /* rem from q */ + break; + +case 0x5E: /* CRC12 - RXH */ + opnd = ReadH (ea, VR); /* zero ext opnd */ + t = (R[r1] & 0x3F) ^ opnd; + for (i = 0; i < 6; i++) { + if (t & 1) t = (t >> 1) ^ 0x0F01; + else t = t >> 1; } + WriteH (ea, t, VW); + break; + +case 0x5F: /* CRC16 - RXH */ + opnd = ReadH (ea, VR); /* zero ext opnd */ + t = (R[r1] & 0xFF) ^ opnd; + for (i = 0; i < 8; i++) { + if (t & 1) t = (t >> 1) ^ 0xA001; + else t = t >> 1; } + WriteH (ea, t, VW); + break; + +case 0xE7: /* TLATE - RXF */ + t = (opnd + ((R[r1] & DMASK8) << 1)) & VAMASK; /* table entry */ + rslt = ReadH (t, VR); /* get entry */ + if (rslt & SIGN16) R[r1] = rslt & DMASK8; /* direct xlate? */ + else { PCQ_ENTRY; /* branch */ + PC = rslt << 1; } + break; + +/* I/O instructions */ + +case 0xDE: /* OC - RX */ + opnd = ReadB (ea, VR); /* fetch operand */ +case 0x9E: /* OCR - RR */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { + dev_tab[dev] (dev, IO_ADR, 0); /* select */ + dev_tab[dev] (dev, IO_OC, opnd & DMASK8); /* send command */ + cc = 0; } + else cc = CC_V; + int_eval (); /* re-eval intr */ + break; + +case 0xDA: /* WD - RX */ + opnd = ReadB (ea, VR); /* fetch operand */ +case 0x9A: /* WDR - RR */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { + dev_tab[dev] (dev, IO_ADR, 0); /* select */ + dev_tab[dev] (dev, IO_WD, opnd & DMASK8); /* send data */ + cc = 0; } + else cc = CC_V; + int_eval (); /* re-eval intr */ + break; + +case 0xD8: /* WH - RX */ + opnd = ReadH (ea, VR); /* fetch operand */ +case 0x98: /* WHR - RR */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { + if (dev_tab[dev] (dev, IO_ADR, 0)) /* select; hw ok? */ + dev_tab[dev] (dev, IO_WH, opnd & DMASK16); /* send data */ + else { /* byte only */ + dev_tab[dev] (dev, IO_WD, (opnd >> 8) & DMASK8); /* hi */ + dev_tab[dev] (dev, IO_WD, opnd & DMASK8); } /* send lo byte */ + cc = 0; } + else cc = CC_V; + int_eval (); /* re-eval intr */ + break; + +case 0x9B: /* RDR - RR */ +case 0xDB: /* RD - RX */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { /* dev exist? */ + dev_tab[dev] (dev, IO_ADR, 0); /* select */ + t = dev_tab[dev] (dev, IO_RD, 0); /* get data */ + cc = 0; } + else { /* no */ + t = 0; + cc = CC_V; } + if (OP_TYPE (op) != OP_RR) WriteB (ea, t, VW); /* RX or RR? */ + else R[r2] = t & DMASK8; + int_eval (); /* re-eval intr */ + break; + +case 0x99: /* RHR - RR */ +case 0xD9: /* RH - RS */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { /* dev exist? */ + if (dev_tab[dev] (dev, IO_ADR, 0)) /* select, hw ok? */ + t = dev_tab[dev] (dev, IO_RH, 0); /* get data */ + else { /* byte only */ + rslt = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ + t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ + t = (rslt << 8) | t; } /* merge */ + cc = 0; } + else { /* no */ + t = 0; + cc = CC_V; } + if (OP_TYPE (op) != OP_RR) WriteH (ea, t, VW); /* RX or RR? */ + else R[r2] = t & DMASK16; + int_eval (); /* re-eval intr */ + break; + +case 0x9D: /* SSR - RR */ +case 0xDD: /* SS - RS */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { /* dev exist? */ + dev_tab[dev] (dev, IO_ADR, 0); /* select */ + t = dev_tab[dev] (dev, IO_SS, 0); } /* get status */ + else t = STA_EX; /* no */ + if (OP_TYPE (op) != OP_RR) WriteB (ea, t, VW); /* RX or RR? */ + else R[r2] = t & DMASK8; + cc = t & 0xF; + int_eval (); /* re-eval intr */ + break; + +/* Block I/O instructions + + On a real Interdata system, the block I/O instructions can't be + interrupted or stopped. To model this behavior, while allowing + the instructions to go back through fetch for I/O processing and + WRU testing, the simulator implements a 'block I/O in progress' + flag and status block. If a block I/O is in progress, normal + interrupts and fetches are suppressed until the block I/O is done. +*/ + +case 0x96: /* WBR - RR */ +case 0xD6: /* WB - RXF */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { /* dev exist? */ + if (OP_TYPE (op) != OP_RR) + lim = ReadF ((ea + 4) & VAMASK, VR); + else lim = R[(r2 + 1) & 0xF]; + if (opnd > lim) cc = 0; /* start > end? */ + else { /* no, start I/O */ + dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ + blk_io.dfl = dev; /* set status block */ + blk_io.cur = opnd; + blk_io.end = lim; + qevent = qevent | EV_BLK; } } /* I/O in prog */ + else cc = CC_V; /* nx dev */ + break; + +case 0x97: /* RBR - RR */ +case 0xD7: /* RB - RXF */ + dev = R[r1] & DEV_MAX; + if (DEV_ACC (dev)) { /* dev exist? */ + if (OP_TYPE (op) != OP_RR) + lim = ReadF ((ea + 4) & VAMASK, VR); + else lim = R[(r2 + 1) & 0xF]; + if (opnd > lim) cc = 0; /* start > end? */ + else { /* no, start I/O */ + dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ + blk_io.dfl = dev | BL_RD; /* set status block */ + blk_io.cur = opnd; + blk_io.end = lim; + qevent = qevent | EV_BLK; } } /* I/O in prog */ + else cc = CC_V; /* nx dev */ + break; + +case 0xD5: /* AL - RX */ + dev = ReadB (AL_DEV, P); /* get device */ + t = ReadB (AL_IOC, P); /* get command */ + if (DEV_ACC (dev)) { /* dev exist? */ + if (AL_BUF > ea) cc = 0; /* start > end? */ + else { /* no, start I/O */ + dev_tab[dev] (dev, IO_ADR, 0); /* select dev */ + dev_tab[dev] (dev, IO_OC, t); /* start dev */ + blk_io.dfl = dev | BL_RD | BL_LZ; /* set status block */ + blk_io.cur = AL_BUF; + blk_io.end = ea; + qevent = qevent | EV_BLK; } } /* I/O in prog */ + else cc = CC_V; /* nx dev */ + break; } /* end switch */ + } /* end while */ + +/* Simulation halted */ + +PSW = BUILD_PSW (cc); +PC = PC & VAMASK; +set_r_display (R); +pcq_r->qptr = pcq_p; /* update pc q ptr */ +return reason; +} + +/* Load new PSW */ + +uint32 newPSW (uint32 val) +{ +uint32 rs = PSW_GETREG (val); /* register set */ + +R = &GREG[rs * 16]; /* set register set */ +PSW = val & PSW_MASK; /* store PSW */ +int_eval (); /* update intreq */ +if (PSW & PSW_WAIT) qevent = qevent | EV_WAIT; /* wait state? */ +else qevent = qevent & ~EV_WAIT; +if (PSW & PSW_EXI) SET_ENB (v_DS); /* enable/disable */ +else CLR_ENB (v_DS); /* console intr */ +return PSW & CC_MASK; +} + +/* Exception handler - 7/32 always uses register set 0 */ + +uint32 exception (uint32 loc, uint32 cc, uint32 flg) +{ +int32 oldPSW = BUILD_PSW (cc); /* save old PSW */ +int32 oldPC = PC; /* save old PC */ + +cc = newPSW (ReadF (loc, P)); /* new PSW */ +PC = ReadF (loc + 4, P) & VAMASK; /* new PC */ +if (cpu_unit.flags & UNIT_832) { /* 8/32? */ + R[14] = oldPSW; /* PSW to new 14 */ + R[15] = oldPC; } /* PC to new 15 */ +else { GREG[14] = oldPSW; /* 7/32, PSW to set 0 14 */ + GREG[15] = oldPC; } /* PC to set 0 15 */ +if (DBG_LOG (LOG_CPU_C)) fprintf (sim_log, + ">>Exc %X: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", + loc, oldPC, oldPSW, PC, PSW | cc | flg); +return cc | flg; /* return CC */ +} + +/* Test for queue interrupts - system queue addresses are physical */ + +uint32 testsysq (uint32 cc) +{ +int32 qb = ReadF (SQP, P); /* get sys q addr */ +int32 usd = ReadH (qb + Q32_USD, P); /* get use count */ + +if (usd) { /* entries? */ + cc = exception (SQTPSW, cc, 0); /* take sysq exc */ + if (cpu_unit.flags & UNIT_832) R[13] = qb; /* R13 = sys q addr */ + else GREG[13] = qb; } +return cc; +} + +/* Add to queue */ + +uint32 addtoq (uint32 ea, uint32 val, uint32 flg) +{ +uint32 slt, usd, wra, t; + +t = ReadF (ea, VR); /* slots/used */ +slt = (t >> 16) & DMASK16; /* # slots */ +usd = t & DMASK16; /* # used */ +if (usd >= slt) return CC_V; /* list full? */ +usd = (usd + 1) & DMASK16; /* inc # used */ +WriteH (ea + Q32_USD, usd, VW); /* rewrite */ +if (flg) { /* ABL? */ + wra = ReadH ((ea + Q32_BOT) & VAMASK, VR); /* get bottom */ + t = wra + 1; /* adv bottom */ + if (t >= slt) t = 0; /* wrap if necc */ + WriteH ((ea + Q32_BOT) & VAMASK, t, VW); } /* rewrite bottom */ +else { wra = ReadH ((ea + Q32_TOP) & VAMASK, VR); /* ATL, get top */ + if (wra == 0) wra = (slt - 1) & DMASK16; /* wrap if necc */ + else wra = wra - 1; /* dec top */ + WriteH ((ea + Q32_TOP) & VAMASK, wra, VW); } /* rewrite top */ +WriteF ((ea + Q32_BASE + (wra * Q32_SLNT)) & VAMASK, val, VW); /* write slot */ +return 0; +} + +/* Remove from queue */ + +uint32 remfmq (uint32 ea, uint32 r1, uint32 flg) +{ +uint32 slt, usd, rda, t; + +t = ReadF (ea, VR); /* get slots/used */ +slt = (t >> 16) & DMASK16; /* # slots */ +usd = t & DMASK16; /* # used */ +if (usd == 0) return CC_V; /* empty? */ +usd = usd - 1; /* dec used */ +WriteH (ea + Q32_USD, usd & DMASK16, VW); /* rewrite */ +if (flg) { /* RBL? */ + rda = ReadH ((ea + Q32_BOT) & VAMASK, VR); /* get bottom */ + if (rda == 0) rda = (slt - 1) & DMASK16; /* wrap if necc */ + else rda = rda - 1; /* dec bottom */ + WriteH ((ea + Q32_BOT) & VAMASK, rda, VW); } /* rewrite bottom */ +else { rda = ReadH ((ea + Q32_TOP) & VAMASK, VR); /* RTL, get top */ + t = rda + 1; /* adv top */ + if (t >= slt) t = 0; /* wrap if necc */ + WriteH ((ea + Q32_TOP) & VAMASK, t, VW); } /* rewrite top */ +R[r1] = ReadF ((ea + Q32_BASE + (rda * Q32_SLNT)) & VAMASK, VR); /* read slot */ +if (usd) return CC_G; +else return 0; +} + +/* Automatic interrupt processing */ + +uint32 int_auto (uint32 dev, uint32 cc) +{ +uint32 addr, vec, by, ccw, ccwa, ccwb; +uint32 i, hw, tblad, tblen, bufe, st, t; +int32 bufc; +uint32 oldPSW = BUILD_PSW (cc); + +vec = ReadH (INTSVT + dev + dev, P); /* get vector */ +newPSW (0x2800); /* new PSW */ +R[0] = oldPSW; /* save old PSW */ +R[1] = PC; /* save PC */ +R[2] = dev; /* set dev # */ +if (DBG_LOG (LOG_CPU_C)) fprintf (sim_log, + ">>Int %X: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", + dev, PC, oldPSW, vec, 0x2800); +if (DEV_ACC (dev)) { /* dev exist? */ + hw = dev_tab[dev] (dev, IO_ADR, 0); /* select, get hw */ + R[3] = st = dev_tab[dev] (dev, IO_SS, 0); } /* sense status */ +else { hw = 0; + R[3] = CC_V; } +if ((vec & 1) == 0) { /* immed int? */ + PC = vec; /* new PC */ + return PSW & CC_MASK; } /* exit */ +R[4] = ccwa = vec & ~1; /* save CCW addr */ +ccw = ReadH (ccwa, VR); /* read CCW */ +if ((ccw & CCW32_EXE) == 0) { /* exec clr? */ + PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */ + return 0; } /* CC = 0 */ +if (!DEV_ACC (dev) || (st & CCW32_STA (ccw))) { /* bad status? */ + PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */ + return CC_L; } /* CC = L */ +if (ccw & CCW32_FST) { /* fast mode? */ + t = ReadH (ccwa + CCB32_B0C, VR); /* get count */ + bufc = SEXT16 (t); /* sign ext */ + if (bufc <= 0) { /* still valid? */ + bufe = ReadF (ccwa + CCB32_B0E, VR); /* get end addr */ + addr = (bufe + bufc) & VAMASK; + if (hw) { /* halfword? */ + if (ccw & CCW32_WR) { /* write? */ + t = ReadH (addr, VR); /* get hw */ + dev_tab[dev] (dev, IO_WH, t); } /* send to dev */ + else { /* read */ + t = dev_tab[dev] (dev, IO_RH, 0); /* get hw */ + WriteH (addr, t, VW); } /* write to mem */ + bufc = bufc + 2; } /* adv buf cnt */ + else { /* byte */ + if (ccw & CCW32_WR) { /* write? */ + t = ReadB (addr, VR); /* get byte */ + dev_tab[dev] (dev, IO_WD, t); } /* send to dev */ + else { /* read */ + t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */ + WriteB (addr, t, VW); } /* write to mem */ + bufc = bufc + 1; } /* adv buf cnt */ + WriteH (ccwa + CCB32_B0C, bufc & DMASK16, VW);/* rewrite cnt */ + if (bufc > 0) { + PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */ + return CC_G; } /* CC = G */ + } /* end if bufc <= 0 */ + } /* end fast */ +else { /* slow mode */ + if (ccw & CCW32_B1) ccwb = ccwa + CCB32_B1C; /* which buf? */ + else ccwb = ccwa + CCB32_B0C; + t = ReadH (ccwb, VR); /* get count */ + bufc = SEXT16 (t); /* sign ext */ + if (bufc <= 0) { /* still valid? */ + bufe = ReadF (ccwb + 2, VR); /* get end addr */ + addr = (bufe + bufc) & VAMASK; + if (ccw & CCW32_WR) { /* write? */ + by = ReadB (addr, VR); /* byte fm mem */ + if (ccw & CCW32_TL) { /* translate? */ + tblad = ReadF (ccwa + CCB32_TAB, VR);/* get tbl addr */ + tblen = (tblad + (by << 1)) & VAMASK; /* tbl entry addr */ + t = ReadH (tblen, VR); /* get tbl entry */ + if ((t & SIGN16) == 0) { /* special xlate? */ + PC = t << 1; /* change PC */ + R[3] = by; /* untrans char */ + return 0; } /* CC = 0 */ + by = t & DMASK8; } /* replace */ + dev_tab[dev] (dev, IO_WD, by); } /* write to dev */ + else { /* read */ + by = dev_tab[dev] (dev, IO_RD, 0); /* get from dev */ + if (ccw & CCW32_TL) { /* translate? */ + tblad = ReadF (ccwa + CCB32_TAB, VR);/* get tbl addr */ + tblen = (tblad + (by << 1)) & VAMASK; /* tbl entry addr */ + t = ReadH (tblen, VR); /* get tbl entry */ + if ((t & SIGN16) == 0) { /* special xlate? */ + PC = t << 1; /* change PC */ + R[3] = by; /* untrans char */ + return 0; } /* CC = 0 */ + WriteB (addr, t & DMASK8, VW); } /* wr trans */ + else WriteB (addr, by, VW); } /* wr orig */ + t = ReadH (ccwa + CCB32_CHK, VR); /* get check wd */ + t = t ^ by; /* start LRC */ + if (ccw & CCW32_CRC) { /* CRC? */ + for (i = 0; i < 8; i++) { + if (t & 1) t = (t >> 1) ^ 0xA001; + else t = t >> 1; } } + WriteH (ccwa + CCB32_CHK, t, VW); /* rewrite chk wd */ + bufc = bufc + 1; /* adv buf cnt */ + WriteH (ccwb, bufc & DMASK16, VW); /* rewrite cnt */ + if (bufc > 0) { /* cnt pos? */ + ccw = ccw ^ CCW32_B1; /* flip buf */ + WriteH (ccwa, ccw, VW); /* rewrite */ + PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */ + return CC_G; } /* CC = G */ + } /* end if bufc */ + } /* end slow */ +PC = R[1]; /* restore PC */ +return newPSW (R[0]); /* restore PSW, CC */ +} + +/* Display register device */ + +uint32 display (uint32 dev, uint32 op, uint32 dat) +{ +int t; + +switch (op) { +case IO_ADR: /* select */ + if (!drmod) drpos = srpos = 0; /* norm mode? clr */ + return BY; /* byte only */ +case IO_OC: /* command */ + op = op & 0xC0; + if (op == 0x40) { /* x40 = inc */ + drmod = 1; + drpos = srpos = 0; } /* init cntrs */ + else if (op == 0x80) drmod = 0; /* x80 = norm */ + break; +case IO_WD: /* write */ + if (drpos < 4) + DR = (DR & ~(DMASK8 << (drpos * 8))) | (dat << (drpos * 8)); + else if (drpos == 4) DRX = dat; + drpos = (drpos + 1) & 0x7; + break; +case IO_RD: /* read */ + t = (SR >> (srpos * 8)) & DMASK8; + srpos = srpos ^ 1; + return t; +case IO_SS: /* status */ + return 0x80; } +return 0; +} + +/* Relocation and protection */ + +uint32 Reloc (uint32 va, uint32 rel) +{ +uint32 seg, off, mapr, lim; + +seg = VA_GETSEG (va); /* get seg num */ +off = VA_GETOFF (va); /* get offset */ +mapr = mac_reg[seg]; /* get seg reg */ +lim = GET_SRL (mapr); /* get limit */ +if (off >= lim) { /* limit viol? */ + mac_sta = MACS_L; /* set status */ + ABORT (MPRO); } /* abort */ +if ((mapr & SR_PRS) == 0) { /* not present? */ + mac_sta = MACS_NP; /* set status */ + ABORT (MPRO); } /* abort */ +if ((rel == VE) && (mapr & SR_EXP)) { /* exec, prot? */ + mac_sta = MACS_EX; /* set status */ + qevent = qevent | EV_MAC; } /* req intr */ +if ((rel == VW) && (mapr & (SR_WPI | SR_WRP))) { /* write, prot? */ + if (mapr & SR_WRP) { /* write abort? */ + mac_sta = MACS_WP; /* set status */ + ABORT (MPRO); } /* abort */ + else { /* write intr */ + mac_sta = MACS_WI; /* set status */ + qevent = qevent | EV_MAC; } } /* req intr */ +return (off + (mapr & SRF_MASK)) & PAMASK32; /* relocate */ +} + +uint32 RelocT (uint32 va, uint32 base, uint32 rel, uint32 *pa) +{ +uint32 seg, off, mapr, lim; + +seg = VA_GETSEG (va); /* get seg num */ +off = VA_GETOFF (va); /* get offset */ +mapr = ReadF ((base + (seg << 2)) & VAMASK, rel); /* get seg reg */ +lim = GET_SRL (mapr); /* get limit */ +if (off >= lim) return CC_C; /* limit viol? */ +if ((mapr & SR_PRS) == 0) return CC_V; /* not present? */ +*pa = off + (mapr & SRF_MASK); /* translate */ +if (mapr & (SR_WRP | SR_WPI)) return CC_G; /* write prot? */ +if (mapr & SR_EXP) return CC_L; /* exec prot? */ +return 0; /* ok */ +} + +/* Memory interface routines + + ReadB read byte (processor) + ReadH read halfword (processor) + ReadF read fullword (processor) + WriteB write byte (processor) + WriteH write halfword (processor) + WriteF write fullword (processor) + IOReadB read byte (IO) + IOWriteB write byte (IO) +*/ + +uint32 ReadB (uint32 loc, uint32 rel) +{ +uint32 val; +uint32 sc = (3 - (loc & 3)) << 3; + +if ((PSW & PSW_REL) == 0) { /* reloc off? */ + val = M[loc >> 2]; /* get mem word */ + if ((loc & ~03) == MAC_STA) { /* MAC status? */ + val = mac_sta; /* read it */ + qevent = qevent & ~EV_MAC; } } /* clr MAC intr */ +else if (rel == 0) val = M[loc >> 2]; /* phys ref? */ +else { uint32 pa = Reloc (loc, rel); /* relocate */ + val = M[pa >> 2]; } +return (val >> sc) & DMASK8; +} + +uint32 ReadH (uint32 loc, uint32 rel) +{ +uint32 val; + +if ((PSW & PSW_REL) == 0) { /* reloc off? */ + val = M[loc >> 2]; /* get mem word */ + if ((loc & ~03) == MAC_STA) { /* MAC status? */ + val = mac_sta; /* read it */ + qevent = qevent & ~EV_MAC; } } /* clr MAC intr */ +else if (rel == 0) val = M[loc >> 2]; /* phys ref? */ +else { uint32 pa = Reloc (loc, rel); /* relocate */ + val = M[pa >> 2]; } +return (val >> ((loc & 2)? 0: 16)) & DMASK16; +} + +uint32 ReadF (uint32 loc, uint32 rel) +{ +uint32 val; + +if ((PSW & PSW_REL) == 0) { /* reloc off? */ + val = M[loc >> 2]; /* get mem word */ + if ((loc & ~03) == MAC_STA) { /* MAC status? */ + val = mac_sta; /* read it */ + qevent = qevent & ~EV_MAC; } } /* clr MAC intr */ +else if (rel == 0) val = M[loc >> 2]; /* phys ref? */ +else { uint32 pa = Reloc (loc, rel); /* relocate */ + val = M[pa >> 2]; } +return val; +} + +void WriteB (uint32 loc, uint32 val, uint32 rel) +{ +uint32 pa = loc; +uint32 sc = (3 - (loc & 3)) << 3; + +val = val & DMASK8; +if ((PSW & PSW_REL) == 0) { /* reloc off? */ + uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */ + if (idx <= MAC_LNT) { + if (idx < MAC_LNT) mac_reg[idx] = + ((mac_reg[idx] & ~(DMASK8 << sc)) | (val << sc)) & SR_MASK; + else { + mac_sta = 0; + qevent = qevent & ~EV_MAC; } } } +else if (rel != 0) pa = Reloc (loc, rel); /* !phys? relocate */ +if (MEM_ADDR_OK (pa)) M[pa >> 2] = + (M[pa >> 2] & ~(DMASK8 << sc)) | (val << sc); +return; +} + +void WriteH (uint32 loc, uint32 val, uint32 rel) +{ +uint32 pa = loc; + +val = val & DMASK16; +if ((PSW & PSW_REL) == 0) { /* reloc off? */ + uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */ + if (idx <= MAC_LNT) { + if (idx < MAC_LNT) mac_reg[idx] = ((loc & 2)? + ((mac_reg[idx] & ~DMASK16) | val): + ((mac_reg[idx] & DMASK16) | (val << 16))) & SR_MASK; + else { + mac_sta = 0; + qevent = qevent & ~EV_MAC; } } } +else if (rel != 0) pa = Reloc (loc, rel); /* !phys? relocate */ +if (MEM_ADDR_OK (pa)) M[pa >> 2] = (loc & 2)? + ((M[pa >> 2] & ~DMASK16) | val): + ((M[pa >> 2] & DMASK16) | (val << 16)); +return; +} + +void WriteF (uint32 loc, uint32 val, uint32 rel) +{ +uint32 pa = loc; + +if (loc & 2) { + WriteH (loc & VAMASK, (val >> 16) & DMASK16, rel); + WriteH ((loc + 2) & VAMASK, val & DMASK16, rel); + return; } +if ((PSW & PSW_REL) == 0) { /* reloc off? */ + uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */ + if (idx <= MAC_LNT) { + if (idx < MAC_LNT) mac_reg[idx] = val & SR_MASK; + else { + mac_sta = 0; + qevent = qevent & ~EV_MAC; } } } +else if (rel != 0) pa = Reloc (loc, rel); /* !phys? relocate */ +if (MEM_ADDR_OK (pa)) M[pa >> 2] = val & DMASK32; +return; +} + +uint32 IOReadB (uint32 loc) +{ +uint32 sc = (3 - (loc & 3)) << 3; + +return (M[loc >> 2] >> sc) & DMASK8; +} + +void IOWriteB (uint32 loc, uint32 val) +{ +uint32 sc = (3 - (loc & 3)) << 3; + +val = val & DMASK8; +M[loc >> 2] = (M[loc >> 2] & ~(DMASK8 << sc)) | (val << sc); +return; +} + +/* Reset routine */ + +t_stat cpu_reset (DEVICE *dptr) +{ +qevent = 0; /* no events */ +mac_sta = 0; /* clear MAC */ +newPSW (0); /* PSW = 0 */ +set_r_display (R); +DR = 0; /* clear display */ +drmod = 0; +blk_io.dfl = blk_io.cur = blk_io.end = 0; /* no block I/O */ +sim_brk_types = sim_brk_dflt = SWMASK ('E'); /* init bkpts */ +if (M == NULL) M = calloc (MAXMEMSIZE32 >> 1, sizeof (uint16)); +if (M == NULL) return SCPE_MEM; +pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */ +if (pcq_r) pcq_r->qptr = 0; +else return SCPE_IERR; +return SCPE_OK; +} + +/* Memory examine */ + +t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) +{ +if ((sw & SWMASK ('V')) && (PSW & PSW_REL)) { + int32 cc = RelocT (addr, MAC_BASE, P, &addr); + if (cc & (CC_C | CC_V)) return SCPE_NXM; } +if (addr >= MEMSIZE) return SCPE_NXM; +if (vptr != NULL) *vptr = IOReadB (addr); +return SCPE_OK; +} + +/* Memory deposit */ + +t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) +{ +if ((sw & SWMASK ('V')) && (PSW & PSW_REL)) { + int32 cc = RelocT (addr, MAC_BASE, P, &addr); + if (cc & (CC_C | CC_V)) return SCPE_NXM; } +if (addr >= MEMSIZE) return SCPE_NXM; +IOWriteB (addr, val & 0xFF); +return SCPE_OK; +} + +t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +uint32 mc = 0; +t_addr i; + +if ((val <= 0) || (val > MAXMEMSIZE32) || ((val & 0xFFFF) != 0)) + return SCPE_ARG; +for (i = val; i < MEMSIZE; i = i + 4) mc = mc | M[i >> 2]; +if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) + return SCPE_OK; +MEMSIZE = val; +for (i = MEMSIZE; i < MAXMEMSIZE32; i = i + 4) M[i >> 2] = 0; +return SCPE_OK; +} + +/* Set current R pointers for SCP */ + +void set_r_display (uint32 *rbase) +{ +extern REG *find_reg (char *cptr, char **optr, DEVICE *dptr); +REG *rptr; +int32 i; + +rptr = find_reg ("R0", NULL, &cpu_dev); +if (rptr == NULL) return; +for (i = 0; i < 16; i++, rptr++) rptr->loc = (void *) (rbase + i); +return; +} + +/* Set console interrupt */ + +t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (PSW & PSW_EXI) SET_INT (v_DS); +return SCPE_OK; +} diff --git a/Interdata/id32_dboot.c b/Interdata/id32_dboot.c new file mode 100644 index 00000000..20f9f1e8 --- /dev/null +++ b/Interdata/id32_dboot.c @@ -0,0 +1,308 @@ +/* id32_dboot.c: Interdata 32b simulator disk bootstrap + + Copyright (c) 2000-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. +*/ + +#include "id_defs.h" + +#define DBOOT_BEG 0x1000 +#define DBOOT_START 0x100E +#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8)) + +/* Transcribed from 32b Bootstrap Loader, 03-074N81R03A13 */ + +static uint8 dboot_rom[] = { + 0xca, 0xf0, 0x00, 0x30, + 0xc5, 0xf0, 0x00, 0x3a, + 0x02, 0x8e, + 0x26, 0xf7, + 0x03, 0x0e, + 0xe6, 0xd0, 0x0f, 0x30, + 0xd1, 0xe0, 0x00, 0x78, + 0xd0, 0xed, 0x03, 0x40, + 0xd3, 0xf0, 0x00, 0x7e, + 0xc4, 0xf0, 0x00, 0x0f, + 0x41, 0xed, 0x00, 0xd0, + 0xd2, 0xfd, 0x03, 0x25, + 0xd3, 0xf0, 0x00, 0x7f, + 0x10, 0xf4, + 0x41, 0xed, 0x00, 0xd0, + 0xd2, 0xfd, 0x03, 0x26, + 0xd3, 0xf0, 0x00, 0x7f, + 0xc4, 0xf0, 0x00, 0x0f, + 0x41, 0xed, 0x00, 0xd0, + 0xd2, 0xfd, 0x03, 0x27, + 0xd3, 0x20, 0x00, 0x7d, + 0xd3, 0x30, 0x00, 0x7c, + 0xd3, 0x40, 0x00, 0x7a, + 0x24, 0x50, + 0xd3, 0xf0, 0x00, 0x7b, + 0xcb, 0xf0, 0x00, 0x33, + 0x23, 0x23, + 0x11, 0xf1, + 0x08, 0x5f, + 0xe6, 0x7d, 0x03, 0x50, + 0xe6, 0x8d, 0x04, 0x4f, + 0x07, 0xcc, + 0x41, 0xed, 0x01, 0xfc, + 0xd1, 0xed, 0x03, 0x5c, + 0xd0, 0xed, 0x03, 0x48, + 0x58, 0xcd, 0x03, 0x58, + 0x43, 0x3d, 0x01, 0x9c, + 0xe6, 0x7d, 0x03, 0x50, + 0x41, 0xed, 0x01, 0xfc, + 0xe6, 0xed, 0x03, 0x54, + 0x24, 0x15, + 0xf8, 0xf0, 0x4f, 0x53, 0x33, 0x32, + 0xd3, 0x7e, 0x00, 0x24, + 0xc3, 0x70, 0x00, 0x10, + 0x23, 0x3e, + 0xce, 0x70, 0x00, 0xe0, + 0x21, 0xeb, + 0x55, 0xfe, 0x00, 0x00, + 0x21, 0x38, + 0x58, 0x6e, 0x00, 0x08, + 0x10, 0x68, + 0x55, 0x6d, 0x03, 0x24, + 0x44, 0x3d, 0x01, 0xb2, + 0xca, 0xe0, 0x00, 0x30, + 0x27, 0x11, + 0x42, 0x3d, 0x01, 0x66, + 0x58, 0xcd, 0x03, 0x50, + 0x42, 0x3d, 0x01, 0x52, + 0x48, 0x10, 0x00, 0x7e, + 0x42, 0x3d, 0x02, 0xf0, + 0x58, 0xcd, 0x03, 0x48, + 0x43, 0x3d, 0x02, 0xf0, + 0x58, 0x8d, 0x03, 0x4c, + 0x23, 0x07, + 0x58, 0xce, 0x00, 0x0c, + 0x58, 0x8e, 0x00, 0x10, + 0x0b, 0x8c, + 0x26, 0xc1, + 0x11, 0x88, + 0x08, 0x18, + 0xe6, 0xf0, 0x11, 0x18, + 0x58, 0x0f, 0x00, 0x00, + 0x50, 0x01, 0x00, 0x00, + 0x59, 0x01, 0x00, 0x00, + 0x42, 0x3d, 0x03, 0x08, + 0x26, 0xf4, + 0x26, 0x14, + 0xc5, 0xf0, 0x12, 0x78, + 0x20, 0x8c, + 0x08, 0xd8, + 0xcb, 0xd0, 0x01, 0xe8, + 0x03, 0x08, + 0x27, 0x81, + 0x07, 0x77, + 0x41, 0xed, 0x01, 0xfc, + 0xd1, 0xed, 0x03, 0x40, + 0xd0, 0xe0, 0x00, 0x78, + 0x43, 0x00, 0x00, 0x60, + 0xde, 0x2d, 0x03, 0x28, + 0x08, 0x0c, + 0x4d, 0x0d, 0x45, 0x00, 0x03, 0x30, + 0x08, 0x91, + 0x4d, 0x0d, 0x45, 0x00, 0x03, 0x38, + 0x08, 0xa1, + 0x08, 0xb0, + 0x08, 0x55, + 0x42, 0x2d, 0x02, 0x4a, + 0xde, 0x3d, 0x03, 0x28, + 0x9d, 0x3f, + 0x22, 0x21, + 0x9d, 0x4f, + 0x42, 0x1d, 0x02, 0xf4, + 0xc3, 0xf0, 0x00, 0x10, + 0x20, 0x35, + 0x11, 0xa5, + 0x06, 0xba, + 0x98, 0x49, + 0xde, 0x4d, 0x03, 0x28, + 0x9d, 0x3f, + 0x22, 0x21, + 0x9d, 0x4f, + 0x42, 0x7d, 0x02, 0xf8, + 0x20, 0x83, + 0x41, 0x6d, 0x02, 0x96, + 0x22, 0x0b, + 0x9d, 0x4f, + 0xc3, 0xf0, 0x00, 0x19, + 0x42, 0x3d, 0x02, 0xfc, + 0xde, 0x4d, 0x03, 0x2c, + 0x9d, 0x3f, + 0x22, 0x21, + 0x98, 0x49, + 0xde, 0x4d, 0x03, 0x2e, + 0x9d, 0x3f, + 0x22, 0x21, + 0xde, 0x4d, 0x03, 0x2d, + 0x9d, 0x3f, + 0x22, 0x21, + 0x98, 0x4a, + 0xde, 0x4d, 0x03, 0x2f, + 0x0d, 0x3f, + 0x22, 0x21, + 0xde, 0x4d, 0x03, 0x2b, + 0x9d, 0x3f, + 0x22, 0x21, + 0x9d, 0x4f, + 0x20, 0x81, + 0xc3, 0xf0, 0x00, 0x53, + 0x42, 0x3d, 0x03, 0x00, + 0x08, 0xfa, + 0x11, 0xfa, + 0x06, 0xf9, + 0xe6, 0x6d, 0x02, 0x54, + 0x34, 0x77, + 0x9a, 0x27, + 0x34, 0x77, + 0x98, 0x27, + 0x34, 0x88, + 0x9a, 0x28, + 0x34, 0x88, + 0x98, 0x28, + 0x08, 0x55, + 0x21, 0x24, + 0x98, 0x49, + 0x9a, 0x3b, + 0x23, 0x03, + 0x9a, 0x3b, + 0x98, 0x3f, + 0xde, 0x3d, 0x03, 0x2a, + 0xde, 0x2d, 0x03, 0x29, + 0x9d, 0x2f, + 0x20, 0x81, + 0xde, 0x2d, 0x03, 0x28, + 0x9b, 0x20, + 0x99, 0x21, + 0x34, 0x00, + 0x06, 0x01, + 0xde, 0x2d, 0x03, 0x28, + 0x9d, 0x3f, + 0x22, 0x21, + 0x42, 0x1d, 0x03, 0x04, + 0xc3, 0xf0, 0x00, 0x10, + 0x03, 0x3e, + 0x0b, 0x07, + 0x26, 0x04, + 0xc4, 0x00, 0xff, 0x00, + 0x0a, 0x70, + 0x26, 0x91, + 0x07, 0xaa, + 0x07, 0xbb, + 0x03, 0x06, + 0x24, 0x11, + 0x23, 0x0c, + 0x24, 0x12, + 0x23, 0x0a, + 0x24, 0x13, + 0x23, 0x08, + 0x24, 0x14, + 0x23, 0x06, + 0x24, 0x15, + 0x23, 0x04, + 0x24, 0x16, + 0x23, 0x02, + 0x24, 0x17, + 0x24, 0x01, + 0xde, 0x0d, 0x03, 0x28, + 0x9a, 0x01, + 0xde, 0x0d, 0x03, 0x28, + 0xd1, 0xed, 0x03, 0x40, + 0xd0, 0xe0, 0x00, 0x78, + 0x11, 0x0f, + 0x95, 0x10, + 0x22, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x48, 0x30, + 0xc1, 0xc2, + 0xc8, 0xc4, + 0xd0, 0xe0, + 0x00, 0x30, + 0x01, 0x90, + 0x01, 0x40, + 0x04, 0xc0, + 0x00, 0x18, + 0x00, 0x14, + 0x00, 0x40, + 0x00, 0x40, + 0x00 +}; + +/* Lower memory setup + + 78 = binary input device address + 79 = binary device input command + 7A = disk device number + 7B = device code + 7C = disk controller address + 7D = selector channel address + 7E:7F = operating system extension (user specified) +*/ + +struct dboot_id { + char *name; + uint32 cap; + uint32 dtype; + uint32 offset; +}; + +static struct dboot_id dboot_tab[] = { + { "DP", 2, 0x31, o_DP0 }, + { "DP", 9, 0x33, o_DP0 }, + { "DM", 64, 0x35, o_ID0 }, + { "DM", 244, 0x36, o_ID0 }, + { NULL } }; + +t_stat id_dboot (int32 u, DEVICE *dptr) +{ +extern DIB pt_dib, sch_dib; +extern uint32 PC; +uint32 i, typ, ctlno, off, cap, sch_dev; +UNIT *uptr; + +DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */ +ctlno = ddib->dno; /* get ctrl devno */ +sch_dev = sch_dib.dno + ddib->sch; /* sch dev # */ +uptr = dptr->units + u; /* get capacity */ +cap = uptr->capac >> 20; +for (i = typ = 0; dboot_tab[i].name != NULL; i++) { + if ((strcmp (dboot_tab[i].name, dptr->name) == 0) && + (dboot_tab[i].cap == cap)) { + typ = dboot_tab[i].dtype; + off = dboot_tab[i].offset; } } +if (typ == 0) return SCPE_NOFNC; + +IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */ +IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */ +IOWriteB (AL_IOC, 0x99); +IOWriteB (AL_DSKU, ctlno + ((u + 1) * off)); /* disk param */ +IOWriteB (AL_DSKT, typ); +IOWriteB (AL_DSKC, ctlno); +IOWriteB (AL_SCH, sch_dev); +PC = DBOOT_START; +return SCPE_OK; +} diff --git a/Interdata/id32_sys.c b/Interdata/id32_sys.c new file mode 100644 index 00000000..6ea5340e --- /dev/null +++ b/Interdata/id32_sys.c @@ -0,0 +1,641 @@ +/* id32_sys.c: Interdata 32b simulator interface + + Copyright (c) 2000-2003, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + 23-Dec-01 RMS Cloned from ID4 sources +*/ + +#include "id_defs.h" +#include + +#define MSK_SBF 0x0100 +#define SEXT15(x) (((x) & 0x4000)? ((x) | 0xFFFF8000): ((x) & 0x7FFF)) + +extern DEVICE cpu_dev; +extern DEVICE sch_dev; +extern DEVICE pt_dev; +extern DEVICE tt_dev, ttp_dev; +extern DEVICE pas_dev, pasl_dev; +extern DEVICE lpt_dev; +extern DEVICE pic_dev, lfc_dev; +extern DEVICE dp_dev, idc_dev; +extern DEVICE fd_dev, mt_dev; +extern UNIT cpu_unit; +extern REG cpu_reg[]; +extern uint32 *M; + +t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val); +t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val); +extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam); +extern pt_dump (FILE *of, char *cptr, char *fnam); + +/* SCP data structures and interface routines + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages + sim_load binary loader +*/ + +char sim_name[] = "Interdata 32b"; + +REG *sim_PC = &cpu_reg[0]; + +int32 sim_emax = 6; + +DEVICE *sim_devices[] = { + &cpu_dev, + &sch_dev, + &pt_dev, + &tt_dev, + &ttp_dev, + &pas_dev, + &pasl_dev, + &pic_dev, + &lfc_dev, + &lpt_dev, + &dp_dev, + &idc_dev, + &fd_dev, + &mt_dev, + NULL }; + +const char *sim_stop_messages[] = { + "Unknown error", + "Reserved instruction", + "HALT instruction", + "Breakpoint", + "Wait state", + "Runaway VFU" }; + +/* Binary loader -- load carriage control tape + Binary dump -- paper tape dump */ + +t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +{ +if (flag) return pt_dump (fileref, cptr, fnam); +return lp_load (fileref, cptr, fnam); +} + +/* Symbol tables */ + +#define I_V_FL 16 /* class bits */ +#define I_M_FL 0xF /* class mask */ +#define I_V_MR 0x0 /* mask-register */ +#define I_V_RR 0x1 /* register-register */ +#define I_V_R 0x2 /* register */ +#define I_V_MX 0x3 /* mask-memory */ +#define I_V_RX 0x4 /* register-memory */ +#define I_V_X 0x5 /* memory */ +#define I_V_FF 0x6 /* float reg-reg */ +#define I_V_FX 0x7 /* float reg-mem */ +#define I_V_SI 0x8 /* short immed */ +#define I_V_SB 0x9 /* short branch */ +#define I_V_SX 0xA /* short ext branch */ +#define I_V_RI 0xB /* halfword imm */ +#define I_V_RF 0xC /* fullword imm */ +#define I_MR (I_V_MR << I_V_FL) +#define I_RR (I_V_RR << I_V_FL) +#define I_R (I_V_R << I_V_FL) +#define I_MX (I_V_MX << I_V_FL) +#define I_RX (I_V_RX << I_V_FL) +#define I_X (I_V_X << I_V_FL) +#define I_FF (I_V_FF << I_V_FL) +#define I_FX (I_V_FX << I_V_FL) +#define I_SI (I_V_SI << I_V_FL) +#define I_SB (I_V_SB << I_V_FL) +#define I_SX (I_V_SX << I_V_FL) +#define I_RI (I_V_RI << I_V_FL) +#define I_RF (I_V_RF << I_V_FL) + +#define R_X 0 /* no R1 */ +#define R_M 1 /* R1 mask */ +#define R_R 2 /* R1 int reg */ +#define R_F 3 /* R1 flt reg */ + +static const int32 masks[] = { + 0xFF00, 0xFF00, 0xFFF0, 0xFF00, + 0xFF00, 0xFFF0, 0xFF00, 0xFF00, + 0xFF00, 0xFE00, 0xFEF0, 0xFF00, + 0xFF00 }; + +static const uint32 r1_type[] = { + R_M, R_R, R_X, R_M, + R_R, R_X, R_F, R_F, + R_R, R_M, R_X, R_R, + R_R }; + +static const uint32 r2_type[] = { + R_X, R_R, R_R, R_X, + R_X, R_X, R_F, R_X, + R_M, R_X, R_X, R_X, + R_X }; + +static const char *opcode[] = { +"BER", "BNER","BZR", "BNZR", +"BPR", "BNPR","BLR", "BNLR", +"BMR", "BNMR","BOR", "BNOR", +"BCR", "BNCR","BR", +"BES", "BNES","BZS", "BNZS", +"BPS", "BNPS","BLS", "BNLS", +"BMS", "BNMS","BOS", "BNOS", +"BCS", "BNCS","BS", +"BE", "BNE", "BZ", "BNZ", +"BP", "BNP", "BL", "BNL", +"BM", "BNM", "BO", "BNO", +"BC", "BNC", "B", + "BALR","BTCR","BFCR", +"NR", "CLR", "OR", "XR", +"LR", "CHR", "AR", "SR", +"MHR", "DHR", +"SRLS","SLLS","CHVR", +"LPSWR", +"MR", "DR", +"BTBS","BTFS","BFBS","BFFS", +"LIS", "LCS", "AIS", "SIS", +"LER", "CER", "AER", "SER", +"MER", "DER", "FXR", "FLR", +"MPBSR", "PBR", +"EXHR", +"LDR", "CDR", "ADR", "SDR", +"MDR", "DDR", "FXDR","FLDR", +"STH", "BAL", "BTC", "BFC", +"NH", "CLH", "OH", "XH", +"LH", "CH", "AH", "SH", +"MH", "DH", +"ST", "AM", +"N", "CL", "O", "X", +"L", "C", "A", "S", +"M", "D", "CRC12","CRC16", +"STE", "AHM", "PB", "LRA", +"ATL", "ABL", "RTL", "RBL", +"LE", "CE", "AE", "SE", +"ME", "DE", +"STD", "STME","LME", "LHL", +"TBT", "SBT", "RBT", "CBT", +"LD", "CD", "AD", "SD", +"MD", "DD", "STMD","LMD", +"SRHLS","SLHLS","STBR","LBR", +"EXBR","EPSR","WBR", "RBR", +"WHR", "RHR", "WDR", "RDR", + "SSR", "OCR", +"BXH", "BXLE","LPSW","THI", +"NHI", "CLHI","OHI", "XHI", +"LHI", "CHI", "AHI", "SHI", +"SRHL","SLHL","SRHA","SLHA", +"STM", "LM", "STB", "LB", +"CLB", "AL", "WB", "RB", +"WH", "RH", "WD", "RD", + "SS", "OC", +"TS", "SVC", "SINT","SCP", + "LA", "TLATE", + "RRL", "RLL", +"SRL", "SLL", "SRA", "SLA", + "TI", +"NI", "CLI", "OI", "XI", +"LI", "CI", "AI", "SI", +NULL }; + +static const uint32 opc_val[] = { +0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R, +0x0220+I_R, 0x0320+I_R, 0x0280+I_R, 0x0380+I_R, +0x0210+I_R, 0x0310+I_R, 0x0240+I_R, 0x0340+I_R, +0x0280+I_R, 0x0380+I_R, 0x0300+I_R, +0x2230+I_SX, 0x2030+I_SX, 0x2230+I_SX, 0x2030+I_SX, +0x2020+I_SX, 0x2220+I_SX, 0x2080+I_SX, 0x2280+I_SX, +0x2010+I_SX, 0x2210+I_SX, 0x2040+I_SX, 0x2240+I_SX, +0x2080+I_SX, 0x2280+I_SX, 0x2200+I_SX, +0x4330+I_X, 0x4230+I_X, 0x4330+I_X, 0x4230+I_X, +0x4220+I_X, 0x4320+I_X, 0x4280+I_X, 0x4380+I_X, +0x4210+I_X, 0x4310+I_X, 0x4240+I_X, 0x4340+I_X, +0x4280+I_X, 0x4380+I_X, 0x4300+I_X, + 0x0100+I_RR, 0x0200+I_MR, 0x0300+I_MR, +0x0400+I_RR, 0x0500+I_RR, 0x0600+I_RR, 0x0700+I_RR, +0x0800+I_RR, 0x0900+I_RR, 0x0A00+I_RR, 0x0B00+I_RR, +0x0C00+I_RR, 0x0D00+I_RR, +0x1000+I_SI, 0x1100+I_SI, 0x1200+I_RR, +0x1800+I_RR, +0x1C00+I_RR, 0x1D00+I_RR, +0x2000+I_SB, 0x2100+I_SB, 0x2200+I_SB, 0x2300+I_SB, +0x2400+I_SI, 0x2500+I_SI, 0x2600+I_SI, 0x2700+I_SI, +0x2800+I_FF, 0x2900+I_FF, 0x2A00+I_FF, 0x2B00+I_FF, +0x2C00+I_FF, 0x2D00+I_FF, 0x2E00+I_RR, 0x2F00+I_RR, +0x3000+I_RR, 0x3200+I_RR, +0x3400+I_RR, +0x3800+I_FF, 0x3900+I_FF, 0x3A00+I_FF, 0x3B00+I_FF, +0x3C00+I_FF, 0x3D00+I_FF, 0x3E00+I_RR, 0x3F00+I_RR, +0x4000+I_RX, 0x4100+I_RX, 0x4200+I_MX, 0x4300+I_MX, +0x4400+I_RX, 0x4500+I_RX, 0x4600+I_RX, 0x4700+I_RX, +0x4800+I_RX, 0x4900+I_RX, 0x4A00+I_RX, 0x4B00+I_RX, +0x4C00+I_RX, 0x4D00+I_RX, +0x5000+I_RX, 0x5100+I_RX, +0x5400+I_RX, 0x5500+I_RX, 0x5600+I_RX, 0x5700+I_RX, +0x5800+I_RX, 0x5900+I_RX, 0x5A00+I_RX, 0x5B00+I_RX, +0x5C00+I_RX, 0x5D00+I_RX, 0x5E00+I_RX, 0x5F00+I_RX, +0x6000+I_RX, 0x6100+I_RX, 0x6200+I_RX, 0x6300+I_RX, +0x6400+I_RX, 0x6500+I_RX, 0x6600+I_RX, 0x6700+I_RX, +0x6800+I_FX, 0x6900+I_FX, 0x6A00+I_FX, 0x6B00+I_FX, +0x6C00+I_FX, 0x6D00+I_FX, +0x7000+I_FX, 0x7100+I_FX, 0x7200+I_FX, 0x7300+I_RX, +0x7400+I_RX, 0x7500+I_RX, 0x7600+I_RX, 0x7700+I_RX, +0x7800+I_FX, 0x7900+I_FX, 0x7A00+I_FX, 0x7B00+I_FX, +0x7C00+I_FX, 0x7D00+I_FX, 0x7E00+I_FX, 0x7F00+I_FX, +0x9000+I_SI, 0x9100+I_SI, 0x9200+I_RR, 0x9300+I_RR, +0x9400+I_RR, 0x9500+I_RR, 0x9600+I_RR, 0x9700+I_RR, +0x9800+I_RR, 0x9900+I_RR, 0x9A00+I_RR, 0x9B00+I_RR, + 0x9D00+I_RR, 0x9E00+I_RR, +0xC000+I_RX, 0xC100+I_RX, 0xC200+I_RX, 0xC300+I_RI, +0xC400+I_RI, 0xC500+I_RI, 0xC600+I_RI, 0xC700+I_RI, +0xC800+I_RI, 0xC900+I_RI, 0xCA00+I_RI, 0xCB00+I_RI, +0xCC00+I_RI, 0xCD00+I_RI, 0xCE00+I_RI, 0xCF00+I_RI, +0xD000+I_RX, 0xD100+I_RX, 0xD200+I_RX, 0xD300+I_RX, +0xD400+I_RX, 0xD500+I_X, 0xD600+I_RX, 0xD700+I_RX, +0xD800+I_RX, 0xD900+I_RX, 0xDA00+I_RX, 0xDB00+I_RX, + 0xDD00+I_RX, 0xDE00+I_RX, +0xE000+I_RX, 0xE100+I_RX, 0xE200+I_RI, 0xE300+I_RX, + 0xE600+I_RX, 0xE700+I_RX, + 0xEA00+I_RI, 0xEB00+I_RI, +0xEC00+I_RI, 0xED00+I_RI, 0xEE00+I_RI, 0xEF00+I_RI, + 0xF300+I_RF, +0xF400+I_RF, 0xF500+I_RF, 0xF600+I_RF, 0xF700+I_RF, +0xF800+I_RF, 0xF900+I_RF, 0xFA00+I_RF, 0xFB00+I_RF, +0xFFFF }; + +/* Print an RX specifier */ + +t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1, uint32 ea2) +{ +uint32 rx2; + +if ((ea1 & 0xC000) == 0) { /* RX1 */ + fprintf (of, "%-X", ea1); + if (rx) fprintf (of, "(R%d)", rx); + return -3; } +if (ea1 & 0x8000) { /* RX2 */ + ea1 = addr + 4 + SEXT15 (ea1); + fprintf (of, "%-X", ea1 & VAMASK32); + if (rx) fprintf (of, "(R%d)", rx); + return -3; } +rx2 = (ea1 >> 8) & 0xF; +fprintf (of, "%-X", ((ea1 << 16) | ea2) & VAMASK32); +if (rx && !rx2) fprintf (of, "(R%d)", rx); +if (rx2) fprintf (of, "(R%d,R%d)", rx, rx2); +return -5; +} + +#define GETNUM(d,n) for (k = d = 0; k < n; k++) \ + d = (d << 8) | (((uint32) val[vp++]) & 0xFF) + +/* Symbolic decode + + Inputs: + *of = output stream + addr = current PC + *val = values to decode + *uptr = pointer to unit + sw = switches + Outputs: + return = if >= 0, error code + if < 0, number of extra bytes retired +*/ + +t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, + UNIT *uptr, int32 sw) +{ +int32 c, k, num, rdx, vp, lnt; +t_stat r; +DEVICE *dptr; + +if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +dptr = find_dev_from_unit (uptr); /* find dev */ +if (dptr == NULL) return SCPE_IERR; +if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ +if (sw & SWMASK ('B')) lnt = 1; /* get length */ +else if (sw & SWMASK ('W')) lnt = 2; +else if (sw & SWMASK ('F')) lnt = 4; +else lnt = (uptr == &cpu_unit)? 4: 1; +if (sw & SWMASK ('D')) rdx = 10; /* get radix */ +else if (sw & SWMASK ('O')) rdx = 8; +else if (sw & SWMASK ('H')) rdx = 16; +else rdx = dptr->dradix; +vp = 0; /* init ptr */ +if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ + if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ + if ((val[0] & 0x7F) == 0) return SCPE_ARG; + while (vp < lnt) { /* print string */ + if ((c = (uint32) val[vp++] & 0x7F) == 0) break; + fprintf (of, (c < 0x20)? "<%02X>": "%c", c); } + return -(vp - 1); } /* return # chars */ + +if (sw & SWMASK ('M')) { /* inst format? */ + r = fprint_sym_m (of, addr, val); /* decode inst */ + if (r <= 0) return r; /* success? */ + lnt = 2; } /* no, skip 16b */ + +GETNUM (num, lnt); /* get number */ +fprint_val (of, num, rdx, lnt * 8, PV_RZRO); +return -(vp - 1); +} + +/* Symbolic decode for -m + + Inputs: + of = output stream + addr = current PC + *val = values to decode + Outputs: + return = if >= 0, error code + if < 0, number of extra bytes retired +*/ + +t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val) +{ +uint32 i, j, k, inst, r1, r2, ea1, ea2, tgt, vp; + +vp = 0; +GETNUM (inst,2); /* high 16b */ +GETNUM (ea1, 2); /* next 16b */ +GETNUM (ea2, 2); /* next 16b */ +for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */ + j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ + if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */ + r1 = (inst >> 4) & 0xF; + r2 = inst & 0xF; + switch (j) { /* case on class */ + case I_V_MR: /* mask-register */ + fprintf (of, "%s %-X,R%d", opcode[i], r1, r2); + return -1; + case I_V_RR: /* register-register */ + case I_V_FF: /* floating-floating */ + fprintf (of, "%s R%d,R%d", opcode[i], r1, r2); + return -1; + case I_V_SI: /* short immediate */ + fprintf (of, "%s R%d,%-X", opcode[i], r1, r2); + return -1; + case I_V_SB: /* short branch */ + if (inst & MSK_SBF) tgt = addr + r2 + r2; + else tgt = addr - r2 - r2; + fprintf (of, "%s %-X,%-X", opcode[i], r1, tgt); + return -1; + case I_V_SX: /* ext short branch */ + if (inst & MSK_SBF) tgt = addr + r2 + r2; + else tgt = addr - r2 - r2; + fprintf (of, "%s %-X", opcode[i], tgt); + return -1; + case I_V_R: /* register */ + fprintf (of, "%s R%d", opcode[i], r2); + return -1; + case I_V_RI: /* reg-immed */ + fprintf (of, "%s R%d,%-X", opcode[i], r1, ea1); + if (r2) fprintf (of, "(R%d)", r2); + return -3; + case I_V_RF: /* reg-full imm */ + fprintf (of, "%s R%d,%-X", opcode[i], r1, + (ea1 << 16) | ea2); + if (r2) fprintf (of, "(R%d)", r2); + return -5; + case I_V_MX: /* mask-memory */ + fprintf (of, "%s %-X,", opcode[i], r1); + return fprint_addr (of, addr, r2, ea1, ea2); + case I_V_RX: /* register-memory */ + case I_V_FX: /* floating-memory */ + fprintf (of, "%s R%d,", opcode[i], r1); + return fprint_addr (of, addr, r2, ea1, ea2); + case I_V_X: /* memory */ + fprintf (of, "%s ", opcode[i]); + return fprint_addr (of, addr, r2, ea1, ea2); } + return SCPE_IERR; } /* end if */ + } /* end for */ +return SCPE_ARG; /* no match */ +} + +/* Register number + + Inputs: + *cptr = pointer to input string + **optr = pointer to pointer to next char + rtype = mask, integer, or float + Outputs: + rnum = output register number, -1 if error +*/ + +int32 get_reg (char *cptr, char **optr, int32 rtype) +{ +int32 reg; + +if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */ + cptr++; /* skip */ + if (rtype == R_M) return -1; } /* cant be mask */ +if ((*cptr >= '0') && (*cptr <= '9')) { + reg = *cptr++ - '0'; + if ((*cptr >= '0') && (*cptr <= '9')) + reg = (reg * 10) + (*cptr - '0'); + else --cptr; + if (reg > 0xF) return -1; } +else if ((*cptr >= 'a') && (*cptr <= 'f')) reg = (*cptr - 'a') + 10; +else if ((*cptr >= 'A') && (*cptr <= 'F')) reg = (*cptr - 'A') + 10; +else return -1; +if ((rtype == R_F) && (reg & 1)) return -1; +*optr = cptr + 1; +return reg; +} + +/* Immediate + + Inputs: + *cptr = pointer to input string + *imm = pointer to output value + *inst = pointer to instruction + max = max value + Outputs: + sta = status +*/ + +t_stat get_imm (char *cptr, uint32 *imm, uint32 *inst, uint32 max) +{ +char *tptr; +uint32 idx; + +errno = 0; +*imm = strtoul (cptr, &tptr, 16); /* get immed */ +if (errno || (*imm > max) || (cptr == tptr)) return SCPE_ARG; +if (*tptr == '(') { /* index? */ + if ((idx = get_reg (tptr + 1, &tptr, R_R)) < 0) + return SCPE_ARG; + if (*tptr++ != ')') return SCPE_ARG; + *inst = *inst | idx; } +if (*tptr != 0) return SCPE_ARG; +return SCPE_OK; +} + +#define PUTNUM(d,n) for (k = n; k > 0; k--) \ + val[vp++] = (d >> ((k - 1) * 8)) & 0xFF + +/* Symbolic input */ + +t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) +{ +int32 k, rdx, lnt, num, vp; +t_stat r; +DEVICE *dptr; +static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF }; + +if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +dptr = find_dev_from_unit (uptr); /* find dev */ +if (dptr == NULL) return SCPE_IERR; +if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */ +if (sw & SWMASK ('B')) lnt = 1; /* get length */ +else if (sw & SWMASK ('W')) lnt = 2; +else if (sw & SWMASK ('F')) lnt = 4; +else lnt = (uptr == &cpu_unit)? 4: 1; +if (sw & SWMASK ('D')) rdx = 10; /* get radix */ +else if (sw & SWMASK ('O')) rdx = 8; +else if (sw & SWMASK ('H')) rdx = 16; +else rdx = dptr->dradix; +vp = 0; +if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ + if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ + if (*cptr == 0) return SCPE_ARG; + while ((vp < lnt) && *cptr) { /* get chars */ + val[vp++] = *cptr++; } + return -(vp - 1); } /* return # chars */ + +if (uptr == &cpu_unit) { /* cpu only */ + r = parse_sym_m (cptr, addr, val); /* try to parse inst */ + if (r <= 0) return r; } + +num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */ +if (r != SCPE_OK) return r; +PUTNUM (num, lnt); /* store */ +return -(lnt - 1); +} + +/* Symbolic input for -m + + Inputs: + *cptr = pointer to input string + addr = current PC + *val = pointer to output values + Outputs: + status = > 0 error code + <= 0 -number of extra words +*/ + +t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val) +{ +uint32 i, j, k, t, df, db, inst, ea, vp; +int32 st, r1, r2, rx2; +t_stat r; +char *tptr, gbuf[CBUFSIZE]; + +vp = 0; +cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; +if (opcode[i] == NULL) return SCPE_ARG; +inst = opc_val[i] & 0xFFFF; /* get value */ +j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ +if (r1_type[j]) { /* any R1 field? */ + cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */ + if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0) + return SCPE_ARG; + if (*tptr != 0) return SCPE_ARG; + inst = inst | (r1 << 4); } /* or in R1 */ + +cptr = get_glyph (cptr, gbuf, 0); /* get operand */ +if (*cptr) return SCPE_ARG; /* should be end */ +switch (j) { /* case on class */ + +case I_V_FF: case I_V_SI: /* flt-flt, sh imm */ +case I_V_MR: case I_V_RR: /* mask/reg-register */ +case I_V_R: /* register */ + if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0) + return SCPE_ARG; + if (*tptr != 0) return SCPE_ARG; + inst = inst | r2; /* or in R2 */ + break; + +case I_V_FX: /* float-memory */ +case I_V_MX: case I_V_RX: /* mask/reg-memory */ +case I_V_X: /* memory */ + errno = 0; + ea = strtoul (gbuf, &tptr, 16); /* get address */ + if (errno || (gbuf == tptr)) return SCPE_ARG; /* error? */ + rx2 = 0; /* assume no 2nd */ + if (*tptr == '(') { /* index? */ + if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0) + return SCPE_ARG; + inst = inst | r2; /* or in R2 */ + if (*tptr == ',') { /* 2nd index? */ + if ((rx2 = get_reg (tptr + 1, &tptr, R_R)) < 0) + return SCPE_ARG; } + if (*tptr++ != ')') return SCPE_ARG; } /* all done? */ + if (*tptr != 0) return SCPE_ARG; + PUTNUM (inst, 2); /* store inst */ + if (rx2 == 0) { /* no 2nd? */ + if (ea < 0x4000) { /* RX1? */ + PUTNUM (ea, 2); /* store ea */ + return -3; } + st = (ea - (addr + 4)); /* displ */ + if ((st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? */ + t = (st & 0x7FFF) | 0x8000; + PUTNUM (t, 2); /* store displ */ + return -3; } } + ea = (ea & VAMASK32) | 0x40000000 | (rx2 << 24); + PUTNUM (ea, 4); /* RX3 */ + return -5; + +case I_V_RI: /* 16b immediate */ + r = get_imm (gbuf, &ea, &inst, DMASK16); /* process imm */ + if (r != SCPE_OK) return r; + PUTNUM (inst, 2); /* store inst */ + PUTNUM (ea, 2); /* store 16b imm */ + return -3; + +case I_V_RF: + r = get_imm (gbuf, &ea, &inst, DMASK32); /* process imm */ + if (r != SCPE_OK) return r; + PUTNUM (inst, 2); /* store inst */ + PUTNUM (ea, 4); /* store 32b imm */ + return -5; + +case I_V_SB: case I_V_SX: /* short branches */ + t = get_uint (gbuf, 16, DMASK16, &r); /* get addr */ + if ((r != SCPE_OK) || (t & 1)) return r; /* error if odd */ + db = (addr - t) & 0x1F; /* back displ */ + df = (t - addr) & 0x1F; /* fwd displ */ + if ((t == ((addr - db) & VAMASK16)) && /* back work and */ + ((j == I_V_SX) || !(inst & MSK_SBF))) { /* ext or back br? */ + inst = inst | (db >> 1); /* or in back displ */ + break; } + if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */ + ((j == I_V_SX) || (inst & MSK_SBF))) { /* ext or fwd br? */ + inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */ + break; } + return SCPE_ARG; } /* end case */ + +PUTNUM (inst, 2); +return -1; +} diff --git a/Interdata/id_defs.h b/Interdata/id_defs.h new file mode 100644 index 00000000..6deb17ac --- /dev/null +++ b/Interdata/id_defs.h @@ -0,0 +1,483 @@ +/* id_defs.h: Interdata 16b/32b simulator definitions + + Copyright (c) 2000-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + The author gratefully acknowledges the help of Carl Friend and Al Kossow, + who provided key documents about the Interdata product line. +*/ + +#include "sim_defs.h" /* simulator defns */ + +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* undef instr */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_WAIT 4 /* wait */ +#define STOP_VFU 5 /* runaway VFU */ + +/* Memory */ + +#define PAWIDTH16 16 +#define PAWIDTH16E 18 +#define PAWIDTH32 20 +#define MAXMEMSIZE16 (1u << PAWIDTH16) /* max mem size, 16b */ +#define MAXMEMSIZE16E (1u << PAWIDTH16E) /* max mem size, 16b E */ +#define MAXMEMSIZE32 (1u << PAWIDTH32) /* max mem size, 32b */ +#define PAMASK16 (MAXMEMSIZE16 - 1) /* phys mem mask */ +#define PAMASK16E (MAXMEMSIZE16E - 1) +#define PAMASK32 (MAXMEMSIZE32 - 1) + +#define MEMSIZE (cpu_unit.capac) /* act memory size */ +#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE) + +/* Single precision floating point registers */ + +#if defined (IFP_IN_MEM) +#define ReadFReg(r) (fp_in_hwre? \ + F[(r) >> 1]: ReadF (((r) << 1) & ~3, P)) +#define WriteFReg(r,v) if (fp_in_hwre) F[(r) >> 1] = (v); \ + else WriteF (((r) << 1) & ~3, (v), P) +#else +#define ReadFReg(r) (F[(r) >> 1]) +#define WriteFReg(r,v) F[(r) >> 1] = (v) +#endif + +/* Double precision floating point registers */ + +struct dpr { + unsigned int32 h; /* high 32b */ + unsigned int32 l; /* low 32b */ +}; + +typedef struct dpr dpr_t; + +/* Architectural constants */ + +#define VAMASK16 (0xFFFF) /* 16b virt addr */ +#define VAMASK32 (0x000FFFFF) /* 32b virt addr */ + +#define SIGN8 0x80 /* 8b sign bit */ +#define DMASK8 0xFF /* 8b data mask */ +#define MMASK8 0x7F /* 8b magnitude mask */ +#define SIGN16 0x8000 /* 16b sign bit */ +#define DMASK16 0xFFFF /* 16b data mask */ +#define MMASK16 0x7FFF /* 16b magnitude mask */ +#define SIGN32 0x80000000 /* 32b sign bit */ +#define DMASK32 0xFFFFFFFF /* 32b data mask */ +#define MMASK32 0x7FFFFFFF /* 32b magn mask */ + +#define CC_C 0x8 /* carry */ +#define CC_V 0x4 /* overflow */ +#define CC_G 0x2 /* greater than */ +#define CC_L 0x1 /* less than */ +#define CC_MASK (CC_C | CC_V | CC_G | CC_L) + +#define PSW_WAIT 0x8000 /* wait */ +#define PSW_EXI 0x4000 /* ext intr enable */ +#define PSW_MCI 0x2000 /* machine check enable */ +#define PSW_AFI 0x1000 /* arith fault enb */ +#define PSW_AIO 0x0800 /* auto I/O int enable */ +#define PSW_FPF 0x0400 /* flt fault enb, 16b */ +#define PSW_REL 0x0400 /* reloc enb, 32b */ +#define PSW_SQI 0x0200 /* sys q int enable */ +#define PSW_PRO 0x0100 /* protect mode */ +#define PSW_V_MAP 4 /* mem map, 16b */ +#define PSW_M_MAP 0xF +#define PSW_MAP (PSW_M_MAP << PSW_V_MAP) +#define PSW_V_REG 4 /* reg set, 32b */ +#define PSW_M_REG 0x1 +#define PSW_ID4 0xF40F /* I3, I4 PSW */ +#define PSW_x16 0xFF0F /* 7/16, 8/16 PSW */ +#define PSW_816E 0xFFFF /* 8/16E PSW */ +#define PSW_x32 0xFFFF /* 7/32, 8/32 PSW */ +#define PSW_GETMAP(x) (((x) >> PSW_V_MAP) & PSW_M_MAP) +#define PSW_GETREG(x) (((x) >> PSW_V_REG) & PSW_M_REG) + +#define MCKOPSW 0x20 /* mchk old PSW, 32b */ +#define FPFPSW 0x28 /* flt fault PSW, 16b */ +#define ILOPSW 0x30 /* ill op PSW */ +#define MCKPSW 0x38 /* mach chk PSW */ +#define EXIPSW 0x40 /* ext intr PSW, 16b */ +#define AFIPSW 0x48 /* arith flt PSW */ +#define SQP 0x80 /* system queue ptr */ +#define SQIPSW 0x82 /* sys q int PSW, 16b */ +#define SQOP 0x8A /* sys q ovf ptr, 16b */ +#define SQVPSW 0x8C /* sys q ovf PSW, 16b */ +#define SQTPSW 0x88 /* sys q int PSW, 32b */ +#define MPRPSW 0x90 /* mprot int PSW, 32b */ +#define SVCAP 0x94 /* svc arg ptr, 16b */ +#define SVOPS 0x96 /* svc old PS, 16b */ +#define SVOPC 0x98 /* svc old PC, 16b */ +#define SVNPS32 0x98 /* svc new PS, 32b */ +#define SVNPS 0x9A /* svc new PS, 16b */ +#define SVNPC 0x9C /* svc new PC */ +#define INTSVT 0xD0 /* int service table */ + +#define AL_DEV 0x78 /* autoload: dev */ +#define AL_IOC 0x79 /* command */ +#define AL_DSKU 0x7A /* disk unit */ +#define AL_DSKT 0x7B /* disk type */ +#define AL_DSKC 0x7C /* disk ctrl */ +#define AL_SCH 0x7D /* sel chan */ +#define AL_EXT 0x7E /* OS extension */ +#define AL_BUF 0x80 /* buffer start */ + +#define Q16_SLT 0 /* list: # slots */ +#define Q16_USD 1 /* # in use */ +#define Q16_TOP 2 /* current top */ +#define Q16_BOT 3 /* next bottom */ +#define Q16_BASE 4 /* base of q */ +#define Q16_SLNT 2 /* slot length */ + +#define Q32_SLT 0 /* list: # slots */ +#define Q32_USD 2 /* # in use */ +#define Q32_TOP 4 /* current top */ +#define Q32_BOT 6 /* next bottom */ +#define Q32_BASE 8 /* base of q */ +#define Q32_SLNT 4 /* slot length */ + +/* CPU event flags */ + +#define EV_MAC 0x01 /* MAC interrupt */ +#define EV_BLK 0x02 /* block I/O in prog */ +#define EV_INT 0x04 /* interrupt pending */ +#define EV_WAIT 0x08 /* wait state pending */ + +/* Block I/O state */ + +struct BlockIO { + uint32 dfl; /* devno, flags */ + t_addr cur; /* current addr */ + t_addr end; /* end addr */ + }; + +#define BL_RD 0x8000 /* block read */ +#define BL_LZ 0x4000 /* skip 0's */ + +/* Instruction decode ROM, for all, 16b, 32b */ + +#define OP_UNDEF 0x0000 /* undefined */ +#define OP_NO 0x0001 /* all: short or fp rr */ +#define OP_RR 0x0002 /* all: reg-reg */ +#define OP_RS 0x0003 /* 16b: reg-storage */ +#define OP_RI1 0x0003 /* 32b: reg-imm 16b */ +#define OP_RX 0x0004 /* all: reg-mem */ +#define OP_RXH 0x0005 /* all: reg-mem, rd HW */ +#define OP_RXF 0x0006 /* 32b: reg-mem, rd FW */ +#define OP_RI2 0x0007 /* 32b: reg-imm 32b */ +#define OP_MASK 0x000F + +#define OP_ID4 0x0010 /* 16b: ID4 */ +#define OP_716 0x0020 /* 16b: 7/16 */ +#define OP_816 0x0040 /* 16b: 8/16 */ +#define OP_816E 0x0080 /* 16b: 8/16E */ + +#define OP_DPF 0x4000 /* all: hwre FP */ +#define OP_PRV 0x8000 /* all: privileged */ + +#define OP_TYPE(x) (decrom[(x)] & OP_MASK) +#define OP_DPFP(x) (decrom[(x)] & OP_DPF) + +/* Device information block */ + +struct interdib { + uint32 dno; /* device number */ + int32 sch; /* sch */ + uint32 irq; /* interrupt */ + uint8 *tplte; /* template */ + uint32 (*iot)(uint32 d, uint32 o, uint32 dat); + void (*ini)(t_bool f); }; + +typedef struct interdib DIB; + +#define TPL_END 0xFF /* template end */ + +/* Device select return codes */ + +#define BY 0 /* 8b only */ +#define HW 1 /* 8b/16b */ + +/* I/O operations */ + +#define IO_ADR 0x0 /* address select */ +#define IO_RD 0x1 /* read byte */ +#define IO_RH 0x2 /* read halfword */ +#define IO_WD 0x3 /* write byte */ +#define IO_WH 0x4 /* write halfword */ +#define IO_OC 0x5 /* output command */ +#define IO_SS 0x6 /* sense status */ + +/* Device command byte */ + +#define CMD_V_INT 6 /* interrupt control */ +#define CMD_M_INT 0x3 +#define CMD_IENB 1 /* enable */ +#define CMD_IDIS 2 /* disable */ +#define CMD_IDSA 3 /* disarm */ +#define CMD_GETINT(x) (((x) >> CMD_V_INT) & CMD_M_INT) + +/* Device status byte */ + +#define STA_BSY 0x8 /* busy */ +#define STA_EX 0x4 /* examine status */ +#define STA_EOM 0x2 /* end of medium */ +#define STA_DU 0x1 /* device unavailable */ + +/* Default device numbers */ + +#define DEV_LOW 0x01 /* lowest intr dev */ +#define DEV_MAX 0xFF /* highest intr dev */ +#define DEVNO (DEV_MAX + 1) /* number of devices */ +#define d_DS 0x01 /* display, switches */ +#define d_TT 0x02 /* teletype */ +#define d_PT 0x03 /* reader */ +#define d_CD 0x04 /* card reader */ +#define d_TTP 0x10 /* PAS as console */ +#define d_PAS 0x10 /* first PAS */ +#define o_PASX 0x01 /* offset to xmt */ +#define d_LPT 0x62 /* line printer */ +#define d_PIC 0x6C /* interval timer */ +#define d_LFC 0x6D /* line freq clk */ +#define d_DPC 0xB6 /* disk controller */ +#define o_DP0 0x10 +#define o_DPF 0x01 /* offset to fixed */ +#define d_FD 0xC1 /* floppy disk */ +#define d_MT 0xC5 /* magtape */ +#define o_MT0 0x10 +#define d_SCH 0xF0 /* selector chan */ +#define d_IDC 0xFB /* MSM disk ctrl */ +#define o_ID0 0x01 + +/* Interrupts + + To make interrupt flags independent of device numbers, each device is + assigned an interrupt flag in one of four interrupt words + + word 0 DMA devices + word 1 programmed I/O devices + word 2-3 PAS devices + + Devices are identified by a level and a bit within a level. Priorities + run low to high in the array, right to left within words +*/ + +#define INTSZ 4 /* interrupt words */ +#define SCH_NUMCH 4 /* #channels */ +#define ID_NUMDR 4 /* # MSM drives */ +#define DP_NUMDR 4 /* # DPC drives */ +#define MT_NUMDR 4 /* # MT drives */ + +/* Word 0, DMA devices */ + +#define i_SCH 0 /* highest priority */ +#define i_IDC (i_SCH + SCH_NUMCH) /* MSM disk ctrl */ +#define i_DPC (i_IDC + ID_NUMDR + 1) /* cartridge disk ctrl */ +#define i_MT (i_DPC + DP_NUMDR + 1) /* magtape */ + +#define l_SCH 0 +#define l_IDC 0 +#define l_DPC 0 +#define l_MT 0 + +#define v_SCH (l_SCH * 32) + i_SCH +#define v_IDC (l_IDC * 32) + i_IDC +#define v_DPC (l_DPC * 32) + i_DPC +#define v_MT (l_MT * 32) + i_MT + +/* Word 1, programmed I/O devices */ + +#define i_PIC 0 /* precision clock */ +#define i_LFC 1 /* line clock */ +#define i_FD 2 /* floppy disk */ +#define i_CD 3 /* card reader */ +#define i_LPT 4 /* line printer */ +#define i_PT 5 /* paper tape */ +#define i_TT 6 /* teletype */ +#define i_DS 7 /* display */ +#define i_TTP 10 /* PAS console */ + +#define l_PIC 1 +#define l_LFC 1 +#define l_FD 1 +#define l_CD 1 +#define l_LPT 1 +#define l_PT 1 +#define l_TT 1 +#define l_DS 1 +#define l_TTP 1 + +#define v_PIC (l_PIC * 32) + i_PIC +#define v_LFC (l_LFC * 32) + i_LFC +#define v_FD (l_FD * 32) + i_FD +#define v_CD (l_CD * 32) + i_CD +#define v_LPT (l_LPT * 32) + i_LPT +#define v_PT (l_PT * 32) + i_PT +#define v_TT (l_TT * 32) + i_TT +#define v_DS (l_DS * 32) + i_DS +#define v_TTP (l_TTP * 32) + i_TTP + +/* Word 2-3, PAS devices */ + +#define i_PAS 0 +#define l_PAS 2 +#define v_PAS (l_PAS * 32) + i_PAS +#define v_PASX (v_PAS + 1) /* offset to xmt */ + +/* I/O macros */ + +#define SET_INT(v) int_req[(v) >> 5] = int_req[(v) >> 5] | (1u << ((v) & 0x1F)) +#define CLR_INT(v) int_req[(v) >> 5] = int_req[(v) >> 5] & ~(1u << ((v) & 0x1F)) +#define SET_ENB(v) int_enb[(v) >> 5] = int_enb[(v) >> 5] | (1u << ((v) & 0x1F)) +#define CLR_ENB(v) int_enb[(v) >> 5] = int_enb[(v) >> 5] & ~(1u << ((v) & 0x1F)) + +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ + +/* Device accessible macro */ + +#define DEV_ACC(d) (dev_tab[d] && !sch_blk (d)) + +/* Automatic I/O channel programs, 16b */ + +#define CCB16_CHN -4 /* chain */ +#define CCB16_DEV -2 /* dev no */ +#define CCB16_STS -1 /* status */ +#define CCB16_CCW 0 /* cmd wd */ +#define CCB16_STR 2 /* start */ +#define CCB16_END 4 /* end */ +#define CCB16_IOC 6 /* OC byte */ +#define CCB16_TRM 7 /* term byte */ + +#define CCW16_INIT 0x8000 /* init */ +#define CCW16_NOP 0x4000 /* nop */ +#define CCW16_V_FNC 12 /* function */ +#define CCW16_M_FNC 0x3 +#define CCW16_FNC(x) (((x) >> CCW16_V_FNC) & CCW16_M_FNC) +#define CCW16_RD 0 /* read */ +#define CCW16_WR 1 /* write */ +#define CCW16_DMT 2 /* dec mem */ +#define CCW16_NUL 3 /* null */ +#define CCW16_TRM 0x0400 /* term char */ +#define CCW16_Q 0x0200 /* queue */ +#define CCW16_HI 0x0100 /* queue hi */ +#define CCW16_OC 0x0080 /* OC */ +#define CCW16_CHN 0x0020 /* chain */ +#define CCW16_CON 0x0010 /* continue */ +#define CCW16_V_BPI 0 /* bytes per int */ +#define CCW16_M_BPI 0xF +#define CCW16_BPI(x) (((x) >> CCW16_V_BPI) & CCW16_M_BPI) + +/* Automatic I/O channel programs, 32b */ + +#define CCB32_CCW 0 /* cmd wd */ +#define CCB32_B0C 2 /* buf 0 cnt */ +#define CCB32_B0E 4 /* buf 0 end */ +#define CCB32_CHK 8 /* check word */ +#define CCB32_B1C 10 /* buf 1 cnt */ +#define CCB32_B1E 12 /* buf 1 end */ +#define CCB32_TAB 16 /* trans table */ +#define CCB32_SUB 20 /* subroutine */ + +#define CCW32_V_STA 8 /* status */ +#define CCW32_M_STA 0xFF +#define CCW32_STA(x) (((x) >> CCW32_V_STA) & CCW32_M_STA) +#define CCW32_EXE 0x80 /* execute */ +#define CCW32_CRC 0x10 +#define CCW32_B1 0x08 /* buffer 1 */ +#define CCW32_WR 0x04 /* write */ +#define CCW32_TL 0x02 /* translate */ +#define CCW32_FST 0x01 /* fast mode */ + +/* MAC, 32b */ + +#define P 0 /* physical */ +#define VE 1 /* virtual inst */ +#define VR 2 /* virtual read */ +#define VW 3 /* virtual write */ + +#define MAC_BASE 0x300 /* MAC base */ +#define MAC_STA 0x340 /* MAC status */ +#define MAC_LNT 16 +#define VA_V_OFF 0 /* offset */ +#define VA_M_OFF 0xFFFF +#define VA_GETOFF(x) (((x) >> VA_V_OFF) & VA_M_OFF) +#define VA_V_SEG 16 /* segment */ +#define VA_M_SEG 0xF +#define VA_GETSEG(x) (((x) >> VA_V_SEG) & VA_M_SEG) + +#define SRF_MASK 0x000FFF00 /* base mask */ +#define SRL_MASK 0x0FF00000 /* limit mask */ +#define GET_SRL(x) ((((x) & SRL_MASK) >> 12) + 0x100) +#define SR_EXP 0x80 /* execute prot */ +#define SR_WPI 0x40 /* wr prot int */ +#define SR_WRP 0x20 /* wr prot */ +#define SR_PRS 0x10 /* present */ +#define SR_MASK (SRF_MASK|SRL_MASK|SR_EXP|SR_WPI|SR_WRP|SR_PRS) + +#define MACS_L 0x10 /* limit viol */ +#define MACS_NP 0x08 /* not present */ +#define MACS_WP 0x04 /* write prot */ +#define MACS_WI 0x02 /* write int */ +#define MACS_EX 0x01 /* exec prot */ + +/* Miscellaneous */ + +#define TMR_LFC 0 /* LFC = timer 0 */ +#define TMR_PIC 1 /* PIC = timer 1 */ +#define TMR_PAS 2 /* PAS = timer 2 */ +#define LPT_WIDTH 132 +#define VFU_LNT 132 +#define MIN(x,y) (((x) < (y))? (x): (y)) +#define MAX(x,y) (((x) > (y))? (x): (y)) + +/* Logging */ + +#define LOG_CPU_I 0x0001 /* instructions */ +#define LOG_CPU_C 0x0002 /* context change */ +#define LOG_DP 0x0010 +#define LOG_IDC 0x0020 +#define LOG_MT 0x0040 +#define LOG_FD 0x0080 + +#define DBG_LOG(x) (sim_log && (cpu_log & (x))) + +/* Function prototypes */ + +int32 int_chg (uint32 irq, int32 dat, int32 arm); +int32 io_2b (int32 val, int32 pos, int32 old); +uint32 IOReadB (uint32 loc); +void IOWriteB (uint32 loc, uint32 val); +uint32 ReadF (uint32 loc, uint32 rel); +void WriteF (uint32 loc, uint32 val, uint32 rel); +uint32 IOReadBlk (uint32 loc, uint32 cnt, uint8 *buf); +uint32 IOWriteBlk (uint32 loc, uint32 cnt, uint8 *buf); +void sch_adr (uint32 ch, uint32 dev); +t_bool sch_actv (uint32 sch, uint32 devno); +void sch_stop (uint32 sch); +uint32 sch_wrmem (uint32 sch, uint8 *buf, uint32 cnt); +uint32 sch_rdmem (uint32 sch, uint8 *buf, uint32 cnt); +t_stat set_sch (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat show_sch (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc); diff --git a/Interdata/id_diag.txt b/Interdata/id_diag.txt new file mode 100644 index 00000000..b987cfd6 --- /dev/null +++ b/Interdata/id_diag.txt @@ -0,0 +1,908 @@ +Interdata Diagnostics + +Summary + +816E CPU diagnostic, part 1 passed 16b n/a +816E CPU diagnostic, part 2 partial 16b n/a +Series 16 CPU diagnostic, part 1 passed 16b n/a +16b memory diagnostic, part 1 passed 16b n/a +16b memory diagnostic, part 2 passed 16b n/a +816e extended memory diagnostic passed 16b n/a +Series 16 selector channel diagnostic passed 16b n/a +32b CPU diagnostic, part 1 n/a passed 32b +32b CPU diagnostic, part 2 n/a passed 32b +32b CPU diagnostic, part 3 n/a passed 32b +32b memory diagnostic, part 1 n/a passed 32b +32b memory diagnostic, part 2 n/a passed 32b +32b memory diagnostic, part 3 n/a passed 32b +32b memory diagnostic 6a, part 1 n/a passed 32b +32b memory diagnostic 6a, part 2 n/a passed 32b +32b MAC diagnostic, part 1 n/a passed 32b +32b MAC diagnostic, part 2 n/a passed 32b +Common line printer diagnostic passed 16b passed 32b +Common magtape diagnostic passed 16b passed 32b +Common 2.5/10MB disk diagnostic passed 16b passed 32b +32b MSM disk diagnostic passed 32b +Common floppy disk diagnostic passed 16b passed 32b +Common clock diagnostic passed 16b passed 32b + +Not tested: +- 16b floating point +- 32b double precision floating point +- IDC +- PASLA + +------------------------------------------------------------------- + +Operating Instructions + +816E CPU diagnostic, part 1 + +sim> set cpu 816e +sim> att -e pt0 diag.bin +sim> br c2 +sim> boot pt0 + +Breakpoint: PC: 00C2 (EXBR R8,R6) + +sim> run 100 + +MODEL 8/16E PROCESSOR TEST PART 1 06-211R00 +CPU +* 8D + +ENTER 0 OR 1 +1 +NO ERROR + +CPU +* + +--- +816E CPU diagnostic, part 2 + +sim> set cpu 816e +sim> d tt ttime 1000 ; timing dependency +sim> att -e pt0 diag.bin +sim> br c2 +sim> boot pt0 + +Breakpoint: PC: 00C2 (EXBR R8,R6) + +sim> run 100 + +MODEL 8/16E PROCESSOR TEST PART 2 06-212R00 +CPU +* 8D + +SUBTEST + +* (type subtest number) + +Subtests 0, 1, 2, 5, 7, 8, 9 run correctly +Subtest 3, 4 cannot be run (initialization, power fail) +Subtest 6 cannot be run (hexadecimal display) + +--- +Series 16 CPU diagnostic, part 1 +(Central error routine is at 21F4) + +sim> set cpu 816e +sim> att -e pt0 diag.bin ; diagnostic +sim> br c0 +sim> boot pt0 + +Breakpoint, PC: 00C0 (8800) + +sim> d 234a 0202 ; patch to use +sim> d 234c a4a8 ; TTY as console +sim> d 17a b1e4 +sim> run 100 + +SERIES SIXTEEN PROCESSOR TEST PART 1 06-242F01R00 +CPU +* 2D +ENTER 0 OR 1 +1 + +1234567890 + +NO ERROR + +000A 0000 + +CPU +* + +--- +16b memory diagnostic, part 1 + +sim> att -e pt0 diag.bin ; diagnostic +sim> br c2 +sim> boot pt0 + +Breakpoint, PC: 00C2 (EPSR R7,R6) + +sim> run 100 + +02-340 PART 1 06-162F01R01 + +NO ERRORS + +--- +16b memory diagnostic, part 2 + +sim> att -e pt0 diag.bin ; diagnostic +sim> br c2 +sim> boot pt0 + +Breakpoint, PC: 00C2 (EPSR R7,R6) + +sim> run 1000 + +02-340 PART 2 06-162F02R01 + +NO ERRORS + +--- +816e extended memory diagnostic, parts 1 and 2 + +sim> set cpu 816e +sim> set cpu 256k +sim> att -e pt0 diag.bin ; diagnostic +sim> br b4 +sim> boot pt0 + +Breakpoint, PC: 00B4 (LPSW R0,B8) + +sim> run 1000 + +8/16 E EXTENDED MEMORY TEST PART 1 06-221R00 +NO ERROR +* (CR to repeat part 1) +8/16 E EXTENDED MEMORY TEST PART 1 06-221R00 +NO ERROR +* (LF to go on to part 2) + +Breakpoint, PC: 00B4 (LPSW R0,B8) +sim> run 100 + +8/16 E EXTENDED MEMORY TEST PART 2 06-221R00 +PROGRAM DETECTED MAXIMUM MEMORY 3FFFE +*TEST ; standard tests +*RUN + +SUBTEST 0 NO ERROR +SUBTEST 1 NO ERROR +SUBTEST 2 NO ERROR +SUBTEST 3 NO ERROR +SUBTEST 4 NO ERROR +SUBTEST 6 NO ERROR +SUBTEST 7 NO ERROR +SUBTEST 8 NO ERROR +END OF TEST + +* + +--- +Series 16 selector channel diagnostic + +sim> set cpu 816e +sim> set cpu 256k +sim> att -e pt0 diag.bin ; diagnostic +sim> att mt0 foo.tap ; magtape to test +sim> br c0 +sim> boot pt0 + +Breakpoint, PC: 00C0 (LPSW R0,C8) + +sim> d 2e68 2 ; console is TTY +sim> run A00 + +S16 SELCH TEST 06-222 R01 + +TOP OF MEMORY 3 FFFF +* IODEV1 C5 ; magtape +* DEV1 2 +* RUN ; bank 0 by default +TEST 00 + +NO ERROR + +TEST 01 + +NO ERROR + +TEST 02 + +NO ERROR + +TEST 03 + +NO ERROR + +TEST 04 + +NO ERROR + + +* MEMMOD 1 {2,3} ; repeat for banks 1,2,3 +* RUN +TEST 00 + +NO ERROR + +TEST 01 + +NO ERROR + +TEST 02 + +NO ERROR + +TEST 03 + +NO ERROR + +TEST 04 + +NO ERROR + +* +--- +32b CPU diagnostic, part 1 + +sim> att -e mt0 mmd_r07.tap +sim> d -b 7f 7 ; file 8 on MMD R07 tape +sim> boot mt0 + +S32PT1 06-154 R03 +CPU + +*7X +NO ERROR +000A 0000 +* + +--- +32b CPU diagnostic, part 2 + +sim> set tt 7b ; test is parity sensitive +sim> att -e mt0 mmd_r07.tap +sim> d -b 7f 8 ; file 9 on MMD R07 tape +sim> boot mt0 + + +S32PT2R02 +CPU +* +7X +SUBTEST +* (type subtest number) + +Subtests 1, 3, 4, 5, 9 run correctly +Subtest 2 cannot be run (7/32 with halfword mode only) +Subtest 6 cannot be run (hexadecimal display) +Subtests 7,8 cannot be run (initialization, power fail) + +--- +32b CPU diagnostic, part 3 + +sim> att -e mt0 mmd_r07.tap +sim> d -b 7f 9 ; file 10 on MMD R07 tape +sim> boot mt0 + +S32PT3 R01 +CPU +* +8X ; 7X denotes 7/32 with halfword mode +MAC RESPONSE AT 000300 + +SUBTEST +* + +Subtests 1, 2, 3 run correctly +Subtest 4 cannot be run (parity option) + +--- +32b memory diagnostic, part 1 + +sim> att -e mt0 mmd_r07.tap +sim> d -b 7f 17 ; file 24 on MMD R07 tape +sim> br 2000 +sim> boot mt0 + +Breakpoint, PC: 02000 (B 2060) +sim> d -w 2010 0202 ; console is TTY +sim> c + +S32MT1 06-156F01R04 +MAC PRESENT ? (Y OR N) +* +Y +01 +02 +03 +04 +05 +06 +NO ERROR +* + +--- +32b memory diagnostic, part 2 + +sim> att -e mt0 c:\temp\mmd_r07.tap +sim> d -b 7f 18 ; file 25 on MMD R07 tape +sim> br a00 +sim> boot mt0 + +Breakpoint, PC: 00A00 (B A60) +sim> d -w a10 0202 ; console is TTY +sim> c + +S32MT2 06-156F02R04 +AVAILABLE MEMORY +000000 - 0FFFFF +SUBTEST * +0 ; all standard tests +01 +TEST STILL RUNNING ; repeated multiple times +: +NO ERROR +02 +TEST STILL RUNNING ; repeated multiple times +: +NO ERROR +03 +TEST STILL RUNNING ; repeated multiple times +: +NO ERROR +04 +TEST STILL RUNNING ; repeated multiple times +: +NO ERROR +05 +TEST STILL RUNNING ; repeated multiple times +: +NO ERROR +06 +TEST STILL RUNNING ; repeated multiple times +: +NO ERROR +07 +TEST STILL RUNNING ; repeated multiple times +: +NO ERROR +SUBTEST * + +--- +32b memory diagnostic, part 3 + +sim> att -e mt0 c:\temp\mmd_r07.tap +sim> d -b 7f 19 ; file 26 on MMD R07 tape +sim> br a00 +sim> boot mt0 + +Breakpoint, PC: 00A00 (B A60) +sim> d -w a10 0202 ; console is TTY + +sim> c +S32MT3 06-156F03R04 +AVAILABLE MEMORY +000000 - 0FFFFF +* + +TEST STILL RUNNING ; repeated multiple times +: +NO ERROR +* + +--- +32b memory diagnostic, 6a, part 1 + +sim> att -e mt0 c:\temp\mmd_r07.tap +sim> d -b 7f 15 ; file 22 on MMD R07 tape +sim> boot mt0 + +32 BIT S6A MEMORY TEST 06-157F01R01 +AVAILABLE MEMORY +0000-3FFF + +MAC ADDRESS = 300 +TYPE= 3 ; any value, 0-4 +SUBTEST +* 0 +01 +NO ERROR +02 +NO ERROR +03 +NO ERROR +04 +NO ERROR +05 +NO ERROR +06 +NO ERROR +07 +NO ERROR +08 +NO ERROR + +SUBTEST +* + +--- +32b memory diagnostic, 6a, part 2 + +sim> att -e mt0 c:\temp\mmd_r07.tap +sim> d -b 7f 16 ; file 23 on MMD R07 tape +sim> boot mt0 + +32 BIT S6A MEMORY TEST 06-157F02R01 +AVAILABLE MEMORY +0000f-FFFFF + +TYPE= 2 ; any value, 0-4 +SUBTEST +* 0 +01 +NO ERROR +02 +NO ERROR +03 +NO ERROR +04 +NO ERROR +05 +NO ERROR +06 +NO ERROR +07 +NO ERROR +08 +NO ERROR + +SUBTEST +* + +--- +32b MAC diagnostic, part 1 + +sim> att -e mt0 c:\temp\mmd_r07.tap +sim> d -b 7f 24 ; file 37 on MMD R07 tape +sim> boot mt0 + +MACT 06-160F01R03 +AVAILABLE MEMORY +00000- FFFFF + +* RUN +TEST 00 NO ERROR +TEST 01 NO ERROR +TEST 02 NO ERROR +TEST 03 NO ERROR +TEST 04 NO ERROR +TEST 05 NO ERROR +TEST 06 NO ERROR +TEST 07 NO ERROR +TEST 08 NO ERROR +TEST 09 NO ERROR +TEST 0B NO ERROR +* + +--- +sim> att -e mt0 c:\temp\mmd_r07.tap +sim> d -b 7f 25 ; file 38 on MMD R07 tape +sim> br ffd0 ; start != load point +sim> boot mt0 + +Breakpoint, PC: 0FFD0 (B 1093E) + +sim> run 10010 + +MACT 06-160F02R03 + +* RUN +TEST 00 NO ERROR +TEST 01 NO ERROR +TEST 02 NO ERROR +TEST 03 NO ERROR +TEST 04 NO ERROR +TEST 05 NO ERROR +TEST 06 NO ERROR +TEST 07 NO ERROR +TEST 08 NO ERROR +* + +--- +Common line printer diagnostic + +sim> att -e pt0 diag.bin +sim> br c2 +sim> boot pt0 + +Breakpoint: PC: 00C2 (EXBR R8,R6) + +sim> run a00 ; 32b +sim> run a04 ; 16b + +COMMON LINE PRINTER TEST 06-170R02 + +*TEST 0,1,2,3 +*RUN + +TEST 00 +NO ERROR +TEST 01 +NO ERROR +TEST 02 +NO ERROR +TEST 03 +NO ERROR +END OF TEST + +*INTRPT 1 +*RUN + +TEST 00 +NO ERROR +TEST 01 +NO ERROR +TEST 02 +NO ERROR +TEST 03 +NO ERROR +END OF TEST + +* + +--- +Common magtape diagnostic + +sim> set mt dev=85 ; 800 bpi default +sim> att -e pt0 diag.bin +sim> br c4 +sim> boot pt0 + +Breakpoint, PC: 00C4 (EXBR R8,R6) + +sim> run a00 ; 32b +sim> run a04 ; 16b + +COMMON MAGNETIC TAPE TEST PROGRAM 06-172R02 + +*TEST 0,1,2,3,4,5 +*MODE 0 ; prog i/o and selch +*RUN + +*MODE 0 +*RUN + +TEST 00 +NO ERROR +TEST 01 +NO ERROR +TEST 02 +NO ERROR +TEST 03 +NO ERROR +TEST 04 +NO ERROR +TEST 05 +NO ERROR +END OF TEST + +* + +--- +Common 2.5/10MB disk diagnostic + +sim> att -e pt0 diag.bin +sim> br c2 +sim> boot pt0 + +Breakpoint, PC: 00C2 (EXBR R8,R6) + +sim> set dp0 5440 +sim> set dp1 5440 +sim> att dp0 test0.dsk +sim> att dp1 test1.dsk +sim> run a00 ; 32b +sim> run a04 ; 16b + +COMMON DISC TEST 06-173R01F01 + +*FILE 2 ; FILE 1 to test fixed platter +*LOCYL 0 +*HICYL 197 +*TIMCON 1C0 +*TEST 0,1,2,3,4,6,7,8,9,A,C ; test 5 requires format capability + ; test B requires manual intervention +*RUN + +TEST 00 +NO ERROR +TEST 01 +NO ERROR +TEST 02 +NO ERROR +TEST 03 +NO ERROR +TEST 04 +NO ERROR +TEST 06 +NO ERROR +TEST 07 +NO ERROR +TEST 08 +NO ERROR +TEST 09 +NO ERROR +TEST 0A +NO ERROR +TEST 0C +NO ERROR +END OF TEST + +* + +--- +32b MSM disk diagnostic + +sim> att -e mt0 c:\temp\mmd_r07.tap +sim> d -b 7f 45 ; file 70 on MMD R07 tape +sim> br a00 +sim> boot mt0 + +Breakpoint, PC: 00A00 (B A5E) + +sim> d -w a10 0101 ; patch for TTY console +sim> att dm0 foo.dsk +sim> att dm1 foo1.dsk +sim> c + +MSM DISC TEST 06-200F02R04 (32-BIT) + +*LOCYL 0 +*HICYL 336 ; tests 8,9,A will run a very long + ; time, use 40 to shorten test +*DRIVE 0 +*PACTYP 0 +*TIMVAL 14D +*XFILE 1 +*TEST 0,1,2,3,4,6,7,8,9,A,C ; test 5 requires format capability + ; test B requires manual intervention +*RUN + +TEST 00 +TEST 01 +TEST 02 +TEST 03 +TEST 04 +TEST 06 +TEST 07 +TEST 08 +TEST 09 +TEST 0A +TEST 0C + +--- +Common floppy disk diagnostic + +sim> att -e pt0 diag.bin +sim> att fd0 foo0.flp +sim> att fd1 foo1.flp +sim> br b8 +sim> boot pt0 + +Breakpoint, PC: 000B8 (BS B2) + +sim> d 2a72 bal r15,320a ; patch for multidrive test +sim> run a00 ; 32b +sim> run a04 ; 16b + +COMMON FLOPPY DISC TEST 06-198R00 +UNPROTECT DISKETTE + +*DRIVE AB +*RUN + +DRIVE A UNDER TEST +TEST 00 +NO ERROR +TEST 01 +NO ERROR +TEST 02 +NO ERROR +TEST 03 +NO ERROR +TEST 04 +NO ERROR +TEST 05 +NO ERROR +TEST 06 +NO ERROR +TEST 07 +NO ERROR +DRIVE B UNDER TEST +TEST 00 +NO ERROR +TEST 01 +NO ERROR +TEST 02 +NO ERROR +TEST 03 +NO ERROR +TEST 04 +NO ERROR +TEST 05 +NO ERROR +TEST 06 +NO ERROR +TEST 07 +NO ERROR +END OF TEST + +*TEST 9 ; test 8 requires formatting +*RUN + +TEST 09 +NO ERROR +END OF TEST + +* + +--- +Common clock diagnostic + +sim> att -e pt0 diag.bin +sim> br c4 +sim> boot pt0 + +Breakpoint, PC: 00C4 (EXBR R8,R6) + +sim> d -w e28 4300 ; R09 patches +sim> d -w e2a 10f4 +sim> id -w 10f4:110a +10f4: 4840 +10f6: 188a +10f8: 4850 +10fa: 188c +10fc: de40 +10fe: 1eaf +1100: de50 +1102: 1eaf +1104: 4810 +1106: 0a24 +1108: 4300 +1110: 0e2c +sim> d 1b9c bs 1ba6 +sim> d -w 1102 1eaf + +sim> run a00 ; 32b +sim> run a04 ; 16b + +COMMON UNIVERSAL CLOCK MODULE TEST 06-133R05 + +*TIMVAL 1A4 ; simulator is a fast CPU +*RUN + +TEST 00 +NO ERROR +TEST 01 +NO ERROR +TEST 02 +NO ERROR +TEST 03 +NO ERROR +TEST 04 +NO ERROR +TEST 05 +NO ERROR +TEST 06 +NO ERROR +TEST 07 +NO ERROR +END OF TEST + +* + +------------------------------------------------------------------- +Bugs found + +1. CPU16: instruction decoding interpreting CPU models incorrectly +2. CPU16: SINT should not be conditional on device existing +3. CPU16: immediate interrupts do not do a PSW swap, new PC is block+6 +4. CPU16: SLA, SLHA setting C incorrectly +5. CPU16: diagnostic requires 816E extended memory to run +6. CPU16: CCW16_OC defined incorrectly +7. CPU16, CPU32: autoload not fetching or outputing OC +8. CPU16, CPU32: block I/O completion is off by 1 +9. CPU16, CPU32: ESPR broken, EPSR rx,rx should copy PSW to rx +10. CPU16, CPU32: PCQ displays in octal instead of hexadecimal +11. CPU16, CPU32: SH and variations overflow calculation wrong +12. CPU16, CPU32: SCH overflow calculation wrong +13. CPU16, CPU32: CH and CLH overflow calculation wrong +14. CPU16, CPU32: CH or'ing into CC's instead of loading +15. CPU16, CPU32: RD, RH, SS, AI store some data on non-existent device +16. CPU16, CPU32: console interrupt not implemented +17. CPU16, CPU32: SRHL(s) setting C incorrectly +18. CPU16, CPU32: WDR, OCR not masking register data to 8b +19. CPU32: WH not masking data to 8b or 16b as required +20. CPU32: 32b register sets ordered incorrectly in memory +21. CPU32: wrong slot length in queue instructions +22. CPU32: display device missing its interrupt declaration +23. CPU32: LPSW(R) must load PC before changing PSW +24. CPU32: SLL setting C incorrectly +25. CPU32: bit instructions use halfword memory access and offsets +26. CPU32: CRC sign-extending rather than zero-extending operands +27. CPU32: SCP incrementing counts before, not after, transfer +28. CPU32: CHVR not implemented +29. CPU32: M(R) algorithm wrong +30. CPU32: M(R) using wrong register as first operand +31. CPU32: memory accesses were fullword rather than halfword aligned +32. CPU32: D(R) overflow calculation incorrect +33. CPU32: on 7/32, exceptions use register set 0, regardless of new PSW +34. CPU32: system queue PSW location misdefined +35. CPU32: autodriver channel not shifting bytes left before use as + translation table index +36. CPU32: MAC, LRA using wrong value for limit test +37. CPU32: LRA using wrong value for segment base +38. CPU32: MAC registers are accessible only if protection is off +39. CPU32: MAC status clears only on write, not read +40. CPU32: MAC write protect abort and interrupts implemented incorrectly +41. CPU32: ex/dep -v test used & instead of && +42. CPU32: fetch tests for MAC abort at end of fetch, not per halfword +43. FP: unpack and pack detecting RR format incorrectly +44. FP: need separate microcode/hardware algorithms for add/sub denormalization +45. FP: multiply and divide have 'early out' detection of overflow/underflow +46. FP: compare less than not setting C +47. FP: fix overflow not setting V +48. FP: fix shift needed to be hex digits not binary digits +49. IO: interrupt evaluation routine never sets an interrupt +50. SELCH: transfer count calculation off by 1 +51. SELCH: device data structure set up incorrectly (reset routine) +52. SELCH: stop clears pending interrupts +53. SELCH: register load algorithm incorrect for 6 byte loads +54. PT, LPT, FD: OR'ing status mask instead of AND'ing +55. PT, TT: SET_INT on status change not conditioned on interrupt armed +56. TT: input char converted to UC incorrectly +57. TT: need SET TT BREAK to run CPU test part 2 +58. LPT: not clearing spacing done +59. MT: WREOF not setting EOF status +60. MT: CMD register pointer to wrong place +61. MT: write record byte count taken from wrong variable +62. MT: overrun processing incorrect for selector channel mode +63. PIC, LFC: write data and overflow detection incorrect +64. PIC, LFC: interpolation algorithm for cic read incorrect +65. PIC, LFC: ric reloaded from output buffer on count overflow +66. PIC, LFC: added diagnostic mode, revised use of count vs timer +67. DP: track increment algorithm incorrect +68. DP,IDC: incorrectly setting overrun for less than full sector reads +69. DP: should interrupt on detach (offline) +70. FD: high water mark not updated on write +71. FD: deleted data not implemented, required for diagnostic +72. FD: header CRC not implemented, required for diagnostic +73. FD: function code not stored for service routine +74. FD: LRN to track and sector conversions incorrect +75. FD: reset status incorrect (should be not busy, LRN = 1) +76. FD: extended status track 0 calculation wrong +77. FD: reset does not clear interrupts, requires delay +78. FD: read/write sequencing incorrect +79. FD: command without write data uses implicit LRN +80. FD: extended status is per drive not per controller +81. FD: command start clears only extended status bytes 0,1 +82. FD: IDLE sets after BUSY drops and generates a separate interrupt +83. SYS16, SYS32: WH mistyped as WD in symbol table +84. SYS32: MHR, DHR misdefined +85. PAS: busy set instead of cleared initially +86. IDC: busy set instead of cleared initially +87. IDC, DP: busy not cleared at transfer command complete +88. IDC: busy is not cleared at drive command complete +89. IDC: for MSM compatibility, must absorb WH of head/cylinder +90. IDC: drive command 0x30 is an instant NOP +91. IDC: set cylinder with invalid cylinder sets SKI +92. IDC: read with invalid head sets ACF, not DTE + diff --git a/Interdata/id_doc.txt b/Interdata/id_doc.txt new file mode 100644 index 00000000..c566fc5b --- /dev/null +++ b/Interdata/id_doc.txt @@ -0,0 +1,960 @@ +To: Users +From: Bob Supnik +Subj: Interdata 16b/32b Simulator Usage +Date: 15-Jan-2003 + + COPYRIGHT NOTICE + +The following copyright notice applies to both the SIMH source and binary: + + Original code published in 1993-2002, written by Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + +This memorandum documents the Interdata 16b and 32b simulators. + + +1. Simulator Files + +sim/ sim_defs.h + sim_rev.h + sim_sock.h + sim_tmxr.h + scp.c + scp_tty.c + sim_sock.c + sim_tmxr.c + +sim/interdata/ id_defs.h + id16_cpu.c [or id32_cpu.c] + id16_dboot.c [or id32_dboot.c] + id_dp.c + id_fd.c + id_fp.c + id_idc.c + id_io.c + id_lp.c + id_mt.c + id_pas.c + id_pt.c + id_tt.c + id_ttp.c + id_uvc.c + id16_sys.c [or id32_sys.c] + +2. Interdata Features + +The Interdata simulator includes simulators for a variety of 16b (I3, I4, +I5, 70, 80, 7/16, 8/16, 8/16E) and 32b (7/32, 8/32) models. This is by +no means a complete sampling of all the variations in the Interdata/Perkin- +Elmer family. The 32b family included options for special communications +instructions (7/32C, 8/32C), as well as a later extension for virtual +memory (3200 series). + +The Interdata simulator is configured as follows: + +device simulates +name(s) + +CPU - 16b Interdata 3, 4, 5, 70, 80, 7/16, or 8/16 CPU with 64KB memory + Interdata 8/16E CPU with 256KB memory +CPU - 32b Interdata 7/32 or 8/32 CPU with 1MB memory +SELCH selector channel (1-4) +PT paper tape reader/punch +TT console terminal, Teletype interface +TTP console terminal, PASLA interface +LFC line frequency clock +PIC programmable interval clock +LPT line printer +FD floppy disk +DP 2.5MB/10MB cartridge disk +DM mass storage module (MSM)/intelligent (IDC) disk controller +MT magnetic tape +PAS programmable asynchronous line controller +PASL programmable asyhchronous lines, up to 32 + +The Interdata simulator implements two unique stop conditions: + + - decode of an undefined instruction, and STOP_INST is set + - runaway carriage control tape in the line printer. + +The LOAD command is used to load a carriage control tape for the line +printer. The DUMP command is used to dump a contiguous portion of +memory as a self-loading bootstrap paper tape. The syntax for the DUMP +command is: + + DUMP lowaddr-highaddr + +The low address must be greater than or equal to X'D0'. + +Devices are assigned their default device numbers, as documented in the +Interdata literature. Device numbers can be changed by the command: + + SET DEVNO=num + +Device number conflicts are not checked until simulation starts. If +there is a device number conflict, simulation stops immediately with +an error message. + +Selector channel devices are assigned by default to selector channel 0. +Selector channel assignments can be changed by the command: + + SET SELCH=num + +Selector channel assignments cannot introduce conflicts. + +Most devices can be disabled and enabled, with the commands: + + SET DISABLED + SET ENABLED + +All devices are enabled by default. + +2.1 CPU (16b) + +The CPU options include memory size and CPU type: + + SET CPU I3 Interdata 3 (base instruction set) + SET CPU I4 Interdata 4 (base plus single precision + floating point) + SET CPU 716 Interdata 7/16 (extended instruction set) + (equivalent to Models 5, 70, and 80) + SET CPU 816 Interdata 8/16 (extended plus double + precision floating point) + SET CPU 816E Interdata 8/16E (extended plus double + precision plus expanded memory) + SET CPU 8K set memory size = 8KB + SET CPU 16K set memory size = 16KB + SET CPU 24K set memory size = 24KB + SET CPU 32K set memory size = 32KB + SET CPU 48K set memory size = 48KB + SET CPU 64K set memory size = 64KB + SET CPU 128K set memory size = 128KB (8/16E only) + SET CPU 256K set memory size = 256KB (8/16E only) + SET CPU CONSINT assert console interrupt (7/16, 8/16, + and 8/16E only) + +If memory size is being reduced, and the memory being truncated contains +non-zero data, the simulator asks for confirmation. Data in the truncated +portion of memory is lost. Initial memory size is 64KB. + +These switches are recognized when examining or depositing in CPU memory +(or any other byte oriented device): + + -b examine/deposit bytes + -w examine/deposit halfwords (CPU default) + -f examine/deposit fullwords + -d data radix is decimal + -o data radix is octal + -h data radix is hexadecimal + -v interpret address as virtual + +CPU registers include the visible state of the processor as well as the +control registers for the interrupt system. + + name size comments + + PC 16 program counter + R0..R15 16 general registers + FR0..F14 32 single precision floating point registers + D0H..D14H 32 double precision floating point registers, + high order + D0L..D14L 32 double precision floating point registers, + low order + PSW 16 processor status word + CC 4 condition codes, PSW<12:15> + SR 16 switch register + DR 32 display register low 16 bits + DRX 8 display register extension (x/16 only) + DRMOD 1 display mode + DRPOS 2 display pointer position + SRPOS 1 switch pointer position + IRQ[0:3] 32 interrupt requests + IEN[0:3] 32 interrupt enables + STOP_INST 1 stop on undefined instruction + STOP_WAIT 1 stop if wait state and no I/O events pending + PCQ[0:63] 16 PC prior to last branch or interrupt; + most recent PC change first + WRU 8 interrupt character + +2.2 CPU (32b) + +The CPU options include memory size and CPU type: + + SET CPU 732 Interdata 7/32, single precision floating point + SET CPU DPFP Interdata 7/32, double precision floating point + SET CPU 832 Interdata 8/32 (double precision floating point) + SET CPU 64K set memory size = 64KB + SET CPU 128K set memory size = 128KB + SET CPU 256K set memory size = 256KB + SET CPU 512K set memory size = 512KB + SET CPU 1M set memory size = 1024KB + SET CPU CONSINT assert console interrupt + +If memory size is being reduced, and the memory being truncated contains +non-zero data, the simulator asks for confirmation. Data in the truncated +portion of memory is lost. Initial memory size is 1024KB. + +These switches are recognized when examining or depositing in CPU memory +(or any other byte oriented device): + + -b examine/deposit bytes + -w examine/deposit halfwords + -f examine/deposit fullwords (CPU default) + -d data radix is decimal + -o data radix is octal + -h data radix is hexadecimal + -v interpret address as virtual + +CPU registers include the visible state of the processor as well as the +control registers for the interrupt system. + + name size comments + + PC 20 program counter + R0..R15 32 active general register set + GREG[32] 32 general register sets, 16 x 2 + FR0..FR14 32 single precision floating point registers + if double precision floating point; for + microcoded floating point, floating point + registers are kept in memory locations 00 - 1F + D0H..D14H 32 double precision floating point registers, + high order + D0L..D14L 32 double precision floating point registers, + low order + PSW 16 processor status word + CC 4 condition codes, PSW<12:15> + SR 16 switch register + DR 32 display register low 16 bits + DRX 8 display register extension (x/16 only) + DRMOD 1 display mode + DRPOS 2 display pointer position + SRPOS 1 switch pointer position + MACREG[0:15] 32 memory access controller segment registers + MACSTA 5 memory access controller interrupt status + IRQ[0:3] 32 interrupt requests + IEN[0:3] 32 interrupt enables + STOP_INST 1 stop on undefined instruction + STOP_WAIT 1 stop if wait state and no I/O events pending + PCQ[0:63] 20 PC prior to last branch or interrupt; + most recent PC change first + WRU 8 interrupt character + +2.3 Selector Channel (SELCH) + +An Interdata system can have 1 to 4 selector channels (SELCH0, SELCH1, +SELCH2, SELCH3). The default number of channels is 2. The number of +channels can be changed with the command: + + SET SELCH CHANNELS=num + +The selector channels implement these registers: + + name size comments + + SA[0:3] 20 start address, channels 0 to 3 + EA[0:3] 20 end address, channels 0 to 3 + CMD[0:3] 8 command, channels 0 to 3 + DEV[0:3] 8 active device, channels 0 to 3 + RDP[0:3] 2 read byte pointer, channels 0 to 3 + WDC[0:3] 3 write data counter, channels 0 to 3 + IREQ 4 interrupt requests; right to left, + channels 0 to 3 + IENB 4 interrupt enables + +2.4 Programmed I/O Devices + +2.4.1 Paper Tape Reader/Punch (PT) + +The paper tape reader and punch (PT units 0 and 1) read data from or +write data to disk files. The RPOS and PPOS registers specify the +number of the next data item to be read and written, respectively. +Thus, by changing RPOS or PPOS, the user can backspace or advance +these devices. + +The paper tape reader supports the BOOT command. BOOT PTR copies the +so-called '50 loader' into memory and starts it running. + +The paper tape controller implements these registers: + + name size comments + + RBUF 8 reader buffer + RPOS 32 reader position in the input file + RTIME 24 time from reader start to interrupt + RSTOP_IOE 1 reader stop on I/O error + PBUF 8 punch buffer + PPOS 32 punch position in the output file + PTIME 24 time from punch start to interrupt + PSTOP_IOE 1 punch stop on I/O error + IREQ 1 paper tape interrupt request + IENB 1 paper tape interrupt enable + IARM 1 paper tape interrupt armed + RD 1 paper tape read/write mode + RUN 1 paper tape running + SLEW 1 paper tape reader slew mode + EOF 1 paper tape reader end of file + +Error handling is as follows: + + type error STOP_IOE processed as + + in,out not attached 1 report error and stop + 0 out of tape + + in end of file 1 report error and stop + 0 out of tape + + in,out OS I/O error x report error and stop + +2.4.2 Console, Teletype Interface (TT) + +The Teletype keyboard (TT0) reads from the console keyboard; the +Teletype printer (TT1) writes to the simulator console window. +The Teletype units (TT0, TT1) can be set to one of three modes: +KSR, 7B, or 8B. In KSR mode, lower case input and output characters +are automatically converted to upper case, and the high order bit is +forced to one on input. In 7B mode, input and output characters are +masked to 7 bits. In 8B mode, characters are not modified. Changing +the mode of either unit changes both. The default mode is KSR. + +The Teletype has a BREAK key, which is not present on today's +keyboards. To simulate pressing the break key, stop the simulator +and use the command: + + SET TT BREAK + +Break status will be asserted, and will remain asserted for the +interval specified by KTIME. + +The Teletype interface implements these registers: + + name size comments + + KBUF 8 input buffer + KPOS 32 number of characters input + KTIME 24 input polling interval + TBUF 8 output buffer + TPOS 32 number of characters output + TTIME 24 time from output start to interrupt + IREQ 1 interrupt request + IENB 1 interrupt enable + IARM 1 interrupt armed + RD 1 read/write mode + FDPX 1 half-duplex + CHP 1 input character pending + +2.4.3 Console, PASLA Interface (TTP) + +Later Interdata system connect the system console via the first +PASLA interface rather than the Teletype interface. The PASLA +console can be simulated with a Telnet session on the first PAS line. +Alternately, the PASLA console can be attached to the simulator +console window, using the TTP device in place of TT. + +To switch the simulator console window to TTP, use the command: + + SET TTP ENABLED or + SET TT DISABLED + +Device TT is automatically disabled and device TTP is enabled. +To switch the simulator console window back to TT, use the command: + + SET TT ENABLED or + SET TTP DISABLED + +Device TTP is automatically disabled and device TT is enabled. +If TTP is enabled at its default device settings, the base address +for the PAS multiplexor must be changed: + + SET PAS DEVNO=12 + +Otherwise, a device number conflict occurs. + +The PASLA keyboard (TTP0) reads from the console keyboard; the +PALSA printer (TTP1) writes to the simulator console window. +The PASLA units (TTP0, TTP1) can be set to one of three modes: +UC, 7B, or 8B. In UC mode, lower case input and output characters +are automatically converted to upper case. In 7B mode, input and +output characters are masked to 7 bits. In 8B mode, characters +are not modified. Changing the mode of either unit changes both. +The default mode is UC. + +To simulate pressing the break key, stop the simulator and use +the command: + + SET TTP BREAK + +Break status will be asserted, and will remain asserted for the +interval specified by KTIME. + +The PASLA console interface implements these registers: + + name size comments + + KBUF 8 input buffer + KPOS 32 number of characters input + KTIME 24 input polling interval + KIREQ 1 input interrupt request + KIENB 1 input interrupt enabled + KARM 1 input interrupt armed + CHP 1 input character pending + TBUF 8 output buffer + TPOS 32 number of characters output + TTIME 24 time from output start to interrupt + TIREQ 1 output interrupt request + TIENB 1 output interrupt enable + TIARM 1 output interrupt armed + +2.4.4 Line Printer (LPT) + +The line printer (LPT) writes data to a disk file. The POS register +specifies the number of the next data item to be written. Thus, +by changing POS, the user can backspace or advance the printer. + +In addition, the line printer can be programmed with a carriage control +tape. The LOAD command loads a new carriage control tape: + + LOAD load carriage control tape file + +The format of a carriage control tape consists of multiple lines. Each +line contains an optional repeat count, enclosed in parentheses, optionally +followed by a series of column numbers separated by commas. Column numbers +must be between 0 and 7; column seven is by convention top of form. The +following are all legal carriage control specifications: + + no punch + (5) 5 lines with no punches + 1,5,7 columns 1, 5, 7 punched + (10)2 10 lines with column 2 punched + 0 column 0 punched + +The default form is 1 line long, with all columns punched. + +The line printer implements these registers: + + name size comments + + BUF 7 last data item processed + BPTR 8 line buffer pointer + LBUF[0:131] 7 line buffer + VFUP 8 vertical forms unit pointer + VFUL 8 vertical forms unit length + VFUT[0:131] 8 vertical forms unit table + IREQ 1 line printer interrupt request + IENB 1 line printer interrupt enable + IARM 1 line printer interrupt armed + POS 32 position in the output file + CTIME 24 character processing time + STIME 24 spacing operation time + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 out of paper + + OS I/O error x report error and stop + +2.4.5 Line Frequency Clock (LFC) + +The line frequency clock (LFC) implements these registers: + + name size comments + + IREQ 1 clock interrupt request + IENB 1 clock interrupt enable + IARM 1 clock interrupt armed + TIME 24 clock frequency + TPS 8 ticks per second (120 or 100) + +The real-time clock autocalibrates; the clock interval is adjusted up or +down so that the clock tracks actual elapsed time. + +2.4.6 Programmable Interval Clock (PIC) + +The programmable interval clock (PIC) implements these registers: + + name size comments + + BUF 16 output buffer + RIC 16 reset interval and rate + CIC 12 current interval + DECR 10 current decrement value + RDP 1 read byte select + OVF 1 interval overflow flag + IREQ 1 clock interrupt request + IENB 1 clock interrupt enable + IARM 1 clock interrupt armed + +If the interval requested is longer than 1 msec, the programmable clock +auto-calibrates; if not, it simply counts instructions. + +2.4.7 Floppy Disk Controller (FD) + +Floppy disk options include the ability to make units write enabled or +write locked. + + SET FDn LOCKED set unit n write locked + SET FDn WRITEENABLED set unit n write enabled + +Units can also be set ONLINE or OFFLINE. + +The floppy disk supports the BOOT command. BOOT FDn copies an autoload +sequence into memory and starts it running. + +The floppy disk controller implements these registers: + + name size comments + + CMD 8 command + STA 8 status + BUF 8 buffer + LRN 16 logical record number + ESTA[0:5] 8 extended status bytes + DBUF[0:127] 8 transfer buffer + DBPTR 8 transfer buffer pointer + IREQ 1 interrupt request + IENB 1 interrupt enabled + IARM 1 interrupt armed + CTIME 24 command response time + STIME 24 seek time, per cylinder + XTIME 24 transfer time, per byte + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 disk not ready + +Floppy disk data is buffered in memory; therefore, end of file and OS +I/O errors cannot occur. + +2.4.8 Programmable Asynchronous Line Adapters (PAS, PASL) + +The Programmable Asynchronous Line Adapters (PAS and PASL) represent, +indistinguishably, individual PASLA interfaces, two lines asynchronous +multiplexors, and 8 line asynchronous multiplexors, with a maximum +of 32 lines. All the lines are modelled as a terminal multiplexor, with +PAS as the multiplexor controller, and PASL as the indivdual lines. The +PASLAs perform input and output through Telnet sessions connected to a +user-specified port. The ATTACH command specifies the port to be used: + + ATTACH PAS set up listening port + +where port is a decimal number between 1 and 65535 that is not being used +for other TCP/IP activities. + +Each line (each unit of PASL) can be set to one of three modes: UC, 7B, +or 8B. In UC mode, lower case input and output characters are converted +automatically to upper case. In 7B mode, input and output characters are +masked to 7 bits. In 8B mode, characters are not modified. The default +mode is UC. Each line (each unit of PASL) can also be set for modem +control with the command SET PASLn DATASET. The defaults are UC mode +and DATASET disabled. + +Once PAS is attached and the simulator is running, the terminals listen +for connections on the specified port. They assume that the incoming +connections are Telnet connections. The connections remain open until +disconnected either by the Telnet client, a SET PAS DISCONNECT command, +or a DETACH PAS command. + +The SHOW PAS CONNECTIONS command displays the current connections to the +extra terminals. The SHOW PAS STATISTICS command displays statistics for +active connections. The SET PAS DISCONNECT=linenumber disconnects the +specified line. + +The controller (PAS) implements these registers: + + name size comments + + STA[0:31] 8 status, lines 0 to 31 + CMD[0:31] 16 command, lines 0 to 31 + RBUF[0:31] 8 receive buffer, lines 0 to 31 + XBUF[0:31] 8 transmit buffer, lines 0 to 31 + RIREQ 32 receive interrupt requests; + right to left, lines 0 to 31 + RIENB 32 receive interrupt enables + RARM[0:31] 1 receive interrupt armed + XIREQ 32 transmit interrupt requests; + right to left, lines 0 to 31 + XIENB 32 transmit interrupt enables + XARM[0:31] 1 transmit interrupt armed + RCHP[0:31] 1 receiver character present, lines 0 to 31 + +The lines (PASL) implements these registers: + + name size comments + + TIME[0:31] 24 transmit time, lines 0 to 31 + +The additional terminals do not support save and restore. All open +connections are lost when the simulator shuts down or PAS is detached. + +2.5 Cartridge Disk Controller (DP) + +Cartridge disk options include the ability to make units write enabled or +write locked, and to select the type of drive: + + SET DPn LOCKED set unit n write locked + SET DPn WRITEENABLED set unit n write enabled + SET DPn 2315 set unit n to 2315 (2.5MB) + SET DPn 5440 set unit n to 5440 (10MB) + +Units can also be set ONLINE or OFFLINE. + +The cartridge disk supports the BOOT command. To boot OS16/32, the hex +form of the operating system file's extension must be placed in locations +7E:7F. The disk bootstrap looks for a valid OS16/32 volume descriptor in +block 0, and uses that to locate the volume directory. It then searches +the directory for a filename of the form OS16xxxx.hhh or OS32xxxx.hhh, +where the xxxx is ignored and hhh is the ASCII form of the extension from +locations 7E:7F. The 32b bootstrap can also boot Wollongong UNIX; locations +7E:7F must be 0. + +All drives have 256 8b bytes per sector. The other disk parameters are: + + drive cylinders surfaces sectors + + 2315 203 2 24 + 5440 408 4 12 + +The cartridge disk controller implements these registers: + + name size comments + + CMD 3 current command + STA 8 controller status + BUF 8 controller buffer + HDSC 8 current head/sector select + CYL 8 current cylinder select + DBUF[0:255] 8 transfer buffer + DBPTR 16 transfer buffer point + DBLNT 16 transfer buffer length + FIRST 1 first DMA service flag + IREQ 5 interrupt requests; right-to-left, + controller, drives 0 to 3 + IENB 5 interrupt enables + IARM[0:3] 1 interrupts armed, drives 0 to 3 + STIME 24 seek latency, per cylinder + RTIME 24 rotational latency, per sector + WTIME 24 inter-word latency + +Error handling is as follows: + + error processed as + + not attached disk not ready + + end of file assume rest of disk is zero + + OS I/O error report error and stop + +2.6 Mass Storage Module/Intelligent Disk Controller (DM) + +MSM/IDC disk controller options include the ability to make units +write enabled or write locked, and to select the type of drive: + + SET DMn LOCKED set unit n write locked + SET DMn WRITEENABLED set unit n write enabled + SET DMn MSM80 set unit n to storage module, 80MB + (67MB formatted) + SET DMn MSM300 set unit n to storage module, 300MB + (262MB formatted) + SET DMn MCCD16 set unit n to medium capacity, 16MB + (13.5MB formatted) + SET DMn MCCD48 set unit n to medium capacity, 48MB + (40.5MB formatted) + SET DMn MCCD80 set unit n to medium capacity, 80MB + (67MB formatted) + SET DMn MSM330F set unit n to storage module, 330MB + (300MB formatted) + +Note that the disk bootstraps can ONLY boot the MSM80 and MSM300. +Units can be set ONLINE or OFFLINE. + +The MSM/IDC controller supports the BOOT command. To boot OS16/32, the hex +form of the operating system file's extension must be placed in locations +7E:7F. The disk bootstrap looks for a valid OS16/32 volume descriptor in +block 0, and uses that to locate the volume directory. It then searches +the directory for a filename of the form OS16xxxx.hhh or OS32xxxx.hhh, +where the xxxx is ignored and hhh is the ASCII form of the extension from +locations 7E:7F. The 32b bootstrap can also boot Wollongong UNIX; locations +7E:7F must be 0. Note that only the MSM80 and MSM300 drives can be boot- +strapped; the boot code does not recognize the other drives. + +All drives have 256 8b bytes per sector. The other disk parameters are: + + drive cylinders surfaces sectors + + MSM80 823 5 64 + MSM300 823 19 64 + MCCD16 823 1 64 + MCCD48 823 3 64 + MCCD80 823 5 64 + MSM300F 1024 16 64 + +The MSM/IDC disk controller implements these registers: + + name size comments + + STA 8 controller status + BUF 8 controller buffer + SEC 8 current sector select + DBUF[0:767] 8 transfer buffer + DBPTR 16 transfer buffer point + DBLNT 16 transfer buffer length + FIRST 1 first DMA service flag + IREQ 5 interrupt requests; right-to-left, + controller, drives 0 to 3 + IENB 5 interrupt enables + SIREQ 5 saved interrupt requests + ICARM 1 controller interrupt armed + IDARM[0:3] 1 drive interrupts armed, drives 0 to 3 + STIME 24 seek latency, per cylinder + RTIME 24 rotational latency, per sector + WTIME 24 inter-word latency + +Error handling is as follows: + + error processed as + + not attached disk not ready + + end of file assume rest of disk is zero + + OS I/O error report error and stop + +2.7 Magnetic Tape Controller (MT) + +Magnetic tape options include the ability to make units write enabled or +or write locked. + + SET MTn LOCKED set unit n write locked + SET MTn WRITEENABLED set unit n write enabled + +Units can also be set ONLINE or OFFLINE. + +The magnetic tape supports the BOOT command. BOOT MTn copies an autoload +sequence into memory and starts it running. + +The magnetic tape controller implements these registers: + + name size comments + + CMD 8 command + STA 8 status + BUF 8 buffer + DBUF[0:65535] 8 transfer buffer + DBPTR 16 transfer buffer pointer + DBLNT 16 transfer buffer length + XFR 1 transfer in progress flag + FIRST 1 first DMA service flag + IREQ 4 interrupt requests; right to left, + drives 0 to 3 + IENB 4 interrupt enables + IARM[0:3] 1 interrupts armed, drives 0 to 3 + STOP_IOE 1 stop on I/O error + WTIME 1 word transfer time + RTIME 1 interrecord latency + UST[0:3] 8 unit status, drives 0 to 3 + POS[0:3] 32 tape position, drives 0 to 3 + +Error handling is as follows: + + error processed as + + not attached tape not ready; if STOP_IOE, stop + + end of file set error flag + + OS I/O error set error flag; if STOP_IOE, stop + +2.8 Symbolic Display and Input + +The Interdata simulator implements symbolic display and input. Display is +controlled by command line switches: + + -a display as ASCII character + -c display as two character string + -m display instruction mnemonics + +Input parsing is controlled by the first character typed in or by command +line switches: + + ' or -a ASCII character + " or -c two character sixbit string + alphabetic instruction mnemonic + numeric octal number + +2.7.1 16b Instruction Input + +Instruction input uses standard Interdata assembler syntax. There are +seven instruction classes: short branch, extended short branch, short +immediate, register, register-register, memory, and register-memory. + +Short branch instructions have the format + + sbop mask,address + +where the mask is a hex (decimal) number between 0 and F (15), and +the address is within +32 (forward branch) or -32 (backward branch) +of the current location. + +Extended short branch instructions have the format + + sbxop address + +where the address is within +32 or -32 of the current location. For +extended short branches, the simulator chooses the forward or backward +direction automatically. + +Short immediate instructions have the format + + siop regnum,immed + +where the register number is a hex (decimal) number, optionally +preceded by R, between 0 and F (15), and the immediate is a hex digit +between 0 and F. + +Register instructions have the format + + rop regnum + +where the register number is a hex (decimal) number, optionally +preceded by R, between 0 and F (15). + +Register-register instructions have the format + + rrop regnum,regnum + +where the register numbers are hex (decimal) numbers, optionally +preceded by R, between 0 and F (15). + +Memory instructions have the format + + mop address{(index)} + +where address is a hex number between 0 and 0xFFFF, and the index +register is a hex (decimal) number, optionally preceded by R, +between 1 and F (15). + +Register-memory instructions have the format + + rmop regnum,address{(index)} + +where the register number is a hex (decimal) number, optionally +preceded by R, between 0 and F (15), the address is a hex number +between 0 and 0xFFFF, and the index register is a hex (decimal) +number, optionally preceded by R, between 1 and F (15). + +2.7.2 32b Instruction Input + +Instruction input uses standard Interdata assembler syntax. There are +nine instruction classes: short branch, extended short branch, short +immediate, 16b immediate, 32b immediate, register, register-register, +memory, and register-memory. + +Short branch instructions have the format + + sbop mask,address + +where the mask is a hex (decimal) number between 0 and F (15), and +the address is within +32 (forward branch) or -32 (backward branch) +of the current location. + +Extended short branch instructions have the format + + sbxop address + +where the address is within +32 or -32 of the current location. For +extended short branches, the simulator chooses the forward or backward +direction automatically. + +Short immediate instructions have the format + + siop regnum,immed + +where the register number is a hex (decimal) number, optionally +preceded by R, between 0 and F (15), and the immediate is a hex digit +between 0 and F. + +16b immediate instructins have the format + + i16op regnum,immed16{(index)} + +where the register number is a hex (decimal) number, optionally +preceded by R, between 0 and F (15), the immediate is a hex number +between 0 and 0xFFFF, and the index register is a hex (decimal) +number, optionally preceded by R, between 1 and F (15). + +32b immediate instructions have the format + + i32op regnum,immed32{(index)} + +where the register number is a hex (decimal) number, optionally +preceded by R, between 0 and F (15), the immediate is a hex number +between 0 and 0xFFFFFFFF, and the index register is a hex (decimal) +number, optionally preceded by R, between 1 and F (15). + +Register instructions have the format + + rop regnum + +where the register number is a hex (decimal) number, optionally +preceded by R, between 0 and F (15). + +Register-register instructions have the format + + rrop regnum,regnum + +where the register numbers are hex (decimal) numbers, optionally +preceded by R, between 0 and F (15). + +Memory instructions have the format + + mop address{(index)} or + mop address{(index1,index2)} + +where address is a hex number between 0 and 0xFFFF, and the index +registers are hex (decimal) numbers, optionally preceded by R, +between 1 and F (15). + +Register-memory instructions have the format + + rmop regnum,address{(index)} or + rmop regnum,address{(index1,index2)} + +where the register number is a hex (decimal) number, optionally +preceded by R, between 0 and F (15), the address is a hex number +between 0 and 0xFFFF, and the index registers are hex (decimal) +numbers, optionally preceded by R, between 1 and F (15). + +For memory operands, the simulator automatically chooses the format +(RX1, RX2, RX3) that consumes the fewest bytes. If both RX1 and RX2 +are feasible, the simulator chooses RX1. + diff --git a/Interdata/id_dp.c b/Interdata/id_dp.c new file mode 100644 index 00000000..3b55ecbb --- /dev/null +++ b/Interdata/id_dp.c @@ -0,0 +1,547 @@ +/* id_dp.c: Interdata 2.5MB/10MB cartridge disk simulator + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + dp M46-421 2.5MB/10MB cartridge disk +*/ + +#include "id_defs.h" +#include + +#define DP_NUMBY 256 /* bytes/sector */ +#define DP_NUMSC 24 /* sectors/track */ + +#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ +#define UNIT_M_DTYPE 0x1 +#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */ +#define UNIT_WLK (1 << UNIT_V_WLK) +#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) +#define UNIT_AUTO (1 << UNIT_V_AUTO) +#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) + +#define CYL u3 /* current cylinder */ +#define STD u4 /* drive status */ +#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ + +/* Controller status */ + +#define STC_OVR 0x80 /* overrun */ +#define STC_ACF 0x40 /* addr cmp fail */ +#define STC_DEF 0x20 /* def track NI */ +#define STC_CYO 0x10 /* cylinder ovflo */ +#define STC_IDL 0x02 /* ctrl idle */ +#define STC_DTE 0x01 /* xfer error */ +#define SETC_EX (STC_OVR|STC_ACF|STC_DEF|STC_CYO) +#define STC_MASK (STC_OVR|STC_ACF|STC_DEF|STC_CYO|STA_BSY|STC_IDL|STC_DTE) + +/* Controller command */ + +#define CMC_MASK 0xF +#define CMC_CLR 0x8 /* reset */ +#define CMC_RD 0x1 /* read */ +#define CMC_WR 0x2 /* write */ +#define CMC_RCHK 0x3 /* read check */ +#define CMC_RFMT 0x5 /* read fmt NI */ +#define CMC_WFMT 0x6 /* write fmt NI */ + +/* Drive status, ^ = dynamic, * = in unit status */ + +#define STD_WRP 0x80 /* ^write prot */ +#define STD_WCK 0x40 /* write check NI */ +#define STD_ILA 0x20 /* *illegal addr */ +#define STD_ILK 0x10 /* ^addr interlock */ +#define STD_MOV 0x08 /* *heads in motion */ +#define STD_INC 0x02 /* seek incomplete NI */ +#define STD_NRDY 0x01 /* ^not ready */ +#define STD_UST (STD_ILA | STD_MOV) /* set from unit */ +#define SETD_EX (STD_WCK | STD_ILA | STD_ILK) /* set examine */ + +/* Drive command */ + +#define CMD_SK 0x02 /* seek */ +#define CMD_RST 0x01 /* restore */ + +/* Head/sector register */ + +#define HS_SMASK 0x1F /* sector mask */ +#define HS_V_SRF 5 /* surface */ +#define HS_HMASK 0x20 /* head mask */ +#define HS_MASK (HS_HMASK | HS_SMASK) +#define GET_SEC(x) ((x) & HS_SMASK) +#define GET_SRF(x) (((x) & HS_HMASK) >> HS_V_SRF) + +#define GET_SA(p,cy,sf,sc,t) (((((((p)*drv_tab[t].cyl)+(cy))*drv_tab[t].surf)+(sf))* \ + DP_NUMSC)+(sc)) +#define GET_ROTATE(x) ((int) fmod (sim_gtime() / ((double) (x)), \ + ((double) DP_NUMSC))) + +/* This controller supports two different disk drive types: + + type #sectors/ #surfaces/ #cylinders/ + surface cylinder drive + + 2315 24 2 203 + 5440 24 4 408 + + In theory, each drive can be a different type. The size field in + each unit selects the drive capacity for each drive and thus the + drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE AND MUST HAVE + THE SAME SECTORS/TRACK. +*/ + +#define TYPE_2315 0 +#define CYL_2315 203 +#define SURF_2315 2 +#define SIZE_2315 (DP_NUMSC * SURF_2315 * CYL_2315 * DP_NUMBY) + +#define TYPE_5440 1 +#define CYL_5440 408 +#define SURF_5440 2 +#define SIZE_5440 (2 * DP_NUMSC * SURF_5440 * CYL_5440 * DP_NUMBY) + +struct drvtyp { + int32 cyl; /* cylinders */ + uint32 surf; /* surfaces */ + uint32 size; /* #blocks */ +}; + +static struct drvtyp drv_tab[] = { + { CYL_2315, SURF_2315, SIZE_2315 }, + { CYL_5440, SURF_5440, SIZE_5440 }, + { 0 } }; + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; + +uint8 dpxb[DP_NUMBY]; /* xfer buffer */ +uint32 dp_bptr = 0; /* buffer ptr */ +uint32 dp_db = 0; /* ctrl buffer */ +uint32 dp_cyl = 0; /* drive buffer */ +uint32 dp_sta = 0; /* ctrl status */ +uint32 dp_cmd = 0; /* ctrl command */ +uint32 dp_plat = 0; /* platter */ +uint32 dp_hdsc = 0; /* head/sector */ +uint32 dp_svun = 0; /* most recent unit */ +uint32 dp_1st = 0; /* first byte */ +uint32 dpd_arm[DP_NUMDR] = { 0 }; /* drives armed */ +int32 dp_stime = 100; /* seek latency */ +int32 dp_rtime = 100; /* rotate latency */ +int32 dp_wtime = 1; /* word time */ +uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */ + +DEVICE dp_dev; +uint32 dp (uint32 dev, uint32 op, uint32 dat); +void dp_ini (t_bool dtpl); +t_stat dp_svc (UNIT *uptr); +t_stat dp_reset (DEVICE *dptr); +t_stat dp_attach (UNIT *uptr, char *cptr); +t_stat dp_detach (UNIT *uptr); +t_stat dp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat dp_rds (UNIT *uptr); +t_stat dp_wds (UNIT *uptr); +t_bool dp_dter (UNIT *uptr, uint32 first); +void dp_done (uint32 flg); + +extern t_stat id_dboot (int32 u, DEVICE *dptr); + +/* DP data structures + + dp_dev DP device descriptor + dp_unit DP unit list + dp_reg DP register list + dp_mod DP modifier list +*/ + +DIB dp_dib = { d_DPC, 0, v_DPC, dp_tplte, &dp, &dp_ini }; + +UNIT dp_unit[] = { + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) } }; + +REG dp_reg[] = { + { HRDATA (CMD, dp_cmd, 3) }, + { HRDATA (STA, dp_sta, 8) }, + { HRDATA (BUF, dp_db, 8) }, + { HRDATA (PLAT, dp_plat, 1) }, + { HRDATA (HDSC, dp_hdsc, 6) }, + { HRDATA (CYL, dp_cyl, 9) }, + { HRDATA (SVUN, dp_svun, 8), REG_HIDDEN }, + { BRDATA (DBUF, dpxb, 16, 8, DP_NUMBY) }, + { HRDATA (DBPTR, dp_bptr, 9), REG_RO }, + { FLDATA (FIRST, dp_1st, 0) }, + { GRDATA (IREQ, int_req[l_DPC], 16, DP_NUMDR + 1, i_DPC) }, + { GRDATA (IENB, int_enb[l_DPC], 16, DP_NUMDR + 1, i_DPC) }, + { BRDATA (IARM, dpd_arm, 16, 1, DP_NUMDR) }, + { DRDATA (RTIME, dp_rtime, 0), PV_LEFT | REG_NZ }, + { DRDATA (STIME, dp_stime, 0), PV_LEFT | REG_NZ }, + { DRDATA (WTIME, dp_wtime, 0), PV_LEFT | REG_NZ }, + { URDATA (UCYL, dp_unit[0].CYL, 16, 9, 0, + DP_NUMDR, REG_RO) }, + { URDATA (UST, dp_unit[0].STD, 16, 8, 0, + DP_NUMDR, REG_RO) }, + { URDATA (CAPAC, dp_unit[0].capac, 10, 31, 0, + DP_NUMDR, PV_LEFT | REG_HRO) }, + { HRDATA (DEVNO, dp_dib.dno, 8), REG_HRO }, + { HRDATA (SELCH, dp_dib.sch, 2), REG_HRO }, + { NULL } }; + +MTAB dp_mod[] = { + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { (UNIT_DTYPE+UNIT_ATT), (TYPE_2315 << UNIT_V_DTYPE) + UNIT_ATT, + "2315", NULL, NULL }, + { (UNIT_DTYPE+UNIT_ATT), (TYPE_5440 << UNIT_V_DTYPE) + UNIT_ATT, + "5440", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_2315 << UNIT_V_DTYPE), + "2315", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_5440 << UNIT_V_DTYPE), + "5440", NULL, NULL }, + { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, + { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, + { (UNIT_AUTO+UNIT_DTYPE), (TYPE_2315 << UNIT_V_DTYPE), + NULL, "2315", &dp_set_size }, + { (UNIT_AUTO+UNIT_DTYPE), (TYPE_5440 << UNIT_V_DTYPE), + NULL, "5440", &dp_set_size }, + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH", + &set_sch, &show_sch, NULL }, + { 0 } }; + +DEVICE dp_dev = { + "DP", dp_unit, dp_reg, dp_mod, + DP_NUMDR, 16, 24, 1, 16, 8, + NULL, NULL, &dp_reset, + &id_dboot, &dp_attach, &dp_detach, + &dp_dib, DEV_DISABLE }; + +/* Controller: IO routine */ + +uint32 dpc (uint32 dev, uint32 op, uint32 dat) +{ +uint32 f, t, u; +UNIT *uptr; +static uint8 good_cmd[8] = { 0, 1, 1, 1, 0, 0, 0, 0 }; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + sch_adr (dp_dib.sch, dev); /* inform sel ch */ + return BY; /* byte only */ +case IO_RD: /* read data */ + if (dp_sta & STC_IDL) /* if idle */ + return GET_ROTATE (dp_rtime); /* return sector */ + else dp_sta = dp_sta | STA_BSY; /* xfr? set busy */ + return dp_db; /* return data */ +case IO_WD: /* write data */ + if (dp_sta & STC_IDL) dp_hdsc = dat & HS_MASK; /* idle? hdsc */ + else { /* data xfer */ + dp_sta = dp_sta | STA_BSY; /* set busy */ + dp_db = dat & 0xFF; } /* store data */ + break; +case IO_SS: /* status */ + t = dp_sta & STC_MASK; /* get status */ + if (t & SETC_EX) t = t | STA_EX; /* test for EX */ + return t; +case IO_OC: /* command */ + f = dat & CMC_MASK; /* get cmd */ + if (f & CMC_CLR) { /* clear? */ + dp_reset (&dp_dev); /* reset world */ + break; } + u = (dp_svun - dp_dib.dno - o_DP0) / o_DP0; /* get unit */ + uptr = dp_dev.units + u; /* ignore if busy */ + if (!(dp_sta & STC_IDL) || sim_is_active (uptr)) break; + dp_cmd = f; /* save cmd */ + if (dp_cmd == CMC_WR) dp_sta = 0; /* write: bsy=0 else */ + else dp_sta = STA_BSY; /* bsy=1,idl,err=0 */ + dp_1st = 1; /* xfr not started */ + dp_bptr = 0; /* buffer empty */ + if (dp_svun & o_DPF) dp_plat = 1; /* upper platter? */ + else dp_plat = 0; /* no, lower */ + if (good_cmd[f]) sim_activate (uptr, dp_rtime); /* legal? sched */ + break; } +return 0; +} + +/* Drives: IO routine */ + +uint32 dp (uint32 dev, uint32 op, uint32 dat) +{ +int32 diff; +uint32 t, u; +UNIT *uptr; + +if (dev == dp_dib.dno) return dpc (dev, op, dat); /* controller? */ +u = (dev - dp_dib.dno - o_DP0) / o_DP0; /* get unit num */ +uptr = dp_dev.units + u; /* get unit ptr */ +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + if (dp_sta & STC_IDL) dp_svun = dev; /* idle? save unit */ + return BY; /* byte only */ +case IO_WD: /* write data */ + if (GET_DTYPE (uptr->flags) == TYPE_2315) /* 2.5MB drive? */ + dp_cyl = dat & 0xFF; /* cyl is 8b */ + else dp_cyl = ((dp_cyl << 8) | dat) & DMASK16; /* insert byte */ + break; +case IO_SS: /* status */ + if (uptr->flags & UNIT_ATT) t = /* onl? */ + ((uptr->flags & UNIT_WPRT)? STD_WRP: 0) | + ((dp_sta & STC_IDL)? 0: STD_ILK) | + (uptr->STD & STD_UST); + else t = STD_MOV | STD_NRDY; /* off = X'09' */ + if (t & SETD_EX) t = t | STA_EX; /* test for ex */ + return t; +case IO_OC: /* command */ + dpd_arm[u] = int_chg (v_DPC + u + 1, dat, dpd_arm[u]); + if (dat & CMD_SK) t = dp_cyl; /* seek? get cyl */ + else if (dat & CMD_RST) t = 0; /* rest? cyl 0 */ + else break; /* no action */ + diff = t - uptr->CYL; + if (diff < 0) diff = -diff; /* ABS cyl diff */ + else if (diff == 0) diff = 1; /* must be nz */ + uptr->STD = STD_MOV; /* stat = moving */ + uptr->CYL = t; /* put on cyl */ + sim_activate (uptr, diff * dp_stime); /* schedule */ + break; } +return 0; +} + +/* Unit service + + If seek done, on cylinder; + if read check, signal completion; + else, do read or write +*/ + +t_stat dp_svc (UNIT *uptr) +{ +uint32 u = uptr - dp_dev.units; /* get unit number */ +int32 cyl = uptr->CYL; /* get cylinder */ +uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ +uint32 t; +t_stat r; + +if (uptr->STD & STD_MOV) { /* seek? */ + uptr->STD = 0; /* clr seek in prog */ + if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* offl? hangs */ + if (cyl >= drv_tab[dtype].cyl) { /* bad cylinder? */ + uptr->STD = STD_ILA; /* error */ + uptr->CYL = drv_tab[dtype].cyl - 1; } /* put at edge */ + if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* req intr */ + return SCPE_OK; } + +switch (dp_cmd & 0x7) { /* case on func */ + +case CMC_RCHK: /* read check */ + dp_dter (uptr, 1); /* check xfr err */ + break; + +case CMC_RD: /* read */ + if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */ + if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */ + if (r = dp_rds (uptr)) return r; /* read sec, err? */ + dp_1st = 0; + t = sch_wrmem (dp_dib.sch, dpxb, DP_NUMBY); /* write to memory */ + if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */ + sim_activate (uptr, dp_rtime); /* reschedule */ + return SCPE_OK; } + break; } /* no, set done */ + + dp_sta = dp_sta | STC_DTE; /* can't work */ + break; + +case CMC_WR: /* write */ + if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */ + dp_bptr = sch_rdmem (dp_dib.sch, dpxb, DP_NUMBY); /* read from mem */ + dp_db = dpxb[dp_bptr - 1]; /* last byte */ + if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */ + if (r = dp_wds (uptr)) return r; /* write sec, err? */ + dp_1st = 0; + if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */ + sim_activate (uptr, dp_rtime); /* reschedule */ + return SCPE_OK; } + break; } /* no, set done */ + + dp_sta = dp_sta | STC_DTE; /* can't work */ + break; } + +dp_done (0); /* done */ +return SCPE_OK; +} + +/* Read data sector */ + +t_stat dp_rds (UNIT *uptr) +{ +uint32 i; + +i = fxread (dpxb, sizeof (uint8), DP_NUMBY, uptr->fileref); +for ( ; i < DP_NUMBY; i++) dpxb[i] = 0; /* fill with 0's */ +if (ferror (uptr->fileref)) { /* error? */ + perror ("DP I/O error"); + clearerr (uptr->fileref); + dp_done (STC_DTE); + return SCPE_IOERR; } +return SCPE_OK; +} + +/* Write data sector */ + +t_stat dp_wds (UNIT *uptr) +{ +for ( ; dp_bptr < DP_NUMBY; dp_bptr++) + dpxb[dp_bptr] = dp_db; /* fill with last */ +fxwrite (dpxb, sizeof (uint8), DP_NUMBY, uptr->fileref); +if (ferror (uptr->fileref)) { /* error? */ + perror ("DP I/O error"); + clearerr (uptr->fileref); + dp_done (STC_DTE); + return SCPE_IOERR; } +return SCPE_OK; +} + +/* Data transfer error test routine */ + +t_bool dp_dter (UNIT *uptr, uint32 first) +{ +uint32 hd, sc, sa; +uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ + +if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */ + ((uptr->flags & UNIT_WPRT) && (dp_cmd == CMC_WR))) { + dp_done (STC_DTE); /* error, done */ + return TRUE; } +hd = GET_SRF (dp_hdsc); /* get head */ +sc = GET_SEC (dp_hdsc); /* get sector */ +if (dp_cyl != (uint32) uptr->CYL) { /* wrong cylinder? */ + dp_done (STC_ACF); /* error, done */ + return TRUE; } +if (sc >= DP_NUMSC) { /* bad sector? */ + dp_done (STC_OVR); /* error, done */ + return TRUE; } +if (!first && (sc == 0) && (hd == 0)) { /* cyl overflow? */ + dp_done (STC_CYO); /* error, done */ + return TRUE; } +sa = GET_SA (dp_plat, uptr->CYL, hd, sc, dtype); /* curr disk addr */ +fseek (uptr->fileref, sa * DP_NUMBY, SEEK_SET); +if ((sc + 1) < DP_NUMSC) dp_hdsc = dp_hdsc + 1; /* end of track? */ +else dp_hdsc = (dp_hdsc ^ HS_HMASK) & HS_HMASK; /* sec 0, nxt srf */ +return FALSE; +} + +/* Data transfer done routine */ + +void dp_done (uint32 flg) +{ +dp_sta = (dp_sta | STC_IDL | flg) & ~STA_BSY; /* set flag, idle */ +SET_INT (v_DPC); /* unmaskable intr */ +if (flg) sch_stop (dp_dib.sch); /* if err, stop ch */ +return; +} + +/* Reset routine */ + +t_stat dp_reset (DEVICE *dptr) +{ +uint32 u; +UNIT *uptr; + +dp_cmd = 0; /* clear cmd */ +dp_sta = STA_BSY | STC_IDL; /* idle, busy */ +dp_1st = 0; /* clear flag */ +dp_svun = dp_db = 0; /* clear unit, buf */ +dp_plat = 0; +dp_hdsc = 0; /* clear addr */ +CLR_INT (v_DPC); /* clear ctrl int */ +SET_ENB (v_DPC); /* always enabled */ +for (u = 0; u < DP_NUMDR; u++) { /* loop thru units */ + uptr = dp_dev.units + u; + uptr->CYL = uptr->STD = 0; + CLR_INT (v_DPC + u + 1); /* clear intr */ + CLR_ENB (v_DPC + u + 1); /* clear enable */ + dpd_arm[u] = 0; /* clear arm */ + sim_cancel (uptr); } /* cancel activity */ +return SCPE_OK; +} + +/* Attach routine (with optional autosizing) */ + +t_stat dp_attach (UNIT *uptr, char *cptr) +{ +uint32 i, p; +t_stat r; + +uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; +r = attach_unit (uptr, cptr); +uptr->CYL = 0; +if ((r != SCPE_OK) || ((uptr->flags & UNIT_AUTO) == 0)) return r; +if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; +if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK; +for (i = 0; drv_tab[i].surf != 0; i++) { + if (p <= drv_tab[i].size) { + uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); + uptr->capac = drv_tab[i].size; + return SCPE_OK; } } +return SCPE_OK; +} + +/* Detach routine (generates an interrupt) */ + +t_stat dp_detach (UNIT *uptr) +{ +uint32 u = uptr - dp_dev.units; + +if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* if arm, intr */ +return detach_unit (uptr); +} + +/* Set size command validation routine */ + +t_stat dp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +uptr->capac = drv_tab[GET_DTYPE (val)].size; +return SCPE_OK; +} + +/* Create device number (T) or interrupt (F) template */ + +void dp_ini (t_bool dtpl) +{ +int32 u, j, dev; + +dp_tplte[0] = 0; /* controller */ +for (u = 0, j = 1; u < DP_NUMDR; u++) { /* loop thru units */ + dev = (u + 1) * o_DP0; /* drive dev # */ + dp_tplte[j++] = dev; + if (dtpl && (GET_DTYPE (dp_unit[u].flags) == TYPE_5440)) + dp_tplte[j++] = dev + o_DPF; } /* if fixed */ +dp_tplte[j] = TPL_END; /* end marker */ +return; +} diff --git a/Interdata/id_fd.c b/Interdata/id_fd.c new file mode 100644 index 00000000..0cc0731d --- /dev/null +++ b/Interdata/id_fd.c @@ -0,0 +1,480 @@ +/* id_fd.c: Interdata floppy disk simulator + + Copyright (c) 2001-2002, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + fd M46-630 floppy disk + + A diskette consists of 77 tracks, each with 26 sectors of 128B. The + Interdata floppy uses a logical record numbering scheme from 1 to 2002. + Physical tracks are numbered 0-76, physical sectors 1-26. + + To allow for deleted data handling, a directory is appended to the end + of the image, one byte per LRN. Zero (the default) is a normal record, + non-zero a deleted record. +*/ + +#include "id_defs.h" + +#define FD_NUMTR 77 /* tracks/disk */ +#define FD_NUMSC 26 /* sectors/track */ +#define FD_NUMBY 128 /* bytes/sector */ +#define FD_NUMLRN (FD_NUMTR * FD_NUMSC) /* LRNs/disk */ +#define FD_SIZE (FD_NUMLRN * FD_NUMBY) /* bytes/disk */ +#define FD_NUMDR 4 /* drives/controller */ +#define UNIT_V_WLK (UNIT_V_UF) /* write locked */ +#define UNIT_WLK (1u << UNIT_V_UF) +#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ +#define LRN u3 /* last LRN */ +#define FNC u4 /* last function */ +#define GET_DA(x) (((x) - 1) * FD_NUMBY) +#define GET_TRK(x) (((x) - 1) / FD_NUMSC) +#define GET_SEC(x) ((((x) - 1) % FD_NUMSC) + 1) +#define LRN_BOOT 5 /* boot block LRN */ + +/* Command byte */ + +#define CMD_V_UNIT 4 /* unit */ +#define CMD_M_UNIT 0x3 +#define GET_UNIT(x) (((x) >> CMD_V_UNIT) & CMD_M_UNIT) +#define CMD_V_FNC 0 /* function */ +#define CMD_M_FNC 0xF +#define GET_FNC(x) (((x) >> CMD_V_FNC) & CMD_M_FNC) +#define FNC_RD 0x1 /* read */ +#define FNC_WR 0x2 /* write */ +#define FNC_RDID 0x3 /* read ID */ +#define FNC_RSTA 0x4 /* read status */ +#define FNC_DEL 0x5 /* write deleted */ +#define FNC_BOOT 0x6 /* boot */ +#define FNC_STOP 0x7 /* stop */ +#define FNC_RESET 0x8 /* reset */ +#define FNC_FMT 0x9 /* format NI */ +#define FNC_STOPPING 0x10 /* stopping */ + +/* Status byte, * = dynamic */ + +#define STA_WRP 0x80 /* *write prot */ +#define STA_DEF 0x40 /* def track NI */ +#define STA_DEL 0x20 /* del record */ +#define STA_ERR 0x10 /* error */ +#define STA_IDL 0x02 /* idle */ +#define STA_OFL 0x01 /* fault */ +#define STA_MASK (STA_DEF|STA_DEL|STA_ERR|STA_BSY|STA_IDL) +#define SET_EX (STA_ERR) /* set EX */ + +/* Extended status, 6 bytes, * = dynamic */ + +#define ES_SIZE 6 +#define ES0_HCRC 0x80 /* ID CRC NI */ +#define ES0_DCRC 0x40 /* data CRC NI */ +#define ES0_LRN 0x20 /* illegal LRN */ +#define ES0_WRP 0x10 /* *write prot */ +#define ES0_ERR 0x08 /* error */ +#define ES0_DEF 0x04 /* def trk NI */ +#define ES0_DEL 0x02 /* del rec NI */ +#define ES0_FLT 0x01 /* fault */ +#define ES1_TK0 0x80 /* track 0 */ +#define ES1_NRDY 0x40 /* not ready */ +#define ES1_NOAM 0x20 /* no addr mk NI */ +#define ES1_CMD 0x10 /* illegal cmd */ +#define ES1_SKE 0x08 /* seek err NI */ +#define ES1_UNS 0x04 /* unsafe NI */ +#define ES1_UNIT 0x03 /* unit # */ + +/* Processing options for commands */ + +#define C_RD 0x1 /* cmd reads disk */ +#define C_WD 0x2 /* cmd writes disk */ + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; + +uint32 fd_sta = 0; /* status */ +uint32 fd_cmd = 0; /* command */ +uint32 fd_db = 0; /* data buffer */ +uint32 fd_bptr = 0; /* buffer pointer */ +uint8 fdxb[FD_NUMBY] = { 0 }; /* sector buffer */ +uint8 fd_es[FD_NUMDR][ES_SIZE] = { 0 }; /* ext status */ +uint32 fd_lrn = 0; /* log rec # */ +uint32 fd_wdv = 0; /* wd valid */ +uint32 fd_stopioe = 1; /* stop on error */ +uint32 fd_arm = 0; /* intr arm */ +int32 fd_ctime = 100; /* command time */ +int32 fd_stime = 10; /* seek, per LRN */ +int32 fd_xtime = 1; /* tr set time */ + +static uint32 ctab[16] = { + 0, C_RD, C_WD, 0, /* 0, rd, wr, 0 */ + 0, C_WD, C_RD, 0, /* 0, del, boot, 0 */ + 0, 0, 0, 0, + 0, 0, 0, 0 }; + +DEVICE fd_dev; +uint32 fd (uint32 dev, uint32 op, uint32 dat); +t_stat fd_svc (UNIT *uptr); +t_stat fd_reset (DEVICE *dptr); +t_stat fd_clr (DEVICE *dptr); +t_stat fd_boot (int32 unitno, DEVICE *dptr); +t_bool fd_dte (UNIT *uptr, t_bool wr); +uint32 fd_crc (uint32 crc, uint32 dat, uint32 cnt); +void fd_done (uint32 u, uint32 nsta, uint32 nes0, uint32 nes1); +void sched_seek (UNIT *uptr, int32 newlrn); + +/* FD data structures + + fd_dev FD device descriptor + fd_unit FD unit list + fd_reg FD register list + fd_mod FD modifier list +*/ + +DIB fd_dib = { d_FD, -1, v_FD, NULL, &fd, NULL }; + +UNIT fd_unit[] = { + { UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) }, + { UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) }, + { UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) }, + { UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) } }; + +REG fd_reg[] = { + { HRDATA (CMD, fd_cmd, 8) }, + { HRDATA (STA, fd_sta, 8) }, + { HRDATA (BUF, fd_db, 8) }, + { HRDATA (LRN, fd_lrn, 16) }, + { BRDATA (ESTA, fd_es, 16, 8, ES_SIZE * FD_NUMDR) }, + { BRDATA (DBUF, fdxb, 16, 8, FD_NUMBY) }, + { HRDATA (DBPTR, fd_bptr, 8) }, + { FLDATA (WDV, fd_wdv, 0) }, + { FLDATA (IREQ, int_req[l_FD], i_FD) }, + { FLDATA (IENB, int_enb[l_FD], i_FD) }, + { FLDATA (IARM, fd_arm, 0) }, + { DRDATA (CTIME, fd_ctime, 24), PV_LEFT }, + { DRDATA (STIME, fd_stime, 24), PV_LEFT }, + { DRDATA (XTIME, fd_xtime, 24), PV_LEFT }, + { FLDATA (STOP_IOE, fd_stopioe, 0) }, + { URDATA (ULRN, fd_unit[0].LRN, 16, 16, 0, FD_NUMDR, REG_HRO) }, + { URDATA (UFNC, fd_unit[0].FNC, 16, 8, 0, FD_NUMDR, REG_HRO) }, + { HRDATA (DEVNO, fd_dib.dno, 8), REG_HRO }, + { NULL } }; + +MTAB fd_mod[] = { + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, NULL }, + { 0 } }; + +DEVICE fd_dev = { + "FD", fd_unit, fd_reg, fd_mod, + FD_NUMDR, 16, 20, 1, 16, 8, + NULL, NULL, &fd_reset, + &fd_boot, NULL, NULL, + &fd_dib, DEV_DISABLE }; + +/* Floppy disk: IO routine */ + +uint32 fd (uint32 dev, uint32 op, uint32 dat) +{ +int32 u, t, fnc; +UNIT *uptr; + +fnc = GET_FNC (fd_cmd); /* get fnc */ +u = GET_UNIT (fd_cmd); /* get unit */ +uptr = fd_dev.units + u; +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + return BY; /* byte only */ +case IO_RD: /* read */ + if (fd_sta & (STA_IDL | STA_BSY)) return fd_db; /* idle, busy? */ + if (fd_bptr < FD_NUMBY) fd_db = fdxb[fd_bptr++];/* get byte */ + if (fd_bptr >= FD_NUMBY) { /* buf end? */ + if (ctab[fnc] & C_RD) { /* disk read? */ + sched_seek (uptr, uptr->LRN + 1); /* sched read */ + fd_sta = fd_sta | STA_BSY; } /* set busy */ + else fd_bptr = 0; } /* just wrap */ + if ((ctab[fnc] & C_RD) && fd_arm) /* if rd & arm, */ + SET_INT (v_FD); /* interrupt */ + return fd_db; /* return buf */ +case IO_WD: /* write */ + if (fd_sta & STA_IDL) { /* idle? */ + fd_lrn = ((fd_lrn << 8) | dat) & DMASK16; /* insert byte */ + fd_wdv = 1; + break; } + if (fd_bptr < FD_NUMBY) /* if room, */ + fdxb[fd_bptr++] = fd_db = dat; /* store byte */ + if (fd_bptr >= FD_NUMBY) { /* buf end? */ + if (ctab[fnc] & C_WD) { /* disk write? */ + sched_seek (uptr, uptr->LRN + 1); /* sched write */ + fd_sta = fd_sta | STA_BSY; } /* set busy */ + else fd_bptr = 0; } /* just wrap */ + if ((ctab[fnc] & C_WD) && fd_arm) /* if wr & arm, */ + SET_INT (v_FD); /* interrupt */ + break; +case IO_SS: /* status */ + t = fd_sta & STA_MASK; /* get status */ + if ((uptr->flags & UNIT_ATT) == 0) t = t | STA_DU; + if (t & SET_EX) t = t | STA_EX; /* test for ex */ + return t; +case IO_OC: /* command */ + fd_arm = int_chg (v_FD, dat, fd_arm); /* upd int ctrl */ + fnc = GET_FNC (dat); /* new fnc */ + fd_cmd = dat; /* save cmd */ + u = GET_UNIT (dat); /* get unit */ + uptr = fd_dev.units + u; + if (fnc == FNC_STOP) { /* stop? */ + uptr->FNC = uptr->FNC | FNC_STOPPING; /* flag stop */ + if (sim_is_active (uptr)) break; /* busy? cont */ + if (ctab[GET_FNC (uptr->FNC)] & C_WD) { /* write? */ + sched_seek (uptr, uptr->LRN + 1); /* sched write */ + fd_sta = fd_sta | STA_BSY; } /* set busy */ + else fd_done (u, 0, 0, 0); /* nrml done */ + break; } + else if (fd_sta & STA_IDL) { /* must be idle */ + if (fnc != FNC_RSTA) { /* !rd status */ + fd_sta = STA_BSY; /* busy, !idle */ + fd_es[u][0] = 0; + fd_es[u][1] = u; } /* init ext sta */ + else fd_sta = (fd_sta & ~STA_IDL) | STA_BSY; + if (fnc == FNC_BOOT) t = LRN_BOOT; /* boot? fixed sec */ + else if (fd_wdv) t = fd_lrn; /* valid data? use */ + else t = uptr->LRN; /* use prev */ + fd_wdv = 0; /* data invalid */ + fd_bptr = 0; /* init buffer */ + uptr->FNC = fnc; /* save function */ + uptr->LRN = t; /* save LRN */ + if (ctab[fnc] & C_RD) sched_seek (uptr, t); /* seek now? */ + else sim_activate (uptr, fd_ctime); } /* start cmd */ + break; } +return 0; +} + +/* Unit service; the action to be taken depends on command */ + +t_stat fd_svc (UNIT *uptr) +{ +uint32 i, u, tk, sc, crc, fnc; +t_addr da; + +u = uptr - fd_dev.units; /* get unit number */ +fnc = GET_FNC (uptr->FNC); /* get function */ +switch (fnc) { /* case on function */ + +case FNC_RESET: /* reset */ + fd_clr (&fd_dev); /* clear device */ + fd_done (u, 0, 0, 0); /* set idle */ + return SCPE_OK; + +case FNC_STOP: /* stop */ + fd_done (u, 0, 0, 0); /* set idle */ + return SCPE_OK; + +case FNC_BOOT: /* boot, buf empty */ +case FNC_RD: /* read, buf empty */ + if (uptr->FNC & FNC_STOPPING) break; /* stopped? */ + if (fd_dte (uptr, FALSE)) return SCPE_OK; /* xfr error? */ + da = GET_DA (uptr->LRN); /* get disk addr */ + for (i = 0; i < FD_NUMBY; i++) /* read sector */ + fdxb[i] = *(((uint8 *) uptr->filebuf) + da + i); + if (*(((uint8 *) uptr->filebuf) + FD_SIZE + uptr->LRN - 1)) { + fd_sta = fd_sta | STA_DEL; /* deleted? set err */ + fd_es[u][0] = fd_es[u][0] | ES0_DEL; } + fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */ + fd_es[u][3] = GET_TRK (uptr->LRN); + fd_bptr = 0; /* init buf */ + uptr->LRN = uptr->LRN + 1; /* next block */ + break; + +case FNC_WR: case FNC_DEL: /* write block */ + if (fd_dte (uptr, TRUE)) return SCPE_OK; /* xfr error? */ + if (fd_bptr) { /* any transfer? */ + da = GET_DA (uptr->LRN); /* get disk addr */ + for (i = fd_bptr; i < FD_NUMBY; i++) /* pad sector */ + fdxb[i] = fd_db; + for (i = 0; i < FD_NUMBY; i++) /* write sector */ + *(((uint8 *) uptr->filebuf) + da + i) = fdxb[i]; + *(((uint8 *) uptr->filebuf) + FD_SIZE + uptr->LRN - 1) = + (fnc == FNC_DEL)? 1: 0; /* write dir */ + uptr->hwmark = uptr->capac; /* rewrite all */ + fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */ + fd_es[u][3] = GET_TRK (uptr->LRN); + fd_bptr = 0; /* init buf */ + uptr->LRN = uptr->LRN + 1; } /* next block */ + break; + +case FNC_RSTA: /* read status */ + if (uptr->flags & UNIT_WPRT) /* wr protected? */ + fd_es[u][0] = fd_es[u][0] | ES0_WRP; + if (GET_TRK (uptr->LRN) == 0) /* on track 0? */ + fd_es[u][1] = fd_es[u][1] | ES1_TK0; + if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */ + fd_es[u][0] = fd_es[u][0] | ES0_FLT; /* set err */ + fd_es[u][1] = fd_es[u][1] | ES1_NRDY; } + for (i = 0; i < ES_SIZE; i++) fdxb[i] = fd_es[u][i]; /* copy to buf */ + for (i = ES_SIZE; i < FD_NUMBY; i++) fdxb[i] = 0; + break; + +case FNC_RDID: /* read ID */ + if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */ + fd_done (u, STA_ERR, ES0_ERR | ES0_FLT, ES1_NRDY); + return SCPE_OK; } + for (i = 0; i < FD_NUMBY; i++) fdxb[i] = 0; /* clr buf */ + tk = GET_TRK (uptr->LRN); /* get track */ + sc = GET_SEC (uptr->LRN); /* get sector */ + fdxb[0] = tk & 0xFF; /* store track */ + fdxb[2] = sc & 0xFF; /* store sector */ + crc = fd_crc (0xFFFF, 0xFE00, 8); /* CRC addr mark */ + crc = fd_crc (crc, tk << 8, 16); /* CRC track */ + crc = fd_crc (crc, sc << 8, 16); /* CRC sector */ + fdxb[4] = (crc >> 8) & 0xFF; /* store CRC */ + fdxb[5] = crc & 0xFF; + break; + +case FNC_FMT: /* format */ +default: + fd_done (u, STA_ERR, ES0_ERR, ES1_CMD); /* ill cmd */ + uptr->LRN = 1; /* on track 0 */ + return SCPE_OK; } + +if (uptr->FNC & FNC_STOPPING) { /* stopping? */ + uptr->FNC = FNC_STOP; /* fnc = STOP */ + sim_activate (uptr, fd_ctime); } /* schedule */ +fd_sta = fd_sta & ~STA_BSY; /* clear busy */ +if (fd_arm) SET_INT (v_FD); /* if armed, int */ +return SCPE_OK; +} + +/* Schedule seek */ + +void sched_seek (UNIT *uptr, int32 newlrn) +{ +int32 diff = newlrn - uptr->LRN; /* LRN diff */ + +if (diff < 0) diff = -diff; /* ABS */ +if (diff < 10) diff = 10; /* MIN 10 */ +sim_activate (uptr, diff * fd_stime); /* schedule */ +return; +} + +/* Command complete */ + +void fd_done (uint32 u, uint32 nsta, uint32 nes0, uint32 nes1) +{ +fd_sta = (fd_sta | STA_IDL | nsta) & ~STA_BSY; /* set idle */ +if (fd_arm) SET_INT (v_FD); /* if armed, int */ +fd_es[u][0] = fd_es[u][0] | nes0; /* set ext state */ +fd_es[u][1] = fd_es[u][1] | nes1; +return; +} + +/* Test for data transfer error */ + +t_bool fd_dte (UNIT *uptr, t_bool wr) +{ +uint32 u = uptr - fd_dev.units; + +if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */ + fd_done (u, STA_ERR, ES0_ERR | ES0_FLT, ES1_NRDY); + return TRUE; } +if (wr && (uptr->flags & UNIT_WPRT)) { /* wr protected? */ + fd_done (u, STA_ERR, ES0_ERR | ES0_WRP, 0); + return TRUE; } +if ((uptr->LRN == 0) || (uptr->LRN > FD_NUMLRN)) { /* bad LRN? */ + fd_done (u, STA_ERR, ES0_ERR | ES0_LRN, 0); + return TRUE; } +return FALSE; +} + +/* Header CRC calculation */ + +uint32 fd_crc (uint32 crc, uint32 dat, uint32 cnt) +{ +uint32 i, wrk; + +for (i = 0; i < cnt; i++) { + wrk = crc ^ dat; + crc = (crc << 1) & DMASK16; + if (wrk & SIGN16) crc = ((crc ^ 0x1020) + 1) & DMASK16; + dat = (dat << 1) & DMASK16; } +return crc; +} + +/* Reset routine */ + +t_stat fd_clr (DEVICE *dptr) +{ +int32 i, j; +UNIT *uptr; + +fd_sta = STA_IDL; /* idle */ +fd_cmd = 0; /* clear state */ +fd_db = 0; +fd_bptr = 0; +fd_lrn = 1; +fd_wdv = 0; +for (i = 0; i < FD_NUMBY; i++) fdxb[i] = 0; /* clr xfr buf */ +for (i = 0; i < FD_NUMDR; i++) { /* loop thru units */ + for (j = 0; j < ES_SIZE; j++) fd_es[i][j] = 0; /* clr ext sta */ + fd_es[i][2] = 1; /* sector 1 */ + uptr = fd_dev.units + i; + sim_cancel (uptr); /* stop drive */ + uptr->LRN = 1; /* clear state */ + uptr->FNC = 0; } +return SCPE_OK; +} + +t_stat fd_reset (DEVICE *dptr) +{ +CLR_INT (v_FD); /* clear int */ +CLR_ENB (v_FD); /* disable int */ +fd_arm = 0; /* disarm int */ +return fd_clr (dptr);; +} + +/* Bootstrap routine */ + +#define BOOT_START 0x50 +#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) + +static uint8 boot_rom[] = { + 0xD5, 0x00, /* ST: AL CF */ + 0x00, 0xCF, + 0x43, 0x00, /* BR 80 */ + 0x00, 0x80 +}; + +t_stat fd_boot (int32 unitno, DEVICE *dptr) +{ +extern uint32 PC, dec_flgs; +extern uint16 decrom[]; + +if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */ +IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */ +IOWriteB (AL_DEV, fd_dib.dno); /* set dev no */ +IOWriteB (AL_IOC, 0x86 + (unitno << CMD_V_UNIT)); /* set dev cmd, unit num */ +IOWriteB (AL_SCH, 0); /* clr sch dev no */ +PC = BOOT_START; +return SCPE_OK; +} diff --git a/Interdata/id_fp.c b/Interdata/id_fp.c new file mode 100644 index 00000000..fa44469d --- /dev/null +++ b/Interdata/id_fp.c @@ -0,0 +1,471 @@ +/* id_fp.c: Interdata floating point instructions + + Copyright (c) 2000-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + The Interdata uses IBM 360 floating point format: + + 0 7 8 15 23 31 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |S| exponent | fraction | :single + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | fraction low | :double + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + where S = 0 for plus, 1 for minus + exponent = 16**n, in excess 64 code + fraction = .hhhhhh, seen as 6-14 hexadecimal digits + + Numbers can be normalized or unnormalized but are always normalized + when loaded. + + Interdata has 8 floating point registers, F0, F2, ... , FE. In floating + point instructions, the low order bit of the register number is ignored. + + On floating point overflow, the exponent and fraction are set to 1's. + On floating point underflow, the exponent and fraction are set to 0's. + + Interdata has both 32b only and 32b/64b floating point implementations. + In 32b only implementations, add and subtract are truncated, but multiply + and divide are rounded, and the floating point registers are kept in + memory. In 64b implementations, all single precision precision operations + are rounded, double precision operations are truncated, and the floating + point registers are kept in separate hardware arrays. +*/ + +#include "id_defs.h" + +struct ufp { /* unpacked fp */ + int32 sign; /* sign */ + int32 exp; /* unbiased exp */ + uint32 h; /* fr high */ + uint32 l; }; /* fr low */ + +#define FP_V_SIGN 31 /* sign */ +#define FP_M_SIGN 0x1 +#define FP_GETSIGN(x) (((x) >> FP_V_SIGN) & FP_M_SIGN) +#define FP_V_EXP 24 /* exponent */ +#define FP_M_EXP 0x7F +#define FP_GETEXP(x) (((x) >> FP_V_EXP) & FP_M_EXP) +#define FP_V_FRH 0 /* fraction */ +#define FP_M_FRH 0xFFFFFF +#define FP_GETFRH(x) (((x) >> FP_V_FRH) & FP_M_FRH) +#define FP_GETFRL(x) (x) + +#define FP_BIAS 0x40 /* exp bias */ +#define FP_CARRY (1 << FP_V_EXP ) /* carry out */ +#define FP_NORM (0xF << (FP_V_EXP - 4)) /* normalized */ +#define FP_ROUND 0x80000000 + +/* Double precision fraction add/subtract/compare */ + +#define FR_ADD(d,s) d.l = (d.l + s.l) & DMASK32; \ + d.h = (d.h + s.h + (d.l < s.l)) & DMASK32 + +#define FR_SUB(d,s) d.h = (d.h - s.h - (d.l < s.l)) & DMASK32; \ + d.l = (d.l - s.l) & DMASK32 + +#define FR_GE(s1,s2) ((s1.h > s2.h) || \ + ((s1.h == s2.h) && (s1.l >= s2.l))) + +/* Variable and constant shifts; for constants, 0 < k < 32 */ + +#define FR_RSH_V(v,s) if ((s) < 32) { \ + v.l = ((v.l >> (s)) | \ + (v.h << (32 - (s)))) & DMASK32; \ + v.h = (v.h >> (s)) & DMASK32; } \ + else { v.l = v.h >> ((s) - 32); \ + v.h = 0; } + +#define FR_RSH_K(v,s) v.l = ((v.l >> (s)) | \ + (v.h << (32 - (s)))) & DMASK32; \ + v.h = (v.h >> (s)) & DMASK32 + +#define FR_LSH_K(v,s) v.h = ((v.h << (s)) | \ + (v.l >> (32 - (s)))) & DMASK32; \ + v.l = (v.l << (s)) & DMASK32 + +#define Q_RND(op) (OP_DPFP (op) == 0) +#define Q_RND_AS(op) ((OP_DPFP (op) == 0) && fp_in_hwre) + +extern uint32 *R; +extern uint32 F[8]; +extern dpr_t D[8]; +extern uint16 decrom[]; +extern uint32 fp_in_hwre; +extern uint32 ReadF (uint32 loc, uint32 rel); +extern void WriteF (uint32 loc, uint32 dat, uint32 rel); +void ReadFP2 (struct ufp *fop, uint32 op, uint32 r2, uint32 ea); +void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1); +void NormUFP (struct ufp *fop); +uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd); +uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1); + +/* Floating point load */ + +uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea) +{ +struct ufp fop2; + +ReadFP2 (&fop2, op, r2, ea); /* get op, normalize */ +return StoreFPR (&fop2, op, r1, 0); /* store, chk unflo */ +} + +/* Floating point compare */ + +uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea) +{ +struct ufp fop1, fop2; + +ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */ +UnpackFPR (&fop1, op, r1); /* get op1, norm */ +if (fop1.sign ^ fop2.sign) /* signs differ? */ + return (fop2.sign? CC_G: (CC_C | CC_L)); +if (fop1.exp != fop2.exp) /* exps differ? */ + return (((fop1.exp > fop2.exp) ^ fop1.sign)? CC_G: (CC_C | CC_L)); +if (fop1.h != fop2.h) /* hi fracs differ? */ + return (((fop1.h > fop2.h) ^ fop1.sign)? CC_G: (CC_C | CC_L)); +if (OP_DPFP (op) && (fop1.l != fop2.l)) /* dp: low fracs diff? */ + return (((fop1.l > fop2.l) ^ fop1.sign)? CC_G: (CC_C | CC_L)); +return 0; +} + +/* Floating to integer conversion */ + +uint32 f_fix (uint32 op, uint32 r1, uint32 r2) /* 16b */ +{ +struct ufp res; +uint32 cc; + +UnpackFPR (&res, op, r2); /* get op2, norm */ +if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */ + R[r1] = 0; + return 0; } +if ((res.exp > 0x44) || /* result too big? */ + ((res.exp == 0x44) && (res.h >= 0x00800000))) { + res.h = MMASK16; + cc = CC_V; } +else { res.h = res.h >> ((0x46 - res.exp) * 4); /* right align frac */ + cc = 0; } +if (res.sign) { + R[r1] = ((res.h ^ DMASK16) + 1) & DMASK16; /* negate result */ + return cc | CC_L; } +R[r1] = res.h & DMASK16; +return cc | CC_G; +} + +uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2) /* 32b */ +{ +struct ufp res; +uint32 cc; + +UnpackFPR (&res, op, r2); /* get op2, norm */ +if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */ + R[r1] = 0; + return 0; } +if ((res.exp > 0x48) || /* result too big? */ + ((res.exp == 0x48) && (res.h >= 0x00800000))) { + res.h = MMASK32; + cc = CC_V; } +else { FR_LSH_K (res, 8); /* get all in 32b */ + res.h = res.h >> ((0x48 - res.exp) * 4); /* right align frac */ + cc = 0; } +if (res.sign) { + R[r1] = (res.h ^ DMASK32) + 1; /* negate result */ + return cc | CC_L; } +R[r1] = res.h; +return cc | CC_G; +} + +/* Integer to floating conversion */ + +uint32 f_flt (uint32 op, uint32 r1, uint32 r2) /* 16b */ +{ +struct ufp res = { 0, 0x44, 0, 0 }; /* +, 16**4 */ +uint32 cc; + +if (R[r2] == 0) cc = 0; /* zero arg? */ +else if (R[r2] & SIGN16) { /* neg arg? */ + res.sign = FP_M_SIGN; /* set sign */ + res.h = ((~R[r2] + 1) & DMASK16) << 8; /* get magnitude */ + cc = CC_L; } +else { res.h = R[r2] << 8; /* pos nz arg */ + cc = CC_G; } +NormUFP (&res); /* normalize */ +StoreFPR (&res, op, r1, 0); /* store result */ +return cc; +} + +uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2) /* 32b */ +{ +struct ufp res = { 0, 0x48, 0, 0 }; /* +, 16**8 */ +uint32 cc, t; + +t = R[r2]; /* int op */ +if (t) { /* nonzero arg? */ + if (t & SIGN32) { /* neg arg? */ + res.sign = FP_M_SIGN; /* set sign */ + t = (~t + 1) & DMASK32; /* get magnitude */ + cc = CC_L; } + else cc = CC_G; /* pos nz arg */ + res.h = t >> 8; /* hi frac */ + res.l = t << 24; } /* lo frac */ +else cc = 0; /* zero arg */ +NormUFP (&res); /* normalize */ +StoreFPR (&res, op, r1, 0); /* store result */ +return cc; +} + +/* Floating point add/subtract */ + +uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea) +{ +struct ufp fop1, fop2, t; +int32 ediff; + +ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */ +UnpackFPR (&fop1, op, r1); /* get op1, norm */ +if (op & 1) fop2.sign = fop2.sign ^ 1; /* if sub, inv sign2 */ +if (fop1.h == 0) fop1 = fop2; /* if op1 = 0, res = op2 */ +else if (fop2.h != 0) { /* if op2 = 0, no add */ + if ((fop1.exp < fop2.exp) || /* |op1| < |op2|? */ + ((fop1.exp == fop2.exp) && + ((fop1.h < fop2.h) || + ((fop1.h == fop2.h) && (fop1.l < fop2.l))))) { + t = fop2; /* swap operands */ + fop2 = fop1; + fop1 = t; } + ediff = fop1.exp - fop2.exp; /* exp difference */ + if (OP_DPFP (op) || fp_in_hwre) { /* dbl prec or hwre? */ + if (ediff >= 14) fop2.h = fop2.l = 0; /* diff too big? */ + else if (ediff) { /* any difference? */ + FR_RSH_V (fop2, ediff * 4); } } /* shift frac */ + else { /* sgl prec ucode */ + if (ediff >= 6) fop2.h = 0; /* diff too big? */ + else if (ediff) /* any difference? */ + fop2.h = fop2.h >> (ediff * 4); } /* shift frac */ + if (fop1.sign ^ fop2.sign) { /* eff subtract */ + FR_SUB (fop1, fop2); /* sub fractions */ + NormUFP (&fop1); } /* normalize result */ + else { + FR_ADD (fop1, fop2); /* add fractions */ + if (fop1.h & FP_CARRY) { /* carry out? */ + FR_RSH_K (fop1, 4); /* renormalize */ + fop1.exp = fop1.exp + 1; } } /* incr exp */ + } /* end if fop2 */ +return StoreFPR (&fop1, op, r1, Q_RND_AS (op)); /* store result */ +} + +/* Floating point multiply + + Notes: + - Exponent overflow/underflow is tested right after the exponent + add, without regard to potential changes due to normalization + - Exponent underflow is tested right after normalization, without + regard to changes due to rounding + - Single precision hardware multiply may generate up to 48b + - Double precision multiply generates 56b with no guard bits +*/ + +int32 f_m (uint32 op, uint32 r1, uint32 r2, uint32 ea) +{ +struct ufp fop1, fop2; +struct ufp res = { 0, 0, 0, 0 }; +uint32 i; + +ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */ +UnpackFPR (&fop1, op, r1); /* get op1, norm */ +if (fop1.h && fop2.h) { /* if both != 0 */ + res.sign = fop1.sign ^ fop2.sign; /* sign = diff */ + res.exp = fop1.exp + fop2.exp - FP_BIAS; /* exp = sum */ + if ((res.exp < 0) || (res.exp > FP_M_EXP)) /* ovf/undf? */ + return StoreFPX (&res, op, r1); /* early out */ + if ((fop1.l | fop2.l) == 0) { /* 24b x 24b? */ + for (i = 0; i < 24; i++) { /* 24 iterations */ + if (fop2.h & 1) res.h = res.h + fop1.h; /* add hi only */ + FR_RSH_K (res, 1); /* shift dp res */ + fop2.h = fop2.h >> 1; } + } + else { /* some low 0's */ + if (fop2.l != 0) { /* 56b x 56b? */ + for (i = 0; i < 32; i++) { /* do low 32b */ + if (fop2.l & 1) { FR_ADD (res, fop1); } + FR_RSH_K (res, 1); + fop2.l = fop2.l >> 1; } } + for (i = 0; i < 24; i++) { /* do hi 24b */ + if (fop2.h & 1) { FR_ADD (res, fop1); } + FR_RSH_K (res, 1); + fop2.h = fop2.h >> 1; } + } + NormUFP (&res); /* normalize */ + if (res.exp < 0) /* underflow? */ + return StoreFPX (&res, op, r1); /* early out */ + } +return StoreFPR (&res, op, r1, Q_RND (op)); /* store */ +} + +/* Floating point divide - see overflow/underflow notes for multiply */ + +int32 f_d (uint32 op, uint32 r1, uint32 r2, uint32 ea) +{ +struct ufp fop1, fop2; +struct ufp quo = { 0, 0, 0, 0 }; +int32 i; + +ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */ +UnpackFPR (&fop1, op, r1); /* get op1, norm */ +if (fop2.h == 0) return CC_C | CC_V; /* div by zero? */ +if (fop1.h) { /* dvd != 0? */ + quo.sign = fop1.sign ^ fop2.sign; /* sign = diff */ + quo.exp = fop1.exp - fop2.exp + FP_BIAS; /* exp = diff */ + if ((quo.exp < 0) || (quo.exp > FP_M_EXP)) /* ovf/undf? */ + return StoreFPX (&quo, op, r1); /* early out */ + if (!FR_GE (fop1, fop2)) { + FR_LSH_K (fop1, 4); } /* ensure success */ + else { /* exp off by 1 */ + quo.exp = quo.exp + 1; /* incr exponent */ + if (quo.exp > FP_M_EXP) /* overflow? */ + return StoreFPX (&quo, op, r1); } /* early out */ + for (i = 0; i < (OP_DPFP (op)? 14: 6); i++) { /* 6/14 hex digits */ + FR_LSH_K (quo, 4); /* shift quotient */ + while (FR_GE (fop1, fop2)) { /* while sub works */ + FR_SUB (fop1, fop2); /* decrement */ + quo.l = quo.l + 1; } /* add quo bit */ + FR_LSH_K (fop1, 4); } /* shift divd */ + if (!OP_DPFP (op)) { /* single? */ + quo.h = quo.l; /* move quotient */ + if (fop1.h >= (fop2.h << 3)) quo.l = FP_ROUND; + else quo.l = 0; } + /* don't need to normalize */ + } /* end if fop1.h */ +return StoreFPR (&quo, op, r1, Q_RND (op)); /* store result */ +} + +/* Utility routines */ + +/* Unpack floating point number */ + +void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1) +{ +uint32 hi; + +if (OP_DPFP (op)) { /* double prec? */ + hi = D[r1 >> 1].h; /* get hi */ + fop->l = FP_GETFRL (D[r1 >> 1].l); } /* get lo */ +else { hi = ReadFReg (r1); /* single prec */ + fop->l = 0; } /* lo is zero */ +fop->h = FP_GETFRH (hi); /* get hi frac */ +if (fop->h || fop->l) { /* non-zero? */ + fop->sign = FP_GETSIGN (hi); /* get sign */ + fop->exp = FP_GETEXP (hi); /* get exp */ + NormUFP (fop); } /* normalize */ +else fop->sign = fop->exp = 0; /* clean zero */ +return; +} + +/* Read memory operand */ + +void ReadFP2 (struct ufp *fop, uint32 op, uint32 r2, uint32 ea) +{ +uint32 hi; + +if (OP_TYPE (op) > OP_RR) { /* mem ref? */ + hi = ReadF (ea, VR); /* get hi */ + if (OP_DPFP (op)) fop->l = ReadF (ea + 4, VR); /* dp? get lo */ + else fop->l = 0; } /* sp, lo = 0 */ +else { if (OP_DPFP (op)) { /* RR */ + hi = D[r2 >> 1].h; /* dp? get dp reg */ + fop->l = D[r2 >> 1].l; } + else { + hi = ReadFReg (r2); /* get sp reg */ + fop->l = 0; } } +fop->h = FP_GETFRH (hi); /* get hi frac */ +if (fop->h || fop->l) { /* non-zero? */ + fop->sign = FP_GETSIGN (hi); /* get sign */ + fop->exp = FP_GETEXP (hi); /* get exp */ + NormUFP (fop); } /* normalize */ +else fop->sign = fop->exp = 0; /* clean zero */ +return; +} + +/* Normalize unpacked floating point number */ + +void NormUFP (struct ufp *fop) +{ +if ((fop->h & FP_M_FRH) || fop->l) { /* any fraction? */ + while ((fop->h & FP_NORM) == 0) { /* until norm */ + fop->h = (fop->h << 4) | ((fop->l >> 28) & 0xF); + fop->l = fop->l << 4; + fop->exp = fop->exp - 1; } } +else fop->sign = fop->exp = 0; /* clean 0 */ +return; +} + +/* Round fp number, store, generate condition codes */ + +uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd) +{ +uint32 hi, cc; + +if (rnd && (fop->l & FP_ROUND)) { /* round? */ + fop->h = fop->h + 1; /* add 1 to frac */ + if (fop->h & FP_CARRY) { /* carry out? */ + fop->h = fop->h >> 4; /* renormalize */ + fop->exp = fop->exp + 1; } } /* incr exp */ +if (fop->h == 0) { /* result 0? */ + hi = fop->l = 0; /* store clean 0 */ + cc = 0; } +else if (fop->exp < 0) { /* underflow? */ + hi = fop->l = 0; /* store clean 0 */ + cc = CC_V; } +else if (fop->exp > FP_M_EXP) { /* overflow? */ + hi = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; + fop->l = 0xFFFFFFFF; + cc = (CC_V | ((fop->sign)? CC_L: CC_G)); } +else { hi = ((fop->sign & FP_M_SIGN) << FP_V_SIGN) | /* pack result */ + ((fop->exp & FP_M_EXP) << FP_V_EXP) | + ((fop->h & FP_M_FRH) << FP_V_FRH); + cc = (fop->sign)? CC_L: CC_G; } /* set cc's */ +if (OP_DPFP (op)) { /* double precision? */ + D[r1 >> 1].h = hi; + D[r1 >> 1].l = fop->l; } +else { WriteFReg (r1, hi); } +return cc; +} + +/* Generate exception result */ + +uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1) +{ +uint32 cc = CC_V; + +if (fop->exp < 0) fop->h = fop->l = 0; /* undf? clean 0 */ +else { fop->h = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; /* overflow */ + fop->l = 0xFFFFFFFF; + cc = cc | ((fop->sign)? CC_L: CC_G); } +if (OP_DPFP (op)) { /* double precision? */ + D[r1 >> 1].h = fop->h; + D[r1 >> 1].l = fop->l; } +else { WriteFReg (r1, fop->h); } +return cc; +} diff --git a/Interdata/id_idc.c b/Interdata/id_idc.c new file mode 100644 index 00000000..6630006a --- /dev/null +++ b/Interdata/id_idc.c @@ -0,0 +1,690 @@ +/* id_idc.c: Interdata MSM/IDC disk controller simulator + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + idc MSM/IDC disk controller + + Note: define flag ID_IDC to enable the extra functions of the intelligent + disk controller +*/ + +#include "id_defs.h" + +#define IDC_NUMBY 256 /* bytes/sector */ +#define IDC_NUMSC 64 /* sectors/track */ + +#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ +#define UNIT_M_DTYPE 0x7 +#define UNIT_V_AUTO (UNIT_V_UF + 4) /* autosize */ +#define UNIT_WLK (1 << UNIT_V_WLK) +#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) +#define UNIT_AUTO (1 << UNIT_V_AUTO) +#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) + +#define CYL u3 /* current cylinder */ +#define HD u4 /* current head */ +#define STD buf /* drive status */ +#define FNC wait /* function */ +#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ + +#define IDC_DRVMASK ((1 << ID_NUMDR) - 1) /* drive bit mask */ +#define IDC_DIRMASK (IDC_DRVMASK << (i_IDC + 1)) /* drive irq mask */ + +/* Controller status */ + +#define STC_WRP 0x80 /* write protected */ +#define STC_ACF 0x40 /* addr cmp fail */ +#define STC_DEF 0x20 /* def track NI */ +#define STC_CYO 0x10 /* cylinder ovflo */ +#define STC_IDL 0x02 /* ctrl idle */ +#define STC_DTE 0x01 /* xfer error */ +#define SETC_EX (STC_WRP|STC_ACF|STC_DEF|STC_CYO) +#define STC_MASK (STC_WRP|STC_ACF|STC_DEF|STC_CYO|STA_BSY|STC_IDL|STC_DTE) + +/* Controller command */ + +#define CMC_MASK 0x3F +#define CMC_CLR 0x08 /* reset */ +#define CMC_RD 0x01 /* read */ +#define CMC_WR 0x02 /* write */ +#define CMC_RCHK 0x03 /* read check */ +#define CMC_FCHK 0x04 /* format check NI */ +#define CMC_RFMT 0x05 /* read fmt NI */ +#define CMC_WFMT 0x06 /* write fmt NI */ +#define CMC_WFTK 0x07 /* write fmt track NI */ + +/* IDC only functions */ + +#define CMC_RRAM 0x10 /* read RAM */ +#define CMC_WRAM 0x11 /* write RAM */ +#define CMC_EXP0 0x12 /* read page 0 NI */ +#define CMC_RUNC 0x21 /* read uncorr */ +#define CMC_STST 0x30 /* self test */ +#define CMC_WLNG 0x32 /* write long NI */ +#define CMC_LAMP 0x37 /* lamp test */ + +#define CMC_DRV 0x100 /* drive func */ +#define CMC_DRV1 0x200 /* drive func, part 2 */ + +/* Drive status, ^ = dynamic, * = in unit status */ + +#define STD_WRP 0x80 /* ^write prot */ +/* 0x40 /* unused */ +#define STD_ACH 0x20 /* alt chan busy NI */ +#define STD_UNS 0x10 /* *unsafe */ +#define STD_NRDY 0x08 /* ^not ready */ +#define STD_SKI 0x02 /* *seek incomplete */ +#define STD_OFFL 0x01 /* ^offline */ +#define STD_UST (STD_UNS | STD_SKI) /* set from unit */ +#define SETD_EX (STD_WRP | STD_UNS) /* set examine */ + +/* Drive command */ + +#define CMDF_SHD 0x20 /* set head */ +#define CMDF_SCY 0x10 /* set cylinder */ +#define CMD_SK 0x02 /* seek */ +#define CMD_RST 0x01 /* restore */ + +#define CMDX_MASK 0x30 /* ext cmd bits */ +#define CMDX_RLS 0x80 /* release */ +#define CMDX_CLF 0x40 /* clear fault */ +#define CMDX_SVP 0x08 /* servo + */ +#define CMDX_SVM 0x04 /* servo - */ +#define CMDX_DSP 0x02 /* strobe + */ +#define CMDX_DSM 0x01 /* strobe - */ + +/* Geometry masks */ + +#define CY_MASK 0xFFF /* cylinder */ +#define HD_MASK 0x1F /* head mask */ +#define SC_MASK 0x3F /* sector mask */ +#define HCYL_V_HD 10 /* head/cyl word */ +#define HCYL_V_CYL 0 + +#define GET_SA(cy,sf,sc,t) (((((cy)*drv_tab[t].surf)+(sf))* \ + IDC_NUMSC)+(sc)) + +/* The MSM (IDC) controller supports (two) six different disk drive types: + + type #sectors/ #surfaces/ #cylinders/ + surface cylinder drive + + MCCDD16 64 1 823 IDC + MCCDD48 64 3 823 IDC + MCCDD80 64 5 823 IDC + MSM80 64 5 823 MSM + MSM300 64 19 823 MSM + MSM330F 64 16 1024 IDC + + In theory, each drive can be a different type. The size field in + each unit selects the drive capacity for each drive and thus the + drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE AND MUST HAVE + THE SAME SECTORS/TRACK. +*/ + +#define TYPE_MCCDD16 0 +#define SURF_MCCDD16 1 +#define CYL_MCCDD16 823 +#define SIZE_MCCDD16 (IDC_NUMSC * SURF_MCCDD16 * CYL_MCCDD16 * IDC_NUMBY) + +#define TYPE_MCCDD48 1 +#define SURF_MCCDD48 3 +#define CYL_MCCDD48 823 +#define SIZE_MCCDD48 (IDC_NUMSC * SURF_MCCDD48 * CYL_MCCDD48 * IDC_NUMBY) + +#define TYPE_MCCDD80 2 +#define SURF_MCCDD80 5 +#define CYL_MCCDD80 823 +#define SIZE_MCCDD80 (IDC_NUMSC * SURF_MCCDD80 * CYL_MCCDD80 * IDC_NUMBY) + +#define TYPE_MSM80 3 +#define SURF_MSM80 5 +#define CYL_MSM80 823 +#define SIZE_MSM80 (IDC_NUMSC * SURF_MSM80 * CYL_MSM80 * IDC_NUMBY) + +#define TYPE_MSM300 4 +#define SURF_MSM300 19 +#define CYL_MSM300 823 +#define SIZE_MSM300 (IDC_NUMSC * SURF_MSM300 * CYL_MSM300 * IDC_NUMBY) + +#define TYPE_MSM330F 5 +#define SURF_MSM330F 16 +#define CYL_MSM330F 1024 +#define SIZE_MSM330F (IDC_NUMSC * SURF_MSM330F * CYL_MSM330F * IDC_NUMBY) + + +struct drvtyp { + uint32 surf; /* surfaces */ + uint32 cyl; /* cylinders */ + uint32 size; /* #blocks */ + uint32 msmf; /* MSM drive */ +}; + +static struct drvtyp drv_tab[] = { + { SURF_MCCDD16, CYL_MCCDD16, SIZE_MCCDD16, 0 }, + { SURF_MCCDD48, CYL_MCCDD48, SIZE_MCCDD48, 0 }, + { SURF_MCCDD80, CYL_MCCDD80, SIZE_MCCDD80, 0 }, + { SURF_MSM80, CYL_MSM80, SIZE_MSM80, 1 }, + { SURF_MSM300, CYL_MSM300, SIZE_MSM300, 1 }, + { SURF_MSM330F, CYL_MSM330F, SIZE_MSM330F, 0 }, + { 0 } }; + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; + +uint8 idcxb[IDC_NUMBY * 3]; /* xfer buffer */ +uint32 idc_bptr = 0; /* buffer ptr */ +uint32 idc_db = 0; /* ctrl buffer */ +uint32 idd_db = 0; /* drive buffer */ +uint32 idc_sta = 0; /* ctrl status */ +uint32 idc_sec = 0; /* sector */ +uint32 idc_hcyl = 0; /* head/cyl */ +uint32 idc_svun = 0; /* most recent unit */ +uint32 idc_1st = 0; /* first byte */ +uint32 idc_arm = 0; /* ctrl armed */ +uint32 idd_arm[ID_NUMDR] = { 0 }; /* drives armed */ +uint16 idd_dcy[ID_NUMDR] = { 0 }; /* desired cyl */ +uint32 idd_sirq = 0; /* drive saved irq */ +int32 idc_stime = 100; /* seek latency */ +int32 idc_rtime = 100; /* rotate latency */ +int32 idc_ctime = 5; /* command latency */ +uint8 idc_tplte[] = { 0, 1, 2, 3, 4, TPL_END }; /* ctrl + drive */ + +DEVICE idc_dev; +uint32 id (uint32 dev, uint32 op, uint32 dat); +t_stat idc_svc (UNIT *uptr); +t_stat idc_reset (DEVICE *dptr); +t_stat idc_attach (UNIT *uptr, char *cptr); +t_stat idc_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat idc_rds (UNIT *uptr); +t_stat idc_wds (UNIT *uptr); +t_bool idc_dter (UNIT *uptr, uint32 first); +void idc_done (uint32 flg); + +extern t_stat id_dboot (int32 u, DEVICE *dptr); + +/* DP data structures + + idc_dev DP device descriptor + idc_unit DP unit list + idc_reg DP register list + idc_mod DP modifier list +*/ + +DIB idc_dib = { d_IDC, 0, v_IDC, idc_tplte, &id, NULL }; + +UNIT idc_unit[] = { + { UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) }, + { UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) }, + { UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) }, + { UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) } }; + +REG idc_reg[] = { + { HRDATA (STA, idc_sta, 8) }, + { HRDATA (BUF, idc_db, 8) }, + { HRDATA (SEC, idc_sec, 8) }, + { HRDATA (HCYL, idc_hcyl, 16) }, + { HRDATA (BUF, idd_db, 8) }, + { HRDATA (SVUN, idc_svun, 2), REG_HIDDEN }, + { BRDATA (DBUF, idcxb, 16, 8, IDC_NUMBY * 3) }, + { HRDATA (DBPTR, idc_bptr, 10), REG_RO }, + { FLDATA (FIRST, idc_1st, 0) }, + { GRDATA (IREQ, int_req[l_IDC], 16, ID_NUMDR + 1, i_IDC) }, + { GRDATA (IENB, int_enb[l_IDC], 16, ID_NUMDR + 1, i_IDC) }, + { GRDATA (SIREQ, idd_sirq, 16, ID_NUMDR, i_IDC + 1), REG_RO }, + { FLDATA (ICARM, idc_arm, 0) }, + { BRDATA (IDARM, idd_arm, 16, 1, ID_NUMDR) }, + { DRDATA (RTIME, idc_rtime, 24), PV_LEFT | REG_NZ }, + { DRDATA (STIME, idc_stime, 24), PV_LEFT | REG_NZ }, + { DRDATA (CTIME, idc_ctime, 24), PV_LEFT | REG_NZ }, + { BRDATA (CYL, idd_dcy, 16, 16, ID_NUMDR) }, + { URDATA (UCYL, idc_unit[0].CYL, 16, 12, 0, + ID_NUMDR, REG_RO) }, + { URDATA (UHD, idc_unit[0].HD, 16, 5, 0, + ID_NUMDR, REG_RO) }, + { URDATA (UFNC, idc_unit[0].FNC, 16, 10, 0, + ID_NUMDR, REG_HRO) }, + { URDATA (UST, idc_unit[0].STD, 16, 8, 0, + ID_NUMDR, REG_RO) }, + { URDATA (CAPAC, idc_unit[0].capac, 10, 31, 0, + ID_NUMDR, PV_LEFT | REG_HRO) }, + { HRDATA (DEVNO, idc_dib.dno, 8), REG_HRO }, + { HRDATA (SELCH, idc_dib.sch, 2), REG_HRO }, + { BRDATA (TPLTE, idc_tplte, 16, 8, ID_NUMDR + 1), REG_HRO }, + { NULL } }; + +MTAB idc_mod[] = { + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { (UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD16 << UNIT_V_DTYPE) + UNIT_ATT, + "MCCDD16", NULL, NULL }, + { (UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD48 << UNIT_V_DTYPE) + UNIT_ATT, + "MCCDD48", NULL, NULL }, + { (UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD80 << UNIT_V_DTYPE) + UNIT_ATT, + "MCCDD80", NULL, NULL }, + { (UNIT_DTYPE+UNIT_ATT), (TYPE_MSM330F << UNIT_V_DTYPE) + UNIT_ATT, + "MSM330F", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD16 << UNIT_V_DTYPE), + "MCCDD16", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD48 << UNIT_V_DTYPE), + "MCCDD48", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD80 << UNIT_V_DTYPE), + "MCCDD80", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MSM330F << UNIT_V_DTYPE), + "MSM330F", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MCCDD16 << UNIT_V_DTYPE), + NULL, "MCCDD16", &idc_set_size }, + { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MCCDD48 << UNIT_V_DTYPE), + NULL, "MCCDD48", &idc_set_size }, + { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MCCDD80 << UNIT_V_DTYPE), + NULL, "MCCDD80", &idc_set_size }, + { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MSM330F << UNIT_V_DTYPE), + NULL, "MSM330F", &idc_set_size }, + { (UNIT_DTYPE+UNIT_ATT), (TYPE_MSM80 << UNIT_V_DTYPE) + UNIT_ATT, + "MSM80", NULL, NULL }, + { (UNIT_DTYPE+UNIT_ATT), (TYPE_MSM300 << UNIT_V_DTYPE) + UNIT_ATT, + "MSM300", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MSM80 << UNIT_V_DTYPE), + "MSM80", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MSM300 << UNIT_V_DTYPE), + "MSM300", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MSM80 << UNIT_V_DTYPE), + NULL, "MSM80", &idc_set_size }, + { (UNIT_AUTO+UNIT_DTYPE), (TYPE_MSM300 << UNIT_V_DTYPE), + NULL, "MSM300", &idc_set_size }, + { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, + { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH", + &set_sch, &show_sch, NULL }, + { 0 } }; + +DEVICE idc_dev = { + "DM", idc_unit, idc_reg, idc_mod, + ID_NUMDR, 16, 29, 1, 16, 8, + NULL, NULL, &idc_reset, + &id_dboot, &idc_attach, NULL, + &idc_dib, DEV_DISABLE }; + +/* Controller: IO routine */ + +uint32 idc (uint32 dev, uint32 op, uint32 dat) +{ +uint32 f, t; +UNIT *uptr; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + sch_adr (idc_dib.sch, dev); /* inform sel ch */ + return HW; /* halfwords */ +case IO_RD: /* read data */ +case IO_RH: /* read halfword */ + return 0; /* return data */ +case IO_WD: /* write data */ + idc_sec = dat; /* sector */ + break; +case IO_WH: /* write halfword */ + idc_hcyl = dat; /* head/cylinder */ + break; +case IO_SS: /* status */ + t = idc_sta & STC_MASK; /* get status */ + if (t & SETC_EX) t = t | STA_EX; /* test for EX */ + return t; +case IO_OC: /* command */ + idc_arm = int_chg (v_IDC, dat, idc_arm); /* upd int ctrl */ + f = dat & CMC_MASK; /* get cmd */ + uptr = idc_dev.units + idc_svun; /* get unit */ + if (f & CMC_CLR) { /* clear? */ + idc_reset (&idc_dev); /* reset world */ + break; } + if (!(idc_sta & STC_IDL) || /* if !idle, */ + sim_is_active (uptr) || /* unit busy, */ + (f == CMC_EXP0)) break; /* expg, ignore */ + idc_sta = STA_BSY; /* bsy=1,idl,err=0 */ + idc_1st = 1; /* xfr not started */ + idc_bptr = 0; /* buffer empty */ + uptr->FNC = f; /* save cmd */ + sim_activate (uptr, idc_rtime); /* schedule */ + idd_sirq = int_req[l_IDC] & IDC_DIRMASK; /* save drv ints */ + int_req[l_IDC] = int_req[l_IDC] & ~IDC_DIRMASK; /* clr drv ints */ + break; } +return 0; +} + +/* Drives: IO routine */ + +uint32 id (uint32 dev, uint32 op, uint32 dat) +{ +uint32 t, u; +UNIT *uptr; + +if (dev == idc_dib.dno) return idc (dev, op, dat); /* controller? */ +u = (dev - idc_dib.dno - o_ID0) / o_ID0; /* get unit num */ +uptr = idc_dev.units + u; /* get unit ptr */ +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + if (idc_sta & STC_IDL) idc_svun = u; /* idle? save unit */ + return HW; /* byte only */ +case IO_RD: /* read data */ +case IO_RH: + return 0; +case IO_WD: /* write data */ +case IO_WH: /* write halfword */ + idd_db = dat; /* save data */ + break; +case IO_SS: /* status */ + if (uptr->flags & UNIT_ATT) t = + ((uptr->flags & UNIT_WPRT)? STD_WRP: 0) | + (sim_is_active (uptr)? STD_NRDY: 0) | + (uptr->STD & STD_UST); + else t = STD_NRDY | STD_OFFL; /* off = X'09' */ + if (t & SETD_EX) t = t | STA_EX; /* test for ex */ + return t; +case IO_OC: /* command */ + idd_arm[u] = int_chg (v_IDC + u + 1, dat, idd_arm[u]); + if (idd_arm[u] == 0) /* disarmed? */ + idd_sirq &= ~(1 << (v_IDC + u + 1)); /* clr saved req */ + if (sim_is_active (uptr) || /* if busy or */ + !(idc_sta & STC_IDL)) break; /* !idle, ignore */ + if ((dat & CMC_MASK) == CMDX_MASK) break; /* ignore 0x30 */ + uptr->FNC = (dat & CMC_MASK) | CMC_DRV; /* save cmd */ + idc_sta = idc_sta & ~STC_IDL; /* clr idle */ + sim_activate (uptr, idc_ctime); /* schedule */ + break; } +return 0; +} + +/* Unit service + + If drive command, process; if an interrupt is needed (positioning + command), schedule second part + + If data transfer command, process; must use selector channel +*/ + +t_stat idc_svc (UNIT *uptr) +{ +int32 diff; +uint32 f, u = uptr - idc_dev.units; /* get unit number */ +uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ +uint32 t; +t_stat r; + +if (uptr->FNC & CMC_DRV) { /* drive cmd? */ + f = uptr->FNC & CMC_MASK; /* get cmd */ + if (uptr->FNC & CMC_DRV1) { /* part 2? */ + if (idd_arm[u]) { /* drv int armed? */ + if (idc_sta & STC_IDL) /* ctrl idle? */ + SET_INT (v_IDC + u + 1); /* req intr */ + else idd_sirq |= (1 << (v_IDC + u + 1)); } /* def intr */ + if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; + if (((f & CMDX_MASK) == 0) && /* seek? */ + (f & (CMD_SK | CMD_RST))) { + if (idd_dcy[u] >= drv_tab[dtype].cyl) /* bad cylinder? */ + uptr->STD = uptr->STD | STD_SKI; /* error */ + uptr->CYL = idd_dcy[u]; } /* put on cyl */ + } /* end if p2 */ + else { /* part 1 */ + idc_sta = idc_sta | STC_IDL; /* set idle */ + uptr->FNC = uptr->FNC | CMC_DRV1; /* set part 2 */ + if (f >= CMDX_MASK) { /* extended? */ + if (f & CMDX_CLF) /* clr fault? */ + uptr->STD = uptr->STD & ~STD_UNS; /* clr unsafe */ + if (f & (CMDX_RLS | CMDX_SVP | CMDX_SVM)) /* intr expected? */ + sim_activate (uptr, idc_ctime); } + else if (f >= CMDF_SCY) { /* tag? */ + if (f & CMDF_SHD) uptr->HD = idd_db & HD_MASK; + else if (f & CMDF_SCY) { + if (idd_db >= drv_tab[dtype].cyl) /* bad cylinder? */ + uptr->STD = uptr->STD | STD_SKI; /* set seek inc */ + idd_dcy[u] = idd_db & CY_MASK; } } + else if (f & (CMD_SK | CMD_RST)) { /* seek? */ + if (f == CMD_RST) idd_dcy[u] = 0; /* restore? */ + if (idd_dcy[u] >= drv_tab[dtype].cyl) { /* bad cylinder? */ + uptr->STD = uptr->STD | STD_SKI; /* set seek inc */ + idd_dcy[u] = uptr->CYL; /* no motion */ + sim_activate (uptr, 0); } /* finish asap */ + else { /* cylinder ok */ + uptr->STD = uptr->STD & ~STD_SKI; /* clr seek inc */ + diff = idd_dcy[u] - uptr->CYL; + if (diff < 0) diff = -diff; /* ABS cyl diff */ + else if (diff == 0) diff = 1; /* must be nz */ + sim_activate (uptr, diff * idc_stime); } } + } /* end else p1 */ + return SCPE_OK; } /* end if drv */ + +switch (uptr->FNC & CMC_MASK) { /* case on func */ + +case CMC_RCHK: /* read check */ + idc_dter (uptr, 1); /* check xfr err */ + break; + +#if defined (ID_IDC) +case CMC_RUNC: /* read uncorr */ +#endif +case CMC_RD: /* read */ + if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */ + if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */ + /* fseek done */ + if (r = idc_rds (uptr)) return r; /* read sec, err? */ + idc_1st = 0; + t = sch_wrmem (idc_dib.sch, idcxb, IDC_NUMBY); /* write mem */ + if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */ + sim_activate (uptr, idc_rtime); /* reschedule */ + return SCPE_OK; } + break; } /* no, set done */ + idc_sta = idc_sta | STC_DTE; /* cant work */ + break; + +case CMC_WR: /* write */ + if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */ + idc_bptr = sch_rdmem (idc_dib.sch, idcxb, IDC_NUMBY); /* read mem */ + idc_db = idcxb[idc_bptr - 1]; /* last byte */ + if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */ + if (r = idc_wds (uptr)) return r; /* write sec, err? */ + idc_1st = 0; + if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */ + sim_activate (uptr, idc_rtime); /* reschedule */ + return SCPE_OK; } + break; } /* no, set done */ + idc_sta = idc_sta | STC_DTE; /* cant work */ + break; + +case CMC_FCHK: case CMC_RFMT: case CMC_WFMT: case CMC_WFTK: + idc_dter (uptr, 1); + idc_sta = idc_sta | STC_WRP; + break; + +#if defined (ID_IDC) +case CMC_RRAM: /* read RAM */ + if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */ + sch_wrmem (idc_dib.sch, idcxb, IDC_NUMBY * 3); + if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */ + sim_activate (uptr, idc_rtime); /* reschedule */ + return SCPE_OK; } + break; } /* no, set done */ + idc_sta = idc_sta | STC_DTE; /* cant work */ + break; + +case CMC_WRAM: /* write RAM */ + if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */ + sch_rdmem (idc_dib.sch, idcxb, IDC_NUMBY * 3); /* read from mem */ + if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */ + sim_activate (uptr, idc_rtime); /* reschedule */ + return SCPE_OK; } + break; } /* no, set done */ + idc_sta = idc_sta | STC_DTE; /* cant work */ + break; + +case CMC_STST: case CMC_LAMP: /* tests */ + break; +#endif + +default: + idc_sta = idc_sta | STC_DTE; + break; } + +idc_done (0); /* done */ +return SCPE_OK; +} + +/* Read data sector */ + +t_stat idc_rds (UNIT *uptr) +{ +uint32 i; + +i = fxread (idcxb, sizeof (uint8), IDC_NUMBY, uptr->fileref); +if (ferror (uptr->fileref)) { /* error? */ + perror ("IDC I/O error"); + clearerr (uptr->fileref); + idc_done (STC_DTE); + return SCPE_IOERR; } +for ( ; i < IDC_NUMBY; i++) idcxb[i] = 0; /* fill with 0's */ +return SCPE_OK; +} + +/* Write data sector */ + +t_bool idc_wds (UNIT *uptr) +{ +for ( ; idc_bptr < IDC_NUMBY; idc_bptr++) + idcxb[idc_bptr] = idc_db; /* fill with last */ +fxwrite (idcxb, sizeof (uint8), IDC_NUMBY, uptr->fileref); +if (ferror (uptr->fileref)) { /* error? */ + perror ("IDC I/O error"); + clearerr (uptr->fileref); + idc_done (STC_DTE); + return SCPE_IOERR; } +return FALSE; +} + +/* Data transfer error test routine */ + +t_bool idc_dter (UNIT *uptr, uint32 first) +{ +uint32 cy; +uint32 hd, sc, sa; +uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ + +if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ + idc_done (STC_DTE); /* error, done */ + return TRUE; } +if ((uptr->flags & UNIT_WPRT) && (uptr->FNC == CMC_WR)) { + idc_done (STC_WRP); /* error, done */ + return TRUE; } +cy = uptr->CYL; /* get cylinder */ +hd = uptr->HD; /* get head */ +sc = idc_sec & SC_MASK; /* get sector */ +if (cy >= drv_tab[dtype].cyl) { /* bad cylinder? */ + uptr->STD = uptr->STD | STD_SKI; /* error */ + idc_done (STC_DTE); /* error, done */ + return TRUE; } +if (hd >= drv_tab[dtype].surf) { /* bad head? */ + if (first) { /* 1st xfer? */ + uptr->STD = uptr->STD | STD_UNS; /* drive unsafe */ + idc_done (STC_ACF); } + else idc_done (STC_CYO); /* no, cyl ovf */ + return TRUE; } +sa = GET_SA (cy, hd, sc, dtype); /* curr disk addr */ +fseek (uptr->fileref, sa * IDC_NUMBY, SEEK_SET); /* seek to pos */ +idc_sec = (idc_sec + 1) & SC_MASK; /* incr disk addr */ +if (idc_sec == 0) uptr->HD = uptr->HD + 1; +return FALSE; +} + +/* Data transfer done routine */ + +void idc_done (uint32 flg) +{ +idc_sta = (idc_sta | STC_IDL | flg) & ~STA_BSY; /* set flag, idle */ +if (idc_arm) SET_INT (v_IDC); /* if armed, intr */ +int_req[l_IDC] = int_req[l_IDC] | idd_sirq; /* restore drv ints */ +idd_sirq = 0; /* clear saved */ +if (flg) sch_stop (idc_dib.sch); /* if err, stop sch */ +return; +} + +/* Reset routine */ + +t_stat idc_reset (DEVICE *dptr) +{ +uint32 u; +UNIT *uptr; + +idc_sta = STC_IDL | STA_BSY; /* idle, busy */ +idc_1st = 0; /* clear flag */ +idc_svun = idc_db = 0; /* clear unit, buf */ +idc_sec = 0; /* clear addr */ +idc_hcyl = 0; +CLR_INT (v_IDC); /* clear ctrl int */ +CLR_ENB (v_IDC); /* clear ctrl enb */ +idc_arm = 0; /* clear ctrl arm */ +idd_sirq = 0; +for (u = 0; u < ID_NUMDR; u++) { /* loop thru units */ + uptr = idc_dev.units + u; + uptr->CYL = uptr->STD = 0; + uptr->HD = uptr->FNC = 0; + idd_dcy[u] = 0; + CLR_INT (v_IDC + u + 1); /* clear intr */ + CLR_ENB (v_IDC + u + 1); /* clear enable */ + idd_arm[u] = 0; /* clear arm */ + sim_cancel (uptr); } /* cancel activity */ +return SCPE_OK; +} + +/* Attach routine (with optional autosizing) */ + +t_stat idc_attach (UNIT *uptr, char *cptr) +{ +uint32 i, p; +t_stat r; + +uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; +r = attach_unit (uptr, cptr); +uptr->CYL = 0; +if ((r != SCPE_OK) || ((uptr->flags & UNIT_AUTO) == 0)) return r; +if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; +if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK; +for (i = 0; drv_tab[i].surf != 0; i++) { + if (p <= drv_tab[i].size) { + uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); + uptr->capac = drv_tab[i].size; + return SCPE_OK; } } +return SCPE_OK; +} + +/* Set size command validation routine */ + +t_stat idc_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (uptr->flags & UNIT_ATT) return SCPE_ALATT; +uptr->capac = drv_tab[GET_DTYPE (val)].size; +return SCPE_OK; +} diff --git a/Interdata/id_io.c b/Interdata/id_io.c new file mode 100644 index 00000000..cb0f1095 --- /dev/null +++ b/Interdata/id_io.c @@ -0,0 +1,542 @@ +/* id_io.c: Interdata CPU-independent I/O routines + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + Interdata I/O devices are defined by a device information block: + + dno base device number + sch selector channel, -1 if none + irq interrupt request flag + tplte device number template, NULL if one device number + iot I/O processing routine + ini initialization routine + + Interdata I/O uses the following interconnected tables: + + dev_tab[dev] Indexed by device number, points to the I/O instruction + processing routine for the device. Initialized in the + device reset routine. + + sch_tab[dev] Indexed by device number, if non-zero, the number + 1 + of the selector channel used by the device. + + int_req[level] Indexed by interrupt level, device interrupt flags. + + int_enb[level] Indexed by interrupt level, device interrupt enable flags. + + int_tab[idx] Indexed by ((interrupt level * 32) + interrupt number), + maps bit positions in int_req to device numbers. +*/ + +#include "id_defs.h" + +/* Selector channel */ + +#define SCHC_EXA 0x40 /* read ext addr */ +#define SCHC_RD 0x20 /* read */ +#define SCHC_GO 0x10 /* go */ +#define SCHC_STOP 0x08 /* stop */ +#define SCHC_SSTA 0x04 /* sel ch status */ +#define SCHC_EXM 0x03 /* ext mem */ + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; +extern uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout); +extern uint32 pawidth; +extern UNIT cpu_unit; +extern FILE *sim_log; +extern DEVICE *sim_devices[]; + +uint32 sch_max = 2; /* sch count */ +uint32 sch_sa[SCH_NUMCH] = { 0 }; /* start addr */ +uint32 sch_ea[SCH_NUMCH] = { 0 }; /* end addr */ +uint8 sch_sdv[SCH_NUMCH] = { 0 }; /* device */ +uint8 sch_cmd[SCH_NUMCH] = { 0 }; /* command */ +uint8 sch_rdp[SCH_NUMCH] = { 0 }; /* read ptr */ +uint8 sch_wdc[SCH_NUMCH] = { 0 }; /* write ctr */ +uint32 sch_tab[DEVNO] = { 0 }; /* dev to sch map */ +uint32 int_tab[INTSZ * 32] = { 0 }; /* int to dev map */ +uint8 sch_tplte[SCH_NUMCH + 1]; /* dnum template */ + +uint32 sch (uint32 dev, uint32 op, uint32 dat); +void sch_ini (t_bool dtpl); +t_stat sch_reset (DEVICE *dptr); +t_stat sch_vchan (UNIT *uptr, int32 val, char *cptr, void *desc); + +/* Selector channel data structures + + sch_dev channel device descriptor + sch_unit channel unit descriptor + sch_mod channel modifiers list + sch_reg channel register list +*/ + +DIB sch_dib = { d_SCH, -1, v_SCH, sch_tplte, &sch, &sch_ini }; + +UNIT sch_unit = { UDATA (NULL, 0, 0) }; + +REG sch_reg[] = { + { HRDATA (CHAN, sch_max, 3), REG_HRO }, + { BRDATA (SA, sch_sa, 16, 20, SCH_NUMCH) }, + { BRDATA (EA, sch_ea, 16, 20, SCH_NUMCH) }, + { BRDATA (CMD, sch_cmd, 16, 8, SCH_NUMCH) }, + { BRDATA (DEV, sch_sdv, 16, 8, SCH_NUMCH) }, + { BRDATA (RDP, sch_rdp, 16, 2, SCH_NUMCH) }, + { BRDATA (WDC, sch_wdc, 16, 3, SCH_NUMCH) }, + { GRDATA (IREQ, int_req[l_SCH], 16, SCH_NUMCH, i_SCH) }, + { GRDATA (IENB, int_enb[l_SCH], 16, SCH_NUMCH, i_SCH) }, + { HRDATA (DEVNO, sch_dib.dno, 8), REG_HRO }, + { NULL } }; + +MTAB sch_mod[] = { + { MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "channels", "CHANNELS", + &sch_vchan, NULL, &sch_reg[0] }, + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, &sch_dib }, + { 0 } }; + +DEVICE sch_dev = { + "SELCH", &sch_unit, sch_reg, sch_mod, + 1, 16, 8, 1, 16, 8, + NULL, NULL, &sch_reset, + NULL, NULL, NULL, + &sch_dib, 0 }; + +/* (Extended) selector channel + + There are really three different selector channels: + - 16b selector channel (max 4B of data) + - 18b selector channel (max 4B of data) + - 20b selector channel (max 6B of data) + The algorithm for loading the start and end addresses is taken + from the maintenance manual for the Extended Selector Channel. +*/ + +#define SCH_EXR(ch) ((sch_cmd[ch] & SCHC_EXA) && (pawidth == PAWIDTH32)) + +uint32 sch (uint32 dev, uint32 op, uint32 dat) +{ +uint32 t, bank, sdv, ch = dev - sch_dib.dno; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + return BY; /* byte only */ +case IO_RD: /* read data */ + t = (sch_sa[ch] >> (sch_rdp[ch] * 8)) & DMASK8; /* get sa byte */ + if (sch_rdp[ch] == 0) sch_rdp[ch] = /* wrap? */ + SCH_EXR (ch)? 2: 1; + else sch_rdp[ch] = sch_rdp[ch] - 1; /* dec byte ptr */ + return t; +case IO_WD: /* write data */ + if (pawidth != PAWIDTH32) { /* 16b? max 4 */ + if (sch_wdc[ch] >= 4) break; /* stop at 4 */ + sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea to sa */ + (sch_ea[ch] >> 8)) & DMASK16; + sch_ea[ch] = ((sch_ea[ch] << 8) | /* ripple ea low */ + dat) & DMASK16; } /* insert byte */ + else { /* 32b? max 6 */ + if (sch_wdc[ch] >= 6) break; /* stop at 6 */ + if (sch_wdc[ch] != 5) { /* if not last */ + sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea<15:8> to sa */ + ((sch_ea[ch] >> 8) & DMASK8)) & PAMASK32; + sch_ea[ch] = /* ripple ea<7:0> */ + (((sch_ea[ch] & DMASK8) << 8) | dat) & PAMASK32; } + else sch_ea[ch] = ((sch_ea[ch] << 8) | dat) & PAMASK32; } + sch_wdc[ch] = sch_wdc[ch] + 1; /* adv sequencer */ + break; +case IO_SS: /* status */ + if (sch_cmd[ch] & SCHC_GO) return STA_BSY; /* test busy */ + if (sch_cmd[ch] & SCHC_SSTA) return 0; /* test sch sta */ + else { + sdv = sch_sdv[ch]; /* get dev */ + if (dev_tab[sdv] == 0) return CC_V; /* not there? */ + dev_tab[sdv] (sdv, IO_ADR, 0); /* select dev */ + t = dev_tab[sdv] (sdv, IO_SS, 0); /* get status */ + return t & ~STA_BSY; } /* clr busy */ +case IO_OC: /* command */ + bank = 0; /* assume no bank */ + if (pawidth != PAWIDTH32) { /* 16b/18b proc? */ + dat = dat & ~(SCHC_EXA | SCHC_SSTA); /* clr ext func */ + if (pawidth == PAWIDTH16E) /* 18b proc? */ + bank = (dat & SCHC_EXM) << 16; } + if (dat & SCHC_STOP) { /* stop? */ + sch_cmd[ch] = dat & (SCHC_EXA | SCHC_SSTA); /* clr go */ + CLR_INT (v_SCH + ch); /* clr intr */ + sch_rdp[ch] = SCH_EXR (ch)? 2: 1; /* init sequencers */ + sch_wdc[ch] = 0; } + else if (dat & SCHC_GO) { /* go? */ + sch_cmd[ch] = dat & (SCHC_GO | SCHC_RD); + if (sch_wdc[ch] <= 4) { /* 4 bytes? */ + sch_sa[ch] = (sch_sa[ch] & PAMASK16) | bank; /* 16b addr */ + sch_ea[ch] = (sch_ea[ch] & PAMASK16) | bank; } + sch_sa[ch] = sch_sa[ch] & ~1; + if (sch_ea[ch] <= sch_sa[ch]) /* wrap? */ + sch_ea[ch] = sch_ea[ch] | /* modify end addr */ + ((pawidth == PAWIDTH32)? PAMASK32: PAMASK16); } + break; } +return 0; +} + +/* CPU call to test if channel blocks access to device */ + +t_bool sch_blk (uint32 dev) +{ +uint32 ch = sch_tab[dev] - 1; + +if ((ch < sch_max) && (sch_cmd[ch] & SCHC_GO)) return TRUE; +return FALSE; +} + +/* Device call to 'remember' last dev on channel */ + +void sch_adr (uint32 ch, uint32 dev) +{ +if (ch < sch_max) sch_sdv[ch] = dev; +return; +} + +/* Device call to see if selector channel is active for device */ + +t_bool sch_actv (uint32 ch, uint32 dev) +{ +if ((ch < sch_max) && /* chan valid, */ + (sch_cmd[ch] & SCHC_GO) && /* on, and */ + (sch_sdv[ch] == dev)) return TRUE; /* set for dev? */ +return FALSE; /* no */ +} + +/* Device call to read a block of memory */ + +uint32 sch_rdmem (uint32 ch, uint8 *buf, uint32 cnt) +{ +uint32 addr, end, xfr, inc; + +if ((ch >= sch_max) || ((sch_cmd[ch] & SCHC_GO) == 0)) return 0; +addr = sch_sa[ch]; /* start */ +end = sch_ea[ch]; /* end */ +xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */ +inc = IOReadBlk (addr, xfr, buf); /* read mem */ +if ((addr + inc) > end) { /* end? */ + SET_INT (v_SCH + ch); /* interrupt */ + sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */ + sch_sa[ch] = sch_sa[ch] + inc - 1; } /* end addr */ +else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */ +return inc; +} + +/* Device call to write a block of memory */ + +uint32 sch_wrmem (uint32 ch, uint8 *buf, uint32 cnt) +{ +uint32 addr, end, xfr, inc; + +if ((ch >= sch_max) || ((sch_cmd[ch] & SCHC_GO) == 0)) return 0; +addr = sch_sa[ch]; /* start */ +end = sch_ea[ch]; /* end */ +xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */ +inc = IOWriteBlk (addr, xfr, buf); /* write mem */ +if ((addr + inc) > end) { /* end? */ + SET_INT (v_SCH + ch); /* interrupt */ + sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */ + sch_sa[ch] = sch_sa[ch] + inc - 1; } /* end addr */ +else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */ +return inc; +} + +/* Device call to stop a selector channel */ + +void sch_stop (uint32 ch) +{ +if (ch < sch_max) { + SET_INT (v_SCH + ch); /* interrupt */ + sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); } /* clear GO */ +return; +} + +/* Reset */ + +void sch_reset_ch (uint32 rst_lim) +{ +uint32 ch; + +for (ch = 0; ch < SCH_NUMCH; ch++) { + if (ch >= rst_lim) { + CLR_INT (v_SCH + ch); + SET_ENB (v_SCH + ch); + sch_sa[ch] = sch_ea[ch] = 0; + sch_cmd[ch] = sch_sdv[ch] = 0; + sch_wdc[ch] = 0; + sch_rdp[ch] = 1; } } +return; +} + +t_stat sch_reset (DEVICE *dptr) +{ +sch_reset_ch (0); /* reset all chan */ +return SCPE_OK; +} + +/* Set number of channels */ + +t_stat sch_vchan (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 i, newmax; +t_stat r; + +if (cptr == NULL) return SCPE_ARG; +newmax = get_uint (cptr, 10, SCH_NUMCH, &r); /* get new max */ +if ((r != SCPE_OK) || (newmax == sch_max)) return r; /* err or no chg? */ +if (newmax == 0) return SCPE_ARG; /* must be > 0 */ +if (newmax < sch_max) { /* reducing? */ + for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */ + dibp = (DIB *) dptr->ctxt; /* get DIB */ + if (dibp && (dibp->sch >= (int32) newmax)) {/* dev using chan? */ + printf ("Device %02X uses channel %d\n", + dibp->dno, dibp->sch); + if (sim_log) fprintf (sim_log, "Device %02X uses channel %d\n", + dibp->dno, dibp->sch); + return SCPE_OK; } } } +sch_max = newmax; /* set new max */ +sch_reset_ch (sch_max); /* reset chan */ +return SCPE_OK; +} + +/* Initialize template */ + +void sch_ini (t_bool dtpl) +{ +uint32 i; + +for (i = 0; i < sch_max; i++) sch_tplte[i] = i; +sch_tplte[sch_max] = TPL_END; +return; +} + +/* Evaluate interrupt */ + +void int_eval (void) +{ +int i; +extern uint32 qevent; + +for (i = 0; i < INTSZ; i++) + if (int_req[i] & int_enb[i]) { + qevent = qevent | EV_INT; + return; } +qevent = qevent & ~EV_INT; +return; +} + +/* Return interrupting device */ + +uint32 int_getdev (void) +{ +int32 i, j, t; +uint32 r; + +for (i = t = 0; i < INTSZ; i++) { /* loop thru array */ + if (r = int_req[i] & int_enb[i]) { /* find nz int wd */ + for (j = 0; j < 32; t++, j++) { + if (r & (1u << j)) { + int_req[i] = int_req[i] & ~(1u << j); /* clr request */ + return int_tab[t]; } } } + else t = t + 32; } +return 0; +} + +/* Update device interrupt status */ + +int32 int_chg (uint32 irq, int32 dat, int32 arm) +{ +int32 t = CMD_GETINT (dat); /* get int ctrl */ + +if (t == CMD_IENB) { /* enable? */ + SET_ENB (irq); + return 1; } +else if (t == CMD_IDIS) { /* disable? */ + CLR_ENB (irq); + return 1; } +if (t == CMD_IDSA) { /* disarm? */ + CLR_ENB (irq); + CLR_INT (irq); + return 0; } +return arm; +} + +/* Process a 2b field and return unchanged, set, clear, complement */ + +int32 io_2b (int32 val, int32 pos, int32 old) +{ +int32 t = (val >> pos) & 3; +if (t == 0) return old; +if (t == 1) return 1; +if (t == 2) return 0; +return old ^1; +} + +/* Block transfer routines */ + +uint32 IOReadBlk (uint32 loc, uint32 cnt, uint8 *buf) +{ +uint32 i; + +if (!MEM_ADDR_OK (loc) || (cnt == 0)) return 0; +if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc; +for (i = 0; i < cnt; i++) buf[i] = IOReadB (loc + i); +return cnt; +} + +uint32 IOWriteBlk (uint32 loc, uint32 cnt, uint8 *buf) +{ +uint32 i; + +if (!MEM_ADDR_OK (loc) || (cnt == 0)) return 0; +if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc; +for (i = 0; i < cnt; i++) IOWriteB (loc + i, buf[i]); +return cnt; +} + +/* Change selector channel for a device */ + +t_stat set_sch (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 newch; +t_stat r; + +if (cptr == NULL) return SCPE_ARG; +if (uptr == NULL) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR; +newch = get_uint (cptr, 16, sch_max - 1, &r); /* get new */ +if (r != SCPE_OK) return r; +dibp->sch = newch; /* store */ +return SCPE_OK; +} + +/* Show selector channel for a device */ + +t_stat show_sch (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +DEVICE *dptr; +DIB *dibp; + +if (uptr == NULL) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR; +fprintf (st, "selch=%X", dibp->sch); +return SCPE_OK; +} + +/* Change device number for a device */ + +t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 newdev; +t_stat r; + +if (cptr == NULL) return SCPE_ARG; +if (uptr == NULL) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +newdev = get_uint (cptr, 16, DEV_MAX, &r); /* get new */ +if ((r != SCPE_OK) || (newdev == dibp->dno)) return r; +if (newdev == 0) return SCPE_ARG; /* must be > 0 */ +dibp->dno = newdev; /* store */ +return SCPE_OK; +} + +/* Show device number for a device */ + +t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +DEVICE *dptr; +DIB *dibp; + +if (uptr == NULL) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if ((dibp == NULL) || (dibp->dno == 0)) return SCPE_IERR; +fprintf (st, "devno=%02X", dibp->dno); +return SCPE_OK; +} + +/* Init device tables */ + +t_bool devtab_init (void) +{ +DEVICE *dptr; +DIB *dibp; +uint32 i, j, dno, dmsk, doff, t, dmap[DEVNO / 32]; +uint8 *tplte, dflt_tplte[] = { 0, TPL_END }; + +/* Clear tables, device map */ + +for (i = 0; i < DEVNO; i++) { + dev_tab[i] = NULL; + sch_tab[i] = 0; } +for (i = 0; i < (INTSZ * 32); i++) int_tab[i] = 0; +for (i = 0; i < (DEVNO / 32); i++) dmap[i] = 0; + +/* Test each device for conflict; add to map; init tables */ + +for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */ + dibp = (DIB *) dptr->ctxt; /* get DIB */ + if ((dibp == NULL) || (dptr->flags & DEV_DIS)) continue; /* exist, enabled? */ + dno = dibp->dno; /* get device num */ + if (dibp->ini) dibp->ini (TRUE); /* gen dno template */ + tplte = dibp->tplte; /* get template */ + if (tplte == NULL) tplte = dflt_tplte; /* none? use default */ + for ( ; *tplte != TPL_END; tplte++) { /* loop thru template */ + t = (dno + *tplte) & DEV_MAX; /* loop thru template */ + dmsk = 1u << (t & 0x1F); /* bit to test */ + doff = t / 32; /* word to test */ + if (dmap[doff] & dmsk) { /* in use? */ + printf ("Device number conflict, devno = %02X\n", t); + if (sim_log) fprintf (sim_log, + "Device number conflict, devno = %02X\n", t); + return TRUE; } + dmap[doff] = dmap[doff] | dmsk; + if (dibp->sch >= 0) sch_tab[t] = dibp->sch + 1; + dev_tab[t] = dibp->iot; } + + if (dibp->ini) dibp->ini (FALSE); /* gen int template */ + tplte = dibp->tplte; /* get template */ + if (tplte == NULL) tplte = dflt_tplte; /* none? use default */ + for (j = dibp->irq; *tplte != TPL_END; j++, tplte++) { + int_tab[j] = (dno + *tplte) & DEV_MAX; } + } /* end for i */ +return FALSE; +} diff --git a/Interdata/id_lp.c b/Interdata/id_lp.c new file mode 100644 index 00000000..6f1d97a3 --- /dev/null +++ b/Interdata/id_lp.c @@ -0,0 +1,288 @@ +/* id_lp.c: Interdata line printer + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + lpt M46-206 line printer +*/ + +#include "id_defs.h" +#include + +/* Device definitions */ + +#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */ +#define UNIT_UC (1 << UNIT_V_UC) +#define SPC_BASE 0x40 /* spacing base */ +#define VFU_BASE 0x78 /* VFU base */ +#define VFU_WIDTH 0x8 /* VFU width */ +#define LF 0xA +#define VT 0xB +#define VT_VFU 4 /* VFU chan for VT */ +#define FF 0xC +#define FF_VFU 8 /* VFU chan for FF */ +#define CR 0xD +#define VFUP(ch,val) ((val) & (1 << (ch))) /* VFU chan test */ + +/* Status byte, * = dynamic */ + +#define STA_PAPE 0x40 /* *paper empty */ +#define STA_MASK (STA_BSY) /* static status */ + +uint32 lpt_sta = STA_BSY; /* status */ +char lpxb[LPT_WIDTH + 1]; /* line buffer */ +uint32 lpt_bptr = 0; /* buf ptr */ +uint32 lpt_spnd = 0; /* space pending */ +uint32 lpt_vfup = 0; /* VFU ptr */ +uint32 lpt_vful = 1; /* VFU lnt */ +uint8 lpt_vfut[VFU_LNT] = { 0xFF }; /* VFU tape */ +uint32 lpt_arm = 0; /* int armed */ +int32 lpt_ctime = 10; /* char time */ +int32 lpt_stime = 1000; /* space time */ +int32 lpt_stopioe = 0; /* stop on err */ + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; + +DEVICE lpt_dev; +uint32 lpt (uint32 dev, uint32 op, uint32 dat); +t_stat lpt_svc (UNIT *uptr); +t_stat lpt_reset (DEVICE *dptr); +t_stat lpt_attach (UNIT *uptr, char *cptr); +t_stat lpt_bufout (UNIT *uptr); +t_stat lpt_vfu (UNIT *uptr, int32 ch); +t_stat lpt_spc (UNIT *uptr, int32 cnt); + +/* LPT data structures + + lpt_dev LPT device descriptor + lpt_unit LPT unit descriptors + lpt_reg LPT register list +*/ + +DIB lpt_dib = { d_LPT, -1, v_LPT, NULL, &lpt, NULL }; + +UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_UC, 0) }; + +REG lpt_reg[] = { + { HRDATA (STA, lpt_sta, 8) }, + { HRDATA (BUF, lpt_unit.buf, 7) }, + { BRDATA (DBUF, lpxb, 16, 7, LPT_WIDTH) }, + { HRDATA (DBPTR, lpt_bptr, 8) }, + { HRDATA (VFUP, lpt_vfup, 8) }, + { HRDATA (VFUL, lpt_vful, 8) }, + { BRDATA (VFUT, lpt_vfut, 16, 8, VFU_LNT) }, + { FLDATA (IREQ, int_req[l_LPT], i_LPT) }, + { FLDATA (IENB, int_enb[l_LPT], i_LPT) }, + { FLDATA (IARM, lpt_arm, 0) }, + { DRDATA (POS, lpt_unit.pos, 32), PV_LEFT }, + { DRDATA (CTIME, lpt_ctime, 24), PV_LEFT }, + { DRDATA (STIME, lpt_stime, 24), PV_LEFT }, + { FLDATA (STOP_IOE, lpt_stopioe, 0) }, + { HRDATA (DEVNO, lpt_dib.dno, 8), REG_HRO }, + { NULL } }; + +MTAB lpt_mod[] = { + { UNIT_UC, 0, "lower case", "LC", NULL }, + { UNIT_UC, UNIT_UC, "upper case", "UC", NULL }, + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, NULL }, + { 0 } }; + +DEVICE lpt_dev = { + "LPT", &lpt_unit, lpt_reg, lpt_mod, + 1, 10, 31, 1, 16, 7, + NULL, NULL, &lpt_reset, + NULL, &lpt_attach, NULL, + &lpt_dib, DEV_DISABLE }; + +/* Line printer: IO routine */ + +uint32 lpt (uint32 dev, uint32 op, uint32 dat) +{ +int32 t; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + return BY; /* byte only */ +case IO_OC: /* command */ + lpt_arm = int_chg (v_LPT, dat, lpt_arm); /* upd int ctrl */ + break; +case IO_WD: /* write */ + t = lpt_unit.buf = dat & 0x7F; /* mask char */ + lpt_sta = STA_BSY; /* set busy */ + if (lpt_spnd || ((t >= LF) && (t <= CR))) /* space op? */ + sim_activate (&lpt_unit, lpt_stime); + else sim_activate (&lpt_unit, lpt_ctime); /* normal char */ + break; +case IO_SS: /* status */ + t = lpt_sta & STA_MASK; /* status byte */ + if ((lpt_unit.flags & UNIT_ATT) == 0) /* test paper out */ + t = t | STA_EX | STA_PAPE | STA_BSY; + return t; } +return 0; +} + +/* Unit service */ + +t_stat lpt_svc (UNIT *uptr) +{ +int32 t; +t_stat r = SCPE_OK; + +lpt_sta = 0; /* clear busy */ +if (lpt_arm) SET_INT (v_LPT); /* armed? intr */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (lpt_stopioe, SCPE_UNATT); +t = uptr->buf; /* get character */ +if (lpt_spnd || ((t >= LF) && (t < CR))) { /* spc pend or spc op? */ + lpt_spnd = 0; + if (lpt_bufout (uptr) != SCPE_OK) return SCPE_IOERR; /* print */ + if ((t == 1) || (t == LF)) lpt_spc (uptr, 1); /* single space */ + else if (t == VT) r = lpt_vfu (uptr, VT_VFU - 1); /* VT->VFU */ + else if (t == 0xC) r = lpt_vfu (uptr, FF_VFU - 1); /* FF->VFU */ + else if ((t >= SPC_BASE) && (t < VFU_BASE)) + lpt_spc (uptr, t - SPC_BASE); /* space */ + else if ((t >= VFU_BASE) && (t < VFU_BASE + VFU_WIDTH)) + r = lpt_vfu (uptr, t - VFU_BASE); /* VFU */ + else fputs ("\r", uptr->fileref); /* overprint */ + uptr->pos = ftell (uptr->fileref); /* update position */ + if (ferror (lpt_unit.fileref)) { + perror ("LPT I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; } } +else if (t == CR) { /* CR? */ + lpt_spnd = 1; /* set spc pend */ + return lpt_bufout (uptr); } /* print line */ +else if (t >= 0x40) { /* printable? */ + if ((uptr->flags & UNIT_UC) && islower (t)) /* UC only? */ + t = toupper (t); + if (lpt_bptr < LPT_WIDTH) lpxb[lpt_bptr++] = t; } +return r; +} + +/* Printing and spacing routines */ + +t_stat lpt_bufout (UNIT *uptr) +{ +int32 i; +t_stat r = SCPE_OK; + +if (lpt_bptr == 0) return SCPE_OK; /* any char in buf? */ +for (i = LPT_WIDTH - 1; (i >= 0) && (lpxb[i] == ' '); i--) + lpxb[i] = 0; /* backscan line */ +if (lpxb[0]) { /* any char left? */ + fputs (lpxb, uptr->fileref); /* write line */ + lpt_unit.pos = ftell (uptr->fileref); /* update position */ + if (ferror (uptr->fileref)) { + perror ("LPT I/O error"); + clearerr (uptr->fileref); + r = SCPE_IOERR; } } +lpt_bptr = 0; /* reset buffer */ +for (i = 0; i < LPT_WIDTH; i++) lpxb[i] = ' '; +lpxb[LPT_WIDTH] = 0; +return r; +} + +t_stat lpt_vfu (UNIT *uptr, int32 ch) +{ +uint32 i, j; + +if ((ch == (FF_VFU - 1)) && VFUP (ch, lpt_vfut[0])) { /* top of form? */ + fputs ("\n\f", uptr->fileref); /* nl + ff */ + lpt_vfup = 0; /* top of page */ + return SCPE_OK; } +for (i = 1; i < lpt_vful + 1; i++) { /* sweep thru cct */ + lpt_vfup = (lpt_vfup + 1) % lpt_vful; /* adv pointer */ + if (VFUP (ch, lpt_vfut[lpt_vfup])) { /* chan punched? */ + for (j = 0; j < i; j++) fputc ('\n', uptr->fileref); + return SCPE_OK; } } +return STOP_VFU; /* runaway channel */ +} + +t_stat lpt_spc (UNIT *uptr, int32 cnt) +{ +int32 i; + +if (cnt == 0) fputc ('\r', uptr->fileref); +else { for (i = 0; i < cnt; i++) fputc ('\n', uptr->fileref); + lpt_vfup = (lpt_vfup + cnt) % lpt_vful; } +return SCPE_OK; +} + +/* Reset routine */ + +t_stat lpt_reset (DEVICE *dptr) +{ +int32 i; + +sim_cancel (&lpt_unit); /* deactivate */ +lpt_sta = 0; /* clr busy */ +lpt_bptr = 0; /* clr buf ptr */ +for (i = 0; i < LPT_WIDTH; i++) lpxb[i] = ' '; /* clr buf */ +lpxb[LPT_WIDTH] = 0; +CLR_INT (v_LPT); /* clearr int */ +CLR_ENB (v_LPT); /* disable int */ +lpt_arm = 0; /* disarm int */ +return SCPE_OK; +} + +/* Attach routine */ + +t_stat lpt_attach (UNIT *uptr, char *cptr) +{ +lpt_vfup = 0; /* top of form */ +return attach_unit (uptr, cptr); +} + +/* Carriage control load routine */ + +t_stat lp_load (FILE *fileref, char *cptr, char *fnam) +{ +int32 col, ptr, mask, vfubuf[VFU_LNT]; +uint32 rpt; +t_stat r; +char cbuf[CBUFSIZE], gbuf[CBUFSIZE]; + +if (*cptr != 0) return SCPE_ARG; +ptr = 0; +for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */ + mask = 0; + if (*cptr == '(') { /* repeat count? */ + cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */ + rpt = get_uint (gbuf, 10, VFU_LNT, &r); /* repeat count */ + if (r != SCPE_OK) return SCPE_FMT; } + else rpt = 1; + while (*cptr != 0) { /* get col no's */ + cptr = get_glyph (cptr, gbuf, ','); /* get next field */ + col = get_uint (gbuf, 10, 7, &r); /* column number */ + if (r != SCPE_OK) return SCPE_FMT; + mask = mask | (1 << col); } /* set bit */ + for ( ; rpt > 0; rpt--) { /* store vals */ + if (ptr >= VFU_LNT) return SCPE_FMT; + vfubuf[ptr++] = mask; } } +if (ptr == 0) return SCPE_FMT; +lpt_vful = ptr; +lpt_vfup = 0; +for (rpt = 0; rpt < lpt_vful; rpt++) lpt_vfut[rpt] = vfubuf[rpt]; +return SCPE_OK; +} diff --git a/Interdata/id_mt.c b/Interdata/id_mt.c new file mode 100644 index 00000000..3053deb3 --- /dev/null +++ b/Interdata/id_mt.c @@ -0,0 +1,529 @@ +/* id_mt.c: Interdata magnetic tape simulator + + Copyright (c) 2001-2002, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + mt M46-494 dual density 9-track magtape controller + + Magnetic tapes are represented as a series of variable 8b records + of the form: + + 32b record length in bytes - exact number + byte 0 + byte 1 + : + byte n-2 + byte n-1 + 32b record length in bytes - exact number + + If the byte count is odd, the record is padded with an extra byte + of junk. File marks are represented by a single record length of 0. + End of tape is two consecutive end of file marks. +*/ + +#include "id_defs.h" + +#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */ +#define UNIT_WLK (1 << UNIT_V_WLK) +#define UNIT_PNU (1 << UNIT_V_PNU) +#define UST u3 /* unit status */ +#define UCMD u4 /* unit command */ +#define MT_MAXFR (1 << 16) /* max transfer */ +#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ + +/* Command - in UCMD */ + +#define MTC_SPCR 0x11 /* backspace */ +#define MTC_SKFR 0x13 /* space file rev */ +#define MTC_CLR 0x20 /* clear */ +#define MTC_RD 0x21 /* read */ +#define MTC_WR 0x22 /* write */ +#define MTC_SKFF 0x23 /* space file fwd */ +#define MTC_WEOF 0x30 /* write eof */ +#define MTC_REW 0x38 /* rewind */ +#define MTC_MASK 0x3F +#define MTC_STOP1 0x40 /* stop, set EOM */ +#define MTC_STOP2 0x80 /* stop, set NMTN */ + +/* Status byte, * = in UST */ + +#define STA_ERR 0x80 /* error */ +#define STA_EOF 0x40 /* end of file */ +#define STA_EOT 0x20 /* *end of tape */ +#define STA_NMTN 0x10 /* *no motion */ +#define STA_UFLGS (STA_EOT|STA_NMTN) /* unit flags */ +#define STA_MASK (STA_ERR|STA_EOF|STA_BSY|STA_EOM) +#define SET_EX (STA_ERR|STA_EOF|STA_NMTN) + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; + +uint8 mtxb[MT_MAXFR]; /* xfer buffer */ +uint32 mt_bptr = 0; /* pointer */ +uint32 mt_blnt = 0; /* length */ +uint32 mt_sta = 0; /* status byte */ +uint32 mt_db = 0; /* data buffer */ +uint32 mt_xfr = 0; /* data xfr in prog */ +uint32 mt_arm[MT_NUMDR] = { 0 }; /* intr armed */ +int32 mt_wtime = 10; /* byte latency */ +int32 mt_rtime = 1000; /* record latency */ +int32 mt_stopioe = 1; /* stop on error */ +uint8 mt_tplte[] = { 0, o_MT0, o_MT0*2, o_MT0*3, TPL_END }; + +static const uint8 bad_cmd[64] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }; + +DEVICE mt_dev; +uint32 mt (uint32 dev, uint32 op, uint32 dat); +t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err); +t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err); +t_bool mt_forwsp (UNIT *uptr, int32 *err); +t_bool mt_backsp (UNIT *uptr, int32 *err); +t_stat mt_svc (UNIT *uptr); +t_stat mt_reset (DEVICE *dptr); +t_stat mt_attach (UNIT *uptr, char *cptr); +t_stat mt_detach (UNIT *uptr); +t_stat mt_boot (int32 unitno, DEVICE *dptr); + +/* MT data structures + + mt_dev MT device descriptor + mt_unit MT unit list + mt_reg MT register list + mt_mod MT modifier list +*/ + +DIB mt_dib = { d_MT, 0, v_MT, mt_tplte, &mt, NULL }; + +UNIT mt_unit[] = { + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } }; + +REG mt_reg[] = { + { HRDATA (STA, mt_sta, 8) }, + { HRDATA (BUF, mt_db, 8) }, + { BRDATA (DBUF, mtxb, 16, 8, MT_MAXFR) }, + { HRDATA (DBPTR, mt_bptr, 16) }, + { HRDATA (DBLNT, mt_blnt, 17), REG_RO }, + { FLDATA (XFR, mt_xfr, 0) }, + { GRDATA (IREQ, int_req[l_MT], 16, MT_NUMDR, i_MT) }, + { GRDATA (IENB, int_enb[l_MT], 16, MT_NUMDR, i_MT) }, + { BRDATA (IARM, mt_arm, 16, 1, MT_NUMDR) }, + { FLDATA (STOP_IOE, mt_stopioe, 0) }, + { DRDATA (WTIME, mt_wtime, 24), PV_LEFT + REG_NZ }, + { DRDATA (RTIME, mt_rtime, 24), PV_LEFT + REG_NZ }, + { URDATA (UST, mt_unit[0].UST, 16, 8, 0, MT_NUMDR, 0) }, + { URDATA (CMD, mt_unit[0].UCMD, 16, 8, 0, MT_NUMDR, 0) }, + { URDATA (POS, mt_unit[0].pos, 10, 32, 0, + MT_NUMDR, PV_LEFT | REG_RO) }, + { HRDATA (DEVNO, mt_dib.dno, 8), REG_HRO }, + { HRDATA (SELCH, mt_dib.sch, 1), REG_HRO }, + { NULL } }; + +MTAB mt_mod[] = { + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH", + &set_sch, &show_sch, NULL }, + { 0 } }; + +DEVICE mt_dev = { + "MT", mt_unit, mt_reg, mt_mod, + MT_NUMDR, 10, 31, 1, 16, 8, + NULL, NULL, &mt_reset, + &mt_boot, &mt_attach, &mt_detach, + &mt_dib, DEV_DISABLE }; + +/* Magtape: IO routine */ + +uint32 mt (uint32 dev, uint32 op, uint32 dat) +{ +uint32 i, f, t; +uint32 u = (dev - mt_dib.dno) / o_MT0; +UNIT *uptr = mt_dev.units + u; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + sch_adr (mt_dib.sch, dev); /* inform sel ch */ + return BY; /* byte only */ +case IO_RD: /* read data */ + if (mt_xfr) mt_sta = mt_sta | STA_BSY; /* xfr? set busy */ + return mt_db; /* return data */ +case IO_WD: /* write data */ + if (mt_xfr) { /* transfer? */ + mt_sta = mt_sta | STA_BSY; /* set busy */ + if ((uptr->UCMD & (MTC_STOP1 | MTC_STOP2)) && + ((uptr->UCMD & MTC_MASK) == MTC_WR)) /* while stopping? */ + mt_sta = mt_sta | STA_ERR; } /* write overrun */ + mt_db = dat & DMASK8; /* store data */ + break; +case IO_SS: /* status */ + mt_sta = mt_sta & STA_MASK; /* ctrl status */ + if (uptr->flags & UNIT_ATT) /* attached? */ + t = mt_sta | (uptr->UST & STA_UFLGS); /* yes, unit status */ + else t = mt_sta | STA_DU; /* no, dev unavail */ + if (t & SET_EX) t = t | STA_EX; /* test for ex */ + return t; +case IO_OC: /* command */ + mt_arm[u] = int_chg (v_MT + u, dat, mt_arm[u]); + f = dat & MTC_MASK; /* get cmd */ + if (f == MTC_CLR) { /* clear? */ + mt_reset (&mt_dev); /* reset world */ + break; } + if (((uptr->flags & UNIT_ATT) == 0) || /* ignore if unatt */ + bad_cmd[f] || /* or bad cmd */ + (((f == MTC_WR) || (f == MTC_WEOF)) && /* or write */ + (uptr->flags & UNIT_WPRT))) break; /* and protected */ + for (i = 0; i < MT_NUMDR; i++) { /* check other drvs */ + if (sim_is_active (&mt_unit[i]) && /* active? */ + (mt_unit[i].UCMD != MTC_REW)) { /* not rewind? */ + sim_cancel (&mt_unit[i]); /* stop */ + mt_unit[i].UCMD = 0; } + if (sim_is_active (uptr) && /* unit active? */ + !(uptr->UCMD & (MTC_STOP1 | MTC_STOP2))) /* not stopping? */ + break; /* ignore */ + if ((f == MTC_WR) || (f == MTC_REW)) mt_sta = 0;/* write, rew: bsy=0 */ + else mt_sta = STA_BSY; /* bsy=1,nmtn,eom,err=0 */ + mt_bptr = mt_blnt = 0; /* not yet started */ + if ((f == MTC_RD) || (f == MTC_WR)) /* data xfr? */ + mt_xfr = 1; /* set xfr flag */ + else mt_xfr = 0; } + uptr->UCMD = f; /* save cmd */ + uptr->UST = 0; /* clr tape stat */ + sim_activate (uptr, mt_rtime); /* start op */ + break; } +return 0; +} + +/* Unit service + + A given operation can generate up to three interrupts + + - EOF generates an interrupt when set (read, space, wreof) + BUSY will still be set, EOM and NMTN will be clear + - After operation complete + delay, EOM generates an interrupt + BUSY will be clear, EOM will be set, NMTN will be clear + - After a further delay, NMTN generates an interrupt + BUSY will be clear, EOM and NMTN will be set + + Rewind generates an interrupt when NMTN sets +*/ + +t_stat mt_svc (UNIT *uptr) +{ +uint32 i, pnu; +int32 err; +int32 u = uptr - mt_dev.units; +uint32 dev = mt_dib.dno + (u * o_MT0); +t_mtrlnt tbc; +static t_mtrlnt bceof = { 0 }; + +err = 0; +pnu = MT_TST_PNU (uptr); /* get pos not upd */ +MT_CLR_PNU (uptr); /* and clear */ + +if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ + uptr->UCMD = 0; /* clr cmd */ + uptr->UST = 0; /* set status */ + mt_xfr = 0; /* clr op flags */ + mt_sta = STA_ERR | STA_EOM; /* set status */ + if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */ + return IORETURN (mt_stopioe, SCPE_UNATT); } + +if (uptr->UCMD & MTC_STOP2) { /* stop, gen NMTN? */ + uptr->UCMD = 0; /* clr cmd */ + uptr->UST = STA_NMTN; /* set nmtn, not eot */ + mt_xfr = 0; /* clr xfr */ + if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ + return SCPE_OK; } + +if (uptr->UCMD & MTC_STOP1) { /* stop, gen EOM? */ + uptr->UCMD = uptr->UCMD | MTC_STOP2; /* clr cmd */ + mt_sta = (mt_sta & ~STA_BSY) | STA_EOM; /* clr busy, set eom */ + if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ + sim_activate (uptr, mt_rtime); /* schedule */ + return SCPE_OK; } /* end case */ + +switch (uptr->UCMD) { /* case on function */ + +case MTC_REW: /* rewind */ + uptr->UCMD = 0; /* clr cmd */ + uptr->pos = 0; /* update position */ + uptr->UST = STA_NMTN | STA_EOT; /* update status */ + mt_sta = mt_sta & ~STA_BSY; /* don't set EOM */ + if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */ + return SCPE_OK; + +/* Unit service, continued + + For read, busy = 1 => buffer empty + For write, busy = 1 => buffer full + For read, data transfers continue for the full length of the + record, or the maximum size of the transfer buffer + For write, data transfers continue until a write is attempted + and the buffer is empty +*/ + +case MTC_RD: /* read */ + if (mt_blnt == 0) { /* first time? */ + if (mt_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */ + mt_blnt = tbc; /* set buf lnt */ + if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */ + i = fxread (mtxb, sizeof (uint8), mt_blnt, uptr->fileref); + if (err = ferror (uptr->fileref)) { /* error? */ + MT_SET_PNU (uptr); /* pos not upd */ + break; } + for ( ; i < mt_blnt; i++) mtxb[i] = 0; /* fill with 0's */ + uptr->pos = uptr->pos + ((tbc + 1) & ~1) /* upd pos */ + + (2 * sizeof (t_mtrlnt)); } + + if (sch_actv (mt_dib.sch, dev)) { /* sch active? */ + i = sch_wrmem (mt_dib.sch, mtxb, mt_blnt); /* store rec in mem */ + if (sch_actv (mt_dib.sch, dev)) /* sch still active? */ + sch_stop (mt_dib.sch); /* stop chan, long rd */ + else if (i < mt_blnt) /* process entire rec? */ + mt_sta = mt_sta | STA_ERR; } /* no, overrun error */ + else if (mt_bptr < mt_blnt) { /* no, if !eor */ + if (!(mt_sta & STA_BSY)) /* busy still clr? */ + mt_sta = mt_sta | STA_ERR; /* read overrun */ + mt_db = mtxb[mt_bptr++]; /* get next byte */ + mt_sta = mt_sta & ~STA_BSY; /* !busy = buf full */ + if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ + sim_activate (uptr, mt_wtime); /* reschedule */ + return SCPE_OK; } + break; /* record done */ + +case MTC_WR: /* write */ + if (sch_actv (mt_dib.sch, dev)) { /* sch active? */ + mt_bptr = sch_rdmem (mt_dib.sch, mtxb, MT_MAXFR); /* get rec */ + if (sch_actv (mt_dib.sch, dev)) /* not done? */ + sch_stop (mt_dib.sch); } /* stop chan */ + else if (mt_sta & STA_BSY) { /* no, if !eor */ + if (mt_bptr < MT_MAXFR) /* if room */ + mtxb[mt_bptr++] = mt_db; /* store in buf */ + mt_sta = mt_sta & ~STA_BSY; /* !busy = buf emp */ + if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ + sim_activate (uptr, mt_wtime); /* reschedule */ + return SCPE_OK; } + + if (mt_bptr) { /* any chars? */ + int32 ebc = (mt_bptr + 1) & ~1; /* force even */ + fseek (uptr->fileref, uptr->pos, SEEK_SET); + fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref); + fxwrite (mtxb, sizeof (uint8), ebc, uptr->fileref); + fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref); + if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); + else uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); } + break; /* record done */ + +/* Unit service, continued */ + +case MTC_WEOF: /* write eof */ + fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ + fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref); + if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); + else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */ + mt_sta = mt_sta | STA_EOF; /* set eof */ + if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */ + break; + +case MTC_SKFF: /* skip file fwd */ + while (mt_forwsp (uptr, &err)) ; /* spc until EOF/EOT */ + break; + +case MTC_SKFR: /* skip file rev */ + while (mt_backsp (uptr, &err)) ; /* spc until EOF/BOT */ + break; + +case MTC_SPCR: /* backspace */ + if (!pnu) mt_backsp (uptr, &err); /* if pos not upd */ + break; } /* end case */ + +if (err != 0) { /* I/O error */ + mt_sta = mt_sta | STA_ERR; + perror ("MT I/O error"); + clearerr (uptr->fileref); + if (mt_stopioe) return SCPE_IOERR; } +uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */ +sim_activate (uptr, mt_rtime); /* schedule */ +return SCPE_OK; +} + +/* Tape motion routines */ + +t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err) +{ +int32 u = uptr - mt_dev.units; + +fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */ +fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */ +if ((*err = ferror (uptr->fileref)) || /* err or eom? */ + feof (uptr->fileref) || (*tbc == MTR_EOM)) { + mt_sta = mt_sta | STA_ERR; /* set err */ + MT_SET_PNU (uptr); /* pos not upd */ + return TRUE; } +if (*tbc == MTR_TMK) { /* tape mark? */ + mt_sta = mt_sta | STA_EOF; /* set eof */ + if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ + uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */ + return TRUE; } +*tbc = MTRL (*tbc); +return FALSE; +} + +t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err) +{ +int32 u = uptr - mt_dev.units; + +if (uptr->pos < sizeof (t_mtrlnt)) { /* at bot? */ + uptr->UST = uptr->UST | STA_EOT; /* set err */ + return TRUE; } +fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET); +fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */ +if ((*err = ferror (uptr->fileref)) || /* err or eof? */ + feof (uptr->fileref)) { + mt_sta = mt_sta | STA_ERR; /* set err */ + return TRUE; } +if (*tbc == MTR_EOM) { /* eom? */ + mt_sta = mt_sta | STA_ERR; /* set err */ + uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */ + return TRUE; } +if (*tbc == MTR_TMK) { /* tape mark? */ + mt_sta = mt_sta | STA_EOF; /* set eof */ + if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ + uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */ + return TRUE; } +*tbc = MTRL (*tbc); +return FALSE; +} + +t_bool mt_forwsp (UNIT *uptr, int32 *err) +{ +t_mtrlnt tbc; + +if (mt_rdlntf (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */ +uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* space to next rec */ + (2 * sizeof (t_mtrlnt)); +return TRUE; +} + +t_bool mt_backsp (UNIT *uptr, int32 *err) +{ +t_mtrlnt tbc; + +if (mt_rdlntr (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */ +uptr->pos = uptr->pos - ((tbc + 1) & ~1) - /* space to prv rec */ + (2 * sizeof (t_mtrlnt)); +return TRUE; +} + +/* Reset routine */ + +t_stat mt_reset (DEVICE *dptr) +{ +uint32 u; +UNIT *uptr; + +mt_bptr = mt_blnt = 0; /* clr buf */ +mt_sta = STA_BSY; /* clr flags */ +mt_xfr = 0; /* clr controls */ +for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ + CLR_INT (v_MT + u); /* clear int */ + CLR_ENB (v_MT + u); /* disable int */ + mt_arm[u] = 0; /* disarm int */ + uptr = mt_dev.units + u; + MT_CLR_PNU (uptr); /* clear pos flag */ + sim_cancel (uptr); /* cancel activity */ + uptr->UST = (uptr->UST & STA_UFLGS) | STA_NMTN; /* init status */ + uptr->UCMD = 0; } /* init cmd */ +return SCPE_OK; +} + +/* Attach routine */ + +t_stat mt_attach (UNIT *uptr, char *cptr) +{ +int32 u = uptr - mt_dev.units; +t_stat r; + +r = attach_unit (uptr, cptr); +if (r != SCPE_OK) return r; +uptr->pos = 0; +MT_CLR_PNU (uptr); +uptr->UST = STA_EOT; +if (mt_arm[u]) SET_INT (v_MT + u); +return r; +} + +/* Detach routine */ + +t_stat mt_detach (UNIT* uptr) +{ +int32 u = uptr - mt_dev.units; +t_stat r; + +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; +r = detach_unit (uptr); +if (r != SCPE_OK) return r; +if (mt_arm[u]) SET_INT (v_MT + u); +MT_CLR_PNU (uptr); +uptr->UST = 0; +return SCPE_OK; +} + +/* Bootstrap routine */ + +#define BOOT_START 0x50 +#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) + +static uint8 boot_rom[] = { + 0xD5, 0x00, /* ST: AL CF */ + 0x00, 0xCF, + 0x43, 0x00, /* BR 80 */ + 0x00, 0x80 +}; + +t_stat mt_boot (int32 unitno, DEVICE *dptr) +{ +extern uint32 PC, dec_flgs; +extern uint16 decrom[]; +extern DIB sch_dib; +uint32 sch_dev; + +if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */ +mt_unit[unitno].pos = 0; /* rewind */ +sch_dev = sch_dib.dno + mt_dib.sch; /* sch dev # */ +IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */ +IOWriteB (AL_DEV, mt_dib.dno + (unitno * o_MT0)); /* set dev no for unit */ +IOWriteB (AL_IOC, 0xA1); /* set dev cmd */ +IOWriteB (AL_SCH, sch_dev); /* set dev no for chan */ +PC = BOOT_START; +return SCPE_OK; +} diff --git a/Interdata/id_pas.c b/Interdata/id_pas.c new file mode 100644 index 00000000..b89ff6ef --- /dev/null +++ b/Interdata/id_pas.c @@ -0,0 +1,546 @@ +/* id_pas.c: Interdata programmable async line adapter simulator + + Copyright (c) 2001-2003, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + pas Programmable asynchronous line adapter(s) + + This module implements up to 32 individual serial interfaces, representing + either individual PASLA modules or combinations of the 2-line and 8-line + multiplexors, which are functionally very similar. These interfaces are mapped + to Telnet based connections as the lines of a terminal multiplexor. The + connection polling mechanism and the character input polling for all lines + are done through a single polling job. +*/ + +#include "id_defs.h" +#include "sim_sock.h" +#include "sim_tmxr.h" +#include + +#define PAS_LINES 32 + +#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ +#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ +#define UNIT_V_MDM (UNIT_V_UF + 2) /* modem control */ +#define UNIT_8B (1 << UNIT_V_8B) +#define UNIT_UC (1 << UNIT_V_UC) +#define UNIT_MDM (1 << UNIT_V_MDM) + +#define PAS_INIT_POLL 8000 +#define PASL_WAIT 500 + +/* Status byte */ + +#define STA_OVR 0x80 /* overrun RO */ +#define STA_PF 0x40 /* parity err RONI */ +#define STA_NCL2S 0x40 /* not clr to snd XO */ +#define STA_FR 0x20 /* framing err RO */ +#define STA_RCR 0x10 /* rv chan rcv NI */ +#define STA_CROF 0x02 /* carrier off RO */ +#define STA_RING 0x01 /* ring RO */ +#define STA_RCV (STA_OVR|STA_PF|STA_FR|STA_RCR|STA_CROF|STA_RING) +#define SET_EX (STA_OVR|STA_PF|STA_FR) +#define STA_XMT (STA_BSY) + +/* Command bytes 1,0 */ + +#define CMD_DTR (0x20 << 8) /* DTR */ +#define CMD_ECHO (0x10 << 8) /* echoplex */ +#define CMD_RCT (0x08 << 8) /* RCT/DTB NI */ +#define CMD_XMTB (0x04 << 8) /* xmt break NI */ +#define CMD_WRT (0x02 << 8) /* write/read */ +#define CMD_V_CLK 6 /* baud rate */ +#define CMD_M_CLK 0x3 +#define CMD_V_DB 4 /* data bits */ +#define CMD_M_DB 0x3 +#define CMD_STOP 0x80 /* stop bit */ +#define CMD_V_PAR 1 /* parity */ +#define CMD_M_PAR 0x3 +#define GET_PAR(x) (((x) >> CMD_V_PAR) & CMD_M_PAR) +#define PAR_NONE 0 +#define PAR_RAW 1 +#define PAR_ODD 2 +#define PAR_EVEN 3 + +#define CMD_TYP 0x01 /* command type */ + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; + +uint8 pas_sta[PAS_LINES]; /* status */ +uint16 pas_cmd[PAS_LINES]; /* command */ +uint8 pas_rbuf[PAS_LINES]; /* rcv buf */ +uint8 pas_xbuf[PAS_LINES]; /* xmt buf */ +uint8 pas_rarm[PAS_LINES]; /* rcvr int armed */ +uint8 pas_xarm[PAS_LINES]; /* xmt int armed */ +uint8 pas_rchp[PAS_LINES]; /* rcvr chr pend */ +uint32 pas_tps = 50; /* polls/second */ +uint8 pas_tplte[PAS_LINES * 2 + 1]; /* template */ + +TMLN pas_ldsc[PAS_LINES] = { 0 }; /* line descriptors */ +TMXR pas_desc = { 8, 0, 0, &pas_ldsc[0], NULL }; /* mux descriptor */ +#define PAS_ENAB pas_desc.lines + +uint32 pas (uint32 dev, uint32 op, uint32 dat); +void pas_ini (t_bool dtpl); +t_stat pasi_svc (UNIT *uptr); +t_stat paso_svc (UNIT *uptr); +t_stat pas_reset (DEVICE *dptr); +t_stat pas_attach (UNIT *uptr, char *cptr); +t_stat pas_detach (UNIT *uptr); +t_stat pas_summ (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc); +int32 pas_par (int32 cmd, int32 c); +t_stat pas_vlines (UNIT *uptr, int32 val, char *cptr, void *desc); +void pas_reset_ln (int32 i); + +/* PAS data structures + + pas_dev PAS device descriptor + pas_unit PAS unit descriptor + pas_reg PAS register list + pas_mod PAS modifiers list +*/ + +DIB pas_dib = { d_PAS, -1, v_PAS, pas_tplte, &pas, &pas_ini }; + +UNIT pas_unit = { UDATA (&pasi_svc, UNIT_ATTABLE, 0), PAS_INIT_POLL }; + +REG pas_nlreg = { DRDATA (NLINES, PAS_ENAB, 6), PV_LEFT }; + +REG pas_reg[] = { + { BRDATA (STA, pas_sta, 16, 8, PAS_LINES) }, + { BRDATA (CMD, pas_cmd, 16, 16, PAS_LINES) }, + { BRDATA (RBUF, pas_rbuf, 16, 8, PAS_LINES) }, + { BRDATA (XBUF, pas_xbuf, 16, 8, PAS_LINES) }, + { BRDATA (IREQ, &int_req[l_PAS], 16, 32, PAS_LINES / 16) }, + { BRDATA (IENB, &int_enb[l_PAS], 16, 32, PAS_LINES / 16) }, + { BRDATA (RARM, pas_rarm, 16, 1, PAS_LINES) }, + { BRDATA (XARM, pas_xarm, 16, 1, PAS_LINES) }, + { BRDATA (RCHP, pas_rchp, 16, 1, PAS_LINES) }, + { HRDATA (DEVNO, pas_dib.dno, 8), REG_HRO }, + { NULL } }; + +MTAB pas_mod[] = { + { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", + &pas_vlines, NULL, &pas_nlreg }, + { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &pas_desc }, + { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &pas_summ }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, + NULL, &pas_show, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, + NULL, &pas_show, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, NULL }, + { 0 } }; + +DEVICE pas_dev = { + "PAS", &pas_unit, pas_reg, pas_mod, + 1, 10, 31, 1, 16, 8, + &tmxr_ex, &tmxr_dep, &pas_reset, + NULL, &pas_attach, &pas_detach, + &pas_dib, DEV_DISABLE }; + +/* PASL data structures + + pasl_dev PASL device descriptor + pasl_unit PASL unit descriptor + pasl_reg PASL register list + pasl_mod PASL modifiers list +*/ + +UNIT pasl_unit[] = { + { UDATA (&paso_svc, 0, 0), PASL_WAIT }, /* all but 8 dis */ + { UDATA (&paso_svc, 0, 0), PASL_WAIT }, + { UDATA (&paso_svc, 0, 0), PASL_WAIT }, + { UDATA (&paso_svc, 0, 0), PASL_WAIT }, + { UDATA (&paso_svc, 0, 0), PASL_WAIT }, + { UDATA (&paso_svc, 0, 0), PASL_WAIT }, + { UDATA (&paso_svc, 0, 0), PASL_WAIT }, + { UDATA (&paso_svc, 0, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT }, + { UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT } }; + +MTAB pasl_mod[] = { + { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", NULL }, + { UNIT_UC+UNIT_8B, 0 , "7b", "7B", NULL }, + { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", NULL }, + { UNIT_MDM, 0, "no dataset", "NODATASET", NULL }, + { UNIT_MDM, UNIT_MDM, "dataset", "DATASET", NULL }, + { 0 } }; + +REG pasl_reg[] = { + { URDATA (TIME, pasl_unit[0].wait, 16, 24, 0, + PAS_LINES, REG_NZ + PV_LEFT) }, + { NULL } }; + +DEVICE pasl_dev = { + "PASL", pasl_unit, pasl_reg, pasl_mod, + PAS_LINES, 10, 31, 1, 16, 8, + NULL, NULL, &pas_reset, + NULL, NULL, NULL, + NULL, 0 }; + +/* PAS: IO routine */ + +uint32 pas (uint32 dev, uint32 op, uint32 dat) +{ +int32 ln = (dev - pas_dib.dno) >> 1; +int32 xmt = (dev - pas_dib.dno) & 1; +int32 t, old_cmd; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + return BY; /* byte only */ +case IO_RD: /* read */ + pas_rchp[ln] = 0; /* clr chr pend */ + pas_sta[ln] = pas_sta[ln] & ~STA_OVR; /* clr overrun */ + return pas_rbuf[ln]; /* return buf */ +case IO_WD: /* write */ + pas_xbuf[ln] = dat & 0xFF; /* store char */ + pas_sta[ln] = pas_sta[ln] | STA_BSY; /* set busy */ + sim_activate (&pasl_unit[ln], pasl_unit[ln].wait); + break; +case IO_SS: /* status */ + if (xmt) { /* xmt side? */ + if (pas_ldsc[ln].conn == 0) /* not conn? */ + t = STA_NCL2S | STA_BSY; /* busy, not clr */ + else t = pas_sta[ln] & STA_XMT; } /* else just busy */ + else { + t = pas_sta[ln] & STA_RCV; /* get static */ + if (!pas_rchp[ln]) t = t | STA_BSY; /* no char? busy */ + if (pas_ldsc[ln].conn == 0) /* not connected? */ + t = t | STA_BSY | STA_EX; /* = !dsr */ + if (t & SET_EX) t = t | STA_EX; } /* test for ex */ + return t; +case IO_OC: /* command */ + old_cmd = pas_cmd[ln]; /* old cmd */ + if (dat & CMD_TYP) { /* type 1? */ + pas_cmd[ln] = (pas_cmd[ln] & 0xFF) | (dat << 8); + if (pas_cmd[ln] & CMD_WRT) /* write? */ + pas_xarm[ln] = int_chg (v_PASX + ln + ln, dat, pas_xarm[ln]); + else pas_rarm[ln] = int_chg (v_PAS + ln + ln, dat, pas_rarm[ln]); } + else pas_cmd[ln] = (pas_cmd[ln] & ~0xFF) | dat; + if (pasl_unit[ln].flags & UNIT_MDM) { /* modem ctrl? */ + if ((pas_cmd[ln] & CMD_DTR) && (pas_sta[ln] & STA_RING)) + pas_sta[ln] = pas_sta[ln] & ~(STA_CROF | STA_RING); + if (old_cmd & ~pas_cmd[ln] & CMD_DTR) { + tmxr_msg (pas_ldsc[ln].conn, "\r\nLine hangup\r\n"); + tmxr_reset_ln (&pas_ldsc[ln]); /* reset line */ + pas_sta[ln] = pas_sta[ln] | STA_CROF; /* no carrier */ + if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); } } + break; } +return 0; +} + +/* Unit service - receive side + + Poll all active lines for input + Poll for new connections +*/ + +t_stat pasi_svc (UNIT *uptr) +{ +int32 ln, c, out, t; + +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +t = sim_rtcn_calb (pas_tps, TMR_PAS); /* calibrate */ +sim_activate (uptr, t); /* continue poll */ +ln = tmxr_poll_conn (&pas_desc); /* look for connect */ +if (ln >= 0) { /* got one? */ + if ((pasl_unit[ln].flags & UNIT_MDM) && /* modem control */ + ((pas_cmd[ln] & CMD_DTR) == 0)) /* & !dtr? */ + pas_sta[ln] = pas_sta[ln] | STA_RING | STA_CROF; /* set ring, no cd */ + else pas_sta[ln] = pas_sta[ln] & ~STA_CROF; /* just answer */ + if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); /* interrupt */ + pas_ldsc[ln].rcve = 1; } /* rcv enabled */ +tmxr_poll_rx (&pas_desc); /* poll for input */ +for (ln = 0; ln < PAS_ENAB; ln++) { /* loop thru lines */ + if (pas_ldsc[ln].conn) { /* connected? */ + if (c = tmxr_getc_ln (&pas_ldsc[ln])) { /* any char? */ + pas_sta[ln] = pas_sta[ln] & ~(STA_FR | STA_PF); + if (pas_rchp[ln]) pas_sta[ln] = pas_sta[ln] | STA_OVR; + if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); + if (c & SCPE_BREAK) { /* break? */ + pas_sta[ln] = pas_sta[ln] | STA_FR; /* framing error */ + pas_rbuf[ln] = 0; } /* no character */ + else { /* normal */ + out = c & 0x7F; /* echo is 7b */ + if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */ + c = c & 0xFF; + else { /* UC or 7b */ + if ((pasl_unit[ln].flags & UNIT_UC) && islower (out)) + out = toupper (out); /* cvt to UC */ + c = pas_par (pas_cmd[ln], out); } /* apply parity */ + pas_rbuf[ln] = c; /* save char */ + pas_rchp[ln] = 1; /* char pending */ + if ((pas_cmd[ln] & CMD_ECHO) && pas_ldsc[ln].xmte) { + TMLN *lp = &pas_ldsc[ln]; /* get line */ + tmxr_putc_ln (lp, out); /* output char */ + tmxr_poll_tx (&pas_desc); } /* poll xmt */ + } /* end else normal */ + } /* end if char */ + } /* end if conn */ + else if ((pas_sta[ln] & STA_CROF) == 0) { /* not conn, was conn? */ + pas_sta[ln] = pas_sta[ln] | STA_CROF; /* no carrier */ + if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); } /* intr */ + } /* end for */ +return SCPE_OK; +} + +/* Unit service - transmit side */ + +t_stat paso_svc (UNIT *uptr) +{ +int32 c; +uint32 ln = uptr - pasl_unit; /* line # */ + +if (pas_ldsc[ln].conn) { /* connected? */ + if (pas_ldsc[ln].xmte) { /* xmt enabled? */ + TMLN *lp = &pas_ldsc[ln]; /* get line */ + if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */ + c = pas_par (pas_cmd[ln], pas_xbuf[ln]);/* apply parity */ + else { /* UC or 7b */ + c = pas_xbuf[ln] & 0x7F; /* mask char */ + if ((pasl_unit[ln].flags & UNIT_UC) && islower (c)) + c = toupper (c); } /* cvt to UC */ + tmxr_putc_ln (lp, c); /* output char */ + tmxr_poll_tx (&pas_desc); } /* poll xmt */ + else { /* buf full */ + tmxr_poll_tx (&pas_desc); /* poll xmt */ + sim_activate (uptr, pasl_unit[ln].wait); /* wait */ + return SCPE_OK; } } +pas_sta[ln] = pas_sta[ln] & ~STA_BSY; /* not busy */ +if (pas_xarm[ln]) SET_INT (v_PASX + ln + ln); /* set intr */ +return SCPE_OK; +} + +int32 pas_par (int32 cmd, int32 c) +{ +int32 pf = GET_PAR (cmd); +static const uint8 odd_par[] = { + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 00 */ + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 10 */ + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 20 */ + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 30 */ + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 40 */ + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 50 */ + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 60 */ + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 70 */ + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 80 */ + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 90 */ + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* A0 */ + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* B0 */ + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* C0 */ + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* D0 */ + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* E0 */ + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, + 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* F0 */ + 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80 }; + +switch (pf) { /* case on parity */ +case PAR_ODD: + return (odd_par[c & 0x7F]) | (c & 0x7F); +case PAR_EVEN: + return (odd_par[c & 0x7F] ^ 0x80) | (c & 0x7F); +case PAR_NONE: +case PAR_RAW: + break; } +return c & 0xFF; +} + +/* Reset routine */ + +t_stat pas_reset (DEVICE *dptr) +{ +int32 i, t; + +if (dptr->flags & DEV_DIS) { /* disabled? */ + pas_dev.flags = pas_dev.flags | DEV_DIS; /* disable lines */ + pasl_dev.flags = pasl_dev.flags | DEV_DIS; } +else { pas_dev.flags = pas_dev.flags & ~DEV_DIS; /* enable lines */ + pasl_dev.flags = pasl_dev.flags & ~DEV_DIS; } +if (pas_unit.flags & UNIT_ATT) { /* master att? */ + if (!sim_is_active (&pas_unit)) { + t = sim_rtcn_init (pas_unit.wait, TMR_PAS); + sim_activate (&pas_unit, t); } } /* activate */ +else sim_cancel (&pas_unit); /* else stop */ +for (i = 0; i < PAS_LINES; i++) { + pas_desc.ldsc[i] = &pas_ldsc[i]; + pas_reset_ln (i); } +return SCPE_OK; +} + +/* Attach master unit */ + +t_stat pas_attach (UNIT *uptr, char *cptr) +{ +t_stat r; + +r = tmxr_attach (&pas_desc, uptr, cptr); /* attach */ +if (r != SCPE_OK) return r; /* error */ +sim_rtcn_init (pas_unit.wait, TMR_PAS); +sim_activate (uptr, 100); /* quick poll */ +return SCPE_OK; +} + +/* Detach master unit */ + +t_stat pas_detach (UNIT *uptr) +{ +int32 i; +t_stat r; + +r = tmxr_detach (&pas_desc, uptr); /* detach */ +for (i = 0; i < PAS_LINES; i++) pas_ldsc[i].rcve = 0; /* disable rcv */ +sim_cancel (uptr); /* stop poll */ +return r; +} + +/* Show summary processor */ + +t_stat pas_summ (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +int32 i, t; + +for (i = t = 0; i < PAS_LINES; i++) t = t + (pas_ldsc[i].conn != 0); +if (t == 1) fprintf (st, "1 connection"); +else fprintf (st, "%d connections", t); +return SCPE_OK; +} + +/* SHOW CONN/STAT processor */ + +t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +int32 i; + +for (i = 0; (i < PAS_LINES) && (pas_ldsc[i].conn == 0); i++) ; +if (i < PAS_LINES) { + for (i = 0; i < PAS_LINES; i++) { + if (pas_ldsc[i].conn) + if (val) tmxr_fconns (st, &pas_ldsc[i], i); + else tmxr_fstats (st, &pas_ldsc[i], i); } } +else fprintf (st, "all disconnected\n"); +return SCPE_OK; +} + +/* Change number of lines */ + +t_stat pas_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 newln, i, t; +t_stat r; + +if (cptr == NULL) return SCPE_ARG; +newln = get_uint (cptr, 10, PAS_LINES, &r); +if ((r != SCPE_OK) || (newln == PAS_ENAB)) return r; +if (newln == 0) return SCPE_ARG; +if (newln < PAS_ENAB) { + for (i = newln, t = 0; i < PAS_ENAB; i++) t = t | pas_ldsc[i].conn; + if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) + return SCPE_OK; + for (i = newln; i < PAS_ENAB; i++) { + if (pas_ldsc[i].conn) { + tmxr_msg (pas_ldsc[i].conn, "\r\nOperator disconnected line\r\n"); + tmxr_reset_ln (&pas_ldsc[i]); } /* reset line */ + pasl_unit[i].flags = pasl_unit[i].flags | UNIT_DIS; + pas_reset_ln (i); } + } +else { for (i = PAS_ENAB; i < newln; i++) { + pasl_unit[i].flags = pasl_unit[i].flags & ~UNIT_DIS; + pas_reset_ln (i); } + } +PAS_ENAB = newln; +return SCPE_OK; +} + +/* Reset an individual line */ + +void pas_reset_ln (int32 i) +{ +CLR_INT (v_PAS + i + i); /* clear int */ +CLR_ENB (v_PAS + i + i); +CLR_INT (v_PASX + i + i); /* disable int */ +CLR_ENB (v_PASX + i + i); +pas_rarm[i] = pas_xarm[i] = 0; /* disarm int */ +pas_rbuf[i] = pas_xbuf[i] = 0; /* clear state */ +pas_cmd[i] = 0; +pas_rchp[i] = 0; +pas_sta[i] = 0; +if (pas_ldsc[i].conn == 0) /* clear carrier */ + pas_sta[i] = pas_sta[i] | STA_CROF; +sim_cancel (&pasl_unit[i]); +return; +} + +/* Init template */ + +void pas_ini (t_bool dtpl) +{ +int32 i, j; + +for (i = j = 0; i < PAS_ENAB; i++) { + pas_tplte[j] = j; + pas_tplte[j + 1] = j + o_PASX; + j = j + 2; } +pas_tplte[j] = TPL_END; +return; +} diff --git a/Interdata/id_pt.c b/Interdata/id_pt.c new file mode 100644 index 00000000..5fd00d34 --- /dev/null +++ b/Interdata/id_pt.c @@ -0,0 +1,350 @@ +/* id_pt.c: Interdata paper tape reader + + Copyright (c) 2000-2001, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + pt paper tape reader and punch +*/ + +#include "id_defs.h" +#include + +/* Device definitions */ + +#define PTR 0 /* unit subscripts */ +#define PTP 1 + +#define STA_OVR 0x80 /* overrun */ +#define STA_NMTN 0x10 /* no motion */ +#define STA_MASK (STA_BSY | STA_OVR | STA_DU) /* static bits */ +#define SET_EX (STA_OVR | STA_NMTN) /* set EX */ + +#define CMD_V_RUN 4 /* run/stop */ +#define CMD_V_SLEW 2 /* slew/step */ +#define CMD_V_RD 0 /* read/write */ + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; + +uint32 pt_run = 0, pt_slew = 0; /* ptr modes */ +uint32 pt_rd = 1, pt_chp = 0; /* pt state */ +uint32 pt_arm = 0; /* int arm */ +uint32 pt_sta = STA_BSY; /* status */ +uint32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ + +DEVICE pt_dev; +uint32 pt (uint32 dev, uint32 op, uint32 dat); +t_stat ptr_svc (UNIT *uptr); +t_stat ptp_svc (UNIT *uptr); +t_stat pt_boot (int32 unitno, DEVICE *dptr); +t_stat pt_reset (DEVICE *dptr); + +/* PT data structures + + pt_dev PT device descriptor + pt_unit PT unit descriptors + pt_reg PT register list +*/ + +DIB pt_dib = { d_PT, -1, v_PT, NULL, &pt, NULL }; + +UNIT pt_unit[] = { + { UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), + SERIAL_IN_WAIT }, + { UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), + SERIAL_OUT_WAIT } }; + +REG pt_reg[] = { + { HRDATA (STA, pt_sta, 8) }, + { HRDATA (RBUF, pt_unit[PTR].buf, 8) }, + { DRDATA (RPOS, pt_unit[PTR].pos, 32), PV_LEFT }, + { DRDATA (RTIME, pt_unit[PTR].wait, 24), PV_LEFT }, + { FLDATA (RSTOP_IOE, ptr_stopioe, 0) }, + { HRDATA (PBUF, pt_unit[PTP].buf, 8) }, + { DRDATA (PPOS, pt_unit[PTP].pos, 32), PV_LEFT }, + { DRDATA (PTIME, pt_unit[PTP].wait, 24), PV_LEFT }, + { FLDATA (PSTOP_IOE, ptp_stopioe, 0) }, + { FLDATA (IREQ, int_req[l_PT], i_PT) }, + { FLDATA (IENB, int_enb[l_PT], i_PT) }, + { FLDATA (IARM, pt_arm, 0) }, + { FLDATA (RD, pt_rd, 0) }, + { FLDATA (RUN, pt_run, 0) }, + { FLDATA (SLEW, pt_slew, 0) }, + { FLDATA (CHP, pt_chp, 0) }, + { HRDATA (DEVNO, pt_dib.dno, 8), REG_HRO }, + { NULL } }; + +MTAB pt_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "devno", "DEVNO", + &set_dev, &show_dev, NULL }, + { 0 } }; + +DEVICE pt_dev = { + "PT", pt_unit, pt_reg, pt_mod, + 2, 10, 31, 1, 16, 8, + NULL, NULL, &pt_reset, + &pt_boot, NULL, NULL, + &pt_dib, DEV_DISABLE }; + +/* Paper tape: IO routine */ + +uint32 pt (uint32 dev, uint32 op, uint32 dat) +{ +uint32 t, old_rd, old_run; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + return BY; /* byte only */ +case IO_OC: /* command */ + old_rd = pt_rd; /* save curr rw */ + old_run = pt_run; /* save curr run */ + pt_arm = int_chg (v_PT, dat, pt_arm); /* upd int ctrl */ + pt_rd = io_2b (dat, CMD_V_RD, pt_rd); /* upd read/wr */ + if (old_rd != pt_rd) { /* rw change? */ + pt_sta = pt_sta & ~STA_OVR; /* clr overrun */ + if (sim_is_active (&pt_unit[pt_rd? PTR: PTP])) { + pt_sta = pt_sta | STA_BSY; /* busy = 1 */ + CLR_INT (v_PT); } /* clear int */ + else { /* not active */ + pt_sta = pt_sta & ~STA_BSY; /* busy = 0 */ + if (pt_arm) SET_INT (v_PT); } } /* no, set int */ + if (pt_rd) { /* reader? */ + pt_run = io_2b (dat, CMD_V_RUN, pt_run); /* upd run/stop */ + pt_slew = io_2b (dat, CMD_V_SLEW, pt_slew); /* upd slew/inc */ + if (pt_run) { /* run set? */ + if (old_run == 0) { /* run 0 -> 1? */ + sim_activate (&pt_unit[PTR], pt_unit[PTR].wait); + pt_sta = pt_sta & ~STA_DU; } } /* clear eof */ + else sim_cancel (&pt_unit[PTR]); } /* clr, stop rdr */ + else pt_sta = pt_sta & ~STA_DU; /* punch, clr eof */ + break; +case IO_RD: /* read */ + if (pt_run && !pt_slew) { /* incremental? */ + sim_activate (&pt_unit[PTR], pt_unit[PTR].wait); + pt_sta = pt_sta & ~STA_DU; } /* clr eof */ + pt_chp = 0; /* clr char pend */ + if (pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */ + return (pt_unit[PTR].buf & 0xFF); /* return char */ +case IO_WD: /* write */ + pt_unit[PTP].buf = dat & DMASK8; /* save char */ + if (!pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */ + sim_activate (&pt_unit[PTP], pt_unit[PTP].wait); + break; +case IO_SS: /* status */ + t = pt_sta & STA_MASK; /* get status */ + if (pt_rd && !pt_run && !sim_is_active (&pt_unit[PTR])) + t = t | STA_NMTN; /* stopped? */ + if ((pt_unit[pt_rd? PTR: PTP].flags & UNIT_ATT) == 0) + t = t | STA_DU; /* offline? */ + if (t & SET_EX) t = t | STA_EX; /* test for EX */ + return t; } +return 0; +} + +/* Unit service */ + +t_stat ptr_svc (UNIT *uptr) +{ +uint32 temp; + +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (ptr_stopioe, SCPE_UNATT); +if (pt_rd) { /* read mode? */ + pt_sta = pt_sta & ~STA_BSY; /* clear busy */ + if (pt_arm) SET_INT (v_PT); /* if armed, intr */ + if (pt_chp) pt_sta = pt_sta | STA_OVR; } /* overrun? */ +pt_chp = 1; /* char pending */ +if ((temp = getc (uptr->fileref)) == EOF) { /* error? */ + if (feof (uptr->fileref)) { /* eof? */ + pt_sta = pt_sta | STA_DU; /* set DU */ + if (ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; } + else perror ("PTR I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; } +uptr->buf = temp & DMASK8; /* store char */ +uptr->pos = uptr->pos + 1; /* incr pos */ +if (pt_slew) sim_activate (uptr, uptr->wait); /* slew? continue */ +return SCPE_OK; +} + +t_stat ptp_svc (UNIT *uptr) +{ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (ptp_stopioe, SCPE_UNATT); +if (!pt_rd) { /* write mode? */ + pt_sta = pt_sta & ~STA_BSY; /* clear busy */ + if (pt_arm) SET_INT (v_PT); } /* if armed, intr */ +if (putc (uptr->buf, uptr -> fileref) == EOF) { /* write char */ + perror ("PTP I/O error"); + clearerr (uptr -> fileref); + return SCPE_IOERR; } +uptr -> pos = uptr -> pos + 1; /* incr pos */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat pt_reset (DEVICE *dptr) +{ +sim_cancel (&pt_unit[PTR]); /* deactivate units */ +sim_cancel (&pt_unit[PTP]); +pt_rd = 1; /* read */ +pt_chp = pt_run = pt_slew = 0; /* stop, inc, disarm */ +pt_sta = STA_BSY; /* buf empty */ +CLR_INT (v_PT); /* clear int */ +CLR_ENB (v_PT); /* disable int */ +pt_arm = 0; /* disarm int */ +return SCPE_OK; +} + +/* Bootstrap routine */ + +#define BOOT_START 0x50 +#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) +#define BOOT3_START 0x3E +#define BOOT3_LEN (sizeof (boot_rom) / sizeof (uint8)) + +static uint8 boot_rom[] = { + 0xD5, 0x00, /* ST AL CF */ + 0x00, 0xCF, + 0x43, 0x00, /* BR 80 */ + 0x00, 0x80 +}; + +static uint8 boot3_rom[] = { + 0xC8, 0x20, /* ST LHI 2,80 */ + 0x00, 0x80, + 0xC8, 0x30, /* LHI 3,1 */ + 0x00, 0x01, + 0xC8, 0x40, /* LHI 4,CF */ + 0x00, 0xCF, + 0xD3, 0xA0, /* LB A,78 */ + 0x00, 0x78, + 0xDE, 0xA0, /* OC A,79 */ + 0x00, 0x79, + 0x9D, 0xAE, /* LP SSR A,E */ + 0x42, 0xF0, /* BTC F,LP */ + 0x00, 0x52, + 0x9B, 0xAE, /* RDR A,E */ + 0x08, 0xEE, /* LHR E,E */ + 0x43, 0x30, /* BZ LP */ + 0x00, 0x52, + 0x43, 0x00, /* BR STO */ + 0x00, 0x6C, + 0x9D, 0xAE, /* LP1 SSR A,E */ + 0x42, 0xF0, /* BTC F,LP1 */ + 0x00, 0x64, + 0x9B, 0xAE, /* RDR A,E */ + 0xD2, 0xE2, /* STO STB E,0(2) */ + 0x00, 0x00, + 0xC1, 0x20, /* BXLE 2,LP1 */ + 0x00, 0x64, + 0x43, 0x00, /* BR 80 */ + 0x00, 0x80 +}; + +t_stat pt_boot (int32 unitno, DEVICE *dptr) +{ +extern uint32 PC, dec_flgs; +extern uint16 decrom[]; + +if (decrom[0xD5] & dec_flgs) /* AL defined? */ + IOWriteBlk (BOOT3_START, BOOT3_LEN, boot3_rom); /* no, 50 seq */ +else IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy AL boot */ +IOWriteB (AL_DEV, pt_dib.dno); /* set dev no */ +IOWriteB (AL_IOC, 0x99); /* set dev cmd */ +IOWriteB (AL_SCH, 0); /* clr sch dev no */ +PC = BOOT_START; +return SCPE_OK; +} + +/* Dump routine */ + +#define LOAD_START 0x80 +#define LOAD_LO 0x8A +#define LOAD_HI 0x8E +#define LOAD_CS 0x93 +#define LOAD_LEN (sizeof (load_rom) / sizeof (uint8)) +#define LOAD_LDR 50 + +static uint8 load_rom[] = { + 0x24, 0x21, /* BOOT LIS R2,1 */ + 0x23, 0x03, /* BS BOOT */ + 0x00, 0x00, /* 32b psw pointer */ + 0x00, 0x00, /* 32b reg pointer */ + 0xC8, 0x10, /* ST LHI R1,lo */ + 0x00, 0x00, + 0xC8, 0x30, /* LHI R3,hi */ + 0x00, 0x00, + 0xC8, 0x60, /* LHI R3,cs */ + 0x00, 0x00, + 0xD3, 0x40, /* LB R4,X'78' */ + 0x00, 0x78, + 0xDE, 0x40, /* OC R4,X'79' */ + 0x00, 0x79, + 0x9D, 0x45, /* LDR SSR R4,R5 */ + 0x20, 0x91, /* BTBS 9,.-2 */ + 0x9B, 0x45, /* RDR R4,R5 */ + 0x08, 0x55, /* L(H)R R5,R5 */ + 0x22, 0x34, /* BZS LDR */ + 0xD2, 0x51, /* LOOP STB R5,0(R1) */ + 0x00, 0x00, + 0x07, 0x65, /* X(H)R R6,R5 */ + 0x9A, 0x26, /* WDR R2,R6 */ + 0x9D, 0x45, /* SSR R4,R5 */ + 0x20, 0x91, /* BTBS 9,.-2 */ + 0x9B, 0x45, /* RDR R4,R5 */ + 0xC1, 0x10, /* BXLE R1,LOOP */ + 0x00, 0xA6, + 0x24, 0x78, /* LIS R7,8 */ + 0x91, 0x7C, /* SLLS R7,12 */ + 0x95, 0x57, /* EPSR R5,R7 */ + 0x22, 0x03 /* BS .-6 */ +}; + +t_stat pt_dump (FILE *of, char *cptr, char *fnam) +{ +t_addr i, lo, hi; +uint32 cs; +char *tptr; +extern DEVICE cpu_dev; + +if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; +tptr = get_range (cptr, &lo, &hi, cpu_dev.aradix, 0xFFFF, 0); +if ((tptr == NULL) || (lo < INTSVT)) return SCPE_ARG; +if (*tptr != 0) return SCPE_2MARG; +for (i = lo, cs = 0; i <= hi; i++) cs = cs ^ IOReadB (i); +IOWriteBlk (LOAD_START, LOAD_LEN, load_rom); +IOWriteB (LOAD_LO, (lo >> 8) & 0xFF); +IOWriteB (LOAD_LO + 1, lo & 0xFF); +IOWriteB (LOAD_HI, (hi >> 8) & 0xFF); +IOWriteB (LOAD_HI + 1, hi & 0xFF); +IOWriteB (LOAD_CS, cs & 0xFF); +for (i = 0; i < LOAD_LDR; i++) fputc (0, of); +for (i = LOAD_START; i < (LOAD_START + LOAD_LEN); i++) + fputc (IOReadB (i), of); +for (i = 0; i < LOAD_LDR; i++) fputc (0, of); +for (i = lo; i <= hi; i++) fputc (IOReadB (i), of); +for (i = 0; i < LOAD_LDR; i++) fputc (0, of); +return SCPE_OK; +} diff --git a/Interdata/id_tt.c b/Interdata/id_tt.c new file mode 100644 index 00000000..c7af6294 --- /dev/null +++ b/Interdata/id_tt.c @@ -0,0 +1,259 @@ +/* id_tt.c: Interdata teletype + + Copyright (c) 2000-2003, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + tt console + + 11-Jan-03 RMS Added TTP support + 22-Dec-02 RMS Added break support +*/ + +#include "id_defs.h" +#include + +#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ +#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ +#define UNIT_8B (1 << UNIT_V_8B) +#define UNIT_KSR (1 << UNIT_V_KSR) + +/* Device definitions */ + +#define TTI 0 +#define TTO 1 + +#define STA_OVR 0x80 /* overrun */ +#define STA_BRK 0x20 /* break */ +#define STA_MASK (STA_OVR | STA_BRK | STA_BSY) /* status mask */ +#define SET_EX (STA_OVR | STA_BRK) /* set EX */ + +#define CMD_V_FDPX 4 /* full/half duplex */ +#define CMD_V_RD 2 /* read/write */ + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; + +uint32 tt_sta = STA_BSY; /* status */ +uint32 tt_fdpx = 1; /* tt mode */ +uint32 tt_rd = 1, tt_chp = 0; /* tt state */ +uint32 tt_arm = 0; /* int arm */ + +uint32 tt (uint32 dev, uint32 op, uint32 dat); +t_stat tti_svc (UNIT *uptr); +t_stat tto_svc (UNIT *uptr); +t_stat tt_reset (DEVICE *dptr); +t_stat tt_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat tt_set_break (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat tt_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc); + +/* TT data structures + + tt_dev TT device descriptor + tt_unit TT unit descriptors + tt_reg TT register list + tt_mod TT modifiers list +*/ + +DIB tt_dib = { d_TT, -1, v_TT, NULL, &tt, NULL }; + +UNIT tt_unit[] = { + { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }, + { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT } +}; + +REG tt_reg[] = { + { HRDATA (STA, tt_sta, 8) }, + { HRDATA (KBUF, tt_unit[TTI].buf, 8) }, + { DRDATA (KPOS, tt_unit[TTI].pos, 32), PV_LEFT }, + { DRDATA (KTIME, tt_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, + { HRDATA (TBUF, tt_unit[TTO].buf, 8) }, + { DRDATA (TPOS, tt_unit[TTO].pos, 32), PV_LEFT }, + { DRDATA (TTIME, tt_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, + { FLDATA (IREQ, int_req[l_TT], i_TT) }, + { FLDATA (IENB, int_enb[l_TT], i_TT) }, + { FLDATA (IARM, tt_arm, 0) }, + { FLDATA (RD, tt_rd, 0) }, + { FLDATA (FDPX, tt_fdpx, 0) }, + { FLDATA (CHP, tt_chp, 0) }, + { HRDATA (DEVNO, tt_dib.dno, 8), REG_HRO }, + { NULL } }; + +MTAB tt_mod[] = { + { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tt_set_mode }, + { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tt_set_mode }, + { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tt_set_mode }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED", + &tt_set_enbdis, NULL, NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED", + &tt_set_enbdis, NULL, NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK", + &tt_set_break, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, &tt_dib }, + { 0 } }; + +DEVICE tt_dev = { + "TT", tt_unit, tt_reg, tt_mod, + 2, 10, 31, 1, 16, 8, + NULL, NULL, &tt_reset, + NULL, NULL, NULL, + &tt_dib, 0 }; + +/* Terminal: IO routine */ + +uint32 tt (uint32 dev, uint32 op, uint32 dat) +{ +uint32 old_rd, t; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + return BY; /* byte only */ +case IO_OC: /* command */ + old_rd = tt_rd; + tt_arm = int_chg (v_TT, dat, tt_arm); /* upd int ctrl */ + tt_fdpx = io_2b (dat, CMD_V_FDPX, tt_fdpx); /* upd full/half */ + tt_rd = io_2b (dat, CMD_V_RD, tt_rd); /* upd rd/write */ + if (tt_rd != old_rd) { /* rw change? */ + if (tt_rd? tt_chp: !sim_is_active (&tt_unit[TTO])) { + tt_sta = 0; /* busy = 0 */ + if (tt_arm) SET_INT (v_TT); } /* req intr */ + else { + tt_sta = STA_BSY; /* busy = 1 */ + CLR_INT (v_TT); } } /* clr int */ + else tt_sta = tt_sta & ~STA_OVR; /* clr ovflo */ + break; +case IO_RD: /* read */ + tt_chp = 0; /* clear pend */ + if (tt_rd) tt_sta = (tt_sta | STA_BSY) & ~STA_OVR; + return (tt_unit[TTI].buf & 0xFF); +case IO_WD: /* write */ + tt_unit[TTO].buf = dat & 0xFF; /* save char */ + if (!tt_rd) tt_sta = tt_sta | STA_BSY; /* set busy */ + sim_activate (&tt_unit[TTO], tt_unit[TTO].wait); + break; +case IO_SS: /* status */ + t = tt_sta & STA_MASK; /* get status */ + if (t & SET_EX) t = t | STA_EX; /* test for EX */ + return t; } +return 0; +} + +/* Unit service routines */ + +t_stat tti_svc (UNIT *uptr) +{ +int32 out, temp; + +sim_activate (uptr, uptr->wait); /* continue poll */ +tt_sta = tt_sta & ~STA_BRK; /* clear break */ +if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ +if (tt_rd) { /* read mode? */ + tt_sta = tt_sta & ~STA_BSY; /* clear busy */ + if (tt_arm) SET_INT (v_TT); /* if armed, intr */ + if (tt_chp) tt_sta = tt_sta | STA_OVR; } /* got char? overrun */ +tt_chp = 1; /* char pending */ +out = temp & 0x7F; /* echo is 7B */ +if (temp & SCPE_BREAK) { /* break? */ + tt_sta = tt_sta | STA_BRK; /* set status */ + uptr->buf = 0; } /* no character */ +else if (uptr->flags & UNIT_KSR) { /* KSR mode? */ + if (islower (out)) out = toupper (out); /* cvt to UC */ + uptr->buf = out | 0x80; } /* set high bit */ +else uptr->buf = temp & ((tt_unit[TTI].flags & UNIT_8B)? 0xFF: 0x7F); +uptr->pos = uptr->pos + 1; /* incr count */ +if (!tt_fdpx) { /* half duplex? */ + if (out) sim_putchar (out); /* write char */ + tt_unit[TTO].pos = tt_unit[TTO].pos + 1; } +return SCPE_OK; +} + +t_stat tto_svc (UNIT *uptr) +{ +int32 ch; +t_stat r; + +if (!tt_rd) { /* write mode? */ + tt_sta = tt_sta & ~STA_BSY; /* clear busy */ + if (tt_arm) SET_INT (v_TT); } /* if armed, intr */ +if (uptr->flags & UNIT_KSR) { /* KSR mode? */ + ch = uptr->buf & 0x7F; /* mask to 7b */ + if (islower (ch)) ch = toupper (ch); } /* cvt to UC */ +else ch = uptr->buf & ((tt_unit[TTO].flags & UNIT_8B)? 0xFF: 0x7F); +if (!(uptr->flags & UNIT_8B) && /* KSR or 7b? */ + ((ch == 0) || (ch == 0x7F))) return SCPE_OK; /* supr NULL, DEL */ +if ((r = sim_putchar (ch)) != SCPE_OK) return r; /* output */ +uptr->pos = uptr->pos + 1; /* incr count */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat tt_reset (DEVICE *dptr) +{ +if (dptr->flags & DEV_DIS) sim_cancel (&tt_unit[TTI]); /* dis? cancel poll */ +else sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* activate input */ +sim_cancel (&tt_unit[TTO]); /* cancel output */ +tt_rd = tt_fdpx = 1; /* read, full duplex */ +tt_chp = 0; /* no char */ +tt_sta = STA_BSY; /* buffer empty */ +CLR_INT (v_TT); /* clear int */ +CLR_ENB (v_TT); /* disable int */ +tt_arm = 0; /* disarm int */ +return SCPE_OK; +} + +/* Make mode flags uniform */ + +t_stat tt_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +tt_unit[TTI].flags = (tt_unit[TTI].flags & ~(UNIT_KSR | UNIT_8B)) | val; +tt_unit[TTO].flags = (tt_unit[TTO].flags & ~(UNIT_KSR | UNIT_8B)) | val; +return SCPE_OK; +} + +/* Set input break */ + +t_stat tt_set_break (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (tt_dev.flags & DEV_DIS) return SCPE_NOFNC; +tt_sta = tt_sta | STA_BRK; +if (tt_rd) { /* read mode? */ + tt_sta = tt_sta & ~STA_BSY; /* clear busy */ + if (tt_arm) SET_INT (v_TT); } /* if armed, intr */ +sim_cancel (&tt_unit[TTI]); /* restart TT poll */ +sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* so brk is seen */ +return SCPE_OK; +} + +/* Set enabled/disabled */ + +t_stat tt_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +extern DEVICE ttp_dev; +extern t_stat ttp_reset (DEVICE *dptr); + +tt_dev.flags = (tt_dev.flags & ~DEV_DIS) | val; +ttp_dev.flags = (ttp_dev.flags & ~DEV_DIS) | (val ^ DEV_DIS); +tt_reset (&tt_dev); +ttp_reset (&ttp_dev); +return SCPE_OK; +} diff --git a/Interdata/id_ttp.c b/Interdata/id_ttp.c new file mode 100644 index 00000000..ce34c576 --- /dev/null +++ b/Interdata/id_ttp.c @@ -0,0 +1,263 @@ +/* id_ttp.c: Interdata PASLA console interface + + Copyright (c) 2000-2003, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + ttp console (on PAS) +*/ + +#include "id_defs.h" +#include + +#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ +#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ +#define UNIT_8B (1 << UNIT_V_8B) +#define UNIT_UC (1 << UNIT_V_UC) + +#define TTI 0 +#define TTO 1 + +/* Status byte */ + +#define STA_OVR 0x80 /* overrun RO */ +#define STA_PF 0x40 /* parity err RO */ +#define STA_FR 0x20 /* framing err RO */ +#define STA_RCV (STA_OVR|STA_PF|STA_FR) +#define SET_EX (STA_OVR|STA_PF|STA_FR) +#define STA_XMT (STA_BSY) + +/* Command bytes 1,0 */ + +#define CMD_ECHO (0x10 << 8) /* echoplex */ +#define CMD_WRT (0x02 << 8) /* write/read */ +#define CMD_TYP 0x01 /* command type */ + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; + +uint32 ttp_sta = 0; /* status */ +uint32 ttp_cmd = 0; /* command */ +uint32 ttp_kchp = 0; /* rcvr chr pend */ +uint32 ttp_karm = 0; /* rcvr int armed */ +uint32 ttp_tarm = 0; /* xmt int armed */ +uint8 ttp_tplte[] = { 0, 1, TPL_END }; + +uint32 ttp (uint32 dev, uint32 op, uint32 dat); +t_stat ttpi_svc (UNIT *uptr); +t_stat ttpo_svc (UNIT *uptr); +t_stat ttp_reset (DEVICE *dptr); +t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat ttp_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc); + +extern int32 pas_par (int32 cmd, int32 c); + +/* TTP data structures */ + +DIB ttp_dib = { d_TTP, -1, v_TTP, ttp_tplte, &ttp, NULL }; + +UNIT ttp_unit[] = { + { UDATA (&ttpi_svc, UNIT_UC, 0), KBD_POLL_WAIT }, + { UDATA (&ttpo_svc, UNIT_UC, 0), SERIAL_OUT_WAIT } +}; + +REG ttp_reg[] = { + { HRDATA (CMD, ttp_cmd, 16) }, + { HRDATA (KBUF, ttp_unit[TTI].buf, 8) }, + { DRDATA (KPOS, ttp_unit[TTI].pos, 32), PV_LEFT }, + { DRDATA (KTIME, ttp_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, + { FLDATA (KIREQ, int_req[l_TTP], i_TTP) }, + { FLDATA (KIENB, int_enb[l_TTP], i_TTP) }, + { FLDATA (KARM, ttp_karm, 0) }, + { FLDATA (CHP, ttp_kchp, 0) }, + { HRDATA (TBUF, ttp_unit[TTO].buf, 8) }, + { DRDATA (TPOS, ttp_unit[TTO].pos, 32), PV_LEFT }, + { DRDATA (TTIME, ttp_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, + { FLDATA (TIREQ, int_req[l_TTP], i_TTP + 1) }, + { FLDATA (TIENB, int_enb[l_TTP], i_TTP + 1) }, + { FLDATA (TARM, ttp_tarm, 0) }, + { HRDATA (DEVNO, ttp_dib.dno, 8), REG_HRO }, + { NULL } }; + +MTAB ttp_mod[] = { + { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &ttp_set_mode }, + { UNIT_UC+UNIT_8B, 0 , "7b", "7B", &ttp_set_mode }, + { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &ttp_set_mode }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED", + &ttp_set_enbdis, NULL, NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED", + &ttp_set_enbdis, NULL, NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK", + &ttp_set_break, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, NULL }, + { 0 } }; + +DEVICE ttp_dev = { + "TTP", ttp_unit, ttp_reg, ttp_mod, + 2, 10, 31, 1, 16, 8, + NULL, NULL, &ttp_reset, + NULL, NULL, NULL, + &ttp_dib, DEV_DIS }; + + +/* Terminal: I/O routine */ + +uint32 ttp (uint32 dev, uint32 op, uint32 dat) +{ +int32 xmt = dev & 1; +int32 t, old_cmd; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + return BY; /* byte only */ +case IO_RD: /* read */ + ttp_kchp = 0; /* clr chr pend */ + ttp_sta = ttp_sta & ~STA_OVR; /* clr overrun */ + return ttp_unit[TTI].buf; /* return buf */ +case IO_WD: /* write */ + ttp_unit[TTO].buf = dat & 0xFF; /* store char */ + ttp_sta = ttp_sta | STA_BSY; /* set busy */ + sim_activate (&ttp_unit[TTO], ttp_unit[TTO].wait); + break; +case IO_SS: /* status */ + if (xmt) t = ttp_sta & STA_XMT; /* xmt? Just busy */ + else { /* rcv */ + t = ttp_sta & STA_RCV; /* get static */ + if (!ttp_kchp) t = t | STA_BSY; /* no char? busy */ + if (t & SET_EX) t = t | STA_EX; } /* test for ex */ + return t; +case IO_OC: /* command */ + old_cmd = ttp_cmd; /* old cmd */ + if (dat & CMD_TYP) { /* type 1? */ + ttp_cmd = (ttp_cmd & 0xFF) | (dat << 8); + if (ttp_cmd & CMD_WRT) /* write? */ + ttp_tarm = int_chg (v_TTP + 1, dat, ttp_tarm); + else ttp_karm = int_chg (v_TTP, dat, ttp_karm); } + else ttp_cmd = (ttp_cmd & ~0xFF) | dat; + break; } +return 0; +} + +/* Unit service */ + +t_stat ttpi_svc (UNIT *uptr) +{ +int32 c, out; + +sim_activate (uptr, uptr->wait); /* continue poll */ +ttp_sta = ttp_sta & ~STA_FR; /* clear break */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ +ttp_sta = ttp_sta & ~STA_PF; /* clear parity err */ +if (ttp_kchp) ttp_sta = ttp_sta | STA_OVR; /* overrun? */ +if (ttp_karm) SET_INT (v_TTP); +if (c & SCPE_BREAK) { /* break? */ + ttp_sta = ttp_sta | STA_FR; /* framing error */ + uptr->buf = 0; } /* no character */ +else { c = c & 0xFF; /* char is 8b */ + out = c & 0x7F; /* echo is 7b */ + if (!(uptr->flags & UNIT_8B)) { /* not 8b? */ + if ((uptr->flags & UNIT_UC) && islower (out)) + out = toupper (out); /* cvt to UC */ + c = pas_par (ttp_cmd, out); } /* apply parity */ + uptr->buf = c; /* save char */ + uptr->pos = uptr->pos + 1; /* incr count */ + ttp_kchp = 1; /* char pending */ + if (ttp_cmd & CMD_ECHO) { + sim_putchar (out); + ttp_unit[TTO].pos = ttp_unit[TTO].pos + 1; } } +return SCPE_OK; +} + +t_stat ttpo_svc (UNIT *uptr) +{ +int32 c; +t_stat r; + +ttp_sta = ttp_sta & ~STA_BSY; /* not busy */ +if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */ +if (uptr->flags & UNIT_8B) /* 8b? */ + c = pas_par (ttp_cmd, uptr->buf); /* apply parity */ +else { c = uptr->buf & 0x7F; /* mask char */ + if ((uptr->flags & UNIT_UC) && islower (c)) + c = toupper (c); } /* cvt to UC */ +if (!(uptr->flags & UNIT_8B) && /* UC or 7b? */ + ((c == 0) || (c == 0x7F))) return SCPE_OK; /* supr NULL, DEL */ +if ((r = sim_putchar (c)) != SCPE_OK) return r; /* output */ +uptr->pos = uptr->pos + 1; /* incr count */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat ttp_reset (DEVICE *dptr) +{ +extern DEVICE tt_dev; + +if (dptr->flags & DEV_DIS) sim_cancel (&ttp_unit[TTI]); +else sim_activate (&ttp_unit[TTI], ttp_unit[TTI].wait); +sim_cancel (&ttp_unit[TTO]); +CLR_INT (v_TTP); /* clear int */ +CLR_ENB (v_TTP); +CLR_INT (v_TTP + 1); /* disable int */ +CLR_ENB (v_TTP + 1); +ttp_karm = ttp_tarm = 0; /* disarm int */ +ttp_cmd = 0; +ttp_sta = 0; +ttp_kchp = 0; +return SCPE_OK; +} + +/* Make mode flags uniform */ + +t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +ttp_unit[TTI].flags = (ttp_unit[TTI].flags & ~(UNIT_UC | UNIT_8B)) | val; +ttp_unit[TTO].flags = (ttp_unit[TTO].flags & ~(UNIT_UC | UNIT_8B)) | val; +return SCPE_OK; +} + +/* Set input break */ + +t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (ttp_dev.flags & DEV_DIS) return SCPE_NOFNC; +ttp_sta = ttp_sta | STA_FR; +if (ttp_karm) SET_INT (v_TTP); /* if armed, intr */ +sim_cancel (&ttp_unit[TTI]); /* restart TT poll */ +sim_activate (&ttp_unit[TTI], ttp_unit[TTI].wait); +return SCPE_OK; +} + +/* Set enabled/disabled */ + +t_stat ttp_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +extern DEVICE tt_dev; +extern t_stat tt_reset (DEVICE *dptr); + +ttp_dev.flags = (ttp_dev.flags & ~DEV_DIS) | val; +tt_dev.flags = (tt_dev.flags & ~DEV_DIS) | (val ^ DEV_DIS); +ttp_reset (&ttp_dev); +tt_reset (&tt_dev); +return SCPE_OK; +} diff --git a/Interdata/id_uvc.c b/Interdata/id_uvc.c new file mode 100644 index 00000000..ee272138 --- /dev/null +++ b/Interdata/id_uvc.c @@ -0,0 +1,311 @@ +/* id_uvc.c: Interdata universal clock + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + pic precision incremental clock + lfc line frequency clock +*/ + +#include "id_defs.h" +#include + +/* Device definitions */ + +#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diag mode */ +#define UNIT_DIAG (1 << UNIT_V_DIAG) + +#define STA_OVF 0x08 /* PIC overflow */ +#define CMD_STRT 0x20 /* start */ +#define PIC_V_RATE 12 /* rate */ +#define PIC_M_RATE 0xF +#define PIC_RATE (PIC_M_RATE << PIC_V_RATE) +#define PIC_CTR 0x0FFF /* PIC counters */ +#define GET_RATE(x) (((x) >> PIC_V_RATE) & PIC_M_RATE) +#define GET_CTR(x) ((x) & PIC_CTR) +#define PIC_TPS 1000 + +extern uint32 int_req[INTSZ], int_enb[INTSZ]; + +int32 pic_db = 0; /* output buf */ +int32 pic_ric = 0; /* reset count */ +int32 pic_cic = 0; /* current count */ +uint32 pic_save = 0; /* saved time */ +uint32 pic_ovf = 0; /* overflow */ +uint32 pic_rdp = 0; +uint32 pic_wdp = 0; +uint32 pic_cnti = 0; /* instr/timer */ +uint32 pic_arm = 0; /* int arm */ +uint16 pic_time[4] = { 1, 10, 100, 1000 }; /* delays */ +static int32 pic_map[16] = { /* map rate to delay */ + 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 }; + +DEVICE pic_dev; +uint32 pic (uint32 dev, uint32 op, uint32 dat); +t_stat pic_svc (UNIT *uptr); +t_stat pic_reset (DEVICE *dptr); +void pic_sched (t_bool strt); +uint32 pic_rd_cic (void); + +int32 lfc_tps = 120; /* ticks per */ +uint32 lfc_arm = 0; /* int arm */ + +DEVICE lfc_dev; +uint32 lfc (uint32 dev, uint32 op, uint32 dat); +t_stat lfc_svc (UNIT *uptr); +t_stat lfc_reset (DEVICE *dptr); + +/* PIC data structures + + pic_dev PIC device descriptor + pic_unit PIC unit descriptor + pic_reg PIC register list +*/ + +DIB pic_dib = { d_PIC, -1, v_PIC, NULL, &pic, NULL }; + +UNIT pic_unit = { UDATA (&pic_svc, 0, 0), 1000 }; + +REG pic_reg[] = { + { HRDATA (BUF, pic_db, 16) }, + { HRDATA (RIC, pic_ric, 16) }, + { HRDATA (CIC, pic_cic, 12) }, + { DRDATA (SAVE, pic_save, 32), REG_HRO + PV_LEFT }, + { FLDATA (RDP, pic_rdp, 0) }, + { FLDATA (WDP, pic_wdp, 0) }, + { FLDATA (OVF, pic_ovf, 0) }, + { FLDATA (IREQ, int_req[l_PIC], i_PIC) }, + { FLDATA (IENB, int_enb[l_PIC], i_PIC) }, + { FLDATA (IARM, pic_arm, 0) }, + { BRDATA (TIME, pic_time, 10, 16, 4), REG_NZ + PV_LEFT }, + { HRDATA (DEVNO, pic_dib.dno, 8), REG_HRO }, + { NULL } }; + +MTAB pic_mod[] = { + { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL }, + { UNIT_DIAG, 0, NULL, "NORMAL", NULL }, + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, NULL }, + { 0 } }; + +DEVICE pic_dev = { + "PIC", &pic_unit, pic_reg, pic_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &pic_reset, + NULL, NULL, NULL, + &pic_dib, DEV_DISABLE }; + +/* LFC data structures + + lfc_dev LFC device descriptor + lfc_unit LFC unit descriptor + lfc_reg LFC register list +*/ + +DIB lfc_dib = { d_LFC, -1, v_LFC, NULL, &lfc, NULL }; + +UNIT lfc_unit = { UDATA (&lfc_svc, 0, 0), 8333 }; + +REG lfc_reg[] = { + { FLDATA (IREQ, int_req[l_LFC], i_LFC) }, + { FLDATA (IENB, int_enb[l_LFC], i_LFC) }, + { FLDATA (IARM, lfc_arm, 0) }, + { DRDATA (TIME, lfc_unit.wait, 24), REG_NZ + PV_LEFT }, + { DRDATA (TPS, lfc_tps, 8), REG_NZ + PV_LEFT }, + { HRDATA (DEVNO, lfc_dib.dno, 8), REG_HRO }, + { NULL } }; + +MTAB lfc_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", + &set_dev, &show_dev, NULL }, + { 0 } }; + +DEVICE lfc_dev = { + "LFC", &lfc_unit, lfc_reg, lfc_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &lfc_reset, + NULL, NULL, NULL, + &lfc_dib, DEV_DISABLE }; + +/* Precision clock: IO routine */ + +uint32 pic (uint32 dev, uint32 op, uint32 dat) +{ +int32 t; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + return HW; /* HW capable */ +case IO_RH: /* read halfword */ + pic_rdp = 0; /* clr ptr */ + return pic_rd_cic (); +case IO_RD: /* read */ + t = pic_rd_cic (); /* get cic */ + if (pic_rdp) t = t & DMASK8; /* 2nd? get lo */ + else t = (t >> 8) & DMASK8; /* 1st? get hi */ + pic_rdp = pic_rdp ^ 1; /* flip byte ptr */ + return t; +case IO_WH: /* write halfword */ + pic_wdp = 0; /* clr ptr */ + pic_db = dat; + break; +case IO_WD: /* write */ + if (pic_wdp) pic_db = (pic_db & 0xFF00) | dat; + else pic_db = (pic_db & 0xFF) | (dat << 8); + pic_wdp = pic_wdp ^ 1; /* flip byte ptr */ + break; +case IO_SS: /* sense status */ + if (pic_ovf) { /* overflow? */ + pic_ovf = 0; /* clear flag */ + CLR_INT (v_PIC); /* clear intr */ + return STA_OVF; } + return 0; +case IO_OC: /* output cmd */ + pic_arm = int_chg (v_PIC, dat, pic_arm); /* upd int ctrl */ + if (dat & CMD_STRT) { /* start? */ + pic_ric = pic_db; /* new ric */ + pic_cic = GET_CTR (pic_ric); /* new cic */ + pic_ovf = 0; /* clear flag */ + sim_cancel (&pic_unit); /* stop clock */ + pic_rdp = pic_wdp = 0; /* init ptrs */ + if (pic_ric & PIC_RATE) pic_sched (TRUE); /* any rate? */ + } /* end if start */ + break; } /* end case */ +return 0; +} + +/* Unit service */ + +t_stat pic_svc (UNIT *uptr) +{ +t_bool rate_chg = FALSE; + +if (pic_cnti) pic_cic = -1; /* one shot? */ +pic_cic = pic_cic - 1; /* decrement */ +if (pic_cic < 0) { /* overflow? */ + if (pic_wdp) pic_ovf = 1; /* broken wr? set flag */ + if (pic_arm) SET_INT (v_PIC); /* if armed, intr */ + if (GET_RATE (pic_ric) != GET_RATE (pic_db)) /* rate change? */ + rate_chg = TRUE; + pic_ric = pic_db; /* new ric */ + pic_cic = GET_CTR (pic_ric); /* new cic */ + if ((pic_ric & PIC_RATE) == 0) return SCPE_OK; } +pic_sched (rate_chg); +return SCPE_OK; +} + +/* Schedule next interval + + If rate < 1ms, or diagnostic mode, count instructions + If rate = 1ms, and not diagnostic mode, use timer +*/ + +void pic_sched (t_bool strt) +{ +int32 r, t; + +pic_save = sim_grtime (); /* save start */ +r = pic_map[GET_RATE (pic_ric)]; /* get mapped rate */ +t = pic_time[r]; /* get delay */ +if ((r == 3) && !(pic_unit.flags & UNIT_DIAG)) { /* timer? */ + pic_cnti = 0; /* clr mode */ + if (strt) t = sim_rtcn_init (t, TMR_PIC); /* init or */ + else t = sim_rtcn_calb (PIC_TPS, TMR_PIC); } /* calibrate */ +else { pic_cnti = 1; /* set mode */ + t = t * (pic_cic + 1); /* interval */ + if (t == 1) t++; } /* for diagn */ +sim_activate (&pic_unit, t); /* activate */ +return; +} + +/* Read (interpolated) current interval */ + +uint32 pic_rd_cic (void) +{ +if (sim_is_active (&pic_unit) && pic_cnti) { /* running, one shot? */ + uint32 delta = sim_grtime () - pic_save; /* interval */ + uint32 tm = pic_time[pic_map[GET_RATE (pic_ric)]]; /* ticks/intv */ + delta = delta / tm; /* ticks elapsed */ + if (delta >= ((uint32) pic_cic)) return 0; /* cap value */ + return pic_cic - delta; } +return pic_cic; +} + +/* Reset routine */ + +t_stat pic_reset (DEVICE *dptr) +{ +sim_cancel (&pic_unit); /* cancel unit */ +pic_ric = pic_cic = 0; +pic_db = 0; +pic_ovf = 0; /* clear state */ +pic_cnti = 0; +pic_rdp = pic_wdp = 0; +CLR_INT (v_PIC); /* clear int */ +CLR_ENB (v_PIC); /* disable int */ +pic_arm = 0; /* disarm int */ +return SCPE_OK; +} + +/* Line clock: IO routine */ + +uint32 lfc (uint32 dev, uint32 op, uint32 dat) +{ +int32 t; + +switch (op) { /* case IO op */ +case IO_ADR: /* select */ + return BY; /* byte only */ +case IO_OC: /* command */ + lfc_arm = int_chg (v_LFC, dat, lfc_arm); /* upd int ctrl */ + if (lfc_arm && !sim_is_active (&lfc_unit)) { /* starting? */ + t = sim_rtcn_init (lfc_unit.wait, TMR_LFC); + sim_activate (&lfc_unit, t); } /* init clock */ + break; } +return 0; +} + +/* Unit service */ + +t_stat lfc_svc (UNIT *uptr) +{ +int32 t; + +if (lfc_arm) { /* armed? */ + SET_INT (v_LFC); /* req intr */ + if (pic_unit.flags & UNIT_DIAG) t = uptr->wait; /* diag? fixed delay */ + else t = sim_rtcn_calb (lfc_tps, TMR_LFC); /* else calibrate */ + sim_activate (uptr, t); } /* reactivate */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat lfc_reset (DEVICE *dptr) +{ +sim_cancel (&lfc_unit); /* cancel unit */ +CLR_INT (v_LFC); /* clear int */ +CLR_ENB (v_LFC); /* disable int */ +lfc_arm = 0; /* disarm int */ +return SCPE_OK; +} diff --git a/NOVA/eclipse_tt.c b/NOVA/eclipse_tt.c index 4858e6e3..58ddccf6 100644 --- a/NOVA/eclipse_tt.c +++ b/NOVA/eclipse_tt.c @@ -26,7 +26,7 @@ t_stat tti_svc (UNIT *uptr); t_stat tto_svc (UNIT *uptr); t_stat tti_reset (DEVICE *dptr); t_stat tto_reset (DEVICE *dptr); -t_stat ttx_setmod (UNIT *uptr, int32 value); +t_stat ttx_setmod (UNIT *uptr, int32 value, char *cptr, void *desc); void translate_in(); int32 translate_out(int32 c); int32 putseq(char *seq); @@ -386,7 +386,7 @@ sim_cancel (&tto_unit); /* deactivate unit */ return SCPE_OK; } -t_stat ttx_setmod (UNIT *uptr, int32 value) +t_stat ttx_setmod (UNIT *uptr, int32 value, char *cptr, void *desc) { tti_unit.flags = (tti_unit.flags & ~UNIT_DASHER) | value; tto_unit.flags = (tto_unit.flags & ~UNIT_DASHER) | value; diff --git a/NOVA/nova_clk.c b/NOVA/nova_clk.c index 383f3070..f5de5e8e 100644 --- a/NOVA/nova_clk.c +++ b/NOVA/nova_clk.c @@ -89,8 +89,8 @@ case iopS: /* start */ dev_done = dev_done & ~INT_CLK; /* clear done, int */ int_req = int_req & ~INT_CLK; if (!sim_is_active (&clk_unit)) /* not running? */ - sim_activate (&clk_unit, /* activate */ - sim_rtc_init (clk_time[clk_sel])); /* init calibr */ + sim_activate (&clk_unit, /* activate */ + sim_rtc_init (clk_time[clk_sel])); /* init calibr */ break; case iopC: /* clear */ dev_busy = dev_busy & ~INT_CLK; /* clear busy */ diff --git a/NOVA/nova_cpu.c b/NOVA/nova_cpu.c index 723de635..e97fe5f2 100644 --- a/NOVA/nova_cpu.c +++ b/NOVA/nova_cpu.c @@ -348,14 +348,14 @@ if (int_req > INT_PENDING) { /* interrupt? */ PCQ_ENTRY; /* save old PC */ M[INT_SAV] = PC; if (int_req & INT_STK) { /* stack overflow? */ - int_req = int_req & ~INT_STK; /* clear */ - MA = STK_JMP; } /* jmp @3 */ + int_req = int_req & ~INT_STK; /* clear */ + MA = STK_JMP; } /* jmp @3 */ else MA = INT_JMP; /* intr: jmp @1 */ for (i = 0, indf = 1; indf && (i < ind_max); i++) { - indf = IND_STEP (MA); } /* indirect loop */ + indf = IND_STEP (MA); } /* indirect loop */ if (i >= ind_max) { - reason = STOP_IND_INT; - break; } + reason = STOP_IND_INT; + break; } PC = MA; } /* end interrupt */ if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ @@ -375,96 +375,96 @@ if (IR & I_OPR) { /* operate? */ dstAC = I_GETDST (IR); switch (I_GETCRY (IR)) { /* decode carry */ case 0: /* load */ - src = AC[srcAC] | C; - break; + src = AC[srcAC] | C; + break; case 1: /* clear */ - src = AC[srcAC]; - break; + src = AC[srcAC]; + break; case 2: /* set */ - src = AC[srcAC] | CBIT; - break; + src = AC[srcAC] | CBIT; + break; case 3: /* complement */ - src = AC[srcAC] | (C ^ CBIT); - break; } /* end switch carry */ + src = AC[srcAC] | (C ^ CBIT); + break; } /* end switch carry */ switch (I_GETALU (IR)) { /* decode ALU */ case 0: /* COM */ - src = src ^ DMASK; - break; + src = src ^ DMASK; + break; case 1: /* NEG */ - src = ((src ^ DMASK) + 1) & CMASK; - break; + src = ((src ^ DMASK) + 1) & CMASK; + break; case 2: /* MOV */ - break; + break; case 3: /* INC */ - src = (src + 1) & CMASK; - break; + src = (src + 1) & CMASK; + break; case 4: /* ADC */ - src = ((src ^ DMASK) + AC[dstAC]) & CMASK; - break; + src = ((src ^ DMASK) + AC[dstAC]) & CMASK; + break; case 5: /* SUB */ - src = ((src ^ DMASK) + AC[dstAC] + 1) & CMASK; - break; + src = ((src ^ DMASK) + AC[dstAC] + 1) & CMASK; + break; case 6: /* ADD */ - src = (src + AC[dstAC]) & CMASK; - break; + src = (src + AC[dstAC]) & CMASK; + break; case 7: /* AND */ - src = src & (AC[dstAC] | CBIT); - break; } /* end switch oper */ + src = src & (AC[dstAC] | CBIT); + break; } /* end switch oper */ /* Operate, continued */ switch (I_GETSHF (IR)) { /* decode shift */ case 0: /* nop */ - break; + break; case 1: /* L */ - src = ((src << 1) | (src >> 16)) & CMASK; - break; + src = ((src << 1) | (src >> 16)) & CMASK; + break; case 2: /* R */ - src = ((src >> 1) | (src << 16)) & CMASK; - break; + src = ((src >> 1) | (src << 16)) & CMASK; + break; case 3: /* S */ - src = ((src & 0377) << 8) | ((src >> 8) & 0377) | - (src & CBIT); - break; } /* end switch shift */ + src = ((src & 0377) << 8) | ((src >> 8) & 0377) | + (src & CBIT); + break; } /* end switch shift */ switch (I_GETSKP (IR)) { /* decode skip */ case 0: /* nop */ - if ((IR & I_NLD) && (cpu_unit.flags & UNIT_STK)) { - int32 indf, MA; /* Nova 3 or 4 trap */ - PCQ_ENTRY; /* save old PC */ - M[TRP_SAV] = (PC - 1) & AMASK; - MA = TRP_JMP; /* jmp @47 */ - for (i = 0, indf = 1; indf && (i < ind_max); i++) { - indf = IND_STEP (MA); } /* resolve ind */ - if (i >= ind_max) { /* indirect loop? */ - reason = STOP_IND_TRP; - break; } - PC = MA; /* new PC */ - break; } - break; + if ((IR & I_NLD) && (cpu_unit.flags & UNIT_STK)) { + int32 indf, MA; /* Nova 3 or 4 trap */ + PCQ_ENTRY; /* save old PC */ + M[TRP_SAV] = (PC - 1) & AMASK; + MA = TRP_JMP; /* jmp @47 */ + for (i = 0, indf = 1; indf && (i < ind_max); i++) { + indf = IND_STEP (MA); } /* resolve ind */ + if (i >= ind_max) { /* indirect loop? */ + reason = STOP_IND_TRP; + break; } + PC = MA; /* new PC */ + break; } + break; case 1: /* SKP */ - PC = (PC + 1) & AMASK; - break; + PC = (PC + 1) & AMASK; + break; case 2: /* SZC */ - if (src < CBIT) PC = (PC + 1) & AMASK; - break; + if (src < CBIT) PC = (PC + 1) & AMASK; + break; case 3: /* SNC */ - if (src >= CBIT) PC = (PC + 1) & AMASK; - break; + if (src >= CBIT) PC = (PC + 1) & AMASK; + break; case 4: /* SZR */ - if ((src & DMASK) == 0) PC = (PC + 1) & AMASK; - break; + if ((src & DMASK) == 0) PC = (PC + 1) & AMASK; + break; case 5: /* SNR */ - if ((src & DMASK) != 0) PC = (PC + 1) & AMASK; - break; + if ((src & DMASK) != 0) PC = (PC + 1) & AMASK; + break; case 6: /* SEZ */ - if (src <= CBIT) PC = (PC + 1) & AMASK; - break; + if (src <= CBIT) PC = (PC + 1) & AMASK; + break; case 7: /* SBN */ - if (src > CBIT) PC = (PC + 1) & AMASK; - break; } /* end switch skip */ + if (src > CBIT) PC = (PC + 1) & AMASK; + break; } /* end switch skip */ if ((IR & I_NLD) == 0) { /* load? */ - AC[dstAC] = src & DMASK; - C = src & CBIT; } /* end if load */ + AC[dstAC] = src & DMASK; + C = src & CBIT; } /* end if load */ } /* end if operate */ /* Memory reference instructions */ @@ -474,70 +474,70 @@ else if (IR < 060000) { /* mem ref? */ MA = I_GETDISP (IR); /* get disp */ switch (I_GETMODE (IR)) { /* decode mode */ case 0: /* page zero */ - break; + break; case 1: /* PC relative */ - if (MA & DISPSIGN) MA = 077400 | MA; - MA = (MA + PC - 1) & AMASK; - break; + if (MA & DISPSIGN) MA = 077400 | MA; + MA = (MA + PC - 1) & AMASK; + break; case 2: /* AC2 relative */ - if (MA & DISPSIGN) MA = 077400 | MA; - MA = (MA + AC[2]) & AMASK; - break; + if (MA & DISPSIGN) MA = 077400 | MA; + MA = (MA + AC[2]) & AMASK; + break; case 3: /* AC3 relative */ - if (MA & DISPSIGN) MA = 077400 | MA; - MA = (MA + AC[3]) & AMASK; - break; } /* end switch mode */ + if (MA & DISPSIGN) MA = 077400 | MA; + MA = (MA + AC[3]) & AMASK; + break; } /* end switch mode */ if (indf = IR & I_IND) { /* indirect? */ - for (i = 0; indf && (i < ind_max); i++) { /* count */ - indf = IND_STEP (MA); } /* resolve indirect */ - if (i >= ind_max) { /* too many? */ - reason = STOP_IND; - break; } } + for (i = 0; indf && (i < ind_max); i++) { /* count */ + indf = IND_STEP (MA); } /* resolve indirect */ + if (i >= ind_max) { /* too many? */ + reason = STOP_IND; + break; } } /* Memory reference, continued */ switch (I_GETOPAC (IR)) { /* decode op + AC */ case 001: /* JSR */ - AC[3] = PC; + AC[3] = PC; case 000: /* JMP */ - PCQ_ENTRY; - PC = MA; - break; + PCQ_ENTRY; + PC = MA; + break; case 002: /* ISZ */ - src = (M[MA] + 1) & DMASK; - if (MEM_ADDR_OK (MA)) M[MA] = src; - if (src == 0) PC = (PC + 1) & AMASK; - break; + src = (M[MA] + 1) & DMASK; + if (MEM_ADDR_OK (MA)) M[MA] = src; + if (src == 0) PC = (PC + 1) & AMASK; + break; case 003: /* DSZ */ - src = (M[MA] - 1) & DMASK; - if (MEM_ADDR_OK (MA)) M[MA] = src; - if (src == 0) PC = (PC + 1) & AMASK; - break; + src = (M[MA] - 1) & DMASK; + if (MEM_ADDR_OK (MA)) M[MA] = src; + if (src == 0) PC = (PC + 1) & AMASK; + break; case 004: /* LDA 0 */ - AC[0] = M[MA]; - break; + AC[0] = M[MA]; + break; case 005: /* LDA 1 */ - AC[1] = M[MA]; - break; + AC[1] = M[MA]; + break; case 006: /* LDA 2 */ - AC[2] = M[MA]; - break; + AC[2] = M[MA]; + break; case 007: /* LDA 3 */ - AC[3] = M[MA]; - break; + AC[3] = M[MA]; + break; case 010: /* STA 0 */ - if (MEM_ADDR_OK (MA)) M[MA] = AC[0]; - break; + if (MEM_ADDR_OK (MA)) M[MA] = AC[0]; + break; case 011: /* STA 1 */ - if (MEM_ADDR_OK (MA)) M[MA] = AC[1]; - break; + if (MEM_ADDR_OK (MA)) M[MA] = AC[1]; + break; case 012: /* STA 2 */ - if (MEM_ADDR_OK (MA)) M[MA] = AC[2]; - break; + if (MEM_ADDR_OK (MA)) M[MA] = AC[2]; + break; case 013: /* STA 3 */ - if (MEM_ADDR_OK (MA)) M[MA] = AC[3]; - break; } /* end switch */ + if (MEM_ADDR_OK (MA)) M[MA] = AC[3]; + break; } /* end switch */ } /* end mem ref */ /* IOT instruction */ @@ -549,200 +549,199 @@ else { /* IOT */ pulse = I_GETPULSE (IR); device = I_GETDEV (IR); if (code == ioSKP) { /* IO skip? */ - switch (pulse) { /* decode IR<8:9> */ - case 0: /* skip if busy */ - if ((device == DEV_CPU)? (int_req & INT_ION) != 0: - (dev_busy & dev_table[device].mask) != 0) - PC = (PC + 1) & AMASK; - break; - case 1: /* skip if not busy */ - if ((device == DEV_CPU)? (int_req & INT_ION) == 0: - (dev_busy & dev_table[device].mask) == 0) - PC = (PC + 1) & AMASK; - break; - case 2: /* skip if done */ - if ((device == DEV_CPU)? pwr_low != 0: - (dev_done & dev_table[device].mask) != 0) - PC = (PC + 1) & AMASK; - break; - case 3: /* skip if not done */ - if ((device == DEV_CPU)? pwr_low == 0: - (dev_done & dev_table[device].mask) == 0) - PC = (PC + 1) & AMASK; - break; } /* end switch */ - } /* end IO skip */ + switch (pulse) { /* decode IR<8:9> */ + case 0: /* skip if busy */ + if ((device == DEV_CPU)? (int_req & INT_ION) != 0: + (dev_busy & dev_table[device].mask) != 0) + PC = (PC + 1) & AMASK; + break; + case 1: /* skip if not busy */ + if ((device == DEV_CPU)? (int_req & INT_ION) == 0: + (dev_busy & dev_table[device].mask) == 0) + PC = (PC + 1) & AMASK; + break; + case 2: /* skip if done */ + if ((device == DEV_CPU)? pwr_low != 0: + (dev_done & dev_table[device].mask) != 0) + PC = (PC + 1) & AMASK; + break; + case 3: /* skip if not done */ + if ((device == DEV_CPU)? pwr_low == 0: + (dev_done & dev_table[device].mask) == 0) + PC = (PC + 1) & AMASK; + break; } /* end switch */ + } /* end IO skip */ /* IOT, continued */ else if (device == DEV_MDV) { - switch (code) { /* case on opcode */ - case ioNIO: /* frame ptr */ - if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) FP = AC[dstAC] & AMASK; - if (pulse == iopC) AC[dstAC] = FP; } - break; - case ioDIA: /* load byte */ - if (cpu_unit.flags & UNIT_BYT) - AC[dstAC] = (M[AC[pulse] >> 1] >> - ((AC[pulse] & 1)? 0: 8)) & 0377; - else AC[dstAC] = 0; - break; - case ioDOA: /* stack ptr */ - if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) SP = AC[dstAC] & AMASK; - if (pulse == iopC) AC[dstAC] = SP; } - break; - case ioDIB: /* push, pop */ - if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) { /* push */ - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; - STK_CHECK (SP, 1); } - if (pulse == iopC) { /* pop */ - AC[dstAC] = M[SP]; - SP = DECA (SP); } - if ((pulse == iopP) && /* Nova 4 pshn */ - (cpu_unit.flags & UNIT_BYT)) { - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; - if (SP > M[042]) int_req = int_req | INT_STK ; - } - } - break; - case ioDOB: /* store byte */ - if (cpu_unit.flags & UNIT_BYT) { - int32 MA, val; - MA = AC[pulse] >> 1; - val = AC[dstAC] & 0377; - if (MEM_ADDR_OK (MA)) M[MA] = (AC[pulse] & 1)? - ((M[MA] & ~0377) | val): - ((M[MA] & 0377) | (val << 8)); } - break; - case ioDIC: /* save, return */ - if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) { /* save */ - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = FP; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | - (AC[3] & AMASK); - AC[3] = FP = SP & AMASK; - STK_CHECK (SP, 5); } - if (pulse == iopC) { /* retn */ - PCQ_ENTRY; - SP = FP & AMASK; - C = (M[SP] << 1) & CBIT; - PC = M[SP] & AMASK; - SP = DECA (SP); - AC[3] = M[SP]; - SP = DECA (SP); - AC[2] = M[SP]; - SP = DECA (SP); - AC[1] = M[SP]; - SP = DECA (SP); - AC[0] = M[SP]; - SP = DECA (SP); - FP = AC[3] & AMASK; } - if ((pulse == iopP) && /* Nova 4 saven */ - (cpu_unit.flags & UNIT_BYT)) { - int32 frameSz = M[PC] ; - PC = INCA (PC) ; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = FP; - SP = INCA (SP); - if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | - (AC[3] & AMASK); - AC[3] = FP = SP & AMASK ; - SP = (SP + frameSz) & AMASK ; - if (SP > M[042]) int_req = int_req | INT_STK; - } - } - break; - case ioDOC: - if ((dstAC == 2) && (cpu_unit.flags & UNIT_MDV)) { - uint32 mddata, uAC0, uAC1, uAC2; - uAC0 = (unsigned int32) AC[0]; - uAC1 = (unsigned int32) AC[1]; - uAC2 = (unsigned int32) AC[2]; - if (pulse == iopP) { /* mul */ - mddata = (uAC1 * uAC2) + uAC0; - AC[0] = (mddata >> 16) & DMASK; - AC[1] = mddata & DMASK; } - if (pulse == iopS) { /* div */ - if ((uAC0 >= uAC2) || (uAC2 == 0)) - C = CBIT; - else { C = 0; - mddata = (uAC0 << 16) | uAC1; - AC[1] = mddata / uAC2; - AC[0] = mddata % uAC2; } } } - if ((dstAC == 3) && (cpu_unit.flags & UNIT_BYT)) { - int32 mddata; - if (pulse == iopC) { /* muls */ - mddata = (SEXT (AC[1]) * SEXT (AC[2])) + - SEXT (AC[0]); - AC[0] = (mddata >> 16) & DMASK; - AC[1] = mddata & DMASK; } - if (pulse == iopN) { /* divs */ - if (AC[2] == 0) C = CBIT; - else { mddata = (SEXT (AC[0]) << 16) | AC[1]; - AC[1] = mddata / SEXT (AC[2]); - AC[0] = mddata % SEXT (AC[2]); - if ((AC[1] > 077777) || (AC[1] < -0100000)) - C = CBIT; - else C = 0; - AC[0] = AC[0] & DMASK; } } } - break; } /* end case code */ - } /* end if mul/div */ + switch (code) { /* case on opcode */ + case ioNIO: /* frame ptr */ + if (cpu_unit.flags & UNIT_STK) { + if (pulse == iopN) FP = AC[dstAC] & AMASK; + if (pulse == iopC) AC[dstAC] = FP; } + break; + case ioDIA: /* load byte */ + if (cpu_unit.flags & UNIT_BYT) + AC[dstAC] = (M[AC[pulse] >> 1] >> + ((AC[pulse] & 1)? 0: 8)) & 0377; + else AC[dstAC] = 0; + break; + case ioDOA: /* stack ptr */ + if (cpu_unit.flags & UNIT_STK) { + if (pulse == iopN) SP = AC[dstAC] & AMASK; + if (pulse == iopC) AC[dstAC] = SP; } + break; + case ioDIB: /* push, pop */ + if (cpu_unit.flags & UNIT_STK) { + if (pulse == iopN) { /* push */ + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; + STK_CHECK (SP, 1); } + if (pulse == iopC) { /* pop */ + AC[dstAC] = M[SP]; + SP = DECA (SP); } + if ((pulse == iopP) && /* Nova 4 pshn */ + (cpu_unit.flags & UNIT_BYT)) { + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; + if (SP > M[042]) int_req = int_req | INT_STK ; + } + } + break; + case ioDOB: /* store byte */ + if (cpu_unit.flags & UNIT_BYT) { + int32 MA, val; + MA = AC[pulse] >> 1; + val = AC[dstAC] & 0377; + if (MEM_ADDR_OK (MA)) M[MA] = (AC[pulse] & 1)? + ((M[MA] & ~0377) | val): + ((M[MA] & 0377) | (val << 8)); } + break; + case ioDIC: /* save, return */ + if (cpu_unit.flags & UNIT_STK) { + if (pulse == iopN) { /* save */ + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = FP; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | + (AC[3] & AMASK); + AC[3] = FP = SP & AMASK; + STK_CHECK (SP, 5); } + if (pulse == iopC) { /* retn */ + PCQ_ENTRY; + SP = FP & AMASK; + C = (M[SP] << 1) & CBIT; + PC = M[SP] & AMASK; + SP = DECA (SP); + AC[3] = M[SP]; + SP = DECA (SP); + AC[2] = M[SP]; + SP = DECA (SP); + AC[1] = M[SP]; + SP = DECA (SP); + AC[0] = M[SP]; + SP = DECA (SP); + FP = AC[3] & AMASK; } + if ((pulse == iopP) && /* Nova 4 saven */ + (cpu_unit.flags & UNIT_BYT)) { + int32 frameSz = M[PC] ; + PC = INCA (PC) ; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = FP; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | + (AC[3] & AMASK); + AC[3] = FP = SP & AMASK ; + SP = (SP + frameSz) & AMASK ; + if (SP > M[042]) int_req = int_req | INT_STK; + } + } + break; + case ioDOC: + if ((dstAC == 2) && (cpu_unit.flags & UNIT_MDV)) { + uint32 mddata, uAC0, uAC1, uAC2; + uAC0 = (unsigned int32) AC[0]; + uAC1 = (unsigned int32) AC[1]; + uAC2 = (unsigned int32) AC[2]; + if (pulse == iopP) { /* mul */ + mddata = (uAC1 * uAC2) + uAC0; + AC[0] = (mddata >> 16) & DMASK; + AC[1] = mddata & DMASK; } + if (pulse == iopS) { /* div */ + if ((uAC0 >= uAC2) || (uAC2 == 0)) C = CBIT; + else { + C = 0; + mddata = (uAC0 << 16) | uAC1; + AC[1] = mddata / uAC2; + AC[0] = mddata % uAC2; } } } + if ((dstAC == 3) && (cpu_unit.flags & UNIT_BYT)) { + int32 mddata; + if (pulse == iopC) { /* muls */ + mddata = (SEXT (AC[1]) * SEXT (AC[2])) + SEXT (AC[0]); + AC[0] = (mddata >> 16) & DMASK; + AC[1] = mddata & DMASK; } + if (pulse == iopN) { /* divs */ + if (AC[2] == 0) C = CBIT; + else { + mddata = (SEXT (AC[0]) << 16) | AC[1]; + AC[1] = mddata / SEXT (AC[2]); + AC[0] = mddata % SEXT (AC[2]); + if ((AC[1] > 077777) || (AC[1] < -0100000)) + C = CBIT; + else C = 0; + AC[0] = AC[0] & DMASK; } } } + break; } /* end case code */ + } /* end if mul/div */ /* IOT, continued */ else if (device == DEV_CPU) { /* CPU control */ - switch (code) { /* decode IR<5:7> */ - case ioDIA: /* read switches */ - AC[dstAC] = SR; - break; - case ioDIB: /* int ack */ - AC[dstAC] = 0; - int_req = (int_req & ~INT_DEV) | - (dev_done & ~dev_disable); - iodata = int_req & (-int_req); - for (i = DEV_LOW; i <= DEV_HIGH; i++) { - if (iodata & dev_table[i].mask) { - AC[dstAC] = i; break; } } - break; - case ioDOB: /* mask out */ - mask_out (pimask = AC[dstAC]); - break; - case ioDIC: /* io reset */ - reset_all (0); /* reset devices */ - break; - case ioDOC: /* halt */ - reason = STOP_HALT; - break; } /* end switch code */ - switch (pulse) { /* decode IR<8:9> */ - case iopS: /* ion */ - int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING; - break; - case iopC: /* iof */ - int_req = int_req & ~INT_ION; - break; } /* end switch pulse */ - } /* end CPU control */ + switch (code) { /* decode IR<5:7> */ + case ioDIA: /* read switches */ + AC[dstAC] = SR; + break; + case ioDIB: /* int ack */ + AC[dstAC] = 0; + int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); + iodata = int_req & (-int_req); + for (i = DEV_LOW; i <= DEV_HIGH; i++) { + if (iodata & dev_table[i].mask) { + AC[dstAC] = i; break; } } + break; + case ioDOB: /* mask out */ + mask_out (pimask = AC[dstAC]); + break; + case ioDIC: /* io reset */ + reset_all (0); /* reset devices */ + break; + case ioDOC: /* halt */ + reason = STOP_HALT; + break; } /* end switch code */ + switch (pulse) { /* decode IR<8:9> */ + case iopS: /* ion */ + int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING; + break; + case iopC: /* iof */ + int_req = int_req & ~INT_ION; + break; } /* end switch pulse */ + } /* end CPU control */ else if (dev_table[device].routine) { /* normal device */ - iodata = dev_table[device].routine (pulse, code, AC[dstAC]); - reason = iodata >> IOT_V_REASON; - if (code & 1) AC[dstAC] = iodata & 0177777; } + iodata = dev_table[device].routine (pulse, code, AC[dstAC]); + reason = iodata >> IOT_V_REASON; + if (code & 1) AC[dstAC] = iodata & 0177777; } else reason = stop_dev; } /* end if IOT */ } /* end while */ @@ -763,7 +762,7 @@ int32 i; dev_disable = 0; for (i = DEV_LOW; i <= DEV_HIGH; i++) { if (newmask & dev_table[i].pi) - dev_disable = dev_disable | dev_table[i].mask; } + dev_disable = dev_disable | dev_table[i].mask; } int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); return; } diff --git a/NOVA/nova_dkp.c b/NOVA/nova_dkp.c index ce7bce7a..5e2aec00 100644 --- a/NOVA/nova_dkp.c +++ b/NOVA/nova_dkp.c @@ -446,21 +446,21 @@ case ioDIA: /* DIA */ dkp_sta = dkp_sta & ~STA_DYN; /* clear dynamic */ if (uptr->flags & UNIT_ATT) dkp_sta = dkp_sta | STA_DRDY; if (uptr->CYL >= drv_tab[dtype].cyl) - dkp_sta = dkp_sta | STA_CYL; /* bad cylinder? */ + dkp_sta = dkp_sta | STA_CYL; /* bad cylinder? */ if (dkp_sta & STA_EFLGS) dkp_sta = dkp_sta | STA_ERR; rval = dkp_sta; break; case ioDOA: /* DOA */ if ((dev_busy & INT_DKP) == 0) { - dkp_fccy = AC; /* save cmd, cyl */ - dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS); } + dkp_fccy = AC; /* save cmd, cyl */ + dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS); } break; case ioDIB: /* DIB */ rval = dkp_ma; /* return buf addr */ break; case ioDOB: /* DOB */ if ((dev_busy & INT_DKP) == 0) dkp_ma = - AC & (drv_tab[dtype].new? DMASK: AMASK); + AC & (drv_tab[dtype].new? DMASK: AMASK); break; case ioDIC: /* DIC */ rval = dkp_ussc; /* return unit, sect */ @@ -559,12 +559,12 @@ rval = SCPE_OK; dtype = GET_DTYPE (uptr->flags); /* get drive type */ if (uptr->FUNC == FCCY_SEEK) { /* seek? */ if (uptr->CYL >= drv_tab[dtype].cyl) /* bad cylinder? */ - dkp_sta = dkp_sta | STA_ERR | STA_CYL; + dkp_sta = dkp_sta | STA_ERR | STA_CYL; dev_done = dev_done | INT_DKP; /* set done */ int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); u = uptr - dkp_dev.units; /* get unit number */ dkp_sta = (dkp_sta | (STA_SKDN0 >> u)) /* set seek done */ - & ~(STA_SEEK0 >> u); /* clear seeking */ + & ~(STA_SEEK0 >> u); /* clear seeking */ return SCPE_OK; } if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */ @@ -581,11 +581,11 @@ else if (GET_CYL (dkp_fccy, dtype) != uptr->CYL) /* address error? */ else { sc = 16 - GET_COUNT (dkp_ussc); /* get sector count */ sa = GET_SA (uptr->CYL, GET_SURF (dkp_ussc, dtype), - GET_SECT (dkp_ussc, dtype), dtype); /* get disk block */ + GET_SECT (dkp_ussc, dtype), dtype); /* get disk block */ xcsa = GET_SA (uptr->CYL + 1, 0, 0, dtype); /* get next cyl addr */ if ((sa + sc) > xcsa ) { /* across cylinder? */ - sc = xcsa - sa; /* limit transfer */ - dkp_sta = dkp_sta | STA_XCY; } /* xcyl error */ + sc = xcsa - sa; /* limit transfer */ + dkp_sta = dkp_sta | STA_XCY; } /* xcyl error */ bda = sa * DKP_NUMWD * sizeof (short); /* to words, bytes */ err = fseek (uptr->fileref, bda, SEEK_SET); /* position drive */ @@ -610,17 +610,17 @@ else { sc = 16 - GET_COUNT (dkp_ussc); /* get sector count */ if (err = ferror (uptr->fileref)) break; } } if (err != 0) { - perror ("DKP I/O error"); - rval = SCPE_IOERR; } + perror ("DKP I/O error"); + rval = SCPE_IOERR; } clearerr (uptr->fileref); sa = sa + sc; /* update sector addr */ newsect = sa % drv_tab[dtype].sect; newsurf = (sa / drv_tab[dtype].sect) % drv_tab[dtype].surf; dkp_ussc = (dkp_ussc & USSC_UNIT) | ((dkp_ussc + sc) & USSC_M_COUNT) | - ((drv_tab[dtype].new)? - ((newsurf << USSC_V_NSURFACE) | (newsect << USSC_V_NSECTOR)): - ((newsurf << USSC_V_OSURFACE) | (newsect << USSC_V_OSECTOR)) ); + ((drv_tab[dtype].new)? + ((newsurf << USSC_V_NSURFACE) | (newsect << USSC_V_NSECTOR)): + ((newsurf << USSC_V_OSURFACE) | (newsect << USSC_V_OSECTOR)) ); dkp_sta = dkp_sta | STA_DONE; } /* set status */ dev_busy = dev_busy & ~INT_DKP; /* clear busy */ @@ -661,9 +661,9 @@ if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK; for (i = 0; drv_tab[i].sect != 0; i++) { if (p <= (drv_tab[i].size * (int) sizeof (short))) { - uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); - uptr->capac = drv_tab[i].size; - return SCPE_OK; } } + uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); + uptr->capac = drv_tab[i].size; + return SCPE_OK; } } return SCPE_OK; } diff --git a/NOVA/nova_doc.txt b/NOVA/nova_doc.txt index 40a33e40..35667828 100644 --- a/NOVA/nova_doc.txt +++ b/NOVA/nova_doc.txt @@ -441,12 +441,12 @@ All drives have 256 16b words per sector. The other disk parameters are: D44 408 4 12 5.014 4234, 6045 C111 203 10 6 3.118 4048 C114 203 20 12 12.472 4057, 2314 - 6225 20 2 245 2.508 - 6099 32 4 192 6.291 - 6227 20 6 245 7.526 - 6070 24 4 408 10.027 - 6103 32 8 192 12.583 - 4231 23 19 411 45.979 + 6225 245 2 20 2.508 + 6099 192 4 32 6.291 + 6227 245 6 20 7.526 + 6070 408 4 24 10.027 + 6103 192 8 32 12.583 + 4231 411 19 23 45.979 The moving head disk controller implements these registers: diff --git a/NOVA/nova_dsk.c b/NOVA/nova_dsk.c index 874ca064..d1283521 100644 --- a/NOVA/nova_dsk.c +++ b/NOVA/nova_dsk.c @@ -164,10 +164,10 @@ if ((pulse == iopP) && ((dsk_wlk >> GET_DISK (dsk_da)) & 1)) { /* wrt lock? */ if (pulse & 1) { /* read or write? */ if (((t_addr) (dsk_da * DSK_NUMWD)) >= dsk_unit.capac) { /* inv sev? */ - dev_done = dev_done | INT_DSK; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */ - return rval; } /* done */ + dev_done = dev_done | INT_DSK; /* set done */ + int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); + dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */ + return rval; } /* done */ dsk_unit.FUNC = pulse; /* save command */ dev_busy = dev_busy | INT_DSK; /* set busy */ t = sector_map[dsk_da & DSK_MMASK] - GET_SECTOR (dsk_time); @@ -193,16 +193,16 @@ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ da = dsk_da * DSK_NUMWD; /* calc disk addr */ if (uptr->FUNC == iopS) { /* read? */ for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */ - pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */ - if (MEM_ADDR_OK (pa)) M[pa] = - *(((int16 *) uptr->filebuf) + da + i); } + pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */ + if (MEM_ADDR_OK (pa)) M[pa] = + *(((int16 *) uptr->filebuf) + da + i); } dsk_ma = (dsk_ma + DSK_NUMWD) & AMASK; } if (uptr->FUNC == iopP) { /* write? */ for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */ - pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */ - *(((int16 *) uptr->filebuf) + da + i) = M[pa]; } + pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */ + *(((int16 *) uptr->filebuf) + da + i) = M[pa]; } if (((t_addr) (da + i)) >= uptr->hwmark) /* past end? */ - uptr->hwmark = da + i + 1; /* upd hwmark */ + uptr->hwmark = da + i + 1; /* upd hwmark */ dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK; } dsk_stat = 0; /* set status */ diff --git a/NOVA/nova_lp.c b/NOVA/nova_lp.c index e5c9151d..d3c1fcad 100644 --- a/NOVA/nova_lp.c +++ b/NOVA/nova_lp.c @@ -81,7 +81,7 @@ case iopS: /* start */ int_req = int_req & ~INT_LPT; if ((lpt_unit.buf != 015) && (lpt_unit.buf != 014) && (lpt_unit.buf != 012)) - return (lpt_svc (&lpt_unit) << IOT_V_REASON); + return (lpt_svc (&lpt_unit) << IOT_V_REASON); sim_activate (&lpt_unit, lpt_unit.wait); break; case iopC: /* clear */ diff --git a/NOVA/nova_mta.c b/NOVA/nova_mta.c index 92e955e8..75852359 100644 --- a/NOVA/nova_mta.c +++ b/NOVA/nova_mta.c @@ -261,31 +261,33 @@ case iopS: /* start */ c = GET_CMD (mta_cu); /* get command */ if (dev_busy & INT_MTA) break; /* ignore if busy */ if ((uptr->USTAT & STA_RDY) == 0) { /* drive not ready? */ - mta_sta = mta_sta | STA_ILL; /* illegal op */ - dev_busy = dev_busy & ~INT_MTA; /* clear busy */ - dev_done = dev_done | INT_MTA; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); } + mta_sta = mta_sta | STA_ILL; /* illegal op */ + dev_busy = dev_busy & ~INT_MTA; /* clear busy */ + dev_done = dev_done | INT_MTA; /* set done */ + int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); } else if ((c == CU_REWIND) || (c == CU_UNLOAD)) { /* rewind, unload? */ - mta_upddsta (uptr, (uptr->USTAT & /* update status */ - ~(STA_BOT | STA_EOF | STA_EOT | STA_RDY)) | STA_REW); - sim_activate (uptr, mta_rwait); /* start IO */ - if (c == CU_UNLOAD) detach_unit (uptr); } - else { mta_sta = 0; /* clear errors */ - dev_busy = dev_busy | INT_MTA; /* set busy */ - dev_done = dev_done & ~INT_MTA; /* clear done */ - int_req = int_req & ~INT_MTA; /* clear int */ - if (ctype[c]) sim_activate (uptr, mta_cwait); - else { mta_upddsta (uptr, uptr->USTAT & - ~(STA_BOT | STA_EOF | STA_EOT | STA_RDY)); - sim_activate (uptr, mta_rwait); } } + mta_upddsta (uptr, (uptr->USTAT & /* update status */ + ~(STA_BOT | STA_EOF | STA_EOT | STA_RDY)) | STA_REW); + sim_activate (uptr, mta_rwait); /* start IO */ + if (c == CU_UNLOAD) detach_unit (uptr); } + else { + mta_sta = 0; /* clear errors */ + dev_busy = dev_busy | INT_MTA; /* set busy */ + dev_done = dev_done & ~INT_MTA; /* clear done */ + int_req = int_req & ~INT_MTA; /* clear int */ + if (ctype[c]) sim_activate (uptr, mta_cwait); + else { + mta_upddsta (uptr, uptr->USTAT & + ~(STA_BOT | STA_EOF | STA_EOT | STA_RDY)); + sim_activate (uptr, mta_rwait); } } mta_updcsta (uptr); /* update status */ break; case iopC: /* clear */ for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */ - uptr = mta_dev.units + u; /* cancel IO */ - if (sim_is_active (uptr) && !(uptr->USTAT & STA_REW)) { - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - sim_cancel (uptr); } } + uptr = mta_dev.units + u; /* cancel IO */ + if (sim_is_active (uptr) && !(uptr->USTAT & STA_REW)) { + mta_upddsta (uptr, uptr->USTAT | STA_RDY); + sim_cancel (uptr); } } dev_busy = dev_busy & ~INT_MTA; /* clear busy */ dev_done = dev_done & ~INT_MTA; /* clear done */ int_req = int_req & ~INT_MTA; /* clear int */ @@ -338,7 +340,7 @@ case CU_CMODE: /* controller mode */ case CU_DMODE: /* drive mode */ if (uptr->pos) mta_sta = mta_sta | STA_ILL; /* must be BOT */ else mta_upddsta (uptr, (mta_cu & CU_PE)? /* update drv status */ - uptr->USTAT | STA_PEM: uptr->USTAT & ~ STA_PEM); + uptr->USTAT | STA_PEM: uptr->USTAT & ~ STA_PEM); break; /* Unit service, continued */ @@ -350,23 +352,24 @@ case CU_READNS: /* read non-stop */ cbc = wc * 2; /* expected bc */ if (tbc & 1) mta_sta = mta_sta | STA_ODD; /* odd byte count? */ if (tbc > cbc) mta_sta = mta_sta | STA_WCO; /* too big? */ - else { cbc = tbc; /* no, use it */ - wc = (cbc + 1) / 2; } /* adjust wc */ + else { + cbc = tbc; /* no, use it */ + wc = (cbc + 1) / 2; } /* adjust wc */ i = fxread (dbuf, sizeof (int8), cbc, uptr->fileref); for ( ; i < cbc; i++) dbuf[i] = 0; mta_upddsta (uptr, uptr->USTAT | STA_RDY); if (err = ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); /* pos not upd */ - break; } + MT_SET_PNU (uptr); /* pos not upd */ + break; } for (i = p = 0; i < wc; i++) { /* copy buf to mem */ - c1 = dbuf[p++]; - c2 = dbuf[p++]; - pa = MapAddr (0, mta_ma); /* map address */ - if (MEM_ADDR_OK (pa)) M[pa] = (c1 << 8) | c2; - mta_ma = (mta_ma + 1) & AMASK; } + c1 = dbuf[p++]; + c2 = dbuf[p++]; + pa = MapAddr (0, mta_ma); /* map address */ + if (MEM_ADDR_OK (pa)) M[pa] = (c1 << 8) | c2; + mta_ma = (mta_ma + 1) & AMASK; } mta_wc = (mta_wc + wc) & DMASK; uptr->pos = uptr->pos + ((tbc + 1) & ~1) + - (2 * sizeof (t_mtrlnt)); + (2 * sizeof (t_mtrlnt)); break; case CU_WRITE: /* write */ @@ -374,16 +377,17 @@ case CU_WRITE: /* write */ tbc = wc * 2; /* io byte count */ fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref); for (i = p = 0; i < wc; i++) { /* copy to buffer */ - pa = MapAddr (0, mta_ma); /* map address */ - dbuf[p++] = (M[pa] >> 8) & 0377; - dbuf[p++] = M[pa] & 0377; - mta_ma = (mta_ma + 1) & AMASK; } + pa = MapAddr (0, mta_ma); /* map address */ + dbuf[p++] = (M[pa] >> 8) & 0377; + dbuf[p++] = M[pa] & 0377; + mta_ma = (mta_ma + 1) & AMASK; } fxwrite (dbuf, sizeof (int8), tbc, uptr->fileref); fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref); mta_upddsta (uptr, uptr->USTAT | STA_RDY); if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */ - else { mta_wc = 0; - uptr->pos = uptr->pos + tbc + (2 * sizeof (t_mtrlnt)); } + else { + mta_wc = 0; + uptr->pos = uptr->pos + tbc + (2 * sizeof (t_mtrlnt)); } break; /* Unit service, continued */ @@ -401,20 +405,23 @@ case CU_ERASE: /* erase */ break; case CU_SPACEF: /* space forward */ - do { mta_wc = (mta_wc + 1) & DMASK; /* incr wc */ - if (mta_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */ - uptr->pos = uptr->pos + ((tbc + 1) & ~1) + - (2 * sizeof (t_mtrlnt)); } + do { + mta_wc = (mta_wc + 1) & DMASK; /* incr wc */ + if (mta_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */ + uptr->pos = uptr->pos + ((tbc + 1) & ~1) + + (2 * sizeof (t_mtrlnt)); } while (mta_wc != 0); mta_upddsta (uptr, uptr->USTAT | STA_RDY); break; case CU_SPACER: /* space reverse */ - do { mta_wc = (mta_wc + 1) & DMASK; /* incr wc */ - if (pnu) pnu = 0; /* pos not upd? */ - else { if (mta_rdlntr (uptr, &tbc, &err)) break; - uptr->pos = uptr->pos - ((tbc + 1) & ~1) - - (2 * sizeof (t_mtrlnt)); } } + do { + mta_wc = (mta_wc + 1) & DMASK; /* incr wc */ + if (pnu) pnu = 0; /* pos not upd? */ + else { + if (mta_rdlntr (uptr, &tbc, &err)) break; + uptr->pos = uptr->pos - ((tbc + 1) & ~1) - + (2 * sizeof (t_mtrlnt)); } } while (mta_wc != 0); mta_upddsta (uptr, uptr->USTAT | STA_RDY); break; @@ -537,9 +544,9 @@ for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */ MT_CLR_PNU (uptr); /* clear pos flag */ sim_cancel (uptr); /* cancel activity */ if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY | - (uptr->USTAT & STA_PEM) | - ((uptr->flags & UNIT_WPRT)? STA_WLK: 0) | - ((uptr->pos)? 0: STA_BOT); + (uptr->USTAT & STA_PEM) | + ((uptr->flags & UNIT_WPRT)? STA_WLK: 0) | + ((uptr->pos)? 0: STA_BOT); else uptr->USTAT = 0; } mta_updcsta (&mta_unit[0]); /* update status */ return SCPE_OK; diff --git a/NOVA/nova_pt.c b/NOVA/nova_pt.c index e7c05ec1..7085bbc8 100644 --- a/NOVA/nova_pt.c +++ b/NOVA/nova_pt.c @@ -138,8 +138,8 @@ if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ptr_stopioe, SCPE_UNATT); if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } + if (ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; } else perror ("PTR I/O error"); clearerr (ptr_unit.fileref); return SCPE_IOERR; } diff --git a/NOVA/nova_sys.c b/NOVA/nova_sys.c index dbde1a05..c874acea 100644 --- a/NOVA/nova_sys.c +++ b/NOVA/nova_sys.c @@ -134,64 +134,64 @@ state = 0; while ((i = getc (fileref)) != EOF) { switch (state) { case 0: /* leader */ - count = i; - state = (count != 0); - break; + count = i; + state = (count != 0); + break; case 1: /* high count */ - csum = count = (i << 8) | count; - state = 2; - break; + csum = count = (i << 8) | count; + state = 2; + break; case 2: /* low origin */ - origin = i; - state = 3; - break; + origin = i; + state = 3; + break; case 3: /* high origin */ - origin = (i << 8) | origin; - csum = csum + origin; - state = 4; - break; + origin = (i << 8) | origin; + csum = csum + origin; + state = 4; + break; case 4: /* low checksum */ - csum = csum + i; - state = 5; - break; + csum = csum + i; + state = 5; + break; case 5: /* high checksum */ - csum = csum + (i << 8); - if (count == 1) saved_PC = origin; /* count = 1? */ - if (count <= 1) { /* count = 0/1? */ - if (csum & 0177777) return SCPE_CSUM; - state = 0; - break; } - if (count < 0100000) { /* count > 1 */ - state = 8; - break; } - count = 0200000 - count; - state = 6; - break; + csum = csum + (i << 8); + if (count == 1) saved_PC = origin; /* count = 1? */ + if (count <= 1) { /* count = 0/1? */ + if (csum & 0177777) return SCPE_CSUM; + state = 0; + break; } + if (count < 0100000) { /* count > 1 */ + state = 8; + break; } + count = 0200000 - count; + state = 6; + break; case 6: /* low data */ - data = i; - state = 7; - break; + data = i; + state = 7; + break; case 7: /* high data */ - data = (i << 8) | data; - csum = csum + data; - if (count > 20) { /* large block */ - for (count = count - 1; count == 1; count--) { - if (origin >= MEMSIZE) return SCPE_NXM; - M[origin] = data; - origin = origin + 1; } } - if (origin >= MEMSIZE) return SCPE_NXM; - M[origin] = data; - origin = origin + 1; - count = count - 1; - if (count == 0) { - if (csum & 0177777) return SCPE_CSUM; - state = 0; - break; } - state = 6; - break; + data = (i << 8) | data; + csum = csum + data; + if (count > 20) { /* large block */ + for (count = count - 1; count == 1; count--) { + if (origin >= MEMSIZE) return SCPE_NXM; + M[origin] = data; + origin = origin + 1; } } + if (origin >= MEMSIZE) return SCPE_NXM; + M[origin] = data; + origin = origin + 1; + count = count - 1; + if (count == 0) { + if (csum & 0177777) return SCPE_CSUM; + state = 0; + break; } + state = 6; + break; case 8: /* error block */ - if (i == 0377) state = 0; - break; } /* end switch */ + if (i == 0377) state = 0; + break; } /* end switch */ } /* end while */ /* Ok to find end of tape between blocks or in error state */ @@ -542,10 +542,11 @@ case 0: /* absolute */ break; case 1: /* PC rel */ if (disp & dsign) { - if (cflag) fprintf (of, "%-o", (addr - (dmax - disp)) & AMASK); - else fprintf (of, ".-%-o", dmax - disp); } - else { if (cflag) fprintf (of, "%-o", (addr + disp) & AMASK); - else fprintf (of, ".+%-o", disp); } + if (cflag) fprintf (of, "%-o", (addr - (dmax - disp)) & AMASK); + else fprintf (of, ".-%-o", dmax - disp); } + else { + if (cflag) fprintf (of, "%-o", (addr + disp) & AMASK); + else fprintf (of, ".+%-o", disp); } break; case 2: /* AC2 rel */ if (disp & dsign) fprintf (of, "-%-o,2", dmax - disp); @@ -610,67 +611,67 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ switch (j) { /* switch on class */ case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; + fprintf (of, "%s", opcode[i]); /* opcode */ + break; case I_V_R: /* reg only */ - fprintf (of, "%s %-o", opcode[i], dst); - break; + fprintf (of, "%s %-o", opcode[i], dst); + break; case I_V_D: /* dev only */ - if (dev_val[dv] >= 0) - fprintf (of, "%s %s", opcode[i], device[dv]); - else fprintf (of, "%s %-o", opcode[i], dev); - break; + if (dev_val[dv] >= 0) + fprintf (of, "%s %s", opcode[i], device[dv]); + else fprintf (of, "%s %-o", opcode[i], dev); + break; case I_V_RD: /* reg, dev */ - if (dev_val[dv] >= 0) - fprintf (of, "%s %-o,%s", opcode[i], dst, device[dv]); - else fprintf (of, "%s %-o,%-o", opcode[i], dst, dev); - break; + if (dev_val[dv] >= 0) + fprintf (of, "%s %-o,%s", opcode[i], dst, device[dv]); + else fprintf (of, "%s %-o,%-o", opcode[i], dst, dev); + break; case I_V_M: /* addr only */ - fprintf (of, "%s ", opcode[i]); - fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); - break; + fprintf (of, "%s ", opcode[i]); + fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); + break; case I_V_RM: /* reg, addr */ - fprintf (of, "%s %-o,", opcode[i], dst); - fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); - break; + fprintf (of, "%s %-o,", opcode[i], dst); + fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); + break; case I_V_RR: /* operate */ - fprintf (of, "%s %-o,%-o", opcode[i], src, dst); - if (skp) fprintf (of, ",%s", skip[skp-1]); - break; + fprintf (of, "%s %-o,%-o", opcode[i], src, dst); + if (skp) fprintf (of, ",%s", skip[skp-1]); + break; case I_V_BY: /* byte */ - fprintf (of, "%s %-o,%-o", opcode[i], byac, dst); - break; + fprintf (of, "%s %-o,%-o", opcode[i], byac, dst); + break; case I_V_2AC: /* reg, reg */ - fprintf (of, "%s %-o,%-o", opcode[i], src, dst); - break; + fprintf (of, "%s %-o,%-o", opcode[i], src, dst); + break; case I_V_RSI: /* reg, short imm */ - fprintf (of, "%s %-o,%-o", opcode[i], src + 1, dst); - break; + fprintf (of, "%s %-o,%-o", opcode[i], src + 1, dst); + break; case I_V_LI: /* long imm */ - fprintf (of, "%s %-o", opcode[i], val[1]); - return -1; + fprintf (of, "%s %-o", opcode[i], val[1]); + return -1; case I_V_RLI: /* reg, long imm */ - fprintf (of, "%s %-o,%-o", opcode[i], val[1], dst); - return -1; + fprintf (of, "%s %-o,%-o", opcode[i], val[1], dst); + return -1; case I_V_LM: /* long addr */ - fprintf (of, "%s ", opcode[i]); - fprint_addr (of, addr, extind, mode, extdisp, TRUE, cflag); - return -1; + fprintf (of, "%s ", opcode[i]); + fprint_addr (of, addr, extind, mode, extdisp, TRUE, cflag); + return -1; case I_V_RLM: /* reg, long addr */ - fprintf (of, "%s %-o,", opcode[i], dst); - fprint_addr (of, addr, extind, mode, extdisp, TRUE, cflag); - return -1; + fprintf (of, "%s %-o,", opcode[i], dst); + fprint_addr (of, addr, extind, mode, extdisp, TRUE, cflag); + return -1; case I_V_FRM: /* flt reg, long addr */ - fprintf (of, "%s %-o,", opcode[i], dst); - fprint_addr (of, addr, extind, src, extdisp, TRUE, cflag); - return -1; + fprintf (of, "%s %-o,", opcode[i], dst); + fprint_addr (of, addr, extind, src, extdisp, TRUE, cflag); + return -1; case I_V_FST: /* flt status */ - fprintf (of, "%s ", opcode[i]); - fprint_addr (of, addr, extind, dst, extdisp, AMASK + 1, cflag); - return -1; + fprintf (of, "%s ", opcode[i]); + fprint_addr (of, addr, extind, dst, extdisp, AMASK + 1, cflag); + return -1; case I_V_XP: /* XOP */ - fprintf (of, "%s %-o,%-o,%-o", opcode[i], src, dst, xop); - break; } /* end case */ + fprintf (of, "%s %-o,%-o,%-o", opcode[i], src, dst, xop); + break; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; @@ -746,8 +747,8 @@ case A_NUM+A_FL: case A_NUM+A_SI+A_FL: /* CPU, (+)num */ else if (((d >= (((int32) addr - dsign) & AMASK)) && (d < (((int32) addr + dsign) & AMASK))) || (d >= ((int32) addr + (-dsign & AMASK)))) { - val[1] = 1; /* PC rel */ - val[2] = (d - addr) & (dmax - 1); } + val[1] = 1; /* PC rel */ + val[2] = (d - addr) & (dmax - 1); } else return NULL; break; case A_PER: case A_PER+A_FL: /* . */ @@ -847,12 +848,13 @@ case I_V_RD: /* IOT reg,dev */ val[0] = val[0] | (d << I_V_DST); /* put in place */ case I_V_D: /* IOT dev */ cptr = get_glyph (cptr, gbuf, 0); /* get device */ - for (i = 0; (device[i] != NULL) && (strcmp (device[i], gbuf) != 0); - i++); + for (i = 0; (device[i] != NULL) && + (strcmp (device[i], gbuf) != 0); i++); if (device[i] != NULL) val[0] = val[0] | dev_val[i]; - else { d = get_uint (gbuf, 8, I_M_DEV, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DEV); } + else { + d = get_uint (gbuf, 8, I_M_DEV, &r); + if (r != SCPE_OK) return SCPE_ARG; + val[0] = val[0] | (d << I_V_DEV); } break; case I_V_RM: /* reg, addr */ cptr = get_glyph (cptr, gbuf, ','); /* get register */ @@ -869,11 +871,11 @@ case I_V_RR: /* operate */ if (cptr == NULL) return SCPE_ARG; val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST); if (*cptr != 0) { /* skip? */ - cptr = get_glyph (cptr, gbuf, 0); /* get skip */ - for (i = 0; (skip[i] != NULL) && - (strcmp (skip[i], gbuf) != 0); i++) ; - if (skip[i] == NULL) return SCPE_ARG; - val[0] = val[0] | (i + 1); } /* end for */ + cptr = get_glyph (cptr, gbuf, 0); /* get skip */ + for (i = 0; (skip[i] != NULL) && + (strcmp (skip[i], gbuf) != 0); i++) ; + if (skip[i] == NULL) return SCPE_ARG; + val[0] = val[0] | (i + 1); } /* end for */ break; case I_V_BY: /* byte */ cptr = get_2reg (cptr, 0, amd); /* get 2 reg */ diff --git a/NOVA/nova_tt.c b/NOVA/nova_tt.c index 88cd8cac..22a2925b 100644 --- a/NOVA/nova_tt.c +++ b/NOVA/nova_tt.c @@ -1,6 +1,6 @@ /* nova_tt.c: NOVA console terminal simulator - Copyright (c) 1993-2002, Robert M. Supnik + Copyright (c) 1993-2003, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ tti terminal input tto terminal output + 05-Jan-02 RMS Fixed calling sequence for setmod 03-Oct-02 RMS Added DIBs 30-May-02 RMS Widened POS to 32b 30-Nov-01 RMS Added extended SET/SHOW support @@ -46,7 +47,7 @@ t_stat tti_svc (UNIT *uptr); t_stat tto_svc (UNIT *uptr); t_stat tti_reset (DEVICE *dptr); t_stat tto_reset (DEVICE *dptr); -t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr); +t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr, void *desc); /* TTI data structures @@ -210,7 +211,7 @@ sim_cancel (&tto_unit); /* deactivate unit */ return SCPE_OK; } -t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr) +t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr, void *desc) { tti_unit.flags = (tti_unit.flags & ~UNIT_DASHER) | val; tto_unit.flags = (tto_unit.flags & ~UNIT_DASHER) | val; diff --git a/NOVA/nova_tt1.c b/NOVA/nova_tt1.c index d45854fc..e98c0e54 100644 --- a/NOVA/nova_tt1.c +++ b/NOVA/nova_tt1.c @@ -1,6 +1,6 @@ /* nova_tt1.c: NOVA second terminal simulator - Copyright (c) 1993-2002, Robert M. Supnik + Copyright (c) 1993-2003, Robert M. Supnik Written by Bruce Ray and used with his gracious permission. Permission is hereby granted, free of charge, to any person obtaining a @@ -27,6 +27,7 @@ tti1 second terminal input tto1 second terminal output + 05-Jan-03 RMS Fixed calling sequence for setmod 03-Oct-02 RMS Added DIBs 22-Aug-02 RMS Updated for changes in sim_tmxr 30-May-02 RMS Widened POS to 32b @@ -58,7 +59,7 @@ t_stat tti1_svc (UNIT *uptr); t_stat tto1_svc (UNIT *uptr); t_stat tti1_reset (DEVICE *dptr); t_stat tto1_reset (DEVICE *dptr); -t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr); +t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat tti1_attach (UNIT *uptr, char *cptr); t_stat tti1_detach (UNIT *uptr); t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc); @@ -259,7 +260,7 @@ sim_cancel (&tto1_unit); /* deactivate unit */ return SCPE_OK; } -t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr) +t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr, void *desc) { tti1_unit.flags = (tti1_unit.flags & ~UNIT_DASHER) | val; tto1_unit.flags = (tto1_unit.flags & ~UNIT_DASHER) | val; diff --git a/PDP1/pdp1_cpu.c b/PDP1/pdp1_cpu.c index aadb48a2..85fa6c88 100644 --- a/PDP1/pdp1_cpu.c +++ b/PDP1/pdp1_cpu.c @@ -25,6 +25,7 @@ cpu PDP-1 central processor + 05-Dec-02 RMS Added drum support 06-Oct-02 RMS Revised for V2.10 20-Aug-02 RMS Added DECtape support 30-Dec-01 RMS Added old PC queue @@ -262,6 +263,7 @@ extern int32 tti (int32 inst, int32 dev, int32 IO); extern int32 tto (int32 inst, int32 dev, int32 IO); extern int32 lpt (int32 inst, int32 dev, int32 IO); extern int32 dt (int32 inst, int32 dev, int32 IO); +extern int32 drm (int32 inst, int32 dev, int32 IO); int32 sc_map[512] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, /* 00000xxxx */ @@ -413,14 +415,15 @@ op = ((IR >> 13) & 037); /* get opcode */ if ((op < 032) && (op != 007)) { /* mem ref instr */ MA = (MA & EPCMASK) | (IR & DAMASK); /* direct address */ if (IR & IA) { /* indirect addr? */ - if (extm) MA = M[MA] & AMASK; /* if ext, one level */ - else { for (i = 0; i < ind_max; i++) { /* count indirects */ - t = M[MA]; /* get indirect word */ - MA = (MA & EPCMASK) | (t & DAMASK); - if ((t & IA) == 0) break; } - if (i >= ind_max) { /* indirect loop? */ - reason = STOP_IND; - break; } } } } + if (extm) MA = M[MA] & AMASK; /* if ext, one level */ + else { /* multi-level */ + for (i = 0; i < ind_max; i++) { /* count indirects */ + t = M[MA]; /* get indirect word */ + MA = (MA & EPCMASK) | (t & DAMASK); + if ((t & IA) == 0) break; } + if (i >= ind_max) { /* indirect loop? */ + reason = STOP_IND; + break; } } } } switch (op) { /* decode IR<0:4> */ @@ -437,8 +440,8 @@ case 003: /* XOR */ break; case 004: /* XCT */ if (xct_count >= xct_max) { /* too many XCT's? */ - reason = STOP_XCT; - break; } + reason = STOP_XCT; + break; } xct_count = xct_count + 1; /* count XCT's */ IR = M[MA]; /* get instruction */ goto xct_instr; /* go execute */ @@ -540,50 +543,52 @@ case 034: /* LAW */ case 026: /* MUL */ if (cpu_unit.flags & UNIT_MDV) { /* hardware? */ - sign = AC ^ M[MA]; /* result sign */ - IO = ABS (AC); /* IO = |AC| */ - v = ABS (M[MA]); /* v = |mpy| */ - for (i = AC = 0; i < 17; i++) { - if (IO & 1) AC = AC + v; - IO = (IO >> 1) | ((AC & 1) << 17); - AC = AC >> 1; } - if ((sign & 0400000) && (AC | IO)) { /* negative, > 0? */ - AC = AC ^ 0777777; - IO = IO ^ 0777777; } } - else { if (IO & 1) AC = AC + M[MA]; /* multiply step */ - if (AC > 0777777) AC = (AC + 1) & 0777777; - if (AC == 0777777) AC = 0; + sign = AC ^ M[MA]; /* result sign */ + IO = ABS (AC); /* IO = |AC| */ + v = ABS (M[MA]); /* v = |mpy| */ + for (i = AC = 0; i < 17; i++) { + if (IO & 1) AC = AC + v; IO = (IO >> 1) | ((AC & 1) << 17); AC = AC >> 1; } + if ((sign & 0400000) && (AC | IO)) { /* negative, > 0? */ + AC = AC ^ 0777777; + IO = IO ^ 0777777; } } + else { /* multiply step */ + if (IO & 1) AC = AC + M[MA]; + if (AC > 0777777) AC = (AC + 1) & 0777777; + if (AC == 0777777) AC = 0; + IO = (IO >> 1) | ((AC & 1) << 17); + AC = AC >> 1; } break; case 027: /* DIV */ if (cpu_unit.flags & UNIT_MDV) { /* hardware */ - sign = AC ^ M[MA]; /* result sign */ - signd = AC; /* remainder sign */ - if (AC & 0400000) { - AC = AC ^ 0777777; /* AC'IO = |AC'IO| */ - IO = IO ^ 0777777; } - v = ABS (M[MA]); /* v = |divr| */ - if (AC >= v) break; /* overflow? */ - for (i = t = 0; i < 18; i++) { - if (t) AC = (AC + v) & 0777777; - else AC = (AC - v) & 0777777; - t = AC >> 17; - if (i != 17) AC = ((AC << 1) | (IO >> 17)) & 0777777; - IO = ((IO << 1) | (t ^ 1)) & 0777777; } - if (t) AC = (AC + v) & 0777777; /* correct remainder */ - t = ((signd & 0400000) && AC)? AC ^ 0777777: AC; - AC = ((sign & 0400000) && IO)? IO ^ 0777777: IO; - IO = t; - PC = INCR_ADDR (PC); } /* skip */ - else { t = AC >> 17; /* divide step */ - AC = ((AC << 1) | (IO >> 17)) & 0777777; - IO = ((IO << 1) | (t ^ 1)) & 0777777; - if (IO & 1) AC = AC + (M[MA] ^ 0777777); - else AC = AC + M[MA] + 1; - if (AC > 0777777) AC = (AC + 1) & 0777777; - if (AC == 0777777) AC = 0; } + sign = AC ^ M[MA]; /* result sign */ + signd = AC; /* remainder sign */ + if (AC & 0400000) { + AC = AC ^ 0777777; /* AC'IO = |AC'IO| */ + IO = IO ^ 0777777; } + v = ABS (M[MA]); /* v = |divr| */ + if (AC >= v) break; /* overflow? */ + for (i = t = 0; i < 18; i++) { + if (t) AC = (AC + v) & 0777777; + else AC = (AC - v) & 0777777; + t = AC >> 17; + if (i != 17) AC = ((AC << 1) | (IO >> 17)) & 0777777; + IO = ((IO << 1) | (t ^ 1)) & 0777777; } + if (t) AC = (AC + v) & 0777777; /* correct remainder */ + t = ((signd & 0400000) && AC)? AC ^ 0777777: AC; + AC = ((sign & 0400000) && IO)? IO ^ 0777777: IO; + IO = t; + PC = INCR_ADDR (PC); } /* skip */ + else { /* divide step */ + t = AC >> 17; + AC = ((AC << 1) | (IO >> 17)) & 0777777; + IO = ((IO << 1) | (t ^ 1)) & 0777777; + if (IO & 1) AC = AC + (M[MA] ^ 0777777); + else AC = AC + M[MA] + 1; + if (AC > 0777777) AC = (AC + 1) & 0777777; + if (AC == 0777777) AC = 0; } break; /* Skip and operate @@ -624,115 +629,120 @@ case 033: sc = sc_map[IR & 0777]; /* map shift count */ switch ((IR >> 9) & 017) { /* case on IR<5:8> */ case 001: /* RAL */ - AC = ((AC << sc) | (AC >> (18 - sc))) & 0777777; - break; + AC = ((AC << sc) | (AC >> (18 - sc))) & 0777777; + break; case 002: /* RIL */ - IO = ((IO << sc) | (IO >> (18 - sc))) & 0777777; - break; + IO = ((IO << sc) | (IO >> (18 - sc))) & 0777777; + break; case 003: /* RCL */ - t = AC; - AC = ((AC << sc) | (IO >> (18 - sc))) & 0777777; - IO = ((IO << sc) | (t >> (18 - sc))) & 0777777; - break; + t = AC; + AC = ((AC << sc) | (IO >> (18 - sc))) & 0777777; + IO = ((IO << sc) | (t >> (18 - sc))) & 0777777; + break; case 005: /* SAL */ - t = (AC & 0400000)? 0777777: 0; - AC = (AC & 0400000) | ((AC << sc) & 0377777) | - (t >> (18 - sc)); - break; + t = (AC & 0400000)? 0777777: 0; + AC = (AC & 0400000) | ((AC << sc) & 0377777) | + (t >> (18 - sc)); + break; case 006: /* SIL */ - t = (IO & 0400000)? 0777777: 0; - IO = (IO & 0400000) | ((IO << sc) & 0377777) | - (t >> (18 - sc)); - break; + t = (IO & 0400000)? 0777777: 0; + IO = (IO & 0400000) | ((IO << sc) & 0377777) | + (t >> (18 - sc)); + break; case 007: /* SCL */ - t = (AC & 0400000)? 0777777: 0; - AC = (AC & 0400000) | ((AC << sc) & 0377777) | - (IO >> (18 - sc)); - IO = ((IO << sc) | (t >> (18 - sc))) & 0777777; - break; + t = (AC & 0400000)? 0777777: 0; + AC = (AC & 0400000) | ((AC << sc) & 0377777) | + (IO >> (18 - sc)); + IO = ((IO << sc) | (t >> (18 - sc))) & 0777777; + break; case 011: /* RAR */ - AC = ((AC >> sc) | (AC << (18 - sc))) & 0777777; - break; + AC = ((AC >> sc) | (AC << (18 - sc))) & 0777777; + break; case 012: /* RIR */ - IO = ((IO >> sc) | (IO << (18 - sc))) & 0777777; - break; + IO = ((IO >> sc) | (IO << (18 - sc))) & 0777777; + break; case 013: /* RCR */ - t = IO; - IO = ((IO >> sc) | (AC << (18 - sc))) & 0777777; - AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; - break; + t = IO; + IO = ((IO >> sc) | (AC << (18 - sc))) & 0777777; + AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; + break; case 015: /* SAR */ - t = (AC & 0400000)? 0777777: 0; - AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; - break; + t = (AC & 0400000)? 0777777: 0; + AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; + break; case 016: /* SIR */ - t = (IO & 0400000)? 0777777: 0; - IO = ((IO >> sc) | (t << (18 - sc))) & 0777777; - break; + t = (IO & 0400000)? 0777777: 0; + IO = ((IO >> sc) | (t << (18 - sc))) & 0777777; + break; case 017: /* SCR */ - t = (AC & 0400000)? 0777777: 0; - IO = ((IO >> sc) | (AC << (18 - sc))) & 0777777; - AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; - break; + t = (AC & 0400000)? 0777777: 0; + IO = ((IO >> sc) | (AC << (18 - sc))) & 0777777; + AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; + break; default: /* undefined */ - reason = stop_inst; - break; } /* end switch shifts */ + reason = stop_inst; + break; } /* end switch shifts */ break; /* IOT */ case 035: if (IR & IO_WAIT) { /* wait? */ - if (ioh) { /* I/O halt? */ - if (ioc) ioh = 0; /* comp pulse? done */ - else { sim_interval = 0; /* force event */ - PC = DECR_ADDR (PC); } /* re-execute */ - break; } /* skip iot */ - ioh = 1; /* turn on halt */ - PC = DECR_ADDR (PC); } /* re-execute */ + if (ioh) { /* I/O halt? */ + if (ioc) ioh = 0; /* comp pulse? done */ + else { /* wait more */ + sim_interval = 0; /* force event */ + PC = DECR_ADDR (PC); } /* re-execute */ + break; } /* skip iot */ + ioh = 1; /* turn on halt */ + PC = DECR_ADDR (PC); } /* re-execute */ dev = IR & 077; /* get dev addr */ io_data = IO; /* default data */ switch (dev) { /* case on dev */ case 000: /* I/O wait */ - break; + break; case 001: - if (IR & 003700) io_data = dt (IR, dev, IO); /* DECtape */ - else io_data = ptr (IR, dev, IO); /* paper tape rdr */ - break; + if (IR & 003700) io_data = dt (IR, dev, IO); /* DECtape */ + else io_data = ptr (IR, dev, IO); /* paper tape rdr */ + break; case 002: case 030: /* paper tape rdr */ - io_data = ptr (IR, dev, IO); - break; + io_data = ptr (IR, dev, IO); + break; case 003: /* typewriter */ - io_data = tto (IR, dev, IO); - break; + io_data = tto (IR, dev, IO); + break; case 004: /* keyboard */ - io_data = tti (IR, dev, IO); - break; + io_data = tti (IR, dev, IO); + break; case 005: case 006: /* paper tape punch */ - io_data = ptp (IR, dev, IO); - break; + io_data = ptp (IR, dev, IO); + break; case 033: /* check status */ - io_data = iosta | ((sbs & SB_ON)? IOS_SQB: 0); - break; + io_data = iosta | ((sbs & SB_ON)? IOS_SQB: 0); + break; case 045: /* line printer */ - io_data = lpt (IR, dev, IO); - break; + io_data = lpt (IR, dev, IO); + break; case 054: /* seq brk off */ - sbs = sbs & ~SB_ON; - break; + sbs = sbs & ~SB_ON; + break; case 055: /* seq brk on */ - sbs = sbs | SB_ON; - break; + sbs = sbs | SB_ON; + break; case 056: /* clear seq brk */ - sbs = sbs & ~SB_IP; - break; + sbs = sbs & ~SB_IP; + break; + case 061: case 062: case 063: case 064: /* drum */ + io_data = drm (IR, dev, IO); + break; case 074: /* extend mode */ - extm = (IR >> 11) & 1; /* set from IR<6> */ - break; + extm = (IR >> 11) & 1; /* set from IR<6> */ + break; default: /* undefined */ - reason = stop_inst; - break; } /* end switch dev */ + reason = stop_inst; + break; } /* end switch dev */ IO = io_data & 0777777; + if (io_data & IOT_SKP) PC = INCR_ADDR (PC); /* skip? */ if (io_data >= IOT_REASON) reason = io_data >> IOT_V_REASON; break; default: /* undefined */ diff --git a/PDP1/pdp1_defs.h b/PDP1/pdp1_defs.h index 5890abce..6fde640d 100644 --- a/PDP1/pdp1_defs.h +++ b/PDP1/pdp1_defs.h @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 05-Dec-02 RMS Added IOT skip support (required by drum) 14-Apr-99 RMS Changed t_addr to unsigned The PDP-1 was Digital's first computer. The system design evolved during @@ -67,7 +68,9 @@ /* IOT subroutine return codes */ -#define IOT_V_REASON 18 /* reason */ +#define IOT_V_SKP 18 /* skip */ +#define IOT_SKP (1 << IOT_V_SKP) +#define IOT_V_REASON (IOT_V_SKP + 1) /* reason */ #define IOT_REASON (1 << IOT_V_REASON) #define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ diff --git a/PDP1/pdp1_doc.txt b/PDP1/pdp1_doc.txt index c7039f05..9dbf079d 100644 --- a/PDP1/pdp1_doc.txt +++ b/PDP1/pdp1_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: PDP-1 Simulator Usage -Date: 15-Nov-2002 +Date: 15-Dec-2002 COPYRIGHT NOTICE @@ -47,6 +47,7 @@ sim/ sim_defs.h sim/pdp1/ pdp1_defs.h pdp1_cpu.c + pdp1_drm.c pdp1_dt.c pdp1_lp.c pdp1_stddev.c @@ -63,6 +64,7 @@ CPU PDP-1 CPU with up to 64KW of memory PTR,PTP integral paper tape reader/punch TTY console typewriter LPT Type 62 line printer +DRM Type 24 serial drum DT Type 550 Microtape (DECtape) The PDP-1 simulator implements the following unique stop conditions: @@ -299,7 +301,32 @@ operate correctly. - ACTIME must be less than DCTIME, and both need to be at least 100 times LTIME -2.4 Symbolic Display and Input +2.4 Type 24 Serial Drum (DRM) + +The serial drum (DRM) implements these registers: + + name size comments + + DA 9 drum address (sector number) + MA 16 current memory address + INT 1 interrupt pending flag + DONE 1 device done flag + ERR 1 error flag + WLK 32 write lock switches + TIME 24 rotational latency, per word + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 disk not ready + +Drum data files are buffered in memory; therefore, end of file and OS +I/O errors cannot occur. + +2.5 Symbolic Display and Input The PDP-1 simulator implements symbolic display and input. Display is controlled by command line switches: @@ -359,7 +386,7 @@ Finally, the LAW instruction has the format where immediate is in the range 0 to 07777. -2.5 Character Sets +2.6 Character Sets The PDP-1's console was a Frieden Flexowriter; its character encoding was known as FIODEC. The PDP-1's line printer used a modified Hollerith diff --git a/PDP1/pdp1_drm.c b/PDP1/pdp1_drm.c new file mode 100644 index 00000000..3346e1e8 --- /dev/null +++ b/PDP1/pdp1_drm.c @@ -0,0 +1,169 @@ +/* pdp1_drm.c: drum/fixed head disk simulator + + Copyright (c) 1993-2002, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + drm Type 24 serial drum + + 05-Dec-02 RMS Cloned from pdp18b_drm.c +*/ + +#include "pdp1_defs.h" +#include + +/* Constants */ + +#define DRM_NUMWDS 256 /* words/sector */ +#define DRM_NUMSC 2 /* sectors/track */ +#define DRM_NUMTR 256 /* tracks/drum */ +#define DRM_NUMDK 1 /* drum/controller */ +#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */ +#define DRM_SIZE (DRM_NUMDK * DRM_NUMTR * DRM_NUMWDT) /* words/drum */ +#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */ + +/* Parameters in the unit descriptor */ + +#define FUNC u4 /* function */ +#define DRM_READ 000 /* read */ +#define DRM_WRITE 010 /* write */ + +#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ + ((double) DRM_NUMWDT))) + +extern int32 M[]; +extern int32 iosta, sbs; +extern int32 stop_inst; +extern UNIT cpu_unit; + +int32 drm_da = 0; /* track address */ +int32 drm_ma = 0; /* memory address */ +int32 drm_err = 0; /* error flag */ +int32 drm_wlk = 0; /* write lock */ +int32 drm_time = 10; /* inter-word time */ +int32 drm_stopioe = 1; /* stop on error */ + +t_stat drm_svc (UNIT *uptr); +t_stat drm_reset (DEVICE *dptr); + +/* DRM data structures + + drm_dev DRM device descriptor + drm_unit DRM unit descriptor + drm_reg DRM register list +*/ + +UNIT drm_unit = + { UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, + DRM_SIZE) }; + +REG drm_reg[] = { + { ORDATA (DA, drm_da, 9) }, + { ORDATA (MA, drm_ma, 16) }, + { FLDATA (DONE, iosta, IOS_V_DRM) }, + { FLDATA (ERR, drm_err, 0) }, + { ORDATA (WLK, drm_wlk, 32) }, + { DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT }, + { FLDATA (STOP_IOE, drm_stopioe, 0) }, + { NULL } }; + +DEVICE drm_dev = { + "DRM", &drm_unit, drm_reg, NULL, + 1, 8, 20, 1, 8, 18, + NULL, NULL, &drm_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE }; + +/* IOT routines */ + +int32 drm (int32 IR, int32 dev, int32 IO) +{ +int32 t; +int32 pulse = (IR >> 6) & 037; + +if (drm_dev.flags & DEV_DIS) /* disabled? */ + return (stop_inst << IOT_V_REASON) | IO; /* stop if requested */ +if ((pulse != 001) & (pulse != 011)) /* invalid pulse? */ + return (stop_inst << IOT_V_REASON) | IO; /* stop if requested */ +switch (dev) { /* switch on device */ +case 061: /* DWR, DRD */ + drm_ma = IO & 0177777; /* load mem addr */ + drm_unit.FUNC = pulse & DRM_WRITE; /* save function */ + break; +case 062: /* DBL, DCN */ + if (pulse & 010) drm_da = IO & DRM_SMASK; /* load sector # */ + iosta = iosta & ~IOS_DRM; /* clear flags */ + drm_err = 0; + t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time); + if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */ + break; +case 063: /* DTD */ + if (iosta & IOS_DRM) return (IO | IOT_SKP); /* skip if done */ +case 064: /* DSE, DSP */ + if ((drm_err == 0) || (pulse & 010)) /* no error, par test? */ + return (IO | IOT_SKP); + } +return IO; +} + +/* Unit service + + This code assumes the entire drum is buffered. +*/ + +t_stat drm_svc (UNIT *uptr) +{ +int32 i; +t_addr da; + +if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ + drm_err = 1; /* set error */ + iosta = iosta | IOS_DRM; /* set done */ + sbs = sbs | SB_RQ; /* req intr */ + return IORETURN (drm_stopioe, SCPE_UNATT); } + +da = drm_da * DRM_NUMWDS; /* compute dev addr */ +for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */ + if (uptr->FUNC == DRM_READ) { + if (MEM_ADDR_OK (drm_ma)) /* read, check nxm */ + M[drm_ma] = *(((int32 *) uptr->filebuf) + da); } + else { + if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; + else { + *(((int32 *) uptr->filebuf) + da) = M[drm_ma]; + if (da >= uptr->hwmark) uptr->hwmark = da + 1; } } + drm_ma = (drm_ma + 1) & 0177777; } /* incr mem addr */ +drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */ +iosta = iosta | IOS_DRM; /* set done */ +sbs = sbs | SB_RQ; /* req intr */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat drm_reset (DEVICE *dptr) +{ +drm_da = drm_ma = drm_err = 0; +iosta = iosta & ~IOS_DRM; +sim_cancel (&drm_unit); +return SCPE_OK; +} diff --git a/PDP1/pdp1_dt.c b/PDP1/pdp1_dt.c index b7eb872d..fd72b409 100644 --- a/PDP1/pdp1_dt.c +++ b/PDP1/pdp1_dt.c @@ -356,7 +356,7 @@ if (pulse == 004) { /* MLC */ (fnc >= FNC_WMRK) || /* write mark? */ ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WLK)) || ((fnc == FNC_WALL) && (uptr->flags & UNIT_WLK))) - dt_seterr (uptr, DTB_SEL); /* select err */ + dt_seterr (uptr, DTB_SEL); /* select err */ else dt_newsa (dtsa); } if (pulse == 005) { /* MRD */ IO = (IO & ~DMASK) | dtdb; @@ -367,10 +367,10 @@ if (pulse == 006) { /* MWR */ if (pulse == 007) { /* MRS */ dtsb = dtsb & ~(DTB_REV | DTB_GO); /* clr rev, go */ if (uptr) { /* valid unit? */ - mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if (mot & DTS_DIR) dtsb = dtsb | DTB_REV; /* rev? set */ - if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700)) - dtsb = dtsb | DTB_GO; } /* accel? go */ + mot = DTS_GETMOT (uptr->STATE); /* get motion */ + if (mot & DTS_DIR) dtsb = dtsb | DTB_REV; /* rev? set */ + if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700)) + dtsb = dtsb | DTB_GO; } /* accel? go */ IO = (IO & ~DMASK) | dtsb; } DT_UPDINT; return IO; @@ -446,17 +446,17 @@ if (new_mving & ~prev_mving) { /* start? */ if (prev_mving & ~new_mving) { /* stop? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, dt_dctime); } /* schedule decel */ DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ return; } if (prev_dir ^ new_dir) { /* dir chg? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, dt_dctime); } /* schedule decel */ DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ DTS_SET2ND (DTS_ACCF | new_dir, 0); /* next = accel */ DTS_SET3RD (DTS_ATSF | new_dir, new_fnc); /* next next = fnc */ @@ -522,25 +522,26 @@ case FNC_MOVE: /* move */ return; /* done */ case FNC_SRCH: /* search */ if (dir) newpos = DT_BLK2LN ((DT_QFEZ (uptr)? - DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; + DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; else newpos = DT_BLK2LN ((DT_QREZ (uptr)? - 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); + 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); if (dt_log & LOG_MS) printf ("[DT%d: searching %s]\n", unum, - (dir? "backward": "forward")); + (dir? "backward": "forward")); break; case FNC_WRIT: /* write */ case FNC_READ: /* read */ case FNC_RALL: /* read all */ case FNC_WALL: /* write all */ if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE; - else newpos = DT_EZLIN + (DT_WSIZE - 1); } - else { newpos = ((uptr->pos) / DT_WSIZE) * DT_WSIZE; - if (!dir) newpos = newpos + (DT_WSIZE - 1); } + if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE; + else newpos = DT_EZLIN + (DT_WSIZE - 1); } + else { + newpos = ((uptr->pos) / DT_WSIZE) * DT_WSIZE; + if (!dir) newpos = newpos + (DT_WSIZE - 1); } if ((dt_log & LOG_RA) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: read all block %d %s%s\n", - unum, blk, (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); + printf ("[DT%d: read all block %d %s%s\n", + unum, blk, (dir? "backward": "forward"), + ((dtsa & DTA_MODE)? " continuous]": "]")); break; default: dt_seterr (uptr, DTB_SEL); /* bad state */ @@ -603,7 +604,7 @@ if (((int32) uptr->pos < 0) || uptr->STATE = uptr->pos = 0; unum = uptr - dt_dev.units; if (unum == DTA_GETUNIT (dtsa)) /* if selected, */ - dt_seterr (uptr, DTB_SEL); /* error */ + dt_seterr (uptr, DTB_SEL); /* error */ return TRUE; } return FALSE; } @@ -633,9 +634,9 @@ t_addr ba; switch (mot) { case DTS_DECF: case DTS_DECR: /* decelerating */ if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ + uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ + sim_activate (uptr, dt_actime); /* must be reversing */ return SCPE_OK; case DTS_ACCF: case DTS_ACCR: /* accelerating */ dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ @@ -671,8 +672,8 @@ case DTS_OFR: /* off reel */ case FNC_SRCH: /* search */ if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ dtdb = blk; /* store block # */ dtsb = dtsb | DTB_DTF; /* set DTF */ @@ -682,27 +683,28 @@ case FNC_SRCH: /* search */ case FNC_READ: case FNC_RALL: if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } sim_activate (uptr, DT_WSIZE * dt_ltime); /* sched next word */ relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - dtdb = bptr[ba]; /* get tape word */ - dtsb = dtsb | DTB_DTF; } /* set flag */ - else { ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1; - wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ - if ((wrd == 0) || /* skip 1st, last */ - (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; - if ((fnc == FNC_READ) && /* read, skip if not */ - (wrd != DT_CSMWD) && /* fwd, rev cksum */ - (wrd != ma)) break; - dtdb = dt_gethdr (uptr, blk, relpos); - if (wrd == (dir? DT_CSMWD: ma)) /* at end csum? */ - dtsb = dtsb | DTB_BEF; /* end block */ - else dtsb = dtsb | DTB_DTF; } /* else next word */ + wrd = DT_LIN2WD (uptr->pos, uptr); + ba = (blk * DTU_BSIZE (uptr)) + wrd; + dtdb = bptr[ba]; /* get tape word */ + dtsb = dtsb | DTB_DTF; } /* set flag */ + else { + ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1; + wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ + if ((wrd == 0) || /* skip 1st, last */ + (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; + if ((fnc == FNC_READ) && /* read, skip if not */ + (wrd != DT_CSMWD) && /* fwd, rev cksum */ + (wrd != ma)) break; + dtdb = dt_gethdr (uptr, blk, relpos); + if (wrd == (dir? DT_CSMWD: ma)) /* at end csum? */ + dtsb = dtsb | DTB_BEF; /* end block */ + else dtsb = dtsb | DTB_DTF; } /* else next word */ if (dir) dtdb = dt_comobv (dtdb); break; @@ -710,27 +712,28 @@ case FNC_READ: case FNC_RALL: case FNC_WRIT: case FNC_WALL: if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } sim_activate (uptr, DT_WSIZE * dt_ltime); /* sched next word */ relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - if (dir) bptr[ba] = dt_comobv (dtdb); /* get data word */ - else bptr[ba] = dtdb; - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1)) - dtsb = dtsb | DTB_BEF; /* end block */ - else dtsb = dtsb | DTB_DTF; } /* else next word */ - else { wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ - if ((wrd == 0) || /* skip 1st, last */ - (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; - if ((fnc == FNC_WRIT) && /* wr, skip if !csm */ - (wrd != ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1))) - break; - dtsb = dtsb | DTB_DTF; } /* set flag */ + wrd = DT_LIN2WD (uptr->pos, uptr); + ba = (blk * DTU_BSIZE (uptr)) + wrd; + if (dir) bptr[ba] = dt_comobv (dtdb); /* get data word */ + else bptr[ba] = dtdb; + if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; + if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1)) + dtsb = dtsb | DTB_BEF; /* end block */ + else dtsb = dtsb | DTB_DTF; } /* else next word */ + else { + wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ + if ((wrd == 0) || /* skip 1st, last */ + (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; + if ((fnc == FNC_WRIT) && /* wr, skip if !csm */ + (wrd != ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1))) + break; + dtsb = dtsb | DTB_DTF; } /* set flag */ break; default: @@ -823,16 +826,17 @@ UNIT *uptr; for (i = 0; i < DT_NUMDR; i++) { /* stop all drives */ uptr = dt_dev.units + i; if (sim_is_running) { /* CAF? */ - prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ - if (dt_setpos (uptr)) continue; /* update pos */ - sim_cancel (uptr); - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); - } } - else { sim_cancel (uptr); /* sim reset */ - uptr->STATE = 0; - uptr->LASTT = sim_grtime (); } } + prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ + if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ + if (dt_setpos (uptr)) continue; /* update pos */ + sim_cancel (uptr); + sim_activate (uptr, dt_dctime); /* sched decel */ + DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); + } } + else { + sim_cancel (uptr); /* sim reset */ + uptr->STATE = 0; + uptr->LASTT = sim_grtime (); } } dtsa = dtsb = 0; /* clear status */ DT_UPDINT; /* reset interrupt */ return SCPE_OK; @@ -939,8 +943,8 @@ if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; if (sim_is_active (uptr)) { sim_cancel (uptr); if ((unum == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) { - dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF; - DT_UPDINT; } + dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF; + DT_UPDINT; } uptr->STATE = uptr->pos = 0; } bptr = uptr->filebuf; /* file buffer */ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ diff --git a/PDP1/pdp1_lp.c b/PDP1/pdp1_lp.c index d4e43a84..d5386cdb 100644 --- a/PDP1/pdp1_lp.c +++ b/PDP1/pdp1_lp.c @@ -89,10 +89,10 @@ if (lpt_dev.flags & DEV_DIS) /* disabled? */ return (stop_inst << IOT_V_REASON) | data; /* stop if requested */ if ((inst & 0700) == 0100) { /* fill buf */ if (bptr < BPTR_MAX) { /* limit test ptr */ - i = bptr * 3; /* cvt to chr ptr */ - lpt_buf[i] = lpt_trans[(data >> 12) & 077]; - lpt_buf[i + 1] = lpt_trans[(data >> 6) & 077]; - lpt_buf[i + 2] = lpt_trans[data & 077]; } + i = bptr * 3; /* cvt to chr ptr */ + lpt_buf[i] = lpt_trans[(data >> 12) & 077]; + lpt_buf[i + 1] = lpt_trans[(data >> 6) & 077]; + lpt_buf[i + 2] = lpt_trans[data & 077]; } bptr = (bptr + 1) & BPTR_MASK; return data; } lpt_rpls = 0; @@ -133,22 +133,22 @@ ioc = ioc | lpt_rpls; /* restart */ if (lpt_iot & 020) { /* space? */ iosta = iosta | IOS_SPC; /* set flag */ if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); + return IORETURN (lpt_stopioe, SCPE_UNATT); fputs (lpt_cc[lpt_iot & 07], lpt_unit.fileref); /* print cctl */ if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } + perror ("LPT I/O error"); + clearerr (lpt_unit.fileref); + return SCPE_IOERR; } lpt_iot = 0; } /* clear state */ else { iosta = iosta | IOS_PNT; /* print */ if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); + return IORETURN (lpt_stopioe, SCPE_UNATT); if (lpt_iot & 010) fputc ('\r', lpt_unit.fileref); fputs (lpt_buf, lpt_unit.fileref); /* print buffer */ if (ferror (lpt_unit.fileref)) { /* test error */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } + perror ("LPT I/O error"); + clearerr (lpt_unit.fileref); + return SCPE_IOERR; } bptr = 0; for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ lpt_iot = 010; } /* set state */ diff --git a/PDP1/pdp1_stddev.c b/PDP1/pdp1_stddev.c index 8a4083ad..7b2efc0b 100644 --- a/PDP1/pdp1_stddev.c +++ b/PDP1/pdp1_stddev.c @@ -28,6 +28,8 @@ tti keyboard tto teleprinter + 22-Dec-02 RMS Added break support + 29-Nov-02 RMS Fixed output flag initialization (found by Derek Peschel) 21-Nov-02 RMS Changed typewriter to half duplex (found by Derek Peschel) 06-Oct-02 RMS Revised for V2.10 30-May-02 RMS Widened POS to 32b @@ -217,8 +219,8 @@ if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ptr_stopioe, SCPE_UNATT); if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } + if (ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; } else perror ("PTR I/O error"); clearerr (ptr_unit.fileref); return SCPE_IOERR; } @@ -346,6 +348,7 @@ if (tti_hold & CW) { /* char waiting? */ tty_buf = tti_hold & TT_WIDTH; /* return char */ tti_hold = 0; } /* not waiting */ else { if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; + if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */ temp = temp & 0177; if (temp == 0177) temp = '\b'; /* rubout? bs */ sim_putchar (temp); /* echo */ @@ -353,10 +356,11 @@ else { if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; in = ascii_to_fiodec[temp]; /* translate char */ if (in == 0) return SCPE_OK; /* no xlation? */ if ((in & BOTH) || ((in & UC) == (tty_uc & UC))) - tty_buf = in & TT_WIDTH; - else { tty_uc = in & UC; /* shift case */ - tty_buf = tty_uc? FIODEC_UC: FIODEC_LC; - tti_hold = in | CW; } } /* set 2nd waiting */ + tty_buf = in & TT_WIDTH; + else { /* must shift */ + tty_uc = in & UC; /* new case */ + tty_buf = tty_uc? FIODEC_UC: FIODEC_LC; + tti_hold = in | CW; } } /* set 2nd waiting */ iosta = iosta | IOS_TTI; /* set flag */ sbs = sbs | SB_RQ; /* req seq break */ PF = PF | 040; /* set prog flag 1 */ @@ -395,7 +399,7 @@ tty_buf = 0; /* clear buffer */ tty_uc = 0; /* clear case */ tti_hold = 0; /* clear hold buf */ tto_rpls = 0; /* clear reset pulse */ -iosta = iosta & ~(IOS_TTI | IOS_TTO); /* clear flag */ +iosta = (iosta & ~IOS_TTI) | IOS_TTO; /* clear flag */ sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate keyboard */ sim_cancel (&tty_unit[TTO]); /* stop printer */ return SCPE_OK; diff --git a/PDP1/pdp1_sys.c b/PDP1/pdp1_sys.c index 2fdfcc6b..5a3204ce 100644 --- a/PDP1/pdp1_sys.c +++ b/PDP1/pdp1_sys.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 05-Dec-02 RMS Added drum support 21-Nov-02 RMS Changed typewriter to half duplex 20-Aug-02 RMS Added DECtape support 17-Sep-01 RMS Removed multiconsole support @@ -32,16 +33,19 @@ 30-Oct-00 RMS Added support for examine to file 27-Oct-98 RMS V2.4 load interface 20-Oct-97 RMS Fixed endian-dependence in RIM loader - (found by Michael Somos) + (found by Michael Somos) */ #include "pdp1_defs.h" #include extern DEVICE cpu_dev; -extern DEVICE ptr_dev, ptp_dev; +extern DEVICE ptr_dev; +extern DEVICE ptp_dev; extern DEVICE tty_dev; -extern DEVICE lpt_dev, dt_dev; +extern DEVICE lpt_dev; +extern DEVICE dt_dev; +extern DEVICE drm_dev; extern UNIT cpu_unit; extern REG cpu_reg[]; extern int32 M[]; @@ -72,6 +76,7 @@ DEVICE *sim_devices[] = { &tty_dev, &lpt_dev, &dt_dev, + &drm_dev, NULL }; const char *sim_stop_messages[] = { @@ -110,12 +115,12 @@ for (;;) { if ((val = getword (fileref)) < 0) return SCPE_FMT; if (((val & 0770000) == 0320000) || /* DIO? */ ((val & 0770000) == 0240000)) { /* DAC? - incorrect */ - origin = val & 07777; - if ((val = getword (fileref)) < 0) return SCPE_FMT; - if (MEM_ADDR_OK (origin)) M[origin++] = val; } + origin = val & 07777; + if ((val = getword (fileref)) < 0) return SCPE_FMT; + if (MEM_ADDR_OK (origin)) M[origin++] = val; } else if ((val & 0770000) == 0600000) { /* JMP? */ - PC = val & 007777; - break; } + PC = val & 007777; + break; } } return SCPE_OK; /* done */ } @@ -268,9 +273,9 @@ int32 i, j; for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ if ((j == class) && (opc_val[i] & inst)) { /* same class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } + inst = inst & ~opc_val[i]; /* mask bit set? */ + fprintf (of, (sp? " %s": "%s"), opcode[i]); + sp = 1; } } return sp; } @@ -318,35 +323,35 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ switch (j) { /* case on class */ case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; + fprintf (of, "%s", opcode[i]); /* opcode */ + break; case I_V_IOT: /* IOT */ - disp = (inst - opc_val[i]) & 017777; - if (disp == IA) fprintf (of, "%s I", opcode[i]); - else if (disp) fprintf (of, "%s %-o", opcode[i], disp); - else fprintf (of, "%s", opcode[i]); - break; + disp = (inst - opc_val[i]) & 017777; + if (disp == IA) fprintf (of, "%s I", opcode[i]); + else if (disp) fprintf (of, "%s %-o", opcode[i], disp); + else fprintf (of, "%s", opcode[i]); + break; case I_V_LAW: /* LAW */ - cflag = 0; /* fall thru to MRF */ + cflag = 0; /* fall thru to MRF */ case I_V_MRF: /* mem ref */ - fprintf (of, "%s%s%-o", opcode[i], - ((inst & IA)? " I ": " "), (cflag? ma: disp)); - break; + fprintf (of, "%s%s%-o", opcode[i], + ((inst & IA)? " I ": " "), (cflag? ma: disp)); + break; case I_V_MRI: /* mem ref no ind */ - fprintf (of, "%s %-o", opcode[i], (cflag? ma: disp)); - break; + fprintf (of, "%s %-o", opcode[i], (cflag? ma: disp)); + break; case I_V_OPR: /* operates */ - sp = fprint_opr (of, inst & 007700, j, 0); - if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); - break; + sp = fprint_opr (of, inst & 007700, j, 0); + if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); + break; case I_V_SKP: /* skips */ - sp = fprint_opr (of, inst & 007700, j, 0); - if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]); - if (inst & IA) fprintf (of, sp? " I": "I"); - break; + sp = fprint_opr (of, inst & 007700, j, 0); + if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]); + if (inst & IA) fprintf (of, sp? " I": "I"); + break; case I_V_SHF: /* shifts */ - fprintf (of, "%s %-d", opcode[i], sc_map[inst & 0777]); - break; } /* end case */ + fprintf (of, "%s %-d", opcode[i], sc_map[inst & 0777]); + break; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; @@ -422,8 +427,8 @@ case I_V_LAW: /* LAW */ case I_V_MRF: case I_V_MRI: /* mem ref */ cptr = get_glyph (cptr, gbuf, 0); /* get next field */ if ((j != I_V_MRI) && strcmp (gbuf, "I") == 0) { /* indirect? */ - val[0] = val[0] | IA; - cptr = get_glyph (cptr, gbuf, 0); } + val[0] = val[0] | IA; + cptr = get_glyph (cptr, gbuf, 0); } d = get_uint (gbuf, 8, AMASK, &r); if (r != SCPE_OK) return SCPE_ARG; if (d <= DAMASK) val[0] = val[0] | d; @@ -439,19 +444,20 @@ case I_V_SHF: /* shift */ break; case I_V_NPN: case I_V_IOT: case I_V_OPR: case I_V_SKP: for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && - (strcmp (opcode[i], gbuf) != 0) ; i++) ; - if (opcode[i] != NULL) { - k = opc_val[i] & 0777777; - if ((k != IA) && (((k ^ val[0]) & 0760000) != 0)) - return SCPE_ARG; - val[0] = val[0] | k; } - else { d = get_sint (gbuf, &sign, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (sign == 0) val[0] = val[0] + d; - else if (sign < 0) val[0] = val[0] - d; - else val[0] = val[0] | d; } } + cptr = get_glyph (cptr, gbuf, 0)) { + for (i = 0; (opcode[i] != NULL) && + (strcmp (opcode[i], gbuf) != 0); i++) ; + if (opcode[i] != NULL) { + k = opc_val[i] & 0777777; + if ((k != IA) && (((k ^ val[0]) & 0760000) != 0)) + return SCPE_ARG; + val[0] = val[0] | k; } + else { + d = get_sint (gbuf, &sign, &r); + if (r != SCPE_OK) return SCPE_ARG; + if (sign == 0) val[0] = val[0] + d; + else if (sign < 0) val[0] = val[0] - d; + else val[0] = val[0] | d; } } break; } /* end case */ if (*cptr != 0) return SCPE_ARG; /* junk at end? */ return SCPE_OK; diff --git a/PDP10/pdp10_cpu.c b/PDP10/pdp10_cpu.c index ca03ce01..48d37c8c 100644 --- a/PDP10/pdp10_cpu.c +++ b/PDP10/pdp10_cpu.c @@ -607,7 +607,7 @@ if (!ITS) its_1pr = 0; /* ~ITS, clr 1-proc */ abortval = setjmp (save_env); /* set abort hdlr */ if ((abortval > 0) || pager_pi) { /* stop or pi err? */ if (pager_pi && (abortval == PAGE_FAIL)) - abortval = STOP_PAGINT; /* stop for pi err */ + abortval = STOP_PAGINT; /* stop for pi err */ saved_PC = pager_PC & AMASK; /* failing instr PC */ set_ac_display (ac_cur); /* set up AC display */ pcq_r->qptr = pcq_p; /* update pc q ptr */ @@ -623,19 +623,20 @@ else if (abortval == PAGE_FAIL) { /* page fail */ rlog = 0; /* clear log */ if (pager_tc) flags = pager_flags; /* trap? get flags */ if (T20) { /* TOPS-20 */ - WriteP (upta + UPT_T20_PFL, pager_word);/* write page fail wd */ - WriteP (upta + UPT_T20_OFL, XWD (flags, 0)); - WriteP (upta + UPT_T20_OPC, pager_PC); - mb = ReadP (upta + UPT_T20_NPC); } - else { a10 ea; /* TOPS-10 or ITS */ - if (ITS) { /* ITS? */ - ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3); - if (its_1pr) flags = flags | F_1PR; /* store 1-proc */ - its_1pr = 0; } /* clear 1-proc */ - else ea = upta + UPT_T10_PAG; - WriteP (ea, pager_word); /* write page fail wd */ - WriteP (ADDA (ea, 1), XWD (flags, pager_PC)); - mb = ReadP (ADDA (ea, 2)); } + WriteP (upta + UPT_T20_PFL, pager_word); /* write page fail wd */ + WriteP (upta + UPT_T20_OFL, XWD (flags, 0)); + WriteP (upta + UPT_T20_OPC, pager_PC); + mb = ReadP (upta + UPT_T20_NPC); } + else { + a10 ea; /* TOPS-10 or ITS */ + if (ITS) { /* ITS? */ + ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3); + if (its_1pr) flags = flags | F_1PR; /* store 1-proc */ + its_1pr = 0; } /* clear 1-proc */ + else ea = upta + UPT_T10_PAG; + WriteP (ea, pager_word); /* write page fail wd */ + WriteP (ADDA (ea, 1), XWD (flags, pager_PC)); + mb = ReadP (ADDA (ea, 2)); } JUMP (mb); /* set new PC */ set_newflags (mb, FALSE); /* set new flags */ pi_eval (); } /* eval pi system */ @@ -667,30 +668,29 @@ if (qintr) { int32 vec, uba; pager_pi = TRUE; /* flag in pi seq */ if (vec = pi_ub_vec (qintr, &uba)) { /* Unibus interrupt? */ - mb = ReadP (epta + EPT_UBIT + uba); /* get dispatch table */ - if (mb == 0) ABORT (STOP_ZERINT); /* invalid? stop */ - inst = ReadE ((((a10) mb) + (vec / 4)) & AMASK); - if (inst == 0) - ABORT (STOP_ZERINT); } + mb = ReadP (epta + EPT_UBIT + uba); /* get dispatch table */ + if (mb == 0) ABORT (STOP_ZERINT); /* invalid? stop */ + inst = ReadE ((((a10) mb) + (vec / 4)) & AMASK); + if (inst == 0) ABORT (STOP_ZERINT); } else inst = ReadP (epta + EPT_PIIT + (2 * qintr)); op = GET_OP (inst); /* get opcode */ ac = GET_AC (inst); /* get ac */ if (its_1pr && ITS) { /* 1-proc set? */ - flags = flags | F_1PR; /* store 1-proc */ - its_1pr = 0; } /* clear 1-proc */ + flags = flags | F_1PR; /* store 1-proc */ + its_1pr = 0; } /* clear 1-proc */ if (op == OP_JSR) { /* JSR? */ - ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */ - WriteE (ea, FLPC); /* save flags+PC, exec */ - JUMP (INCA (ea)); /* PC = ea + 1 */ - set_newflags (0, FALSE); } /* set new flags */ + ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */ + WriteE (ea, FLPC); /* save flags+PC, exec */ + JUMP (INCA (ea)); /* PC = ea + 1 */ + set_newflags (0, FALSE); } /* set new flags */ else if ((op == OP_JRST) && (ac == AC_XPCW)) { /* XPCW? */ - ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */ - WriteE (ea, XWD (flags, 0)); /* write flags, exec */ - WriteE (ADDA (ea, 1), PC); /* write PC, exec */ - rs[0] = ReadE (ADDA (ea, 2)); /* read new flags */ - rs[1] = ReadE (ADDA (ea, 3)); /* read new PC */ - JUMP (rs[1]); /* set new PC */ - set_newflags (rs[0], FALSE); } /* set new flags */ + ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */ + WriteE (ea, XWD (flags, 0)); /* write flags, exec */ + WriteE (ADDA (ea, 1), PC); /* write PC, exec */ + rs[0] = ReadE (ADDA (ea, 2)); /* read new flags */ + rs[1] = ReadE (ADDA (ea, 3)); /* read new PC */ + JUMP (rs[1]); /* set new PC */ + set_newflags (rs[0], FALSE); } /* set new flags */ else ABORT (STOP_ILLINT); /* invalid instr */ pi_act = pi_act | pi_l2bit[qintr]; /* set level active */ pi_eval (); /* eval pi system */ @@ -712,7 +712,7 @@ if (TSTF (F_T1 | F_T2) && PAGING) { pager_tc = TRUE; /* in a trap sequence */ pager_flags = flags; /* save flags */ ea = (TSTF (F_USR)? upta + UPT_TRBASE: epta + EPT_TRBASE) - + GET_TRAPS (flags); + + GET_TRAPS (flags); inst = ReadP (ea); /* get trap instr */ CLRF (F_T1 | F_T2); } /* clear flags */ @@ -720,7 +720,7 @@ if (TSTF (F_T1 | F_T2) && PAGING) { else { if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - ABORT (STOP_IBKPT); } /* stop simulation */ + ABORT (STOP_IBKPT); } /* stop simulation */ /* Ready (at last) to get an instruction */ @@ -790,12 +790,12 @@ case 0037: /* case 0100: MUUO /* UJEN */ /* case 0101: MUUO /* unassigned */ case 0102: if (ITS && !TSTF (F_USR)) { /* GFAD (KL), XCTRI (ITS) */ - inst = Read (ea, MM_OPND); - pflgs = pflgs | ac; goto XCT; } + inst = Read (ea, MM_OPND); + pflgs = pflgs | ac; goto XCT; } goto MUUO; case 0103: if (ITS && !TSTF (F_USR)) { /* GFSB (KL), XCTR (ITS) */ - inst = Read (ea, MM_OPND); - pflgs = pflgs | ac; goto XCT; } + inst = Read (ea, MM_OPND); + pflgs = pflgs | ac; goto XCT; } goto MUUO; /* case 0104: MUUO /* JSYS (T20) */ case 0105: AC(ac) = adjsp (AC(ac), ea); break; /* ADJSP */ @@ -919,9 +919,9 @@ case 0252: AOBAC; if (TGE (AC(ac))) JUMP (ea); break; /* AOBJP */ case 0253: AOBAC; if (TL (AC(ac))) JUMP (ea); break; /* AOBJN */ /* case 0254: /* shown later /* JRST */ case 0255: if (flags & (ac << 14)) { /* JFCL */ - JUMP (ea); CLRF (ac << 14); } break; + JUMP (ea); CLRF (ac << 14); } break; case 0256: if (xct_cnt++ >= xct_max) /* XCT */ - ABORT (STOP_XCT); + ABORT (STOP_XCT); inst = Read (ea, MM_OPND); if (ac && !TSTF (F_USR) && !ITS) pflgs = pflgs | ac; goto XCT; @@ -1263,16 +1263,17 @@ case 0725: IOA; io725 (AC(ac), ea); break; /* BCIOB, IOWRBQ */ default: MUUO: its_2pr = 0; /* clear trap */ if (T20) { /* TOPS20? */ - int32 tf = (op << (INST_V_OP - 18)) | (ac << (INST_V_AC - 18)); - WriteP (upta + UPT_MUUO, XWD ( /* store flags,,op+ac */ - flags & ~(F_T2 | F_T1), tf)); /* traps clear */ - WriteP (upta + UPT_MUPC, PC); /* store PC */ - WriteP (upta + UPT_T20_UEA, ea); /* store eff addr */ - WriteP (upta + UPT_T20_CTX, UBRWORD); } /* store context */ - else { WriteP (upta + UPT_MUUO, UUOWORD); /* store instr word */ - WriteP (upta + UPT_MUPC, XWD ( /* store flags,,PC */ - flags & ~(F_T2 | F_T1), PC)); /* traps clear */ - WriteP (upta + UPT_T10_CTX, UBRWORD); } /* store context */ + int32 tf = (op << (INST_V_OP - 18)) | (ac << (INST_V_AC - 18)); + WriteP (upta + UPT_MUUO, XWD ( /* store flags,,op+ac */ + flags & ~(F_T2 | F_T1), tf)); /* traps clear */ + WriteP (upta + UPT_MUPC, PC); /* store PC */ + WriteP (upta + UPT_T20_UEA, ea); /* store eff addr */ + WriteP (upta + UPT_T20_CTX, UBRWORD); } /* store context */ + else { /* TOPS10/ITS */ + WriteP (upta + UPT_MUUO, UUOWORD); /* store instr word */ + WriteP (upta + UPT_MUPC, XWD ( /* store flags,,PC */ + flags & ~(F_T2 | F_T1), PC)); /* traps clear */ + WriteP (upta + UPT_T10_CTX, UBRWORD); } /* store context */ ea = upta + (TSTF (F_USR)? UPT_UNPC: UPT_ENPC) + (pager_tc? UPT_NPCT: 0); /* calculate vector */ mb = ReadP (ea); /* new flags, PC */ @@ -1292,69 +1293,69 @@ MUUO: its_2pr = 0; /* clear trap */ case 0254: /* JRST */ i = jrst_tab[ac]; /* get subop flags */ if ((i == 0) || ((i == JRST_E) && TSTF (F_USR)) || - ((i == JRST_UIO) && TSTF (F_USR) && !TSTF (F_UIO))) - goto MUUO; /* not legal */ + ((i == JRST_UIO) && TSTF (F_USR) && !TSTF (F_UIO))) + goto MUUO; /* not legal */ switch (ac) { /* case on subopcode */ case 000: /* JRST 0 = jump */ case 001: /* JRST 1 = portal */ - JUMP (ea); - break; + JUMP (ea); + break; case 002: /* JRST 2 = JRSTF */ - mb = calc_jrstfea (inst, pflgs); /* recalc addr w flgs */ - JUMP (ea); /* set new PC */ - set_newflags (mb, TRUE); /* set new flags */ - break; + mb = calc_jrstfea (inst, pflgs); /* recalc addr w flgs */ + JUMP (ea); /* set new PC */ + set_newflags (mb, TRUE); /* set new flags */ + break; case 004: /* JRST 4 = halt */ - JUMP (ea); /* old_PC = halt + 1 */ - pager_PC = PC; /* force right PC */ - ABORT (STOP_HALT); /* known to be exec */ - break; + JUMP (ea); /* old_PC = halt + 1 */ + pager_PC = PC; /* force right PC */ + ABORT (STOP_HALT); /* known to be exec */ + break; case 005: /* JRST 5 = XJRSTF */ - RD2; /* read doubleword */ - JUMP (rs[1]); /* set new PC */ - set_newflags (rs[0], TRUE); /* set new flags */ - break; + RD2; /* read doubleword */ + JUMP (rs[1]); /* set new PC */ + set_newflags (rs[0], TRUE); /* set new flags */ + break; case 006: /* JRST 6 = XJEN */ - RD2; /* read doubleword */ - pi_dismiss (); /* page ok, dismiss */ - JUMP (rs[1]); /* set new PC */ - set_newflags (rs[0], FALSE); /* known to be exec */ - break; + RD2; /* read doubleword */ + pi_dismiss (); /* page ok, dismiss */ + JUMP (rs[1]); /* set new PC */ + set_newflags (rs[0], FALSE); /* known to be exec */ + break; case 007: /* JRST 7 = XPCW */ - ea = ADDA (i = ea, 2); /* new flags, PC */ - RD2; /* read, test page fail */ - ReadM (INCA (i), MM_OPND); /* test PC write */ - Write (i, XWD (flags, 0), MM_OPND); /* write flags */ - Write (INCA (i), PC, MM_OPND); /* write PC */ - JUMP (rs[1]); /* set new PC */ - set_newflags (rs[0], FALSE); /* known to be exec */ - break; + ea = ADDA (i = ea, 2); /* new flags, PC */ + RD2; /* read, test page fail */ + ReadM (INCA (i), MM_OPND); /* test PC write */ + Write (i, XWD (flags, 0), MM_OPND); /* write flags */ + Write (INCA (i), PC, MM_OPND); /* write PC */ + JUMP (rs[1]); /* set new PC */ + set_newflags (rs[0], FALSE); /* known to be exec */ + break; case 010: /* JRST 10 = dismiss */ - pi_dismiss (); /* dismiss int */ - JUMP (ea); /* set new PC */ - break; + pi_dismiss (); /* dismiss int */ + JUMP (ea); /* set new PC */ + break; case 012: /* JRST 12 = JEN */ - mb = calc_jrstfea (inst, pflgs); /* recalc addr w flgs */ - JUMP (ea); /* set new PC */ - set_newflags (mb, TRUE); /* set new flags */ - pi_dismiss (); /* dismiss int */ - break; + mb = calc_jrstfea (inst, pflgs); /* recalc addr w flgs */ + JUMP (ea); /* set new PC */ + set_newflags (mb, TRUE); /* set new flags */ + pi_dismiss (); /* dismiss int */ + break; case 014: /* JRST 14 = SFM */ - Write (ea, XWD (flags, 0), MM_OPND); - break; + Write (ea, XWD (flags, 0), MM_OPND); + break; case 015: /* JRST 15 = XJRST */ - if (!T20) goto MUUO; /* only in TOPS20 */ - JUMP (Read (ea, MM_OPND)); /* jump to M[ea] */ - break; } /* end case subop */ + if (!T20) goto MUUO; /* only in TOPS20 */ + JUMP (Read (ea, MM_OPND)); /* jump to M[ea] */ + break; } /* end case subop */ break; } /* end case op */ if (its_2pr) { /* 1-proc trap? */ its_1pr = its_2pr = 0; /* clear trap */ if (ITS) { /* better be ITS */ - WriteP (upta + UPT_1PO, FLPC); /* wr old flgs, PC */ - mb = ReadP (upta + UPT_1PN); /* rd new flgs, PC */ - JUMP (mb); /* set PC */ - set_newflags (mb, TRUE); } /* set new flags */ + WriteP (upta + UPT_1PO, FLPC); /* wr old flgs, PC */ + mb = ReadP (upta + UPT_1PN); /* rd new flgs, PC */ + JUMP (mb); /* set PC */ + set_newflags (mb, TRUE); } /* set new flags */ } /* end if 2-proc */ } /* end for */ @@ -1490,15 +1491,17 @@ int32 sc = LIT8 (ea); if (sc > 71) AC(ac) = AC(p1) = 0; else if (ea & RSIGN) { if (sc >= 36) { - AC(p1) = AC(ac) >> (sc - 36); - AC(ac) = 0; } - else { AC(p1) = ((AC(p1) >> sc) | (AC(ac) << (36 - sc))) & DMASK; - AC(ac) = AC(ac) >> sc; } } + AC(p1) = AC(ac) >> (sc - 36); + AC(ac) = 0; } + else { + AC(p1) = ((AC(p1) >> sc) | (AC(ac) << (36 - sc))) & DMASK; + AC(ac) = AC(ac) >> sc; } } else { if (sc >= 36) { - AC(ac) = (AC(p1) << (sc - 36)) & DMASK; - AC(p1) = 0; } - else { AC(ac) = ((AC(ac) << sc) | (AC(p1) >> (36 - sc))) & DMASK; - AC(p1) = (AC(p1) << sc) & DMASK; } } + AC(ac) = (AC(p1) << (sc - 36)) & DMASK; + AC(p1) = 0; } + else { + AC(ac) = ((AC(ac) << sc) | (AC(p1) >> (36 - sc))) & DMASK; + AC(p1) = (AC(p1) << sc) & DMASK; } } return; } @@ -1530,10 +1533,10 @@ d10 fill = sign? ONES: 0; d10 so; if (sc == 0) return val; -if (sc > 35) sc = 35; /* cap sc at 35 */ +if (sc > 35) sc = 35; /* cap sc at 35 */ if (ea & RSIGN) return (((val >> sc) | (fill << (36 - sc))) & DMASK); -so = val >> (35 - sc); /* bits lost left + sign */ +so = val >> (35 - sc); /* bits lost left + sign */ if (so != (sign? bytemask[sc + 1]: 0)) SETF (F_AOV | F_T1); return (sign | ((val << sc) & MMASK)); } @@ -1552,22 +1555,24 @@ AC(ac) = CLRS (AC(ac)); /* clear signs */ AC(p1) = CLRS (AC(p1)); if (ea & RSIGN) { if (sc >= 35) { /* right 36..70 */ - AC(p1) = ((AC(ac) >> (sc - 35)) | (fill << (70 - sc))) & DMASK; - AC(ac) = fill; } - else { AC(p1) = sign | /* right 1..35 */ - (((AC(p1) >> sc) | (AC(ac) << (35 - sc))) & MMASK); - AC(ac) = ((AC(ac) >> sc) | (fill << (35 - sc))) & DMASK; } } + AC(p1) = ((AC(ac) >> (sc - 35)) | (fill << (70 - sc))) & DMASK; + AC(ac) = fill; } + else { + AC(p1) = sign | /* right 1..35 */ + (((AC(p1) >> sc) | (AC(ac) << (35 - sc))) & MMASK); + AC(ac) = ((AC(ac) >> sc) | (fill << (35 - sc))) & DMASK; } } else { if (sc >= 35) { /* left 36..70 */ - so = AC(p1) >> (70 - sc); /* bits lost left */ - if ((AC(ac) != (sign? MMASK: 0)) || - (so != (sign? bytemask[sc - 35]: 0))) SETF (F_AOV | F_T1); - AC(ac) = sign | ((AC(p1) << (sc - 35)) & MMASK); - AC(p1) = sign; } - else { so = AC(ac) >> (35 - sc); /* bits lost left */ - if (so != (sign? bytemask[sc]: 0)) SETF (F_AOV | F_T1); - AC(ac) = sign | - (((AC(ac) << sc) | (AC(p1) >> (35 - sc))) & MMASK); - AC(p1) = sign | ((AC(p1) << sc) & MMASK); } } + so = AC(p1) >> (70 - sc); /* bits lost left */ + if ((AC(ac) != (sign? MMASK: 0)) || + (so != (sign? bytemask[sc - 35]: 0))) SETF (F_AOV | F_T1); + AC(ac) = sign | ((AC(p1) << (sc - 35)) & MMASK); + AC(p1) = sign; } + else { + so = AC(ac) >> (35 - sc); /* bits lost left */ + if (so != (sign? bytemask[sc]: 0)) SETF (F_AOV | F_T1); + AC(ac) = sign | + (((AC(ac) << sc) | (AC(p1) >> (35 - sc))) & MMASK); + AC(p1) = sign | ((AC(p1) << sc) & MMASK); } } return; } @@ -1713,14 +1718,14 @@ if (s) { left = (36 - p) / s; /* bytes to left of p */ bywrd = left + (p / s); /* bytes per word */ if (bywrd == 0) { /* zero bytes? */ - SETF (F_AOV | F_T1 | F_DCK); /* set flags */ - return; } /* abort operation */ + SETF (F_AOV | F_T1 | F_DCK); /* set flags */ + return; } /* abort operation */ newby = left + SXT (val); /* adjusted byte # */ wdadj = newby / bywrd; /* word adjustment */ byadj = (newby >= 0)? newby % bywrd: -((-newby) % bywrd); if (byadj <= 0) { - byadj = byadj + bywrd; /* make adj positive */ - wdadj = wdadj - 1; } + byadj = byadj + bywrd; /* make adj positive */ + wdadj = wdadj - 1; } p = (36 - ((int32) byadj) * s) - ((36 - p) % s); /* new p */ bp = (PUT_P (bp, p) & LMASK) | ((bp + wdadj) & RMASK); } AC(ac) = bp; @@ -1745,14 +1750,14 @@ int32 flg, t; AC(ac) = XWD (srca + lnt, dsta + lnt); for (flg = 0; dsta <= ea; flg++) { /* loop */ if (flg && (t = test_int ())) { /* timer event? */ - AC(ac) = XWD (srca, dsta); /* AC for intr */ - ABORT (t); } + AC(ac) = XWD (srca, dsta); /* AC for intr */ + ABORT (t); } if (AccViol (srca & AMASK, MM_BSTK, PTF_RD)) { /* src access viol? */ - AC(ac) = XWD (srca, dsta); /* AC for page fail */ - Read (srca & AMASK, MM_BSTK); } /* force trap */ + AC(ac) = XWD (srca, dsta); /* AC for page fail */ + Read (srca & AMASK, MM_BSTK); } /* force trap */ if (AccViol (dsta & AMASK, MM_OPND, PTF_WR)) { /* dst access viol? */ - AC(ac) = XWD (srca, dsta); /* AC for page fail */ - ReadM (dsta & AMASK, MM_OPND); } /* force trap */ + AC(ac) = XWD (srca, dsta); /* AC for page fail */ + ReadM (dsta & AMASK, MM_OPND); } /* force trap */ srcv = Read (srca & AMASK, MM_BSTK); /* read */ Write (dsta & AMASK, srcv, MM_OPND); /* write */ srca = srca + 1; /* incr addr */ @@ -1779,19 +1784,19 @@ int32 flg, t; AC(ac) = XWD (srca + lnt, dsta + lnt); for (flg = 0; dsta <= ea; flg++) { /* loop */ if (flg && (t = test_int ())) { /* timer event? */ - AC(ac) = XWD (srca, dsta); /* AC for intr */ - ABORT (t); } + AC(ac) = XWD (srca, dsta); /* AC for intr */ + ABORT (t); } if (AccViol (srca & AMASK, MM_BSTK, PTF_RD)) { /* src access viol? */ - AC(ac) = XWD (srca, dsta); /* AC for page fail */ - Read (srca & AMASK, MM_BSTK); } /* force trap */ + AC(ac) = XWD (srca, dsta); /* AC for page fail */ + Read (srca & AMASK, MM_BSTK); } /* force trap */ if (AccViol (dsta & AMASK, MM_OPND, PTF_WR)) { /* dst access viol? */ - AC(ac) = XWD (srca, dsta); /* AC for page fail */ - ReadM (dsta & AMASK, MM_OPND); } /* force trap */ + AC(ac) = XWD (srca, dsta); /* AC for page fail */ + ReadM (dsta & AMASK, MM_OPND); } /* force trap */ srcv = Read (srca & AMASK, MM_BSTK); /* read */ if (dir) dstv = ((srcv << 10) & BYTE1) | ((srcv >> 6) & BYTE2) | - ((srcv << 12) & BYTE3) | ((srcv >> 4) & BYTE4); + ((srcv << 12) & BYTE3) | ((srcv >> 4) & BYTE4); else dstv = ((srcv & BYTE1) >> 10) | ((srcv & BYTE2) << 6) | - ((srcv & BYTE3) >> 12) | ((srcv & BYTE4) << 4); + ((srcv & BYTE3) >> 12) | ((srcv & BYTE4) << 4); Write (dsta & AMASK, dstv, MM_OPND); /* write */ srca = srca + 1; /* incr addr */ dsta = dsta + 1; } diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h index 09bcc653..f27b6d94 100644 --- a/PDP10/pdp10_defs.h +++ b/PDP10/pdp10_defs.h @@ -1,6 +1,6 @@ /* pdp10_defs.h: PDP-10 simulator definitions - Copyright (c) 1993-2002, Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 09-Jan-03 RMS Added DEUNA/DELUA support 29-Sep-02 RMS Added variable vector, RX211 support 22-Apr-02 RMS Removed magtape record length error 20-Jan-02 RMS Added multiboard DZ11 support @@ -637,6 +638,8 @@ typedef struct pdp_dib DIB; #define IOLN_UBCS3 001 #define IOBA_UBMNT3 (IO_UBA3 + 0763101) /* Unibus 3 maint reg */ #define IOLN_UBMNT3 001 +#define IOBA_XU (IO_UBA3 + 0774510) /* DEUNA/DELUA */ +#define IOLN_XU 010 #define IOBA_RY (IO_UBA3 + 0777170) /* RX211 */ #define IOLN_RY 004 #define IOBA_TU (IO_UBA3 + 0772440) /* RH11/tape */ @@ -672,6 +675,7 @@ typedef struct pdp_dib DIB; #define INT_V_RP 6 /* RH11/RP,RM drives */ #define INT_V_TU 7 /* RH11/TM03/TU45 */ +#define INT_V_XU 15 /* DEUNA/DELUA */ #define INT_V_DZRX 16 /* DZ11 */ #define INT_V_DZTX 17 #define INT_V_RY 18 /* RX211 */ @@ -681,6 +685,7 @@ typedef struct pdp_dib DIB; #define INT_RP (1u << INT_V_RP) #define INT_TU (1u << INT_V_TU) +#define INT_XU (1u << INT_V_XU) #define INT_DZRX (1u << INT_V_DZRX) #define INT_DZTX (1u << INT_V_DZTX) #define INT_RY (1u << INT_V_RY) @@ -690,6 +695,7 @@ typedef struct pdp_dib DIB; #define IPL_RP 6 /* int levels */ #define IPL_TU 6 +#define IPL_XU 5 #define IPL_DZRX 5 #define IPL_DZTX 5 #define IPL_RY 5 @@ -708,6 +714,7 @@ typedef struct pdp_dib DIB; #define VEC_Q 0000 /* vector base */ #define VEC_PTR 0070 /* interrupt vectors */ #define VEC_PTP 0074 +#define VEC_XU 0120 #define VEC_TU 0224 #define VEC_RP 0254 #define VEC_RY 0264 diff --git a/PDP10/pdp10_doc.txt b/PDP10/pdp10_doc.txt index c8c686c0..cfcceac0 100644 --- a/PDP10/pdp10_doc.txt +++ b/PDP10/pdp10_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik Subj: PDP-10 Simulator Usage -Date: 15-Nov-2002 +Date: 15-Jan-2003 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2002, written by Robert M Supnik - Copyright (c) 1993-2002, Robert M Supnik + Original code published in 1993-2003, written by Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -45,10 +45,12 @@ sim/ dec_dz.h sim_rev.h sim_sock.h sim_tmxr.h + sim_ether.h scp.c scp_tty.c sim_sock.c sim_tmxr.c + sim_ether.c sim/pdp10/ pdp10_defs.h pdp10_cpu.c @@ -65,6 +67,7 @@ sim/pdp10/ pdp10_defs.h pdp10_xtnd.c sim/pdp11/ pdp11_ry.c + pdp11_xu.c 2. PDP-10 Features @@ -85,6 +88,7 @@ LP20 LP20 line printer RP RH11/RP04/RP05/RP06/RP07/RM03/RM05/RM80 controller with eight drives TU RH11/TM02/TU45 controller with eight drives +XU DEUNA/DELUA Ethernet controller The PTR, PTP, and RX211 are initially set DISABLED. The DZ11 and LP20 can also be set DISABLED. Some devices support the SET ADDRESS command, which @@ -563,7 +567,12 @@ Error handling is as follows: RX02 data files are buffered in memory; therefore, end of file and OS I/O errors cannot occur. -2.13 Symbolic Display and Input +2.13 DEUNA/DELUA Ethernet Controller (XU) + +XU simulates the DEUNA/DELUA Ethernet controller. The current implementation +is a stub and is permanently disabled. + +2.14 Symbolic Display and Input The PDP-10 simulator implements symbolic display and input. Display is controlled by command line switches: diff --git a/PDP10/pdp10_fe.c b/PDP10/pdp10_fe.c index fc820cf1..cadb6b20 100644 --- a/PDP10/pdp10_fe.c +++ b/PDP10/pdp10_fe.c @@ -25,6 +25,7 @@ fe KS10 console front end + 22-Dec-02 RMS Added break support 30-May-02 RMS Widened COUNT to 32b 30-Nov-01 RMS Added extended SET/SHOW support 23-Oct-01 RMS New IO page address constants @@ -128,6 +129,7 @@ int32 temp; sim_activate (&fei_unit, fei_unit.wait); /* continue poll */ if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ +if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */ fei_unit.buf = temp & 0177; fei_unit.pos = fei_unit.pos + 1; M[FE_CTYIN] = fei_unit.buf | FE_CVALID; /* put char in mem */ diff --git a/PDP10/pdp10_ksio.c b/PDP10/pdp10_ksio.c index 9200fb3c..9eb4b034 100644 --- a/PDP10/pdp10_ksio.c +++ b/PDP10/pdp10_ksio.c @@ -371,9 +371,9 @@ DIB *dibp; for (i = 0; dibp = dib_tab[i]; i++ ) { if ((pa >= dibp->ba) && (pa < (dibp->ba + dibp->lnt))) { - dibp->rd (&val, pa, READ); - pi_eval (); - return ((d10) val); } } + dibp->rd (&val, pa, READ); + pi_eval (); + return ((d10) val); } } UBNXM_FAIL (pa, READ); } @@ -386,9 +386,9 @@ DIB *dibp; for (i = 0; dibp = dib_tab[i]; i++ ) { if ((pa >= dibp->ba) && (pa < (dibp->ba + dibp->lnt))) { - dibp->wr ((int32) val, pa, mode); - pi_eval (); - return; } } + dibp->wr ((int32) val, pa, mode); + pi_eval (); + return; } } UBNXM_FAIL (pa, mode); } @@ -414,8 +414,8 @@ lim = ba + bc; for ( ; ba < lim; ba++) { /* by bytes */ pa10 = Map_Addr10 (ba, ub); /* map addr */ if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ + ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ + return (lim - ba); } /* return bc */ *buf++ = (uint8) ((M[pa10] >> ubashf[ba & 3]) & 0377); } return 0; @@ -431,8 +431,8 @@ lim = ba + (bc & ~01); for ( ; ba < lim; ba = ba + 2) { /* by words */ pa10 = Map_Addr10 (ba, ub); /* map addr */ if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ + ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ + return (lim - ba); } /* return bc */ *buf++ = (uint16) ((M[pa10] >> ((ba & 2)? 0: 18)) & 0177777); } return 0; @@ -448,8 +448,8 @@ lim = ba + bc; for ( ; ba < lim; ba++) { /* by bytes */ pa10 = Map_Addr10 (ba, ub); /* map addr */ if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ + ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ + return (lim - ba); } /* return bc */ M[pa10] = (M[pa10] & ~(mask << ubashf[ba & 3])) | (((d10) *buf++) << ubashf[ba & 3]); } return 0; @@ -466,8 +466,8 @@ lim = ba + (bc & ~01); for ( ; ba < lim; ba++) { /* by bytes */ pa10 = Map_Addr10 (ba, ub); /* map addr */ if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ + ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */ + return (lim - ba); } /* return bc */ val = *buf++; /* get data */ if (ba & 2) M[pa10] = (M[pa10] & 0777777600000) | val; else M[pa10] = (M[pa10] & 0600000777777) | (val << 18); @@ -483,9 +483,9 @@ int32 i, lvl; for (i = lvl = 0; i < UBANUM; i++) { if (int_req & ubabr76[i]) - lvl = lvl | pi_l2bit[UBCS_GET_HI (ubcs[i])]; + lvl = lvl | pi_l2bit[UBCS_GET_HI (ubcs[i])]; if (int_req & ubabr54[i]) - lvl = lvl | pi_l2bit[UBCS_GET_LO (ubcs[i])]; } + lvl = lvl | pi_l2bit[UBCS_GET_LO (ubcs[i])]; } return lvl; } @@ -502,15 +502,15 @@ int32 i, masked_irq; for (i = masked_irq = 0; i < UBANUM; i++) { if ((rlvl == UBCS_GET_HI (ubcs[i])) && /* req on hi level? */ - (masked_irq = int_req & ubabr76[i])) break; + (masked_irq = int_req & ubabr76[i])) break; if ((rlvl == UBCS_GET_LO (ubcs[i])) && /* req on lo level? */ - (masked_irq = int_req & ubabr54[i])) break; } + (masked_irq = int_req & ubabr54[i])) break; } *uba = (i << 1) + 1; /* store uba # */ for (i = 0; (i < 32) && masked_irq; i++) { /* find hi pri req */ if ((masked_irq >> i) & 1) { - int_req = int_req & ~(1u << i); /* clear req */ - if (int_ack[i]) return int_ack[i](); - return int_vec[i]; } } /* return vector */ + int_req = int_req & ~(1u << i); /* clear req */ + if (int_ack[i]) return int_ack[i](); + return int_vec[i]; } } /* return vector */ return 0; } diff --git a/PDP10/pdp10_lp20.c b/PDP10/pdp10_lp20.c index 31dd95c0..a3b7b6eb 100644 --- a/PDP10/pdp10_lp20.c +++ b/PDP10/pdp10_lp20.c @@ -272,17 +272,17 @@ update_lpcs (0); /* update csr's */ switch ((pa >> 1) & 07) { /* case on PA<3:1> */ case 00: /* LPCSA */ if (access == WRITEB) data = (pa & 1)? - (lpcsa & 0377) | (data << 8): (lpcsa & ~0377) | data; + (lpcsa & 0377) | (data << 8): (lpcsa & ~0377) | data; if (data & CSA_ECLR) { /* error clear? */ - lpcsa = (lpcsa | CSA_DONE) & ~CSA_GO; /* set done, clr go */ - lpcsb = lpcsb & ~CSB_ECLR; /* clear err */ - sim_cancel (&lp20_unit); } /* cancel I/O */ + lpcsa = (lpcsa | CSA_DONE) & ~CSA_GO; /* set done, clr go */ + lpcsb = lpcsb & ~CSB_ECLR; /* clear err */ + sim_cancel (&lp20_unit); } /* cancel I/O */ if (data & CSA_INIT) lp20_reset (&lp20_dev); /* init? */ if (data & CSA_GO) { /* go set? */ - if ((lpcsa & CSA_GO) == 0) { /* not set before? */ - if (lpcsb & CSB_ERR) lpcsb = lpcsb | CSB_GOE; - lpcsum = 0; /* clear checksum */ - sim_activate (&lp20_unit, lp20_unit.time); } } + if ((lpcsa & CSA_GO) == 0) { /* not set before? */ + if (lpcsb & CSB_ERR) lpcsb = lpcsb | CSB_GOE; + lpcsum = 0; /* clear checksum */ + sim_activate (&lp20_unit, lp20_unit.time); } } else sim_cancel (&lp20_unit); /* go clr, stop DMA */ lpcsa = (lpcsa & ~CSA_RW) | (data & CSA_RW); break; @@ -290,31 +290,32 @@ case 01: /* LPCSB */ break; /* ignore writes to TEST */ case 02: /* LPBA */ if (access == WRITEB) data = (pa & 1)? - (lpba & 0377) | (data << 8): (lpba & ~0377) | data; + (lpba & 0377) | (data << 8): (lpba & ~0377) | data; lpba = data; break; case 03: /* LPBC */ if (access == WRITEB) data = (pa & 1)? - (lpbc & 0377) | (data << 8): (lpbc & ~0377) | data; + (lpbc & 0377) | (data << 8): (lpbc & ~0377) | data; lpbc = data & BC_MASK; lpcsa = lpcsa & ~CSA_DONE; break; case 04: /* LPPAGC */ if (access == WRITEB) data = (pa & 1)? - (lppagc & 0377) | (data << 8): (lppagc & ~0377) | data; + (lppagc & 0377) | (data << 8): (lppagc & ~0377) | data; lppagc = data & PAGC_MASK; break; case 05: /* LPRDAT */ if (access == WRITEB) data = (pa & 1)? - (lprdat & 0377) | (data << 8): (lprdat & ~0377) | data; + (lprdat & 0377) | (data << 8): (lprdat & ~0377) | data; lprdat = data & RDAT_MASK; txram[lpcbuf & TX_AMASK] = lprdat; /* load RAM */ break; case 06: /* LPCOLC/LPCBUF */ if ((access == WRITEB) && (pa & 1)) /* odd byte */ - lpcolc = data & 0377; - else { lpcbuf = data & 0377; /* even byte, word */ - if (access == WRITE) lpcolc = (data >> 8) & 0377; } + lpcolc = data & 0377; + else { + lpcbuf = data & 0377; /* even byte, word */ + if (access == WRITE) lpcolc = (data >> 8) & 0377; } break; case 07: /* LPCSUM/LPPDAT */ break; } /* read only */ @@ -371,9 +372,9 @@ if ((fnc == FNC_PR) && (dvlnt == 0)) { for (i = 0, cont = TRUE; (i < tbc) && cont; ba++, i++) { if (Map_ReadW (ba, 2, &wd10, MAP)) { /* get word, err? */ - lpcsb = lpcsb | CSB_MTE; /* set NXM error */ - update_lpcs (CSA_ERR); /* set done */ - break; } + lpcsb = lpcsb | CSB_MTE; /* set NXM error */ + update_lpcs (CSA_ERR); /* set done */ + break; } lpcbuf = (wd10 >> ((ba & 1)? 8: 0)) & 0377; /* get character */ lpcsum = (lpcsum + lpcbuf) & 0377; /* add into checksum */ switch (fnc) { /* switch on function */ @@ -381,8 +382,8 @@ for (i = 0, cont = TRUE; (i < tbc) && cont; ba++, i++) { /* Translation RAM load */ case FNC_RAM: /* RAM load */ - txram[(i >> 1) & TX_AMASK] = wd10 & TX_DMASK; - break; + txram[(i >> 1) & TX_AMASK] = wd10 & TX_DMASK; + break; /* DAVFU RAM load. The DAVFU RAM is actually loaded in bytes, delimited by a start (354 to 356) and stop (357) byte pair. If the number of bytes @@ -390,48 +391,48 @@ for (i = 0, cont = TRUE; (i < tbc) && cont; ba++, i++) { */ case FNC_DVU: /* DVU load */ - if ((lpcbuf >= 0354) && (lpcbuf <= 0356)) /* start DVU load? */ - dvld = dvlnt = 0; /* reset lnt */ - else if (lpcbuf == 0357) { /* stop DVU load? */ - dvptr = 0; /* reset ptr */ - if (dvld & 1) dvlnt = 0; } /* if odd, invalid */ - else if (dvld == 0) { /* even state? */ - temp = lpcbuf & DV_DMASK; - dvld = 1; } - else if (dvld == 1) { /* odd state? */ - if (dvlnt < DV_SIZE) davfu[dvlnt++] = - temp | ((lpcbuf & DV_DMASK) << 6); - dvld = 0; } - break; + if ((lpcbuf >= 0354) && (lpcbuf <= 0356)) /* start DVU load? */ + dvld = dvlnt = 0; /* reset lnt */ + else if (lpcbuf == 0357) { /* stop DVU load? */ + dvptr = 0; /* reset ptr */ + if (dvld & 1) dvlnt = 0; } /* if odd, invalid */ + else if (dvld == 0) { /* even state? */ + temp = lpcbuf & DV_DMASK; + dvld = 1; } + else if (dvld == 1) { /* odd state? */ + if (dvlnt < DV_SIZE) davfu[dvlnt++] = + temp | ((lpcbuf & DV_DMASK) << 6); + dvld = 0; } + break; /* Print characters */ case FNC_PR: /* print */ - lprdat = txram[lpcbuf]; /* get RAM char */ - txst = (TX_GETFL (lprdat) << 1) | /* get state */ - ((lpcsa & CSA_DELH)? 1: 0); /* plus delim hold */ - if (lprdat & TX_DELH) lpcsa = lpcsa | CSA_DELH; - else lpcsa = lpcsa & ~CSA_DELH; - lpcsa = lpcsa & ~CSA_UNDF; /* assume char ok */ - switch (txcase[txst]) { /* case on state */ - case TX_CHR: /* take char */ - cont = lp20_print (lpcbuf); - break; - case TX_RAM: /* take translation */ - cont = lp20_print (lprdat); - break; - case TX_DVU: /* DAVFU action */ - if (lprdat & TX_SLEW) - cont = lp20_adv (lprdat & TX_VMASK, TRUE); - else cont = lp20_davfu (lprdat & TX_VMASK); - break; - case TX_INT: /* interrupt */ - lpcsa = lpcsa | CSA_UNDF; /* set flag */ - cont = FALSE; /* force stop */ - break; } /* end case char state */ + lprdat = txram[lpcbuf]; /* get RAM char */ + txst = (TX_GETFL (lprdat) << 1) | /* get state */ + ((lpcsa & CSA_DELH)? 1: 0); /* plus delim hold */ + if (lprdat & TX_DELH) lpcsa = lpcsa | CSA_DELH; + else lpcsa = lpcsa & ~CSA_DELH; + lpcsa = lpcsa & ~CSA_UNDF; /* assume char ok */ + switch (txcase[txst]) { /* case on state */ + case TX_CHR: /* take char */ + cont = lp20_print (lpcbuf); break; + case TX_RAM: /* take translation */ + cont = lp20_print (lprdat); + break; + case TX_DVU: /* DAVFU action */ + if (lprdat & TX_SLEW) + cont = lp20_adv (lprdat & TX_VMASK, TRUE); + else cont = lp20_davfu (lprdat & TX_VMASK); + break; + case TX_INT: /* interrupt */ + lpcsa = lpcsa | CSA_UNDF; /* set flag */ + cont = FALSE; /* force stop */ + break; } /* end case char state */ + break; case FNC_TST: /* test */ - break; } /* end case function */ + break; } /* end case function */ } /* end for */ lpba = ba & 0177777; lpcsa = (lpcsa & ~CSA_UAE) | ((ba >> (16 - CSA_V_UAE)) & CSA_UAE); @@ -467,12 +468,12 @@ if (lppdat == 015) lpcolc = 0; /* CR? reset col cntr */ else if (lppdat == 011) { /* TAB? simulate */ lppdat = ' '; /* with spaces */ if (lpcolc >= 128) { - r = lp20_adv (1, TRUE); /* eol? adv carriage */ - rpt = 8; } /* adv to col 9 */ + r = lp20_adv (1, TRUE); /* eol? adv carriage */ + rpt = 8; } /* adv to col 9 */ else rpt = 8 - (lpcolc & 07); } /* else adv 1 to 8 */ else { if (lppdat < 040) lppdat = ' '; /* cvt non-prnt to spc */ if (lpcolc >= LP_WIDTH) /* line full? */ - r = lp20_adv (1, TRUE); } /* adv carriage */ + r = lp20_adv (1, TRUE); } /* adv carriage */ for (i = 0; i < rpt; i++) putc (lppdat, lp20_unit.fileref); lp20_unit.pos = lp20_unit.pos + rpt; lpcolc = lpcolc + rpt; @@ -490,10 +491,11 @@ lp20_unit.pos = lp20_unit.pos + cnt; /* print 'n' newlines */ if (dvuadv) dvptr = (dvptr + cnt) % dvlnt; /* update DAVFU ptr */ if (davfu[dvptr] & (1 << DV_TOF)) { /* at top of form? */ if (lppagc = (lppagc - 1) & PAGC_MASK) { /* decr page cntr */ - lpcsa = lpcsa & ~CSA_PZRO; /* update status */ - return TRUE; } - else { lpcsa = lpcsa | CSA_PZRO; /* stop if zero */ - return FALSE; } } + lpcsa = lpcsa & ~CSA_PZRO; /* update status */ + return TRUE; } + else { + lpcsa = lpcsa | CSA_PZRO; /* stop if zero */ + return FALSE; } } return TRUE; } @@ -506,15 +508,16 @@ for (i = 0; i < dvlnt; i++) { /* search DAVFU */ dvptr = dvptr + 1; /* adv DAVFU ptr */ if (dvptr >= dvlnt) dvptr = 0; /* wrap at end */ if (davfu[dvptr] & (1 << cnt)) { /* channel stop set? */ - if (cnt) return lp20_adv (i + 1, FALSE); /* ~TOF, adv */ - if (lpcolc) lp20_adv (1, FALSE); /* TOF, need newline? */ - putc ('\f', lp20_unit.fileref); /* print form feed */ - lp20_unit.pos = lp20_unit.pos + 1; - if (lppagc = (lppagc - 1) & PAGC_MASK) { /* decr page cntr */ - lpcsa = lpcsa & ~CSA_PZRO; /* update status */ - return TRUE; } - else { lpcsa = lpcsa | CSA_PZRO; /* stop if zero */ - return FALSE; } } + if (cnt) return lp20_adv (i + 1, FALSE); /* ~TOF, adv */ + if (lpcolc) lp20_adv (1, FALSE); /* TOF, need newline? */ + putc ('\f', lp20_unit.fileref); /* print form feed */ + lp20_unit.pos = lp20_unit.pos + 1; + if (lppagc = (lppagc - 1) & PAGC_MASK) { /* decr page cntr */ + lpcsa = lpcsa & ~CSA_PZRO; /* update status */ + return TRUE; } + else { + lpcsa = lpcsa | CSA_PZRO; /* stop if zero */ + return FALSE; } } } /* end for */ dvlnt = 0; /* DAVFU error */ return FALSE; diff --git a/PDP10/pdp10_mdfp.c b/PDP10/pdp10_mdfp.c index a822b077..f5e4a830 100644 --- a/PDP10/pdp10_mdfp.c +++ b/PDP10/pdp10_mdfp.c @@ -245,12 +245,12 @@ if (dvd[0] >= dvr) { /* divide fail? */ return FALSE; } if (dvd[0] & FIT27) { /* fit in 63b? */ for (i = 0, rs[0] = 0; i < 35; i++) { /* 35 quotient bits */ - dvd[0] = (dvd[0] << 1) | ((dvd[1] >> 34) & 1); - dvd[1] = (dvd[1] << 1) & MMASK; /* shift dividend */ - rs[0] = rs[0] << 1; /* shift quotient */ - if (dvd[0] >= dvr) { /* subtract work? */ - dvd[0] = dvd[0] - dvr; /* quo bit is 1 */ - rs[0] = rs[0] + 1; } } + dvd[0] = (dvd[0] << 1) | ((dvd[1] >> 34) & 1); + dvd[1] = (dvd[1] << 1) & MMASK; /* shift dividend */ + rs[0] = rs[0] << 1; /* shift quotient */ + if (dvd[0] >= dvr) { /* subtract work? */ + dvd[0] = dvd[0] - dvr; /* quo bit is 1 */ + rs[0] = rs[0] + 1; } } rs[1] = dvd[0]; } /* store remainder */ else { t = (dvd[0] << 35) | dvd[1]; /* concatenate */ rs[0] = t / dvr; /* quotient */ @@ -282,16 +282,16 @@ AC(ac) = AC(p1) = AC(p2) = AC(p3) = 0; /* clear AC's */ if (((mpy[0] | mpy[1]) == 0) || ((mpc[0] | mpc[1]) == 0)) return; for (i = 0; i < 71; i++) { /* 71 mpyer bits */ if (i) { /* shift res, mpy */ - AC(p3) = (AC(p3) >> 1) | ((AC(p2) & 1) << 34); - AC(p2) = (AC(p2) >> 1) | ((AC(p1) & 1) << 34); - AC(p1) = (AC(p1) >> 1) | ((AC(ac) & 1) << 34); - AC(ac) = AC(ac) >> 1; - mpy[1] = (mpy[1] >> 1) | ((mpy[0] & 1) << 34); - mpy[0] = mpy[0] >> 1; } + AC(p3) = (AC(p3) >> 1) | ((AC(p2) & 1) << 34); + AC(p2) = (AC(p2) >> 1) | ((AC(p1) & 1) << 34); + AC(p1) = (AC(p1) >> 1) | ((AC(ac) & 1) << 34); + AC(ac) = AC(ac) >> 1; + mpy[1] = (mpy[1] >> 1) | ((mpy[0] & 1) << 34); + mpy[0] = mpy[0] >> 1; } if (mpy[1] & 1) { /* if mpy lo bit = 1 */ - AC(p1) = AC(p1) + mpc[1]; - AC(ac) = AC(ac) + mpc[0] + (TSTS (AC(p1) != 0)); - AC(p1) = CLRS (AC(p1)); } } + AC(p1) = AC(p1) + mpc[1]; + AC(ac) = AC(ac) + mpc[0] + (TSTS (AC(p1) != 0)); + AC(p1) = CLRS (AC(p1)); } } if (TSTS (sign)) { /* result minus? */ AC(p3) = (-AC(p3)) & MMASK; /* quad negate */ AC(p2) = (~AC(p2) + (AC(p3) == 0)) & MMASK; @@ -317,8 +317,8 @@ for (i = 1; i < 4; i++) dvd[i] = CLRS (AC(ADDAC (ac, i))); sign = AC(ac) ^ dvr[0]; /* sign of result */ if (TSTS (AC(ac))) { /* get abs (dividend) */ for (i = 3, cryin = 1; i > 0; i--) { /* negate quad */ - dvd[i] = (~dvd[i] + cryin) & MMASK; /* comp + carry in */ - if (dvd[i]) cryin = 0; } /* next carry in */ + dvd[i] = (~dvd[i] + cryin) & MMASK; /* comp + carry in */ + if (dvd[i]) cryin = 0; } /* next carry in */ dvd[0] = (~dvd[0] + cryin) & DMASK; } if (TSTS (dvr[0])) { DMOVN (dvr); } /* get abs (divisor) */ else dvr[1] = CLRS (dvr[1]); @@ -334,9 +334,9 @@ for (i = 0; i < 70; i++) { /* 70 quotient bits */ qu[0] = (qu[0] << 1) | ((qu[1] >> 34) & 1); /* shift quotient */ qu[1] = (qu[1] << 1) & MMASK; if (DCMPGE (dvd, dvr)) { /* subtract work? */ - dvd[0] = dvd[0] - dvr[0] - (dvd[1] < dvr[1]); - dvd[1] = (dvd[1] - dvr[1]) & MMASK; /* do subtract */ - qu[1] = qu[1] + 1; } } /* set quotient bit */ + dvd[0] = dvd[0] - dvr[0] - (dvd[1] < dvr[1]); + dvd[1] = (dvd[1] - dvr[1]) & MMASK; /* do subtract */ + qu[1] = qu[1] + 1; } } /* set quotient bit */ if (TSTS (sign) && (qu[0] | qu[1])) { MKDNEG (qu); } if (TSTS (AC(ac)) && (dvd[0] | dvd[1])) { MKDNEG (dvd); } AC(ac) = qu[0]; /* quotient */ @@ -369,22 +369,23 @@ else { funpack (op1, 0, &a, SFRC); /* unpack operands */ funpack (op2, 0, &b, SFRC); /* fracs are 2's comp */ ediff = a.exp - b.exp; /* get exp diff */ if (ediff < 0) { /* a < b? switch */ - t = a; - a = b; - b = t; - ediff = -ediff; } + t = a; + a = b; + b = t; + ediff = -ediff; } if (ediff > 63) ediff = 63; /* cap diff at 63 */ if (ediff) b.fhi = (t_int64) b.fhi >> ediff; /* shift b (signed) */ a.fhi = a.fhi + b.fhi; /* add fractions */ if (a.sign ^ b.sign) { /* add or subtract? */ - if (a.fhi & FP_UCRY) { /* subtract, frac -? */ - a.fhi = UNEG (a.fhi); /* complement result */ - a.sign = 1; } /* result is - */ - else a.sign = 0; } /* result is + */ - else { if (a.sign) a.fhi = UNEG (a.fhi); /* add, src -? comp */ - if (a.fhi & FP_UCRY) { /* check for carry */ - a.fhi = a.fhi >> 1; /* flo won't be used */ - a.exp = a.exp + 1; } } } + if (a.fhi & FP_UCRY) { /* subtract, frac -? */ + a.fhi = UNEG (a.fhi); /* complement result */ + a.sign = 1; } /* result is - */ + else a.sign = 0; } /* result is + */ + else { + if (a.sign) a.fhi = UNEG (a.fhi); /* add, src -? comp */ + if (a.fhi & FP_UCRY) { /* check for carry */ + a.fhi = a.fhi >> 1; /* flo won't be used */ + a.exp = a.exp + 1; } } } fnorm (&a, (rnd? FP_URNDS: 0)); /* normalize, round */ return fpack (&a, NULL, FALSE); } @@ -434,11 +435,11 @@ if (savhi = a.fhi) { /* dvd = 0? quo = 0 */ a.exp = a.exp - b.exp + FP_BIAS + 1; /* result exponent */ a.fhi = a.fhi / (b.fhi >> (FP_N_FHI + 1)); /* do divide */ if (a.sign && (savhi != (a.fhi * (b.fhi >> (FP_N_FHI + 1))))) - rem = TRUE; /* KL/KS hack */ + rem = TRUE; /* KL/KS hack */ a.fhi = a.fhi << (FP_V_UNORM - FP_N_FHI - 1); /* put quo in place */ if ((a.fhi & FP_UNORM) == 0) { /* normalize 1b */ - a.fhi = a.fhi << 1; /* before masking */ - a.exp = a.exp - 1; } + a.fhi = a.fhi << 1; /* before masking */ + a.exp = a.exp - 1; } a.fhi = a.fhi & (FP_UFHI | FP_URNDS); } /* mask quo to 28b */ fnorm (&a, (rnd? FP_URNDS: 0)); /* normalize, round */ *rs = fpack (&a, NULL, rem); /* pack result */ @@ -489,8 +490,8 @@ else if (a.exp < (FP_BIAS - 1)) AC(ac) = 0; else { sc = FP_V_UNORM - (a.exp - FP_BIAS) + 1; AC(ac) = a.fhi >> sc; if (rnd) { - so = a.fhi << (64 - sc); - if (so >= (0x8000000000000000 + a.sign)) AC(ac) = AC(ac) + 1; } + so = a.fhi << (64 - sc); + if (so >= (0x8000000000000000 + a.sign)) AC(ac) = AC(ac) + 1; } if (a.sign) AC(ac) = NEG (AC(ac)); } return; } @@ -508,35 +509,36 @@ UFP a, b, t; if (inv) { DMOVN (rs); } /* subtract? -b */ if ((AC(ac) | AC(p1)) == 0) funpack (rs[0], rs[1], &a, AFRC); - /* a == 0? sum = b */ + /* a == 0? sum = b */ else if ((rs[0] | rs[1]) == 0) funpack (AC(ac), AC(p1), &a, AFRC); - /* b == 0? sum = a */ + /* b == 0? sum = a */ else { funpack (AC(ac), AC(p1), &a, SFRC); /* unpack operands */ funpack (rs[0], rs[1], &b, SFRC); ediff = a.exp - b.exp; /* get exp diff */ if (ediff < 0) { /* a < b? switch */ - t = a; - a = b; - b = t; - ediff = -ediff; } + t = a; + a = b; + b = t; + ediff = -ediff; } if (ediff > 127) ediff = 127; /* cap diff at 127 */ if (ediff > 63) { /* diff > 63? */ - a.flo = (t_int64) b.fhi >> (ediff - 64); /* b hi to a lo */ - b.fhi = b.sign? FP_ONES: 0; } /* hi = all sign */ + a.flo = (t_int64) b.fhi >> (ediff - 64); /* b hi to a lo */ + b.fhi = b.sign? FP_ONES: 0; } /* hi = all sign */ else if (ediff) { /* diff <= 63 */ - a.flo = (b.flo >> ediff) | (b.fhi << (64 - ediff)); - b.fhi = (t_int64) b.fhi >> ediff; } /* shift b (signed) */ + a.flo = (b.flo >> ediff) | (b.fhi << (64 - ediff)); + b.fhi = (t_int64) b.fhi >> ediff; } /* shift b (signed) */ a.fhi = a.fhi + b.fhi; /* do add */ if (a.sign ^ b.sign) { /* add or subtract? */ - if (a.fhi & FP_UCRY) { /* subtract, frac -? */ - DUNEG (a); /* complement result */ - a.sign = 1; } /* result is - */ - else a.sign = 0; } /* result is + */ - else { if (a.sign) { DUNEG (a); }; /* add, src -? comp */ - if (a.fhi & FP_UCRY) { /* check for carry */ - a.fhi = a.fhi >> 1; /* flo won't be used */ - a.exp = a.exp + 1; } } } + if (a.fhi & FP_UCRY) { /* subtract, frac -? */ + DUNEG (a); /* complement result */ + a.sign = 1; } /* result is - */ + else a.sign = 0; } /* result is + */ + else { + if (a.sign) { DUNEG (a); }; /* add, src -? comp */ + if (a.fhi & FP_UCRY) { /* check for carry */ + a.fhi = a.fhi >> 1; /* flo won't be used */ + a.exp = a.exp + 1; } } } fnorm (&a, FP_URNDD); /* normalize, round */ AC(ac) = fpack (&a, &AC(p1), FALSE); /* pack result */ return; @@ -600,14 +602,14 @@ if (a.fhi) { /* dvd = 0? quo = 0 */ a.sign = a.sign ^ b.sign; /* result sign */ a.exp = a.exp - b.exp + FP_BIAS + 1; /* result exponent */ if (a.fhi < b.fhi) { /* make sure initial */ - a.fhi = a.fhi << 1; /* divide step will work */ - a.exp = a.exp - 1; } + a.fhi = a.fhi << 1; /* divide step will work */ + a.exp = a.exp - 1; } for (i = 0; i < 63; i++) { /* 63b of quotient */ - qu = qu << 1; /* shift quotient */ - if (a.fhi >= b.fhi) { /* will div work? */ - a.fhi = a.fhi - b.fhi; /* sub, quo = 1 */ - qu = qu + 1; } - a.fhi = a.fhi << 1; } /* shift dividend */ + qu = qu << 1; /* shift quotient */ + if (a.fhi >= b.fhi) { /* will div work? */ + a.fhi = a.fhi - b.fhi; /* sub, quo = 1 */ + qu = qu + 1; } + a.fhi = a.fhi << 1; } /* shift dividend */ a.fhi = qu; } fnorm (&a, FP_URNDD); /* normalize, round */ AC(ac) = fpack (&a, &AC(p1), FALSE); /* pack result */ @@ -629,9 +631,11 @@ r->flo = 0; if (r->sign) { r->exp = r->exp ^ FP_M_EXP; if (sgn) r->fhi = r->fhi | FP_UCRY; /* ext sign */ - else { if (r->fhi) r->fhi = UNEG (r->fhi) & FP_UFRAC; - else { r->exp = r->exp + 1; - r->fhi = FP_UNORM; } } } + else { + if (r->fhi) r->fhi = UNEG (r->fhi) & FP_UFRAC; + else { + r->exp = r->exp + 1; + r->fhi = FP_UNORM; } } } return; } @@ -650,15 +654,15 @@ if ((a->fhi | a->flo) == 0) { /* if fraction = 0 */ return; } while ((a->fhi & FP_UNORM) == 0) { /* normalized? */ for (i = 0; i < 6; i++) { - if (a->fhi & normmask[i]) break; } + if (a->fhi & normmask[i]) break; } a->fhi = (a->fhi << normtab[i]) | (a->flo >> (64 - normtab[i])); a->flo = a->flo << normtab[i]; a->exp = a->exp - normtab[i]; } if (rnd) { /* rounding? */ a->fhi = a->fhi + rnd; /* add round const */ if (a->fhi & FP_UCRY) { /* if carry out, */ - a->fhi = a->fhi >> 1; /* renormalize */ - a->exp = a->exp + 1; } } + a->fhi = a->fhi >> 1; /* renormalize */ + a->exp = a->exp + 1; } } return; } @@ -676,8 +680,8 @@ if (lo) val[1] = ((r->fhi & FP_UFLO) >> FP_V_UFLO) & MMASK; else val[1] = 0; if (r->sign) { /* negate? */ if (fdvneg) { /* fdvr special? */ - val[1] = ~val[1] & MMASK; /* 1's comp */ - val[0] = ~val[0] & DMASK; } + val[1] = ~val[1] & MMASK; /* 1's comp */ + val[0] = ~val[0] & DMASK; } else { DMOVN (val); } } /* 2's comp */ if (lo) *lo = val[1]; return val[0]; diff --git a/PDP10/pdp10_pag.c b/PDP10/pdp10_pag.c index a4be66d2..f008ba63 100644 --- a/PDP10/pdp10_pag.c +++ b/PDP10/pdp10_pag.c @@ -306,24 +306,24 @@ if (ITS) { /* ITS paging */ vpn = ITS_GETVPN (ea); /* get ITS pagno */ if (tbl == uptbl) - ptead = ((ea & RSIGN)? dbr2: dbr1) + ((vpn >> 1) & 077); + ptead = ((ea & RSIGN)? dbr2: dbr1) + ((vpn >> 1) & 077); else ptead = ((ea & RSIGN)? dbr3: dbr4) + ((vpn >> 1) & 077); ptewd = ReadP (ptead); /* get PTE pair */ pte = (int32) ((ptewd >> ((vpn & 1)? 0: 18)) & RMASK); acc = ITS_GETACC (pte); /* get access */ pager_word = PF_VIRT | ea | ((tbl == uptbl)? PF_USER: 0) | - ((mode & PTF_WR)? PF_ITS_WRITE: 0) | (acc << PF_ITS_V_ACC); + ((mode & PTF_WR)? PF_ITS_WRITE: 0) | (acc << PF_ITS_V_ACC); if ((acc != ITS_ACC_NO) && (!(mode & PTF_WR) || (acc == ITS_ACC_RW))) { - pte = pte & ~PTE_ITS_AGE; /* clear age */ - if (vpn & 1) WriteP (ptead, (ptewd & LMASK) | pte); - else WriteP (ptead, (ptewd & RMASK) | (((d10) pte) << 18)); - xpte = ((pte & PTE_ITS_PPMASK) << ITS_V_PN) | PTBL_V | - ((acc == ITS_ACC_RW)? PTBL_M: 0); - decvpn = PAG_GETVPN (ea); /* get tlb idx */ - if (!(mode & PTF_CON)) { - tbl[decvpn & ~1] = xpte; /* map lo ITS page */ - tbl[decvpn | 1] = xpte + PAG_SIZE; } /* map hi */ - return (xpte + ((decvpn & 1)? PAG_SIZE: 0)); } + pte = pte & ~PTE_ITS_AGE; /* clear age */ + if (vpn & 1) WriteP (ptead, (ptewd & LMASK) | pte); + else WriteP (ptead, (ptewd & RMASK) | (((d10) pte) << 18)); + xpte = ((pte & PTE_ITS_PPMASK) << ITS_V_PN) | PTBL_V | + ((acc == ITS_ACC_RW)? PTBL_M: 0); + decvpn = PAG_GETVPN (ea); /* get tlb idx */ + if (!(mode & PTF_CON)) { + tbl[decvpn & ~1] = xpte; /* map lo ITS page */ + tbl[decvpn | 1] = xpte + PAG_SIZE; } /* map hi */ + return (xpte + ((decvpn & 1)? PAG_SIZE: 0)); } PAGE_FAIL_TRAP; } /* end ITS paging */ @@ -349,14 +349,14 @@ else if (!T20) { /* TOPS-10 paging */ pager_word = PF_VIRT | ea | ((tbl == uptbl)? PF_USER: 0) | ((mode & PTF_WR)? PF_WRITE: 0) | ((pte & PTE_T10_A)? PF_T10_A | - ((pte & PTE_T10_S)? PF_T10_S: 0): 0); + ((pte & PTE_T10_S)? PF_T10_S: 0): 0); if (mode & PTF_MAP) pager_word = pager_word | /* map? add to pf wd */ ((pte & PTE_T10_W)? PF_T10_W: 0) | /* W, S, C bits */ ((pte & PTE_T10_S)? PF_T10_S: 0) | ((pte & PTE_T10_C)? PF_C: 0); if ((pte & PTE_T10_A) && (!(mode & PTF_WR) || (pte & PTE_T10_W))) { xpte = ((pte & PTE_PPMASK) << PAG_V_PN) | /* calc exp pte */ - PTBL_V | ((pte & PTE_T10_W)? PTBL_M: 0); + PTBL_V | ((pte & PTE_T10_W)? PTBL_M: 0); if (!(mode & PTF_CON)) tbl[vpn] = xpte; /* set tbl if ~cons */ return xpte; } PAGE_FAIL_TRAP; @@ -389,7 +389,7 @@ else { /* TOPS-20 paging */ d10 acc = PTE_T20_W | PTE_T20_C; /* init access bits */ pager_word = PF_VIRT | ea | ((tbl == uptbl)? PF_USER: 0) | - ((mode & PTF_WR)? PF_WRITE: 0); /* set page fail word */ + ((mode & PTF_WR)? PF_WRITE: 0); /* set page fail word */ /* First phase - evaluate section pointers - returns a ptr to a page map As a single section machine, the KS10 short circuits this part of the @@ -411,90 +411,90 @@ else { /* TOPS-20 paging */ pa = (tbl == uptbl)? upta + UPT_T20_SCTN: epta + EPT_T20_SCTN; READPT (ptr, pa & PAMASK); /* get section 0 ptr */ for (stop = FALSE, flg = 0; !stop; flg++) { /* eval section ptrs */ - acc = acc & ptr; /* cascade acc bits */ - switch (T20_GETTYP (ptr)) { /* case on ptr type */ - case T20_NOA: /* no access */ - default: /* undefined type */ - PAGE_FAIL_TRAP; /* page fail */ - case T20_IMM: /* immediate */ - stop = TRUE; /* exit */ - break; - case T20_SHR: /* shared */ - pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ - READPT (ptr, pa & PAMASK); /* get SPT entry */ - stop = TRUE; /* exit */ - break; - case T20_IND: /* indirect */ - if (flg && (t = test_int ())) ABORT (t); - pmi = T20_GETPMI (ptr); /* get sect tbl idx */ - pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ - if (pmi) { /* for dskec */ - pag_nxm ((pmi << 18) | pa, REF_P, PF_OK); - PAGE_FAIL_TRAP; } - READPT (ptr, pa & PAMASK); /* get SPT entry */ - if (ptr & PTE_T20_STM) { PAGE_FAIL_TRAP; } - pa = PAG_PTEPA (ptr, pmi); /* index off page */ - READPT (ptr, pa & PAMASK); /* get pointer */ - break; /* continue in loop */ - } /* end case */ - } /* end for */ + acc = acc & ptr; /* cascade acc bits */ + switch (T20_GETTYP (ptr)) { /* case on ptr type */ + case T20_NOA: /* no access */ + default: /* undefined type */ + PAGE_FAIL_TRAP; /* page fail */ + case T20_IMM: /* immediate */ + stop = TRUE; /* exit */ + break; + case T20_SHR: /* shared */ + pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ + READPT (ptr, pa & PAMASK); /* get SPT entry */ + stop = TRUE; /* exit */ + break; + case T20_IND: /* indirect */ + if (flg && (t = test_int ())) ABORT (t); + pmi = T20_GETPMI (ptr); /* get sect tbl idx */ + pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ + if (pmi) { /* for dskec */ + pag_nxm ((pmi << 18) | pa, REF_P, PF_OK); + PAGE_FAIL_TRAP; } + READPT (ptr, pa & PAMASK); /* get SPT entry */ + if (ptr & PTE_T20_STM) { PAGE_FAIL_TRAP; } + pa = PAG_PTEPA (ptr, pmi); /* index off page */ + READPT (ptr, pa & PAMASK); /* get pointer */ + break; /* continue in loop */ + } /* end case */ + } /* end for */ /* Second phase - found page map ptr, evaluate page pointers */ pa = PAG_PTEPA (ptr, vpn); /* get ptbl address */ for (stop = FALSE, flg = 0; !stop; flg++) { /* eval page ptrs */ - if (ptr & PTE_T20_STM) { PAGE_FAIL_TRAP; } /* non-res? */ - if (cst) { /* cst really there? */ - csta = (int32) ((cst + (ptr & PTE_PPMASK)) & PAMASK); - READPT (cste, csta); /* get CST entry */ - if ((cste & CST_AGE) == 0) { PAGE_FAIL_TRAP; } - cste = (cste & cstm) | pur; /* update entry */ - WriteP (csta, cste); } /* rewrite */ - READPT (ptr, pa & PAMASK); /* get pointer */ - acc = acc & ptr; /* cascade acc bits */ - switch (T20_GETTYP (ptr)) { /* case on ptr type */ - case T20_NOA: /* no access */ - default: /* undefined type */ - PAGE_FAIL_TRAP; /* page fail */ - case T20_IMM: /* immediate */ - stop = TRUE; /* exit */ - break; - case T20_SHR: /* shared */ - pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ - READPT (ptr, pa & PAMASK); /* get SPT entry */ - stop = TRUE; /* exit */ - break; - case T20_IND: /* indirect */ - if (flg && (t = test_int ())) ABORT (t); - pmi = T20_GETPMI (ptr); /* get section index */ - pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ - READPT (ptr, pa & PAMASK); /* get SPT entry */ - pa = PAG_PTEPA (ptr, pmi); /* index off page */ - break; /* continue in loop */ - } /* end case */ - } /* end for */ + if (ptr & PTE_T20_STM) { PAGE_FAIL_TRAP; } /* non-res? */ + if (cst) { /* cst really there? */ + csta = (int32) ((cst + (ptr & PTE_PPMASK)) & PAMASK); + READPT (cste, csta); /* get CST entry */ + if ((cste & CST_AGE) == 0) { PAGE_FAIL_TRAP; } + cste = (cste & cstm) | pur; /* update entry */ + WriteP (csta, cste); } /* rewrite */ + READPT (ptr, pa & PAMASK); /* get pointer */ + acc = acc & ptr; /* cascade acc bits */ + switch (T20_GETTYP (ptr)) { /* case on ptr type */ + case T20_NOA: /* no access */ + default: /* undefined type */ + PAGE_FAIL_TRAP; /* page fail */ + case T20_IMM: /* immediate */ + stop = TRUE; /* exit */ + break; + case T20_SHR: /* shared */ + pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ + READPT (ptr, pa & PAMASK); /* get SPT entry */ + stop = TRUE; /* exit */ + break; + case T20_IND: /* indirect */ + if (flg && (t = test_int ())) ABORT (t); + pmi = T20_GETPMI (ptr); /* get section index */ + pa = (int32) (spt + (ptr & RMASK)); /* get SPT idx */ + READPT (ptr, pa & PAMASK); /* get SPT entry */ + pa = PAG_PTEPA (ptr, pmi); /* index off page */ + break; /* continue in loop */ + } /* end case */ + } /* end for */ /* Last phase - have final page pointer, check modifiability */ if (ptr & PTE_T20_STM) { PAGE_FAIL_TRAP; } /* non-resident? */ if (cst) { /* CST really there? */ - csta = (int32) ((cst + (ptr & PTE_PPMASK)) & PAMASK); - READPT (cste, csta); /* get CST entry */ - if ((cste & CST_AGE) == 0) { PAGE_FAIL_TRAP; } - cste = (cste & cstm) | pur; } /* update entry */ + csta = (int32) ((cst + (ptr & PTE_PPMASK)) & PAMASK); + READPT (cste, csta); /* get CST entry */ + if ((cste & CST_AGE) == 0) { PAGE_FAIL_TRAP; } + cste = (cste & cstm) | pur; } /* update entry */ else cste = 0; /* no, entry = 0 */ pager_word = pager_word | PF_T20_DN; /* set eval done */ xpte = ((int32) ((ptr & PTE_PPMASK) << PAG_V_PN)) | PTBL_V; if (mode & PTF_WR) { /* write? */ - if (acc & PTE_T20_W) { /* writable? */ - xpte = xpte | PTBL_M; /* set PTE M */ - cste = cste | CST_M; } /* set CST M */ - else { PAGE_FAIL_TRAP; } } /* no, trap */ + if (acc & PTE_T20_W) { /* writable? */ + xpte = xpte | PTBL_M; /* set PTE M */ + cste = cste | CST_M; } /* set CST M */ + else { PAGE_FAIL_TRAP; } } /* no, trap */ if (cst) WriteP (csta, cste); /* write CST entry */ if (mode & PTF_MAP) pager_word = pager_word | /* map? more in pf wd */ - ((xpte & PTBL_M)? PF_T20_M: 0) | /* M, W, C bits */ - ((acc & PTE_T20_W)? PF_T20_W: 0) | - ((acc & PTE_T20_C)? PF_C: 0); + ((xpte & PTBL_M)? PF_T20_M: 0) | /* M, W, C bits */ + ((acc & PTE_T20_W)? PF_T20_W: 0) | + ((acc & PTE_T20_C)? PF_C: 0); if (!(mode & PTF_CON)) tbl[vpn] = xpte; /* set tbl if ~cons */ return xpte; } /* end TOPS20 paging */ @@ -510,8 +510,9 @@ if (PAGING) { ac_cur = &acs[UBR_GETCURAC (ubr) * AC_NUM]; ac_prv = &acs[UBR_GETPRVAC (ubr) * AC_NUM]; if (TSTF (F_USR)) ptbl_cur = ptbl_prv = &uptbl[0]; - else { ptbl_cur = &eptbl[0]; - ptbl_prv = TSTF (F_UIO)? &uptbl[0]: &eptbl[0]; } } + else { + ptbl_cur = &eptbl[0]; + ptbl_prv = TSTF (F_UIO)? &uptbl[0]: &eptbl[0]; } } else { ac_cur = ac_prv = &acs[0]; ptbl_cur = ptbl_prv = &physptbl[0]; } t = EBR_GETEBR (ebr); diff --git a/PDP10/pdp10_rp.c b/PDP10/pdp10_rp.c index 2d9e99db..f1794119 100644 --- a/PDP10/pdp10_rp.c +++ b/PDP10/pdp10_rp.c @@ -508,7 +508,7 @@ case 006: /* RPER1 */ case 007: /* RPAS */ *data = 0; for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) *data = *data | (AS_U0 << i); + if (rpds[i] & DS_ATA) *data = *data | (AS_U0 << i); break; case 010: /* RPLA */ *data = GET_SECTOR (rp_rwait, dtype) << LA_V_SC; @@ -575,50 +575,51 @@ switch (j) { /* decode PA<5:1> */ case 000: /* RPCS1 */ if ((access == WRITEB) && (PA & 1)) data = data << 8; if (data & CS1_TRE) { /* error clear? */ - rpcs1 = rpcs1 & ~CS1_TRE; /* clr CS1 */ - rpcs2 = rpcs2 & ~CS2_ERR; } /* clr CS2<15:8> */ + rpcs1 = rpcs1 & ~CS1_TRE; /* clr CS1 */ + rpcs2 = rpcs2 & ~CS2_ERR; } /* clr CS2<15:8> */ if ((access == WRITE) || (PA & 1)) { /* hi byte write? */ - if (rpcs1 & CS1_DONE) /* done set? */ - rpcs1 = (rpcs1 & ~CS1_UAE) | (data & CS1_UAE); } + if (rpcs1 & CS1_DONE) /* done set? */ + rpcs1 = (rpcs1 & ~CS1_UAE) | (data & CS1_UAE); } if ((access == WRITE) || !(PA & 1)) { /* lo byte write? */ - if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */ - rpiff = 1; /* set CSTB INTR */ - rpcs1 = (rpcs1 & ~CS1_IE) | (data & CS1_IE); - if (uptr->flags & UNIT_DIS) { /* nx disk? */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - cs1f = CS1_SC; } /* req interrupt */ - else if (sim_is_active (uptr)) - rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */ - else if (data & CS1_GO) { /* start op */ - uptr->FUNC = GET_FNC (data); /* set func */ - if ((uptr->FUNC >= FNC_XFER) && /* data xfer and */ - ((rpcs1 & CS1_DONE) == 0)) /* ~rdy? PGE */ - rpcs2 = rpcs2 | CS2_PGE; - else rp_go (drv, uptr->FUNC); } } + if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */ + rpiff = 1; /* set CSTB INTR */ + rpcs1 = (rpcs1 & ~CS1_IE) | (data & CS1_IE); + if (uptr->flags & UNIT_DIS) { /* nx disk? */ + rpcs2 = rpcs2 | CS2_NED; /* set error flag */ + cs1f = CS1_SC; } /* req interrupt */ + else if (sim_is_active (uptr)) + rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */ + else if (data & CS1_GO) { /* start op */ + uptr->FUNC = GET_FNC (data); /* set func */ + if ((uptr->FUNC >= FNC_XFER) && /* data xfer and */ + ((rpcs1 & CS1_DONE) == 0)) /* ~rdy? PGE */ + rpcs2 = rpcs2 | CS2_PGE; + else rp_go (drv, uptr->FUNC); } } break; case 001: /* RPWC */ if (access == WRITEB) data = (PA & 1)? - (rpwc & 0377) | (data << 8): (rpwc & ~0377) | data; + (rpwc & 0377) | (data << 8): (rpwc & ~0377) | data; rpwc = data; break; case 002: /* RPBA */ if (access == WRITEB) data = (PA & 1)? - (rpba & 0377) | (data << 8): (rpba & ~0377) | data; + (rpba & 0377) | (data << 8): (rpba & ~0377) | data; rpba = data & ~BA_MBZ; break; case 003: /* RPDA */ if (access == WRITEB) data = (PA & 1)? - (rpda & 0377) | (data << 8): (rpda & ~0377) | data; + (rpda & 0377) | (data << 8): (rpda & ~0377) | data; rpda = data & ~DA_MBZ; break; case 004: /* RPCS2 */ if ((access == WRITEB) && (PA & 1)) data = data << 8; if (data & CS2_CLR) rp_reset (&rp_dev); /* init? */ - else { if ((data & ~rpcs2) & (CS2_PE | CS2_MXF)) - cs1f = CS1_SC; /* diagn intr */ - if (access == WRITEB) data = (rpcs2 & /* merge data */ - ((PA & 1)? 0377: 0177400)) | data; - rpcs2 = (rpcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; } + else { + if ((data & ~rpcs2) & (CS2_PE | CS2_MXF)) + cs1f = CS1_SC; /* diagn intr */ + if (access == WRITEB) data = (rpcs2 & /* merge data */ + ((PA & 1)? 0377: 0177400)) | data; + rpcs2 = (rpcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; } drv = GET_UNIT (rpcs2); break; case 006: /* RPER1 */ @@ -628,29 +629,28 @@ case 006: /* RPER1 */ case 007: /* RPAS */ if ((access == WRITEB) && (PA & 1)) break; for (i = 0; i < RP_NUMDR; i++) - if (data & (AS_U0 << i)) rpds[i] = rpds[i] & ~DS_ATA; + if (data & (AS_U0 << i)) rpds[i] = rpds[i] & ~DS_ATA; break; case 011: /* RPDB */ if (access == WRITEB) data = (PA & 1)? - (rpdb & 0377) | (data << 8): (rpdb & ~0377) | data; + (rpdb & 0377) | (data << 8): (rpdb & ~0377) | data; rpdb = data; break; case 012: /* RPMR */ if (access == WRITEB) data = (PA & 1)? - (rpmr & 0377) | (data << 8): (rpmr & ~0377) | data; + (rpmr & 0377) | (data << 8): (rpmr & ~0377) | data; rpmr = data; break; case 015: /* RPOF */ if (access == WRITEB) data = (PA & 1)? - (rpof & 0377) | (data << 8): (rpof & ~0377) | data; + (rpof & 0377) | (data << 8): (rpof & ~0377) | data; rpof = data & ~OF_MBZ; break; case 016: /* RPDC */ if (access == WRITEB) data = (PA & 1)? - (rpdc & 0377) | (data << 8): (rpdc & ~0377) | data; + (rpdc & 0377) | (data << 8): (rpdc & ~0377) | data; rpdc = data & ~DC_MBZ; break; - break; case 005: /* RPDS */ case 010: /* RPLA */ case 013: /* RPDT */ @@ -708,8 +708,8 @@ case FNC_PACK: /* pack acknowledge */ case FNC_OFFSET: /* offset mode */ case FNC_RETURN: if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } + rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ + break; } rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ sim_activate (uptr, rp_swait); /* time operation */ return; @@ -720,13 +720,13 @@ case FNC_RECAL: /* recalibrate */ case FNC_SEEK: /* seek */ case FNC_SEARCH: /* search */ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } + rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ + break; } if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ (GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */ (GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */ - rper1[drv] = rper1[drv] | ER1_IAE; - break; } + rper1[drv] = rper1[drv] | ER1_IAE; + break; } rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ t = abs (dc - uptr->CYL); /* cyl diff */ if (t == 0) t = 1; /* min time */ @@ -740,15 +740,15 @@ case FNC_WCHK: /* write check */ case FNC_READ: /* read */ case FNC_READH: /* read headers */ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } + rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ + break; } rpcs2 = rpcs2 & ~CS2_ERR; /* clear errors */ rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE); if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ (GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */ (GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */ - rper1[drv] = rper1[drv] | ER1_IAE; - break; } + rper1[drv] = rper1[drv] | ER1_IAE; + break; } rpds[drv] = rpds[drv] & ~DS_RDY; /* clear drive rdy */ sim_activate (uptr, rp_rwait + (rp_swait * abs (dc - uptr->CYL))); uptr->CYL = dc; /* save cylinder */ @@ -812,9 +812,9 @@ case FNC_SEEK: /* seek */ case FNC_WRITE: /* write */ if (uptr->flags & UNIT_WPRT) { /* write locked? */ - rper1[drv] = rper1[drv] | ER1_WLE; /* set drive error */ - update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ - break; } + rper1[drv] = rper1[drv] | ER1_WLE; /* set drive error */ + update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ + break; } case FNC_WCHK: /* write check */ case FNC_READ: /* read */ case FNC_READH: /* read headers */ @@ -822,9 +822,9 @@ case FNC_READH: /* read headers */ wc10 = (0200000 - rpwc) >> 1; /* get PDP-10 wc */ da = GET_DA (rpdc, rpda, dtype) * RP_NUMWD; /* get disk addr */ if ((da + wc10) > drv_tab[dtype].size) { /* disk overrun? */ - rper1[drv] = rper1[drv] | ER1_AOE; - if (wc10 > (drv_tab[dtype].size - da)) - wc10 = drv_tab[dtype].size - da; } + rper1[drv] = rper1[drv] | ER1_AOE; + if (wc10 > (drv_tab[dtype].size - da)) + wc10 = drv_tab[dtype].size - da; } err = fseek (uptr->fileref, da * sizeof (d10), SEEK_SET); if (uptr->FUNC == FNC_WRITE) { /* write? */ @@ -885,11 +885,11 @@ case FNC_READH: /* read headers */ rpdc = da / drv_tab[dtype].surf; if (err != 0) { /* error? */ - rper1[drv] = rper1[drv] | ER1_PAR; /* set drive error */ - update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ - perror ("RP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } + rper1[drv] = rper1[drv] | ER1_PAR; /* set drive error */ + update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ + perror ("RP I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; } case FNC_WRITEH: /* write headers stub */ update_rpcs (CS1_DONE, drv); /* set done */ break; } /* end case func */ @@ -961,7 +961,7 @@ for (i = 0; i < RP_NUMDR; i++) { sim_cancel (uptr); uptr->CYL = uptr->FUNC = 0; if (uptr->flags & UNIT_ATT) rpds[i] = (rpds[i] & DS_VV) | - DS_DPR | DS_RDY | DS_MOL | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); + DS_DPR | DS_RDY | DS_MOL | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); else if (uptr->flags & UNIT_DIS) rpds[i] = 0; else rpds[i] = DS_DPR; rper1[i] = 0; } @@ -1008,7 +1008,7 @@ if (sim_is_active (uptr)) { /* unit active? */ sim_cancel (uptr); /* cancel operation */ rper1[drv] = rper1[drv] | ER1_OPI; /* set drive error */ if (uptr->FUNC >= FNC_WCHK) /* data transfer? */ - rpcs1 = rpcs1 | CS1_DONE | CS1_TRE; } /* set done, err */ + rpcs1 = rpcs1 | CS1_DONE | CS1_TRE; } /* set done, err */ update_rpcs (CS1_SC, drv); /* request intr */ return detach_unit (uptr); } diff --git a/PDP10/pdp10_sys.c b/PDP10/pdp10_sys.c index ba7dde3a..be8e230b 100644 --- a/PDP10/pdp10_sys.c +++ b/PDP10/pdp10_sys.c @@ -1,6 +1,6 @@ /* pdp10_sys.c: PDP-10 simulator interface - Copyright (c) 1993-2002, Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 09-Jan-03 RMS Added DEUNA/DELUA support 12-Sep-02 RMS Added RX211 support 22-Apr-02 RMS Removed magtape record length error 17-Sep-01 RMS Removed multiconsole support @@ -44,6 +45,7 @@ extern DEVICE ptr_dev, ptp_dev; extern DEVICE rp_dev, tu_dev; extern DEVICE dz_dev, ry_dev; extern DEVICE lp20_dev; +extern DEVICE xu_dev; extern UNIT cpu_unit; extern REG cpu_reg[]; extern d10 *M; @@ -78,6 +80,7 @@ DEVICE *sim_devices[] = { &rp_dev, &tu_dev, &dz_dev, + &xu_dev, NULL }; const char *sim_stop_messages[] = { @@ -129,8 +132,8 @@ word = 0; for (i = 0; i < 6;) { if ((tmp = getc (fileref)) == EOF) return -1; if (tmp & 0200) { - word = (word << 6) | ((d10) tmp & 077); - i++; } } + word = (word << 6) | ((d10) tmp & 077); + i++; } } return word; } @@ -144,20 +147,21 @@ for ( ;; ) { /* loop until JRST */ count = cksm = getrimw (fileref); /* get header */ if (count < 0) return SCPE_FMT; /* read err? */ if (TSTS (count)) { /* hdr = IOWD? */ - for ( ; TSTS (count); count = AOB (count)) { - data = getrimw (fileref); /* get data wd */ - if (data < 0) return SCPE_FMT; - cksm = cksm + data; /* add to cksm */ - pa = ((a10) count + 1) & AMASK; /* store */ - M[pa] = data; } /* end for */ - data = getrimw (fileref); /* get cksm */ - if (data < 0) return SCPE_FMT; - if ((cksm + data) & DMASK) return SCPE_CSUM; /* test cksm */ - } /* end if count */ - else { op = GET_OP (count); /* not IOWD */ - if (op != OP_JRST) return SCPE_FMT; /* JRST? */ - saved_PC = (a10) count & AMASK; /* set PC */ - return SCPE_OK; } /* end else */ + for ( ; TSTS (count); count = AOB (count)) { + data = getrimw (fileref); /* get data wd */ + if (data < 0) return SCPE_FMT; + cksm = cksm + data; /* add to cksm */ + pa = ((a10) count + 1) & AMASK; /* store */ + M[pa] = data; } /* end for */ + data = getrimw (fileref); /* get cksm */ + if (data < 0) return SCPE_FMT; + if ((cksm + data) & DMASK) return SCPE_CSUM;/* test cksm */ + } /* end if count */ + else { + op = GET_OP (count); /* not IOWD */ + if (op != OP_JRST) return SCPE_FMT; /* JRST? */ + saved_PC = (a10) count & AMASK; /* set PC */ + return SCPE_OK; } /* end else */ } /* end for */ return SCPE_FMT; } @@ -185,16 +189,17 @@ for ( ;; ) { /* loop */ wc = fxread (&count, sizeof (d10), 1, fileref); /* read IOWD */ if (wc == 0) return SCPE_OK; /* done? */ if (TSTS (count)) { /* IOWD? */ - for ( ; TSTS (count); count = AOB (count)) { - wc = fxread (&data, sizeof (d10), 1, fileref); - if (wc == 0) return SCPE_FMT; - pa = ((a10) count + 1) & AMASK; /* store data */ - M[pa] = data; } /* end for */ - } /* end if count*/ - else { op = GET_OP (count); /* not IOWD */ - if (op != OP_JRST) return SCPE_FMT; /* JRST? */ - saved_PC = (a10) count & AMASK; /* set PC */ - return SCPE_OK; } /* end else */ + for ( ; TSTS (count); count = AOB (count)) { + wc = fxread (&data, sizeof (d10), 1, fileref); + if (wc == 0) return SCPE_FMT; + pa = ((a10) count + 1) & AMASK; /* store data */ + M[pa] = data; } /* end for */ + } /* end if count*/ + else { + op = GET_OP (count); /* not IOWD */ + if (op != OP_JRST) return SCPE_FMT; /* JRST? */ + saved_PC = (a10) count & AMASK; /* set PC */ + return SCPE_OK; } /* end else */ } /* end for */ return SCPE_FMT; } @@ -241,25 +246,25 @@ do { wc = fxread (&data, sizeof (d10), 1, fileref); /* read blk hdr */ bty = (int32) LRZ (data); /* get type */ switch (bty) { /* case type */ case EXE_DIR: /* directory */ - if (ndir) return SCPE_FMT; /* got one */ - ndir = fxread (dirbuf, sizeof (d10), bsz, fileref); - if (ndir < bsz) return SCPE_FMT; /* error */ - break; + if (ndir) return SCPE_FMT; /* got one */ + ndir = fxread (dirbuf, sizeof (d10), bsz, fileref); + if (ndir < bsz) return SCPE_FMT; /* error */ + break; case EXE_PDV: /* ??? */ - fseek (fileref, bsz * sizeof (d10), SEEK_CUR); - break; + fseek (fileref, bsz * sizeof (d10), SEEK_CUR); + break; case EXE_VEC: /* entry vec */ - if (bsz != 2) return SCPE_FMT; /* must be 2 wds */ - entvec = fxread (entbuf, sizeof (d10), bsz, fileref); - if (entvec < 2) return SCPE_FMT; /* error? */ - cont = 0; /* stop */ - break; + if (bsz != 2) return SCPE_FMT; /* must be 2 wds */ + entvec = fxread (entbuf, sizeof (d10), bsz, fileref); + if (entvec < 2) return SCPE_FMT; /* error? */ + cont = 0; /* stop */ + break; case EXE_END: /* end */ - if (bsz != 0) return SCPE_FMT; /* must be hdr */ - cont = 0; /* stop */ - break; + if (bsz != 0) return SCPE_FMT; /* must be hdr */ + cont = 0; /* stop */ + break; default: - return SCPE_FMT; } /* end switch */ + return SCPE_FMT; } /* end switch */ } /* end do */ while (cont); @@ -268,17 +273,17 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */ mpage = (int32) (dirbuf[i + 1] & RMASK); /* memory page */ rpt = (int32) ((dirbuf[i + 1] >> 27) + 1); /* repeat count */ for (j = 0; j < rpt; j++, mpage++) { /* loop thru rpts */ - if (fpage) { /* file pages? */ - fseek (fileref, (fpage << PAG_V_PN) * sizeof (d10), SEEK_SET); - wc = fxread (pagbuf, sizeof (d10), PAG_SIZE, fileref); - if (wc < PAG_SIZE) return SCPE_FMT; - fpage++; } - ma = mpage << PAG_V_PN; /* mem addr */ - for (k = 0; k < PAG_SIZE; k++, ma++) { /* copy buf to mem */ - if (MEM_ADDR_NXM (ma)) return SCPE_NXM; - M[ma] = fpage? (pagbuf[k] & DMASK): 0; - } /* end copy */ - } /* end rpt */ + if (fpage) { /* file pages? */ + fseek (fileref, (fpage << PAG_V_PN) * sizeof (d10), SEEK_SET); + wc = fxread (pagbuf, sizeof (d10), PAG_SIZE, fileref); + if (wc < PAG_SIZE) return SCPE_FMT; + fpage++; } + ma = mpage << PAG_V_PN; /* mem addr */ + for (k = 0; k < PAG_SIZE; k++, ma++) { /* copy buf to mem */ + if (MEM_ADDR_NXM (ma)) return SCPE_NXM; + M[ma] = fpage? (pagbuf[k] & DMASK): 0; + } /* end copy */ + } /* end rpt */ } /* end directory */ if (entvec && entbuf[1]) saved_PC = (int32) entbuf[1] & RMASK; /* start addr */ @@ -638,13 +643,13 @@ if (sw & SWMASK ('A')) { /* ASCII? */ return SCPE_OK; } if (sw & SWMASK ('C')) { /* character? */ for (i = 30; i >= 0; i = i - 6) { - c = (int32) ((inst >> i) & 077); - fprintf (of, "%c", SIXTOASC (c)); } + c = (int32) ((inst >> i) & 077); + fprintf (of, "%c", SIXTOASC (c)); } return SCPE_OK; } if (sw & SWMASK ('P')) { /* packed? */ for (i = 29; i >= 0; i = i - 7) { - c = (int32) ((inst >> i) & 0177); - fprintf (of, FMTASC (c)); } + c = (int32) ((inst >> i) & 0177); + fprintf (of, FMTASC (c)); } return SCPE_OK; } if (!(sw & SWMASK ('M'))) return SCPE_ARG; @@ -657,23 +662,23 @@ dev = GET_DEV (inst); for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ j = (int32) ((opc_val[i] >> I_V_FL) & I_M_FL); /* get class */ if (((opc_val[i] & DMASK) == (inst & masks[j])) && /* match? */ - (((opc_val[i] & I_ITS) == 0) || ITS)) { + (((opc_val[i] & I_ITS) == 0) || ITS)) { fprintf (of, "%s ", opcode[i]); /* opcode */ switch (j) { /* case on class */ case I_V_AC: /* AC + address */ - fprintf (of, "%-o,", ac); /* print AC, fall thru */ + fprintf (of, "%-o,", ac); /* print AC, fall thru */ case I_V_OP: /* address only */ - if (inst & INST_IND) fprintf (of, "@"); - if (xr) fprintf (of, "%-o(%-o)", y, xr); - else fprintf (of, "%-o", y); - break; + if (inst & INST_IND) fprintf (of, "@"); + if (xr) fprintf (of, "%-o(%-o)", y, xr); + else fprintf (of, "%-o", y); + break; case I_V_IO: /* I/O */ - if (dev < NUMDEV) fprintf (of, "%s,", devnam[dev]); - else fprintf (of, "%-o,", dev); - if (inst & INST_IND) fprintf (of, "@"); - if (xr) fprintf (of, "%-o(%-o)", y, xr); - else fprintf (of, "%-o", y); - break; } /* end case */ + if (dev < NUMDEV) fprintf (of, "%s,", devnam[dev]); + else fprintf (of, "%-o,", dev); + if (inst & INST_IND) fprintf (of, "@"); + if (xr) fprintf (of, "%-o(%-o)", y, xr); + else fprintf (of, "%-o", y); + break; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; @@ -710,7 +715,7 @@ if (*cptr == '(') { cptr++; xr = strtotv (cptr, &tptr, 8); if ((cptr == tptr) || (*tptr != ')') || - (xr > AC_NUM) || (xr == 0)) return 0; + (xr > AC_NUM) || (xr == 0)) return 0; cptr = ++tptr; } if (*cptr == 0) *status = SCPE_OK; return (ind | (xr << 18) | val); @@ -739,8 +744,8 @@ cflag = (uptr == NULL) || (uptr == &cpu_unit); while (isspace (*cptr)) cptr++; for (i = 0; i < 6; i++) { if (cptr[i] == 0) { - for (j = i + 1; j <= 6; j++) cptr[j] = 0; - break; } } + for (j = i + 1; j <= 6; j++) cptr[j] = 0; + break; } } if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ val[0] = (t_value) cptr[0]; @@ -748,9 +753,9 @@ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ for (i = 0; i < 6; i++) { - val[0] = (val[0] << 6); - if (cptr[i]) val[0] = val[0] | - ((t_value) ((cptr[i] + 040) & 077)); } + val[0] = (val[0] << 6); + if (cptr[i]) val[0] = val[0] | + ((t_value) ((cptr[i] + 040) & 077)); } return SCPE_OK; } if ((sw & SWMASK ('P')) || ((*cptr == '#') && cptr++)) { /* packed string? */ if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ @@ -768,11 +773,11 @@ j = (int32) ((opc_val[i] >> I_V_FL) & I_M_FL); /* get class */ switch (j) { /* case on class */ case I_V_AC: /* AC + operand */ if (strchr (cptr, ',')) { /* AC specified? */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if (gbuf[0]) { /* can be omitted */ - ac = get_uint (gbuf, 8, AC_NUM - 1, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (ac << INST_V_AC); } } + cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ + if (gbuf[0]) { /* can be omitted */ + ac = get_uint (gbuf, 8, AC_NUM - 1, &r); + if (r != SCPE_OK) return SCPE_ARG; + val[0] = val[0] | (ac << INST_V_AC); } } case I_V_OP: /* operand */ cptr = get_glyph (cptr, gbuf, 0); val[0] = val[0] | get_opnd (gbuf, &r); @@ -782,8 +787,8 @@ case I_V_IO: /* I/O */ cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ for (dev = 0; (dev < NUMDEV) && (strcmp (devnam[dev], gbuf) != 0); dev++); if (dev >= NUMDEV) { - dev = get_uint (gbuf, 8, INST_M_DEV, &r); - if (r != SCPE_OK) return SCPE_ARG; } + dev = get_uint (gbuf, 8, INST_M_DEV, &r); + if (r != SCPE_OK) return SCPE_ARG; } val[0] = val[0] | (dev << INST_V_DEV); cptr = get_glyph (cptr, gbuf, 0); val[0] = val[0] | get_opnd (gbuf, &r); diff --git a/PDP10/pdp10_tim.c b/PDP10/pdp10_tim.c index f143c70b..99592d52 100644 --- a/PDP10/pdp10_tim.c +++ b/PDP10/pdp10_tim.c @@ -153,8 +153,8 @@ if (ttg <= 0) { /* timeout? */ if (ITS) { /* ITS? */ if (pi_act == 0) quant = (quant + TIM_HWRE) & DMASK; if (TSTS (pcst)) { /* PC sampling? */ - WriteP ((a10) pcst & AMASK, pager_PC); /* store sample */ - pcst = AOB (pcst); } /* add 1,,1 */ + WriteP ((a10) pcst & AMASK, pager_PC); /* store sample */ + pcst = AOB (pcst); } /* add 1,,1 */ } /* end ITS */ return SCPE_OK; } diff --git a/PDP10/pdp10_tu.c b/PDP10/pdp10_tu.c index 8d366976..fd5ac0c2 100644 --- a/PDP10/pdp10_tu.c +++ b/PDP10/pdp10_tu.c @@ -471,48 +471,50 @@ switch (j) { /* decode PA<4:1> */ case 000: /* MTCS1 */ if ((access == WRITEB) && (PA & 1)) data = data << 8; if (data & CS1_TRE) { /* error clear? */ - tucs1 = tucs1 & ~CS1_TRE; /* clr CS1 */ - tucs2 = tucs2 & ~CS2_ERR; } /* clr CS2<15:8> */ + tucs1 = tucs1 & ~CS1_TRE; /* clr CS1 */ + tucs2 = tucs2 & ~CS2_ERR; } /* clr CS2<15:8> */ if ((access == WRITE) || (PA & 1)) { /* hi byte write? */ - if (tucs1 & CS1_DONE) /* done set? */ - tucs1 = (tucs1 & ~CS1_UAE) | (data & CS1_UAE); } + if (tucs1 & CS1_DONE) /* done set? */ + tucs1 = (tucs1 & ~CS1_UAE) | (data & CS1_UAE); } if ((access == WRITE) || !(PA & 1)) { /* lo byte write? */ - if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */ - tuiff = 1; /* set CSTB INTR */ - tucs1 = (tucs1 & ~CS1_IE) | (data & CS1_IE); - if (fmtr != 0) { /* nx formatter? */ - tucs2 = tucs2 | CS2_NEF; /* set error flag */ - cs1f = CS1_SC; } /* req interrupt */ - else if (tucs1 & CS1_GO) { /* busy? */ - if (tucs1 & CS1_DONE) tuer = tuer | ER_RMR; - else tucs2 = tucs2 | CS2_PGE; } - else { tucs1 = (tucs1 & ~CS1_DRV) | (data & CS1_DRV); - if (tucs1 & CS1_GO) tu_go (drv); } } + if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */ + tuiff = 1; /* set CSTB INTR */ + tucs1 = (tucs1 & ~CS1_IE) | (data & CS1_IE); + if (fmtr != 0) { /* nx formatter? */ + tucs2 = tucs2 | CS2_NEF; /* set error flag */ + cs1f = CS1_SC; } /* req interrupt */ + else if (tucs1 & CS1_GO) { /* busy? */ + if (tucs1 & CS1_DONE) tuer = tuer | ER_RMR; + else tucs2 = tucs2 | CS2_PGE; } + else { + tucs1 = (tucs1 & ~CS1_DRV) | (data & CS1_DRV); + if (tucs1 & CS1_GO) tu_go (drv); } } break; case 001: /* MTWC */ if (access == WRITEB) data = (PA & 1)? - (tuwc & 0377) | (data << 8): (tuwc & ~0377) | data; + (tuwc & 0377) | (data << 8): (tuwc & ~0377) | data; tuwc = data; break; case 002: /* MTBA */ if (access == WRITEB) data = (PA & 1)? - (tuba & 0377) | (data << 8): (tuba & ~0377) | data; + (tuba & 0377) | (data << 8): (tuba & ~0377) | data; tuba = data & ~BA_MBZ; break; case 003: /* MTFC */ if (access == WRITEB) data = (PA & 1)? - (tufc & 0377) | (data << 8): (tufc & ~0377) | data; + (tufc & 0377) | (data << 8): (tufc & ~0377) | data; tufc = data; tutc = tutc | TC_FCS; /* set fc flag */ break; case 004: /* MTCS2 */ if ((access == WRITEB) && (PA & 1)) data = data << 8; if (data & CS2_CLR) tu_reset (&tu_dev); /* init? */ - else { if ((data & ~tucs2) & (CS2_PE | CS2_MXF)) - cs1f = CS1_SC; /* diagn intr */ - if (access == WRITEB) data = (tucs2 & /* merge data */ - ((PA & 1)? 0377: 0177400)) | data; - tucs2 = (tucs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; } + else { + if ((data & ~tucs2) & (CS2_PE | CS2_MXF)) + cs1f = CS1_SC; /* diagn intr */ + if (access == WRITEB) data = (tucs2 & /* merge data */ + ((PA & 1)? 0377: 0177400)) | data; + tucs2 = (tucs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; } break; case 007: /* MTAS */ if ((access == WRITEB) && (PA & 1)) break; @@ -520,17 +522,17 @@ case 007: /* MTAS */ break; case 011: /* MTDB */ if (access == WRITEB) data = (PA & 1)? - (tudb & 0377) | (data << 8): (tudb & ~0377) | data; + (tudb & 0377) | (data << 8): (tudb & ~0377) | data; tudb = data; break; case 012: /* MTMR */ if (access == WRITEB) data = (PA & 1)? - (tumr & 0377) | (data << 8): (tumr & ~0377) | data; + (tumr & 0377) | (data << 8): (tumr & ~0377) | data; tumr = (tumr & ~MR_RW) | (data & MR_RW); break; case 015: /* MTTC */ if (access == WRITEB) data = (PA & 1)? - (tutc & 0377) | (data << 8): (tutc & ~0377) | data; + (tutc & 0377) | (data << 8): (tutc & ~0377) | data; tutc = (tutc & ~TC_RW) | (data & TC_RW) | TC_SAC; drv = GET_DRV (tutc); break; @@ -586,8 +588,8 @@ case FNC_RIP: /* read-in preset */ case FNC_UNLOAD: /* unload */ if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } + tuer = tuer | ER_UNS; + break; } detach_unit (uptr); uptr->USTAT = FS_REW; sim_activate (uptr, tu_time); @@ -595,8 +597,8 @@ case FNC_UNLOAD: /* unload */ return; case FNC_REWIND: if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } + tuer = tuer | ER_UNS; + break; } uptr->USTAT = FS_PIP | FS_REW; sim_activate (uptr, tu_time); tucs1 = tucs1 & ~CS1_GO; @@ -606,47 +608,47 @@ case FNC_SPACEF: space_test = FS_EOT; case FNC_SPACER: if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } + tuer = tuer | ER_UNS; + break; } if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) { - tuer = tuer | ER_NXF; - break; } + tuer = tuer | ER_NXF; + break; } uptr->USTAT = FS_PIP; goto GO_XFER; case FNC_WCHKR: /* wchk = read */ case FNC_READR: /* read rev */ if (tufs & FS_BOT) { /* beginning of tape? */ - tuer = tuer | ER_NXF; - break; } + tuer = tuer | ER_NXF; + break; } goto DATA_XFER; case FNC_WRITE: /* write */ if (((tutc & TC_FCS) == 0) || /* frame cnt = 0? */ ((den == TC_800) && (tufc > 0777765))) { /* NRZI, fc < 13? */ - tuer = tuer | ER_NXF; - break; } + tuer = tuer | ER_NXF; + break; } case FNC_WREOF: /* write tape mark */ case FNC_ERASE: /* erase */ if (uptr->flags & UNIT_WPRT) { /* write locked? */ - tuer = tuer | ER_NXF; - break; } + tuer = tuer | ER_NXF; + break; } case FNC_WCHKF: /* wchk = read */ case FNC_READF: /* read */ DATA_XFER: if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } + tuer = tuer | ER_UNS; + break; } if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */ - tuer = tuer | ER_FER; - break; } + tuer = tuer | ER_FER; + break; } if (den_test[den] == 0) { /* invalid density? */ - tuer = tuer | ER_NXF; - break; } + tuer = tuer | ER_NXF; + break; } if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ /* else if (uptr->UDENS != den) { /* density mismatch? */ -/* tuer = tuer | ER_NXF; -/* break; } */ +/* tuer = tuer | ER_NXF; +/* break; } */ uptr->USTAT = 0; tucs1 = tucs1 & ~CS1_DONE; /* clear done */ GO_XFER: @@ -706,10 +708,11 @@ switch (f) { /* case on function */ /* Unit service - non-data transfer commands - set ATA when done */ case FNC_SPACEF: /* space forward */ - do { tufc = (tufc + 1) & 0177777; /* incr fc */ - if (tu_rdlntf (uptr, &tbc, &err)) break;/* read rec lnt, err? */ - uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) + - (2 * sizeof (t_mtrlnt)); } + do { + tufc = (tufc + 1) & 0177777; /* incr fc */ + if (tu_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */ + uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) + + (2 * sizeof (t_mtrlnt)); } while (tufc != 0); if (tufc) tuer = tuer | ER_FCE; else tutc = tutc & ~TC_FCS; @@ -717,11 +720,13 @@ case FNC_SPACEF: /* space forward */ break; case FNC_SPACER: /* space reverse */ - do { tufc = (tufc + 1) & 0177777; /* incr wc */ - if (pnu) pnu = 0; /* pos not upd? */ - else { if (tu_rdlntr (uptr, &tbc, &err)) break; - uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) - - (2 * sizeof (t_mtrlnt)); } } + do { + tufc = (tufc + 1) & 0177777; /* incr wc */ + if (pnu) pnu = 0; /* pos not upd? */ + else { + if (tu_rdlntr (uptr, &tbc, &err)) break; + uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) - + (2 * sizeof (t_mtrlnt)); } } while (tufc != 0); if (tufc) tuer = tuer | ER_FCE; else tutc = tutc & ~TC_FCS; @@ -757,28 +762,28 @@ case FNC_READF: /* read */ case FNC_WCHKF: /* wcheck = read */ tufc = 0; /* clear frame count */ if ((uptr->UDENS == TC_1600) && (uptr->pos == 0)) - tufs = tufs | FS_ID; /* PE BOT? ID burst */ + tufs = tufs | FS_ID; /* PE BOT? ID burst */ TXFR (ba, wc, 0); /* validate transfer */ if (tu_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */ if (MTRF (tbc)) { /* bad record? */ - tuer = tuer | ER_CRC; /* set error flag */ - uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) + - (2 * sizeof (t_mtrlnt)); - break; } + tuer = tuer | ER_CRC; /* set error flag */ + uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) + + (2 * sizeof (t_mtrlnt)); + break; } if (tbc > XBUFLNT) return SCPE_MTRLNT; /* bad rec length? */ abc = fxread (xbuf, sizeof (int8), tbc, uptr->fileref); if (err = ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); /* pos not upd */ - break; } + MT_SET_PNU (uptr); /* pos not upd */ + break; } for ( ; abc < tbc + 4; abc++) xbuf[abc] = 0; /* fill/pad with 0's */ for (i = j = 0; (i < wc10) && (j < ((int32) tbc)); i++) { - if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */ - MAPM (ba10 + i, mpa10, 0); } - for (k = 0; k < 4; k++) v[k] = xbuf[j++]; - val = (v[0] << 28) | (v[1] << 20) | (v[2] << 12) | (v[3] << 4); - if (fmt == TC_10C) val = val | ((d10) xbuf[j++] & 017); - if (f == FNC_READF) M[mpa10] = val; - mpa10 = mpa10 + 1; } /* end for */ + if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */ + MAPM (ba10 + i, mpa10, 0); } + for (k = 0; k < 4; k++) v[k] = xbuf[j++]; + val = (v[0] << 28) | (v[1] << 20) | (v[2] << 12) | (v[3] << 4); + if (fmt == TC_10C) val = val | ((d10) xbuf[j++] & 017); + if (f == FNC_READF) M[mpa10] = val; + mpa10 = mpa10 + 1; } /* end for */ uptr->pos = uptr->pos + ((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt)); tufc = tbc & 0177777; tuwc = (tuwc + (i << 1)) & 0177777; @@ -789,26 +794,27 @@ case FNC_WRITE: /* write */ TXFR (ba, wc, 0); /* validate transfer */ fseek (uptr->fileref, uptr->pos, SEEK_SET); for (i = j = 0; (i < wc10) && (j < fc); i++) { - if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */ - MAPM (ba10 + i, mpa10, 0); } - val = M[mpa10]; - xbuf[j++] = (uint8) ((val >> 28) & 0377); - xbuf[j++] = (uint8) ((val >> 20) & 0377); - xbuf[j++] = (uint8) ((val >> 12) & 0377); - xbuf[j++] = (uint8) ((val >> 4) & 0377); - if (fmt == TC_10C) xbuf[j++] = (uint8) (val & 017); - mpa10 = mpa10 + 1; } /* end for */ + if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */ + MAPM (ba10 + i, mpa10, 0); } + val = M[mpa10]; + xbuf[j++] = (uint8) ((val >> 28) & 0377); + xbuf[j++] = (uint8) ((val >> 20) & 0377); + xbuf[j++] = (uint8) ((val >> 12) & 0377); + xbuf[j++] = (uint8) ((val >> 4) & 0377); + if (fmt == TC_10C) xbuf[j++] = (uint8) (val & 017); + mpa10 = mpa10 + 1; } /* end for */ if (j < fc) fc = j; /* short record? */ fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr->fileref); fxwrite (xbuf, sizeof (int8), (fc + 1) & ~1, uptr->fileref); fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr->fileref); if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); - else { uptr->pos = uptr->pos + ((fc + 1) & ~1) + - (2 * sizeof (t_mtrlnt)); - tufc = (tufc + fc) & 0177777; - if (tufc == 0) tutc = tutc & ~TC_FCS; - tuwc = (tuwc + (i << 1)) & 0177777; - ba = ba + (i << 2); } + else { + uptr->pos = uptr->pos + ((fc + 1) & ~1) + + (2 * sizeof (t_mtrlnt)); + tufc = (tufc + fc) & 0177777; + if (tufc == 0) tutc = tutc & ~TC_FCS; + tuwc = (tuwc + (i << 1)) & 0177777; + ba = ba + (i << 2); } break; case FNC_READR: /* read reverse */ @@ -817,24 +823,24 @@ case FNC_WCHKR: /* wcheck = read */ TXFR (ba, wc, 1); /* validate xfer rev */ if (tu_rdlntr (uptr, &tbc, &err)) break; /* read rec lnt, err? */ if (MTRF (tbc)) { /* bad record? */ - tuer = tuer | ER_CRC; /* set error flag */ - uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) - - (2 * sizeof (t_mtrlnt)); - break; } + tuer = tuer | ER_CRC; /* set error flag */ + uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) - + (2 * sizeof (t_mtrlnt)); + break; } if (tbc > XBUFLNT) return SCPE_MTRLNT; /* bad rec length? */ fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt) - - ((tbc + 1) & ~1), SEEK_SET); + - ((tbc + 1) & ~1), SEEK_SET); fxread (xbuf + 4, sizeof (int8), tbc, uptr->fileref); for (i = 0; i < 4; i++) xbuf[i] = 0; err = ferror (uptr->fileref); /* set err but finish */ for (i = 0, j = tbc + 4; (i < wc10) && (j >= 4); i++) { - if ((i == 0) || NEWPAGE (ba10 - i, PAG_M_OFF)) { /* map page */ - MAPM (ba10 - i, mpa10, UMAP_RRV); } - val = ((fmt == TC_10C)? (((d10) xbuf [--j]) & 017): 0); - for (k = 0; k < 4; i++) v[k] = xbuf[--j]; - val = val | (v[0] << 4) | (v[1] << 12) | (v[2] << 20) | (v[3] << 28); - if (f == FNC_READR) M[mpa10] = val; - mpa10 = mpa10 - 1; } /* end for */ + if ((i == 0) || NEWPAGE (ba10 - i, PAG_M_OFF)) { /* map page */ + MAPM (ba10 - i, mpa10, UMAP_RRV); } + val = ((fmt == TC_10C)? (((d10) xbuf [--j]) & 017): 0); + for (k = 0; k < 4; i++) v[k] = xbuf[--j]; + val = val | (v[0] << 4) | (v[1] << 12) | (v[2] << 20) | (v[3] << 28); + if (f == FNC_READR) M[mpa10] = val; + mpa10 = mpa10 - 1; } /* end for */ uptr->pos = uptr->pos - ((tbc + 1) & ~1) - (2 * sizeof (t_mtrlnt)); tufc = tbc & 0177777; tuwc = (tuwc + (i << 1)) & 0177777; @@ -871,10 +877,10 @@ if ((flag & ~tucs1) & CS1_DONE) /* DONE 0 to 1? */ if (GET_FMTR (tucs2) == 0) { /* formatter present? */ tufs = (tufs & ~FS_DYN) | FS_FPR; if (tu_unit[drv].flags & UNIT_ATT) { - tufs = tufs | FS_MOL | tu_unit[drv].USTAT; - if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE; - if (tu_unit[drv].flags & UNIT_WPRT) tufs = tufs | FS_WRL; - if ((tu_unit[drv].pos == 0) && !act) tufs = tufs | FS_BOT; } + tufs = tufs | FS_MOL | tu_unit[drv].USTAT; + if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE; + if (tu_unit[drv].flags & UNIT_WPRT) tufs = tufs | FS_WRL; + if ((tu_unit[drv].pos == 0) && !act) tufs = tufs | FS_BOT; } if (tuer) tufs = tufs | FS_ERR; } else tufs = 0; tucs1 = (tucs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ)) | CS1_DVA | flag; diff --git a/PDP10/pdp10_xtnd.c b/PDP10/pdp10_xtnd.c index 8023ab0a..da5e76a9 100644 --- a/PDP10/pdp10_xtnd.c +++ b/PDP10/pdp10_xtnd.c @@ -216,14 +216,14 @@ case XT_CMPSG: /* CMPSG */ f2 = Read (ADDA (ea, 2), MM_OPND) & bytemask[GET_S (AC(p4))]; b1 = b2 = 0; for (flg = 0; (AC(ac) | AC(p3)) && (b1 == b2); flg++) { - if (flg && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - if (AC(ac)) b1 = incloadbp (p1, pflgs); /* src1 */ - else b1 = f1; - if (AC(p3)) b2 = incloadbp (p4, pflgs); /* src2 */ - else b2 = f2; - if (AC(ac)) AC(ac) = (AC(ac) - 1) & XLNTMASK; - if (AC(p3)) AC(p3) = (AC(p3) - 1) & XLNTMASK; } + if (flg && (t = test_int ())) ABORT (t); + rlog = 0; /* clear log */ + if (AC(ac)) b1 = incloadbp (p1, pflgs); /* src1 */ + else b1 = f1; + if (AC(p3)) b2 = incloadbp (p4, pflgs); /* src2 */ + else b2 = f2; + if (AC(ac)) AC(ac) = (AC(ac) - 1) & XLNTMASK; + if (AC(p3)) AC(p3) = (AC(p3) - 1) & XLNTMASK; } switch (xop) { case XT_CMPSL: return (b1 < b2)? XT_SKIP: XT_NOSK; case XT_CMPSE: return (b1 == b2)? XT_SKIP: XT_NOSK; @@ -245,42 +245,43 @@ case XT_CVTBDO: /* CVTBDO */ case XT_CVTBDT: /* CVTBDT */ e1 = calc_ea (xinst, MM_EA); /* get ext inst addr */ if (xop == XT_CVTBDO) /* offset? */ - xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */ + xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */ rs[0] = AC(ac); /* get src opnd */ rs[1] = CLRS (AC(p1)); if (!TSTF (F_FPD)) { /* set up done yet? */ - if (TSTS (AC(ac))) { DMOVN (rs); } /* get abs value */ - for (i = 22; i > 1; i--) { /* find field width */ - if (DCMPGE (rs, pwrs10[i])) break; } - if (i > (AC(p3) & XLNTMASK)) return XT_NOSK; - if ((i < (AC(p3) & XLNTMASK)) && (AC(p3) & XT_LFLG)) { - f1 = Read (ADDA (ea, 1), MM_OPND); - filldst (f1, p3, (AC(p3) & XLNTMASK) - i, pflgs); } - else AC(p3) = (AC(p3) & XFLGMASK) | i; - if (TSTS (AC(ac))) AC(p3) = AC(p3) | XT_MFLG; - if (AC(ac) | AC(p1)) AC(p3) = AC(p3) | XT_NFLG; - AC(ac) = rs[0]; /* update state */ - AC(p1) = rs[1]; - SETF (F_FPD); } /* mark set up done */ + if (TSTS (AC(ac))) { DMOVN (rs); } /* get abs value */ + for (i = 22; i > 1; i--) { /* find field width */ + if (DCMPGE (rs, pwrs10[i])) break; } + if (i > (AC(p3) & XLNTMASK)) return XT_NOSK; + if ((i < (AC(p3) & XLNTMASK)) && (AC(p3) & XT_LFLG)) { + f1 = Read (ADDA (ea, 1), MM_OPND); + filldst (f1, p3, (AC(p3) & XLNTMASK) - i, pflgs); } + else AC(p3) = (AC(p3) & XFLGMASK) | i; + if (TSTS (AC(ac))) AC(p3) = AC(p3) | XT_MFLG; + if (AC(ac) | AC(p1)) AC(p3) = AC(p3) | XT_NFLG; + AC(ac) = rs[0]; /* update state */ + AC(p1) = rs[1]; + SETF (F_FPD); } /* mark set up done */ /* Now do actual binary to decimal conversion */ for (flg = 0; AC(p3) & XLNTMASK; flg++) { - if (flg && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - i = (int32) AC(p3) & XLNTMASK; /* get length */ - if (i > 22) i = 22; /* put in range */ - for (digit = 0; (digit < 10) && DCMPGE (rs, pwrs10[i]); digit++) { - rs[0] = rs[0] - pwrs10[i][0] - (rs[1] < pwrs10[i][1]); - rs[1] = (rs[1] - pwrs10[i][1]) & MMASK; } - if (xop == XT_CVTBDO) digit = (digit + xoff) & DMASK; - else { f1 = Read (e1 + (int32) digit, MM_OPND); - if ((i == 1) && (AC(p3) & XT_LFLG)) f1 = f1 >> 18; - digit = f1 & RMASK; } - incstorebp (digit, p4, pflgs); /* store digit */ - AC(ac) = rs[0]; /* mem access ok */ - AC(p1) = rs[1]; /* update state */ - AC(p3) = (AC(p3) & XFLGMASK) | ((AC(p3) - 1) & XLNTMASK); } + if (flg && (t = test_int ())) ABORT (t); + rlog = 0; /* clear log */ + i = (int32) AC(p3) & XLNTMASK; /* get length */ + if (i > 22) i = 22; /* put in range */ + for (digit = 0; (digit < 10) && DCMPGE (rs, pwrs10[i]); digit++) { + rs[0] = rs[0] - pwrs10[i][0] - (rs[1] < pwrs10[i][1]); + rs[1] = (rs[1] - pwrs10[i][1]) & MMASK; } + if (xop == XT_CVTBDO) digit = (digit + xoff) & DMASK; + else { + f1 = Read (e1 + (int32) digit, MM_OPND); + if ((i == 1) && (AC(p3) & XT_LFLG)) f1 = f1 >> 18; + digit = f1 & RMASK; } + incstorebp (digit, p4, pflgs); /* store digit */ + AC(ac) = rs[0]; /* mem access ok */ + AC(p1) = rs[1]; /* update state */ + AC(p3) = (AC(p3) & XFLGMASK) | ((AC(p3) - 1) & XLNTMASK); } CLRF (F_FPD); /* clear FPD */ return XT_SKIP; @@ -298,31 +299,32 @@ case XT_CVTDBO: /* CVTDBO */ if ((AC(ac) & XT_SFLG) == 0) AC(p3) = AC(p4) = 0; /* !S? clr res */ else AC(p4) = CLRS (AC(p4)); /* clear low sign */ if (xop == XT_CVTDBO) { /* offset? */ - xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */ - AC(ac) = AC(ac) | XT_SFLG; } /* set S flag */ + xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */ + AC(ac) = AC(ac) | XT_SFLG; } /* set S flag */ xflgs = AC(ac) & XFLGMASK; /* get xlation flags */ for (flg = 0; AC(ac) & XLNTMASK; flg++) { - if (flg && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - b1 = incloadbp (p1, pflgs); /* get byte */ - if (xop == XT_CVTDBO) b1 = (b1 + xoff) & DMASK; - else { b1 = xlate (b1, e1, &xflgs, MM_OPND); - if (b1 < 0) { /* terminated? */ - AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); - if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4)); - return XT_NOSK; } - if (xflgs & XT_SFLG) b1 = b1 & XT_DGMASK; - else b1 = 0; } - AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); - if ((b1 < 0) || (b1 > 9)) { /* bad digit? done */ - if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4)); - return XT_NOSK; } - AC(p4) = (AC(p4) * 10) + b1; /* base * 10 + digit */ - AC(p3) = ((AC(p3) * 10) + (AC(p4) >> 35)) & DMASK; - AC(p4) = AC(p4) & MMASK; } + if (flg && (t = test_int ())) ABORT (t); + rlog = 0; /* clear log */ + b1 = incloadbp (p1, pflgs); /* get byte */ + if (xop == XT_CVTDBO) b1 = (b1 + xoff) & DMASK; + else { + b1 = xlate (b1, e1, &xflgs, MM_OPND); + if (b1 < 0) { /* terminated? */ + AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); + if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4)); + return XT_NOSK; } + if (xflgs & XT_SFLG) b1 = b1 & XT_DGMASK; + else b1 = 0; } + AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); + if ((b1 < 0) || (b1 > 9)) { /* bad digit? done */ + if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4)); + return XT_NOSK; } + AC(p4) = (AC(p4) * 10) + b1; /* base * 10 + digit */ + AC(p3) = ((AC(p3) * 10) + (AC(p4) >> 35)) & DMASK; + AC(p4) = AC(p4) & MMASK; } if (AC(ac) & XT_MFLG) { - AC(p4) = -AC(p4) & MMASK; - AC(p3) = (~AC(p3) + (AC(p4) == 0)) & DMASK; } + AC(p4) = -AC(p4) & MMASK; + AC(p3) = (~AC(p3) + (AC(p4) == 0)) & DMASK; } if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4)); return XT_SKIP; @@ -343,24 +345,24 @@ case XT_MOVSLJ: /* MOVSLJ */ f1 = Read (ADDA (ea, 1), MM_OPND); /* get fill */ switch (xop) { /* case on instr */ case XT_MOVSO: /* MOVSO */ - AC(ac) = AC(ac) & XLNTMASK; /* trim src length */ - xoff = calc_ea (xinst, MM_EA); /* get offset */ - if (xoff & RSIGN) xoff = xoff | LMASK; /* sign extend 18b */ - s2 = GET_S (AC(p4)); /* get dst byte size */ - break; + AC(ac) = AC(ac) & XLNTMASK; /* trim src length */ + xoff = calc_ea (xinst, MM_EA); /* get offset */ + if (xoff & RSIGN) xoff = xoff | LMASK; /* sign extend 18b */ + s2 = GET_S (AC(p4)); /* get dst byte size */ + break; case XT_MOVST: /* MOVST */ - e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */ - break; + e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */ + break; case XT_MOVSRJ: /* MOVSRJ */ - AC(ac) = AC(ac) & XLNTMASK; /* trim src length */ - if (AC(p3) == 0) return (AC(ac)? XT_NOSK: XT_SKIP); - if (AC(ac) > AC(p3)) { /* adv src ptr */ - for (flg = 0; AC(ac) > AC(p3); flg++) { - if (flg && (t = test_int ())) ABORT (t); - AC(p1) = incbp (AC(p1)); - AC(ac) = (AC(ac) - 1) & XLNTMASK; } } - else if (AC(ac) < AC(p3)) - filldst (f1, p3, AC(p3) - AC(ac), pflgs); + AC(ac) = AC(ac) & XLNTMASK; /* trim src length */ + if (AC(p3) == 0) return (AC(ac)? XT_NOSK: XT_SKIP); + if (AC(ac) > AC(p3)) { /* adv src ptr */ + for (flg = 0; AC(ac) > AC(p3); flg++) { + if (flg && (t = test_int ())) ABORT (t); + AC(p1) = incbp (AC(p1)); + AC(ac) = (AC(ac) - 1) & XLNTMASK; } } + else if (AC(ac) < AC(p3)) + filldst (f1, p3, AC(p3) - AC(ac), pflgs); break; case XT_MOVSLJ: /* MOVSLJ */ AC(ac) = AC(ac) & XLNTMASK; /* trim src length */ @@ -369,27 +371,27 @@ case XT_MOVSLJ: /* MOVSLJ */ xflgs = AC(ac) & XFLGMASK; /* get xlation flags */ if (AC(p3) == 0) return (AC(ac)? XT_NOSK: XT_SKIP); for (flg = 0; AC(p3) & XLNTMASK; flg++) { - if (flg && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - if (AC(ac) & XLNTMASK) { /* any source? */ - b1 = incloadbp (p1, pflgs); /* src byte */ - if (xop == XT_MOVSO) { /* offset? */ - b1 = (b1 + xoff) & DMASK; /* test fit */ - if (b1 & ~bytemask[s2]) { - AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); - return XT_NOSK; } } - else if (xop == XT_MOVST) { /* translate? */ - b1 = xlate (b1, e1, &xflgs, MM_OPND); - if (b1 < 0) { /* upd flags in AC */ - AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); - return XT_NOSK; } - if (xflgs & XT_SFLG) b1 = b1 & XT_BYMASK; - else b1 = -1; } } - else b1 = f1; - if (b1 >= 0) { /* valid byte? */ - incstorebp (b1, p4, pflgs); /* store byte */ - AC(p3) = (AC(p3) - 1) & XLNTMASK; } /* update state */ - if (AC(ac) & XLNTMASK) AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); } + if (flg && (t = test_int ())) ABORT (t); + rlog = 0; /* clear log */ + if (AC(ac) & XLNTMASK) { /* any source? */ + b1 = incloadbp (p1, pflgs); /* src byte */ + if (xop == XT_MOVSO) { /* offset? */ + b1 = (b1 + xoff) & DMASK; /* test fit */ + if (b1 & ~bytemask[s2]) { + AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); + return XT_NOSK; } } + else if (xop == XT_MOVST) { /* translate? */ + b1 = xlate (b1, e1, &xflgs, MM_OPND); + if (b1 < 0) { /* upd flags in AC */ + AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); + return XT_NOSK; } + if (xflgs & XT_SFLG) b1 = b1 & XT_BYMASK; + else b1 = -1; } } + else b1 = f1; + if (b1 >= 0) { /* valid byte? */ + incstorebp (b1, p4, pflgs); /* store byte */ + AC(p3) = (AC(p3) - 1) & XLNTMASK; } /* update state */ + if (AC(ac) & XLNTMASK) AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); } return (AC(ac) & XLNTMASK)? XT_NOSK: XT_SKIP; /* Edit - checked against KS10 ucode @@ -406,80 +408,82 @@ case XT_EDIT: /* EDIT */ xflgs = AC(ac) & XFLGMASK; /* get xlation flags */ e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */ for (ppi = 1, ret = -1, flg = 0; ret < 0; flg++, ppi = 1) { - if (flg && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - pp = (int32) AC(ac) & AMASK; /* get pattern ptr */ - b1 = Read (pp, MM_OPND); /* get pattern word */ - pat = ED_PBYTE (b1, AC(ac)); /* get pattern byte */ - switch ((pat < 0100)? pat: ((pat >> ED_V_POPC) + 0100)) { - case ED_STOP: /* stop */ - ret = XT_SKIP; /* exit loop */ - break; - case ED_SELECT: /* select source */ - b1 = incloadbp (p1, pflgs); /* get src */ - entad = (e1 + ((int32) b1 >> 1)) & AMASK; - f1 = ((Read (entad, MM_OPND) >> ((b1 & 1)? 0: 18)) & RMASK); - i = XT_GETCODE (f1); - if (i & 2) xflgs = - (i & 1)? xflgs | XT_MFLG: xflgs & ~XT_MFLG; - switch (i) { - case 00: case 02: case 03: - if (xflgs & XT_SFLG) f1 = f1 & XT_BYMASK; - else { f1 = Read (INCA (ea), MM_OPND); - if (f1 == 0) break; } - incstorebp (f1, p4, pflgs); - break; - case 01: - ret = XT_NOSK; /* exit loop */ - break; - case 04: case 06: case 07: - xflgs = xflgs | XT_NFLG; - f1 = f1 & XT_BYMASK; - if ((xflgs & XT_SFLG) == 0) { - f2 = Read (ADDA (ea, 2), MM_OPND); - Write ((a10) AC(p3), AC(p4), MM_OPND); - if (f2) incstorebp (f2, p4, pflgs); - xflgs = xflgs | XT_SFLG; } - incstorebp (f1, p4, pflgs); - break; - case 05: - xflgs = xflgs | XT_NFLG; - ret = XT_NOSK; /* exit loop */ - break; } /* end case xlate op */ - break; + if (flg && (t = test_int ())) ABORT (t); + rlog = 0; /* clear log */ + pp = (int32) AC(ac) & AMASK; /* get pattern ptr */ + b1 = Read (pp, MM_OPND); /* get pattern word */ + pat = ED_PBYTE (b1, AC(ac)); /* get pattern byte */ + switch ((pat < 0100)? pat: ((pat >> ED_V_POPC) + 0100)) { + case ED_STOP: /* stop */ + ret = XT_SKIP; /* exit loop */ + break; + case ED_SELECT: /* select source */ + b1 = incloadbp (p1, pflgs); /* get src */ + entad = (e1 + ((int32) b1 >> 1)) & AMASK; + f1 = ((Read (entad, MM_OPND) >> ((b1 & 1)? 0: 18)) & RMASK); + i = XT_GETCODE (f1); + if (i & 2) xflgs = + (i & 1)? xflgs | XT_MFLG: xflgs & ~XT_MFLG; + switch (i) { + case 00: case 02: case 03: + if (xflgs & XT_SFLG) f1 = f1 & XT_BYMASK; + else { + f1 = Read (INCA (ea), MM_OPND); + if (f1 == 0) break; } + incstorebp (f1, p4, pflgs); + break; + case 01: + ret = XT_NOSK; /* exit loop */ + break; + case 04: case 06: case 07: + xflgs = xflgs | XT_NFLG; + f1 = f1 & XT_BYMASK; + if ((xflgs & XT_SFLG) == 0) { + f2 = Read (ADDA (ea, 2), MM_OPND); + Write ((a10) AC(p3), AC(p4), MM_OPND); + if (f2) incstorebp (f2, p4, pflgs); + xflgs = xflgs | XT_SFLG; } + incstorebp (f1, p4, pflgs); + break; + case 05: + xflgs = xflgs | XT_NFLG; + ret = XT_NOSK; /* exit loop */ + break; } /* end case xlate op */ + break; case ED_SIGST: /* start significance */ - if ((xflgs & XT_SFLG) == 0) { - f2 = Read (ADDA (ea, 2), MM_OPND); - Write ((a10) AC(p3), AC(p4), MM_OPND); - if (f2) incstorebp (f2, p4, pflgs); - xflgs = xflgs | XT_SFLG; } - break; + if ((xflgs & XT_SFLG) == 0) { + f2 = Read (ADDA (ea, 2), MM_OPND); + Write ((a10) AC(p3), AC(p4), MM_OPND); + if (f2) incstorebp (f2, p4, pflgs); + xflgs = xflgs | XT_SFLG; } + break; case ED_FLDSEP: /* separate fields */ - xflgs = 0; - break; + xflgs = 0; + break; case ED_EXCHMD: /* exchange */ - f2 = Read ((int32) (AC(p3) & AMASK), MM_OPND); - Write ((int32) (AC(p3) & AMASK), AC(p4), MM_OPND); - AC(p4) = f2; - break; + f2 = Read ((int32) (AC(p3) & AMASK), MM_OPND); + Write ((int32) (AC(p3) & AMASK), AC(p4), MM_OPND); + AC(p4) = f2; + break; case (0100 + (ED_MESSAG >> ED_V_POPC)): /* message */ - if (xflgs & XT_SFLG) - f1 = Read (ea + (pat & ED_M_NUM) + 1, MM_OPND); - else { f1 = Read (ea + 1, MM_OPND); - if (f1 == 0) break; } - incstorebp (f1, p4, pflgs); - break; + if (xflgs & XT_SFLG) + f1 = Read (ea + (pat & ED_M_NUM) + 1, MM_OPND); + else { + f1 = Read (ea + 1, MM_OPND); + if (f1 == 0) break; } + incstorebp (f1, p4, pflgs); + break; case (0100 + (ED_SKPM >> ED_V_POPC)): /* skip on M */ - if (xflgs & XT_MFLG) ppi = (pat & ED_M_NUM) + 2; - break; + if (xflgs & XT_MFLG) ppi = (pat & ED_M_NUM) + 2; + break; case (0100 + (ED_SKPN >> ED_V_POPC)): /* skip on N */ - if (xflgs & XT_NFLG) ppi = (pat & ED_M_NUM) + 2; - break; + if (xflgs & XT_NFLG) ppi = (pat & ED_M_NUM) + 2; + break; case (0100 + (ED_SKPA >> ED_V_POPC)): /* skip always */ - ppi = (pat & ED_M_NUM) + 2; - break; + ppi = (pat & ED_M_NUM) + 2; + break; default: /* NOP or undefined */ - break; } /* end case pttrn op */ + break; } /* end case pttrn op */ AC(ac) = AC(ac) + ((ppi & ED_M_PBYN) << ED_V_PBYN); AC(ac) = AC(ac) + (ppi >> 2) + ((AC(ac) & ED_PBYNO)? 1: 0); AC(ac) = xflgs | (AC(ac) & ~(XT_MBZE | XFLGMASK)); } @@ -631,8 +635,8 @@ int32 p, reg; while (logv) { XT_REMRLOG (reg, logv); /* get next reg */ if ((reg >= 0) && (reg < AC_NUM)) { - p = GET_P (AC(reg)) + GET_S (AC(reg)); /* get p + s */ - AC(reg) = PUT_P (AC(reg), p); } /* p <- p + s */ + p = GET_P (AC(reg)) + GET_S (AC(reg)); /* get p + s */ + AC(reg) = PUT_P (AC(reg), p); } /* p <- p + s */ } return; } diff --git a/PDP11/pdp11_cis.c b/PDP11/pdp11_cis.c index 96dbbb8c..c567dfb6 100644 --- a/PDP11/pdp11_cis.c +++ b/PDP11/pdp11_cis.c @@ -325,36 +325,36 @@ op = IR & 0177; /* IR <6:0> */ for (i = j = 0; (i < MAXOPN) && opntab[op][i]; i++) { /* parse operands */ switch (opntab[op][i]) { /* case on op type */ case R0_DESC: - arg[j++] = R[0]; - arg[j++] = R[1]; - break; + arg[j++] = R[0]; + arg[j++] = R[1]; + break; case R2_DESC: - arg[j++] = R[2]; - arg[j++] = R[3]; - break; + arg[j++] = R[2]; + arg[j++] = R[3]; + break; case R4_DESC: - arg[j++] = R[4]; - arg[j++] = R[5]; - break; + arg[j++] = R[4]; + arg[j++] = R[5]; + break; case R4_ARG: - arg[j++] = R[4]; - break; + arg[j++] = R[4]; + break; case IN_DESC: - addr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - arg[j++] = ReadW (addr | dsenable); - arg[j++] = ReadW (((addr + 2) & 0177777) | dsenable); - break; + addr = ReadW (PC | isenable); + PC = (PC + 2) & 0177777; + arg[j++] = ReadW (addr | dsenable); + arg[j++] = ReadW (((addr + 2) & 0177777) | dsenable); + break; case IN_DESC_R0: - addr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - R[0] = ReadW (addr | dsenable); - R[1] = ReadW (((addr + 2) & 0177777) | dsenable); - break; + addr = ReadW (PC | isenable); + PC = (PC + 2) & 0177777; + R[0] = ReadW (addr | dsenable); + R[1] = ReadW (((addr + 2) & 0177777) | dsenable); + break; case IN_ARG: - arg[j++] = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - break; } /* end case */ + arg[j++] = ReadW (PC | isenable); + PC = (PC + 2) & 0177777; + break; } /* end case */ } /* end for */ switch (op) { /* case on opcode */ @@ -387,23 +387,23 @@ switch (op) { /* case on opcode */ case 030: case 032: case 0130: case 0132: mvlnt = (A1LNT < A2LNT)? A1LNT: A2LNT; /* calc move lnt */ for (i = 0; i < mvlnt; i++) { - movbuf[i] = ReadB (((A1ADR + i) & 0177777) | dsenable); } + movbuf[i] = ReadB (((A1ADR + i) & 0177777) | dsenable); } for (i = 0; i < mvlnt; i++) { - t = movbuf[i]; - if (op & 2) t = ReadB (((A3ADR + t) & 0177777) | dsenable); - WriteB (t, ((A2ADR + i) & 0177777) | dsenable); } + t = movbuf[i]; + if (op & 2) t = ReadB (((A3ADR + t) & 0177777) | dsenable); + WriteB (t, ((A2ADR + i) & 0177777) | dsenable); } fill = A3LNT & 0377; /* do fill, if any */ for (i = mvlnt; i < A2LNT; i++) { - WriteB (fill, ((A2ADR + i) & 0177777) | dsenable); } + WriteB (fill, ((A2ADR + i) & 0177777) | dsenable); } t = A1LNT - A2LNT; /* src.lnt - dst.lnt */ N = GET_SIGN_W (t); /* set cc's from diff */ Z = GET_Z (t); V = GET_SIGN_W ((A1LNT ^ A2LNT) & (~A2LNT ^ t)); C = (A1LNT < A2LNT); if ((op & INLINE) == 0) { /* if reg, set reg */ - R[0] = C? 0: t & 0177777; - R[1] = R[2] = R[3] = 0; - R[4] = R[4] & 0377; } + R[0] = C? 0: t & 0177777; + R[1] = R[2] = R[3] = 0; + R[4] = R[4] & 0377; } return; /* MOVRC, MOVRCI @@ -428,22 +428,22 @@ case 031: case 0131: mvlnt = (A1LNT < A2LNT)? A1LNT: A2LNT; /* calc move lnt */ addr = A1ADR + A1LNT - mvlnt; for (i = 0; i < mvlnt; i++) { - movbuf[i] = ReadB (((addr + i) & 0177777) | dsenable); } + movbuf[i] = ReadB (((addr + i) & 0177777) | dsenable); } addr = A2ADR + A2LNT - mvlnt; for (i = 0; i < mvlnt; i++) { - WriteB (movbuf[i], ((addr + i) & 0177777) | dsenable); } + WriteB (movbuf[i], ((addr + i) & 0177777) | dsenable); } fill = A3LNT & 0377; /* do fill, if any */ for (i = mvlnt, j = 0; i < A2LNT; i++, j++) { - WriteB (fill, ((A2ADR + j) & 0177777) | dsenable); } + WriteB (fill, ((A2ADR + j) & 0177777) | dsenable); } t = A1LNT - A2LNT; /* src.lnt - dst.lnt */ N = GET_SIGN_W (t); /* set cc's from diff */ Z = GET_Z (t); V = GET_SIGN_W ((A1LNT ^ A2LNT) & (~A2LNT ^ t)); C = (A1LNT < A2LNT); if ((op & INLINE) == 0) { /* if reg, set reg */ - R[0] = C? 0: t & 0177777; - R[1] = R[2] = R[3] = 0; - R[4] = R[4] & 0377; } + R[0] = C? 0: t & 0177777; + R[1] = R[2] = R[3] = 0; + R[4] = R[4] & 0377; } return; /* Load descriptors - no operands */ @@ -457,9 +457,9 @@ case 064: case 065: case 066: case 067: t = R[rn]; spc = (rn == 7)? isenable: dsenable; for (j = 0; j < limit; j = j + 2) { /* loop for 2,3 dscr */ - addr = ReadW (((t + j) & 0177777) | spc); - R[j] = ReadW (addr | dsenable); - R[j + 1] = ReadW (((addr + 2) & 0177777) | dsenable); } + addr = ReadW (((t + j) & 0177777) | spc); + R[j] = ReadW (addr | dsenable); + R[j + 1] = ReadW (((addr + 2) & 0177777) | dsenable); } if (rn >= limit) R[rn] = (R[rn] + limit) & 0177777; return; @@ -480,9 +480,9 @@ case 064: case 065: case 066: case 067: case 040: case 041: case 0140: case 0141: match = A1LNT & 0377; /* match character */ for ( ; R[0] != 0; R[0]--) { /* loop */ - c = ReadB (R[1] | dsenable); /* get char */ - if ((c == match) ^ (op & 1)) break; /* = + LOC, != + SKP? */ - R[1] = (R[1] + 1) & 0177777; } + c = ReadB (R[1] | dsenable); /* get char */ + if ((c == match) ^ (op & 1)) break; /* = + LOC, != + SKP? */ + R[1] = (R[1] + 1) & 0177777; } N = GET_SIGN_W (R[0]); Z = GET_Z (R[0]); V = C = 0; @@ -507,10 +507,10 @@ case 040: case 041: case 0140: case 0141: case 042: case 043: case 0142: case 0143: mask = A1LNT & 0377; /* mask character */ for (; R[0] != 0; R[0]--) { /* loop */ - t = ReadB (R[1] | dsenable); /* get char as index */ - c = ReadB (((A1ADR + t) & 0177777) | dsenable); - if (((c & mask) != 0) ^ (op & 1)) break; /* != + SCN, = + SPN? */ - R[1] = (R[1] + 1) & 0177777; } + t = ReadB (R[1] | dsenable); /* get char as index */ + c = ReadB (((A1ADR + t) & 0177777) | dsenable); + if (((c & mask) != 0) ^ (op & 1)) break; /* != + SCN, = + SPN? */ + R[1] = (R[1] + 1) & 0177777; } N = GET_SIGN_W (R[0]); Z = GET_Z (R[0]); V = C = 0; @@ -536,24 +536,24 @@ case 042: case 043: case 0142: case 0143: case 044: case 0144: c = t = 0; for (i = 0; i < ((A1LNT > A2LNT)? A1LNT: A2LNT); i++) { - if (i < A1LNT) c = ReadB (((A1ADR + i) & 0177777) | dsenable); - else c = A3LNT & 0377; - if (i < A2LNT) t = ReadB (((A2ADR + i) & 0177777) | dsenable); - else t = A3LNT & 0377; - if (c != t) break; } + if (i < A1LNT) c = ReadB (((A1ADR + i) & 0177777) | dsenable); + else c = A3LNT & 0377; + if (i < A2LNT) t = ReadB (((A2ADR + i) & 0177777) | dsenable); + else t = A3LNT & 0377; + if (c != t) break; } j = c - t; /* last chars read */ N = GET_SIGN_B (j); /* set cc's */ Z = GET_Z (j); V = GET_SIGN_B ((c ^ t) & (~t ^ j)); C = (c < t); if ((op & INLINE) == 0) { /* if reg, set reg */ - j = (i > A1LNT)? A1LNT: i; /* #src1 chars used */ - k = (i > A2LNT)? A2LNT: i; /* #src2 chars used */ - R[0] = A1LNT - j; - R[1] = (A1ADR + j) & 0177777; - R[2] = A2LNT - k; - R[3] = (A2ADR + k) & 0177777; - R[4] = R[4] & 0377; } + j = (i > A1LNT)? A1LNT: i; /* #src1 chars used */ + k = (i > A2LNT)? A2LNT: i; /* #src2 chars used */ + R[0] = A1LNT - j; + R[1] = (A1ADR + j) & 0177777; + R[2] = A2LNT - k; + R[3] = (A2ADR + k) & 0177777; + R[4] = R[4] & 0377; } return; /* MATC, MATCI @@ -583,15 +583,15 @@ case 044: case 0144: case 0045: case 0145: for (match = 0; R[0] >= A1LNT; R[0]--) { /* loop thru string */ - for (i = 0, match = 1; match && (i < A1LNT); i++) { - c = ReadB (((R[1] + i) & 0177777) | dsenable); - t = ReadB (((A1ADR + i) & 0177777) | dsenable); - match = (c == t); } /* end for substring */ - if (match) break; /* exit if match */ - R[1] = (R[1] + 1) & 0177777; } /* end for string */ + for (i = 0, match = 1; match && (i < A1LNT); i++) { + c = ReadB (((R[1] + i) & 0177777) | dsenable); + t = ReadB (((A1ADR + i) & 0177777) | dsenable); + match = (c == t); } /* end for substring */ + if (match) break; /* exit if match */ + R[1] = (R[1] + 1) & 0177777; } /* end for string */ if (!match) { /* if no match */ - R[1] = (R[1] + R[0]) & 0177777; - R[0] = 0; } + R[1] = (R[1] + R[0]) & 0177777; + R[0] = 0; } N = GET_SIGN_W (R[0]); Z = GET_Z (R[0]); V = C = 0; @@ -618,19 +618,20 @@ case 0150: case 0151: case 0170: case 0171: ReadDstr (A2, &src2, op); /* get source2 */ if (op & 1) src1.sign = src1.sign ^ 1; /* sub? invert sign */ if (src1.sign ^ src2.sign) { /* opp signs? sub */ - if (CmpDstr (&src1, &src2) < 0) { /* src1 < src2? */ - SubDstr (&src1, &src2, &dst); /* src2 - src1 */ - dst.sign = src2.sign; } /* sign = src2 */ - else { SubDstr (&src2, &src1, &dst); /* src1 - src2 */ - dst.sign = src1.sign; } /* sign = src1 */ - V = 0; } /* can't carry */ + if (CmpDstr (&src1, &src2) < 0) { /* src1 < src2? */ + SubDstr (&src1, &src2, &dst); /* src2 - src1 */ + dst.sign = src2.sign; } /* sign = src2 */ + else { + SubDstr (&src2, &src1, &dst); /* src1 - src2 */ + dst.sign = src1.sign; } /* sign = src1 */ + V = 0; } /* can't carry */ else { /* addition */ - V = AddDstr (&src1, &src2, &dst, 0); /* add magnitudes */ - dst.sign = src1.sign; } /* set result sign */ + V = AddDstr (&src1, &src2, &dst, 0); /* add magnitudes */ + dst.sign = src1.sign; } /* set result sign */ C = 0; WriteDstr (A3, &dst, op); /* store result */ if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[2] = R[3] = 0; + R[0] = R[1] = R[2] = R[3] = 0; return; /* MULP, MULPI @@ -651,17 +652,17 @@ case 0150: case 0151: case 0170: case 0171: case 074: case 0174: dst = Dstr0; /* clear result */ if (ReadDstr (A1, &src1, op) && ReadDstr (A2, &src2, op)) { - dst.sign = src1.sign ^ src2.sign; /* sign of result */ - accum = Dstr0; /* clear accum */ - NibbleRshift (&src1, 1, 0); /* shift out sign */ - CreateTable (&src1, mptable); /* create *1, *2, ... */ - for (i = 1; i < (DSTRLNT * 8); i++) { /* 31 iterations */ - digit = (src2.val[i / 8] >> ((i % 8) * 4)) & 0xF; - if (digit > 0) /* add in digit*mpcnd */ - AddDstr (&mptable[digit], &accum, &accum, 0); - nc = NibbleRshift (&accum, 1, 0); /* ac right 4 */ - NibbleRshift (&dst, 1, nc); } /* result right 4 */ - V = TestDstr (&accum) != 0; } /* if ovflo, set V */ + dst.sign = src1.sign ^ src2.sign; /* sign of result */ + accum = Dstr0; /* clear accum */ + NibbleRshift (&src1, 1, 0); /* shift out sign */ + CreateTable (&src1, mptable); /* create *1, *2, ... */ + for (i = 1; i < (DSTRLNT * 8); i++) { /* 31 iterations */ + digit = (src2.val[i / 8] >> ((i % 8) * 4)) & 0xF; + if (digit > 0) /* add in digit*mpcnd */ + AddDstr (&mptable[digit], &accum, &accum, 0); + nc = NibbleRshift (&accum, 1, 0); /* ac right 4 */ + NibbleRshift (&dst, 1, nc); } /* result right 4 */ + V = TestDstr (&accum) != 0; } /* if ovflo, set V */ else V = 0; /* result = 0 */ C = 0; /* C = 0 */ WriteDstr (A3, &dst, op); /* store result */ @@ -687,8 +688,8 @@ case 074: case 0174: case 075: case 0175: ldivr = ReadDstr (A1, &src1, op); /* get divisor */ if (ldivr == 0) { /* divisor = 0? */ - V = C = 1; /* set cc's */ - return; } + V = C = 1; /* set cc's */ + return; } ldivr = LntDstr (&src1, ldivr); /* get exact length */ ldivd = ReadDstr (A2, &src2, op); /* get dividend */ ldivd = LntDstr (&src2, ldivd); /* get exact length */ @@ -696,24 +697,24 @@ case 075: case 0175: NibbleRshift (&src1, 1, 0); /* right justify ops */ NibbleRshift (&src2, 1, 0); if ((t = ldivd - ldivr) >= 0) { /* any divide to do? */ - WordLshift (&src1, t / 8); /* align divr to divd */ - NibbleLshift (&src1, t % 8, 0); - CreateTable (&src1, mptable); /* create *1, *2, ... */ - for (i = 0; i <= t; i++) { /* divide loop */ - for (digit = 9; digit > 0; digit--) { /* find digit */ - if (CmpDstr (&src2, &mptable[digit]) >= 0) { - SubDstr (&mptable[digit], &src2, &src2); - dst.val[0] = dst.val[0] | digit; - break; } } /* end if, for */ - NibbleLshift (&src2, 1, 0); /* shift dividend */ - NibbleLshift (&dst, 1, 0); /* shift quotient */ - } /* end divide loop */ - dst.sign = src1.sign ^ src2.sign; /* calculate sign */ - } /* end if */ + WordLshift (&src1, t / 8); /* align divr to divd */ + NibbleLshift (&src1, t % 8, 0); + CreateTable (&src1, mptable); /* create *1, *2, ... */ + for (i = 0; i <= t; i++) { /* divide loop */ + for (digit = 9; digit > 0; digit--) { /* find digit */ + if (CmpDstr (&src2, &mptable[digit]) >= 0) { + SubDstr (&mptable[digit], &src2, &src2); + dst.val[0] = dst.val[0] | digit; + break; } } /* end if, for */ + NibbleLshift (&src2, 1, 0); /* shift dividend */ + NibbleLshift (&dst, 1, 0); /* shift quotient */ + } /* end divide loop */ + dst.sign = src1.sign ^ src2.sign; /* calculate sign */ + } /* end if */ V = C = 0; WriteDstr (A3, &dst, op); /* store result */ if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[2] = R[3] = 0; + R[0] = R[1] = R[2] = R[3] = 0; return; /* CMPN, CMPP, CMPNI, CMPPI @@ -735,11 +736,12 @@ case 052: case 072: case 0152: case 0172: ReadDstr (A2, &src2, op); /* get source2 */ N = Z = V = C = 0; if (src1.sign != src2.sign) N = src1.sign; - else { t = CmpDstr (&src1, &src2); /* compare strings */ - if (t < 0) N = 1; - else if (t == 0) Z = 1; } + else { + t = CmpDstr (&src1, &src2); /* compare strings */ + if (t < 0) N = 1; + else if (t == 0) Z = 1; } if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[2] = R[3] = 0; + R[0] = R[1] = R[2] = R[3] = 0; return; /* ASHN, ASHP, ASHNI, ASHPI @@ -763,21 +765,21 @@ case 056: case 076: case 0156: case 0176: V = C = 0; /* init cc's */ shift = GET_ASHLNT (A3LNT); /* get shift count */ if (shift & ASHSGN) { /* right shift? */ - shift = (ASHLNT_M + 1 - shift); /* !shift! */ - WordRshift (&src1, shift / 8); /* do word shifts */ - NibbleRshift (&src1, shift % 8, 0); /* do nibble shifts */ - t = GET_ASHRND (A3LNT); /* get rounding digit */ - if ((t + (src1.val[0] & 0xF)) > 9) /* rounding needed? */ - AddDstr (&src1, &Dstr1, &src1, 0); /* round */ - src1.val[0] = src1.val[0] & ~0xF; /* clear sign */ + shift = (ASHLNT_M + 1 - shift); /* !shift! */ + WordRshift (&src1, shift / 8); /* do word shifts */ + NibbleRshift (&src1, shift % 8, 0); /* do nibble shifts */ + t = GET_ASHRND (A3LNT); /* get rounding digit */ + if ((t + (src1.val[0] & 0xF)) > 9) /* rounding needed? */ + AddDstr (&src1, &Dstr1, &src1, 0); /* round */ + src1.val[0] = src1.val[0] & ~0xF; /* clear sign */ } /* end right shift */ else if (shift) { /* left shift? */ - if (WordLshift (&src1, shift / 8)) V = 1; /* do word shifts */ - if (NibbleLshift (&src1, shift % 8, 0)) V = 1; + if (WordLshift (&src1, shift / 8)) V = 1; /* do word shifts */ + if (NibbleLshift (&src1, shift % 8, 0)) V = 1; } /* end left shift */ WriteDstr (A2, &src1, op); /* store result */ if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[4] = 0; + R[0] = R[1] = R[4] = 0; return; /* CVTPN, CVTPNI @@ -841,24 +843,25 @@ case 053: case 073: case 0153: case 0173: ReadDstr (A1, &src1, op); /* get source */ V = result = 0; /* clear V, result */ for (i = (DSTRLNT * 8) - 1; i > 0; i--) { /* loop thru digits */ - digit = (src1.val[i / 8] >> ((i % 8) * 4)) & 0xF; - if (digit || result || V) { /* skip initial 0's */ - if (result >= MAXDVAL) V = 1; - result = (result * 10) + digit; - if (result < digit) V = 1; } /* end if */ - } /* end for */ + digit = (src1.val[i / 8] >> ((i % 8) * 4)) & 0xF; + if (digit || result || V) { /* skip initial 0's */ + if (result >= MAXDVAL) V = 1; + result = (result * 10) + digit; + if (result < digit) V = 1; } /* end if */ + } /* end for */ if (src1.sign) result = (~result + 1) & 0xFFFFFFFF; N = GET_SIGN_L (result); Z = GET_Z (result); V = V | (N ^ src1.sign); /* overflow if +2**31 */ C = src1.sign && (Z == 0); /* set C based on std */ if (op & INLINE) { /* inline? */ - WriteW (result & 0177777, A2LNT | dsenable); - WriteW ((result >> 16) & 0177777, - ((A2LNT + 2) & 0177777) | dsenable); } - else { R[0] = R[1] = 0; - R[2] = (result >> 16) & 0177777; - R[3] = result & 0177777; } + WriteW (result & 0177777, A2LNT | dsenable); + WriteW ((result >> 16) & 0177777, + ((A2LNT + 2) & 0177777) | dsenable); } + else { + R[0] = R[1] = 0; + R[2] = (result >> 16) & 0177777; + R[3] = result & 0177777; } return; /* CVTLN, CVTLP, CVTLNI, CVTLPI @@ -886,9 +889,9 @@ CVTLx: dst = Dstr0; /* clear result */ if (dst.sign = GET_SIGN_L (result)) result = (~result + 1) & 0xFFFFFFFF; for (i = 1; (i < (DSTRLNT * 8)) && result; i++) { - digit = result % 10; - result = result / 10; - dst.val[i / 8] = dst.val[i / 8] | (digit << ((i % 8) * 4)); } + digit = result % 10; + result = result / 10; + dst.val[i / 8] = dst.val[i / 8] | (digit << ((i % 8) * 4)); } V = C = 0; WriteDstr (A1, &dst, op); /* write result */ return; @@ -932,31 +935,31 @@ lnt = GET_DLNT (dscr[0]); /* get string length */ if (flag & PACKED) { /* packed? */ end = lnt / 2; /* last byte */ for (i = 0; i <= end; i++) { /* loop thru string */ - c = ReadB (((dscr[1] + end - i) & 0177777) | dsenable); - if (i == 0) t = c & 0xF; /* save sign */ - if ((i == end) && ((lnt & 1) == 0)) c = c & 0xF; - if (c >= 0xA0) c = c & 0xF; /* check hi digit */ - if ((c & 0xF) >= 0xA) c = c & 0xF0; /* check lo digit */ - src->val[i / 4] = src->val[i / 4] | (c << ((i % 4) * 8)); - } /* end for */ + c = ReadB (((dscr[1] + end - i) & 0177777) | dsenable); + if (i == 0) t = c & 0xF; /* save sign */ + if ((i == end) && ((lnt & 1) == 0)) c = c & 0xF; + if (c >= 0xA0) c = c & 0xF; /* check hi digit */ + if ((c & 0xF) >= 0xA) c = c & 0xF0; /* check lo digit */ + src->val[i / 4] = src->val[i / 4] | (c << ((i % 4) * 8)); + } /* end for */ if ((t == 0xB) || (t == 0xD)) src->sign = 1; /* if -, set sign */ src->val[0] = src->val[0] & ~0xF; /* clear sign */ } /* end packed */ else { /* numeric */ if (type >= TS) src->sign = (ReadB ((((type == TS)? - dscr[1] + lnt: dscr[1] - 1) & 0177777) | dsenable) == '-'); + dscr[1] + lnt: dscr[1] - 1) & 0177777) | dsenable) == '-'); for (i = 1; i <= lnt; i++) { /* loop thru string */ - c = ReadB (((dscr[1] + lnt - i) & 0177777) | dsenable); - if ((i == 1) && (type == XZ) && ((c & 0xF0) == 0x70)) - src->sign = 1; /* signed zoned */ - else if (((i == 1) && (type == TO)) || - ((i == lnt) && (type == LO))) { - c = overbin[c & 0177]; /* get sign and digit */ - src->sign = c >> 7; } /* set sign */ - c = c & 0xF; /* get digit */ - if (c > 9) c = 0; /* range check */ - src->val[i / 8] = src->val[i / 8] | (c << ((i % 8) * 4)); - } /* end for */ + c = ReadB (((dscr[1] + lnt - i) & 0177777) | dsenable); + if ((i == 1) && (type == XZ) && ((c & 0xF0) == 0x70)) + src->sign = 1; /* signed zoned */ + else if (((i == 1) && (type == TO)) || + ((i == lnt) && (type == LO))) { + c = overbin[c & 0177]; /* get sign and digit */ + src->sign = c >> 7; } /* set sign */ + c = c & 0xF; /* get digit */ + if (c > 9) c = 0; /* range check */ + src->val[i / 8] = src->val[i / 8] | (c << ((i % 8) * 4)); + } /* end for */ } /* end numeric */ return TestDstr (src); /* clean -0 */ } @@ -1008,23 +1011,23 @@ if (flag & PACKED) { /* packed? */ if (type == UP) dst->val[0] = dst->val[0] | 0xF; else dst->val[0] = dst->val[0] | 0xC | dst->sign; for (i = 0; i <= end; i++) { /* store string */ - c = (dst->val[i / 4] >> ((i % 4) * 8)) & 0xFF; - WriteB (c, ((dscr[1] + end - i) & 0177777)); + c = (dst->val[i / 4] >> ((i % 4) * 8)) & 0xFF; + WriteB (c, ((dscr[1] + end - i) & 0177777)); } /* end for */ } /* end packed */ else { if (type >= TS) WriteB (dst->sign? '-': '+', (((type == TS)? - dscr[1] + lnt: dscr[1] - 1) & 0177777) | dsenable); + dscr[1] + lnt: dscr[1] - 1) & 0177777) | dsenable); for (i = 1; i <= lnt; i++) { /* store string */ - c = (dst->val[i / 8] >> ((i % 8) * 4)) & 0xF; /* get digit */ - if ((i == 1) && (type == XZ) && dst->sign) - c = c | 0x70; /* signed zoned */ - else if (((i == 1) && (type == TO)) || - ((i == lnt) && (type == LO))) - c = binover[dst->sign][c]; /* get sign and digit */ - else c = c | 0x30; /* default */ - WriteB (c, ((dscr[1] + lnt - i) & 0177777)); - } /* end for */ + c = (dst->val[i / 8] >> ((i % 8) * 4)) & 0xF; /* get digit */ + if ((i == 1) && (type == XZ) && dst->sign) + c = c | 0x70; /* signed zoned */ + else if (((i == 1) && (type == TO)) || + ((i == lnt) && (type == LO))) + c = binover[dst->sign][c]; /* get sign and digit */ + else c = c | 0x30; /* default */ + WriteB (c, ((dscr[1] + lnt - i) & 0177777)); + } /* end for */ } /* end numeric */ return; } @@ -1190,8 +1193,8 @@ int32 i; if (sc) { for (i = 0; i < DSTRLNT; i++) { - if ((i + sc) < DSTRLNT) dsrc->val[i] = dsrc->val[i + sc]; - else dsrc->val[i] = 0; } } + if ((i + sc) < DSTRLNT) dsrc->val[i] = dsrc->val[i + sc]; + else dsrc->val[i] = 0; } } return; } @@ -1209,9 +1212,9 @@ int32 i, c; c = 0; if (sc) { for (i = DSTRMAX; i >= 0; i--) { - if (i > (DSTRMAX - sc)) c = c | dsrc->val[i]; - if ((i - sc) >= 0) dsrc->val[i] = dsrc->val[i - sc]; - else dsrc->val[i] = 0; } } + if (i > (DSTRMAX - sc)) c = c | dsrc->val[i]; + if ((i - sc) >= 0) dsrc->val[i] = dsrc->val[i - sc]; + else dsrc->val[i] = 0; } } return c; } @@ -1230,10 +1233,10 @@ int32 i, s, rs, nc; if (s = sc * 4) { rs = 32 - s; for (i = DSTRMAX; i >= 0; i--) { - nc = dsrc->val[i]; - dsrc->val[i] = ((dsrc->val[i] >> s) | - (cin << rs)) & 0xFFFFFFFF; - cin = nc; } + nc = dsrc->val[i]; + dsrc->val[i] = ((dsrc->val[i] >> s) | + (cin << rs)) & 0xFFFFFFFF; + cin = nc; } return cin; } return 0; } @@ -1253,10 +1256,10 @@ int32 i, s, rs, nc; if (s = sc * 4) { rs = 32 - s; for (i = 0; i < DSTRLNT; i++) { - nc = dsrc->val[i]; - dsrc->val[i] = ((dsrc->val[i] << s) | - (cin >> rs)) & 0xFFFFFFFF; - cin = nc; } + nc = dsrc->val[i]; + dsrc->val[i] = ((dsrc->val[i] << s) | + (cin >> rs)) & 0xFFFFFFFF; + cin = nc; } return cin; } return 0; } diff --git a/PDP11/pdp11_cpu.c b/PDP11/pdp11_cpu.c index 9a37cc5d..44e00682 100644 --- a/PDP11/pdp11_cpu.c +++ b/PDP11/pdp11_cpu.c @@ -1,6 +1,6 @@ /* pdp11_cpu.c: PDP-11 CPU simulator - Copyright (c) 1993-2002, Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ cpu PDP-11 CPU (J-11 microprocessor) + 05-Jan-03 RMS Added memory size restore support 17-Oct-02 RMS Fixed bug in examine/deposit (found by Hans Pufal) 08-Oct-02 RMS Revised to build dib_tab dynamically Added SHOW IOSPACE @@ -559,7 +560,8 @@ DEVICE cpu_dev = { "CPU", &cpu_unit, cpu_reg, cpu_mod, 1, 8, 22, 2, 8, 16, &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; + NULL, NULL, NULL, + NULL, DEV_DYNM, &cpu_set_size }; t_stat sim_instr (void) { @@ -631,10 +633,10 @@ if (abortval != 0) { if ((trapea > 0) && (stop_vecabort)) reason = STOP_VECABORT; if ((trapea < 0) && (stop_spabort)) reason = STOP_SPABORT; if (trapea == ~KERNEL) { /* kernel stk abort? */ - setTRAP (TRAP_RED); - setCPUERR (CPUE_RED); - STACKFILE[KERNEL] = 4; - if (cm == KERNEL) SP = 4; } } + setTRAP (TRAP_RED); + setCPUERR (CPUE_RED); + STACKFILE[KERNEL] = 4; + if (cm == KERNEL) SP = 4; } } /* Main instruction fetch/decode loop @@ -662,23 +664,24 @@ if (sim_interval <= 0) { /* intv cnt expired? */ if (trap_req) { /* check traps, ints */ trapea = 0; /* assume srch fails */ if (t = trap_req & TRAP_ALL) { /* if a trap */ - for (trapnum = 0; trapnum < TRAP_V_MAX; trapnum++) { - if ((t >> trapnum) & 1) { /* trap set? */ - trapea = trap_vec[trapnum]; /* get vec, clr */ - trap_req = trap_req & ~trap_clear[trapnum]; - if ((stop_trap >> trapnum) & 1) /* stop on trap? */ - reason = trapnum + 1; - break; - } /* end if t & 1 */ - } /* end for */ - } /* end if t */ - else { trapea = get_vector (ipl); /* get int vector */ - trapnum = TRAP_V_MAX; /* defang stk trap */ - } /* end else t*/ + for (trapnum = 0; trapnum < TRAP_V_MAX; trapnum++) { + if ((t >> trapnum) & 1) { /* trap set? */ + trapea = trap_vec[trapnum]; /* get vec, clr */ + trap_req = trap_req & ~trap_clear[trapnum]; + if ((stop_trap >> trapnum) & 1) /* stop on trap? */ + reason = trapnum + 1; + break; + } /* end if t & 1 */ + } /* end for */ + } /* end if t */ + else { + trapea = get_vector (ipl); /* get int vector */ + trapnum = TRAP_V_MAX; /* defang stk trap */ + } /* end else t*/ if (trapea == 0) { /* nothing to do? */ - trap_req = calc_ints (ipl, 0); /* recalculate */ - continue; /* back to fetch */ - } /* end if trapea */ + trap_req = calc_ints (ipl, 0); /* recalculate */ + continue; /* back to fetch */ + } /* end if trapea */ /* Process a trap or interrupt @@ -715,9 +718,9 @@ if (trap_req) { /* check traps, ints */ V = (src2 >> PSW_V_V) & 01; C = (src2 >> PSW_V_C) & 01; if (rs != oldrs) { /* if rs chg, swap */ - for (i = 0; i < 6; i++) { - REGFILE[i][oldrs] = R[i]; - R[i] = REGFILE[i][rs]; } } + for (i = 0; i < 6; i++) { + REGFILE[i][oldrs] = R[i]; + R[i] = REGFILE[i][rs]; } } SP = (STACKFILE[cm] - 4) & 0177777; /* update SP, PC */ JMP_PC (src); isenable = calc_is (cm); @@ -725,8 +728,8 @@ if (trap_req) { /* check traps, ints */ trap_req = calc_ints (ipl, trap_req); if ((SP < STKLIM) && (cm == KERNEL) && (trapnum != TRAP_V_RED) && (trapnum != TRAP_V_YEL)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } + setTRAP (TRAP_YEL); + setCPUERR (CPUE_YEL); } continue; } /* end if traps */ /* Fetch and decode next instruction */ @@ -758,289 +761,292 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */ case 000: switch ((IR >> 6) & 077) { /* decode IR<11:6> */ case 000: /* no operand */ - if (IR >= 000010) { /* 000010 - 000077 */ - setTRAP (TRAP_ILL); /* illegal */ - break; } - switch (IR) { /* decode IR<2:0> */ - case 0: /* HALT */ - if ((cm == KERNEL) && ((MAINT & MAINT_HTRAP) == 0)) - reason = STOP_HALT; - else { setTRAP (TRAP_PRV); - setCPUERR (CPUE_HALT); } - break; - case 1: /* WAIT */ - if (cm == KERNEL && wait_enable) wait_state = 1; - break; - case 3: /* BPT */ - setTRAP (TRAP_BPT); - break; - case 4: /* IOT */ - setTRAP (TRAP_IOT); - break; - case 5: /* RESET */ - if (cm == KERNEL) { - reset_all (1); - PIRQ = 0; - for (i = 0; i < IPL_HLVL; i++) - int_req[i] = 0; - MMR0 = MMR0 & ~(MMR0_MME | MMR0_FREEZE); - MMR3 = 0; - trap_req = trap_req & ~TRAP_INT; - dsenable = calc_ds (cm); } - break; + if (IR >= 000010) { /* 000010 - 000077 */ + setTRAP (TRAP_ILL); /* illegal */ + break; } + switch (IR) { /* decode IR<2:0> */ + case 0: /* HALT */ + if ((cm == KERNEL) && ((MAINT & MAINT_HTRAP) == 0)) + reason = STOP_HALT; + else { + setTRAP (TRAP_PRV); + setCPUERR (CPUE_HALT); } + break; + case 1: /* WAIT */ + if (cm == KERNEL && wait_enable) wait_state = 1; + break; + case 3: /* BPT */ + setTRAP (TRAP_BPT); + break; + case 4: /* IOT */ + setTRAP (TRAP_IOT); + break; + case 5: /* RESET */ + if (cm == KERNEL) { + reset_all (1); + PIRQ = 0; + for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0; + MMR0 = MMR0 & ~(MMR0_MME | MMR0_FREEZE); + MMR3 = 0; + trap_req = trap_req & ~TRAP_INT; + dsenable = calc_ds (cm); } + break; /* Opcode 0: specials, continued */ - case 2: /* RTI */ - case 6: /* RTT */ - src = ReadW (SP | dsenable); - src2 = ReadW (((SP + 2) & 0177777) | dsenable); - STACKFILE[cm] = SP = (SP + 4) & 0177777; - oldrs = rs; - if (cm == KERNEL) { - cm = (src2 >> PSW_V_CM) & 03; - pm = (src2 >> PSW_V_PM) & 03; - rs = (src2 >> PSW_V_RS) & 01; - ipl = (src2 >> PSW_V_IPL) & 07; } - else { cm = cm | ((src2 >> PSW_V_CM) & 03); - pm = pm | ((src2 >> PSW_V_PM) & 03); - rs = rs | ((src2 >> PSW_V_RS) & 01); } - tbit = (src2 >> PSW_V_TBIT) & 01; - N = (src2 >> PSW_V_N) & 01; - Z = (src2 >> PSW_V_Z) & 01; - V = (src2 >> PSW_V_V) & 01; - C = (src2 >> PSW_V_C) & 01; - trap_req = calc_ints (ipl, trap_req); - isenable = calc_is (cm); - dsenable = calc_ds (cm); - if (rs != oldrs) { - for (i = 0; i < 6; i++) { - REGFILE[i][oldrs] = R[i]; - R[i] = REGFILE[i][rs]; } } - SP = STACKFILE[cm]; - JMP_PC (src); - if ((IR == 000002) && tbit) setTRAP (TRAP_TRC); - break; - case 7: /* MFPT */ - R[0] = 5; /* report J-11 */ - break; } /* end switch no ops */ - break; /* end case no ops */ + case 2: /* RTI */ + case 6: /* RTT */ + src = ReadW (SP | dsenable); + src2 = ReadW (((SP + 2) & 0177777) | dsenable); + STACKFILE[cm] = SP = (SP + 4) & 0177777; + oldrs = rs; + if (cm == KERNEL) { + cm = (src2 >> PSW_V_CM) & 03; + pm = (src2 >> PSW_V_PM) & 03; + rs = (src2 >> PSW_V_RS) & 01; + ipl = (src2 >> PSW_V_IPL) & 07; } + else { + cm = cm | ((src2 >> PSW_V_CM) & 03); + pm = pm | ((src2 >> PSW_V_PM) & 03); + rs = rs | ((src2 >> PSW_V_RS) & 01); } + tbit = (src2 >> PSW_V_TBIT) & 01; + N = (src2 >> PSW_V_N) & 01; + Z = (src2 >> PSW_V_Z) & 01; + V = (src2 >> PSW_V_V) & 01; + C = (src2 >> PSW_V_C) & 01; + trap_req = calc_ints (ipl, trap_req); + isenable = calc_is (cm); + dsenable = calc_ds (cm); + if (rs != oldrs) { + for (i = 0; i < 6; i++) { + REGFILE[i][oldrs] = R[i]; + R[i] = REGFILE[i][rs]; } } + SP = STACKFILE[cm]; + JMP_PC (src); + if ((IR == 000002) && tbit) setTRAP (TRAP_TRC); + break; + case 7: /* MFPT */ + R[0] = 5; /* report J-11 */ + break; } /* end switch no ops */ + break; /* end case no ops */ /* Opcode 0: specials, continued */ case 001: /* JMP */ - if (dstreg) setTRAP (TRAP_ILL); - else { JMP_PC (GeteaW (dstspec) & 0177777); } - break; /* end JMP */ + if (dstreg) setTRAP (TRAP_ILL); + else { + JMP_PC (GeteaW (dstspec) & 0177777); } + break; /* end JMP */ case 002: /* RTS et al*/ - if (IR < 000210) { /* RTS */ - dstspec = dstspec & 07; - JMP_PC (R[dstspec]); - R[dstspec] = ReadW (SP | dsenable); - if (dstspec != 6) SP = (SP + 2) & 0177777; - break; } /* end if RTS */ - if (IR < 000230) { - setTRAP (TRAP_ILL); - break; } - if (IR < 000240) { /* SPL */ - if (cm == KERNEL) ipl = IR & 07; - trap_req = calc_ints (ipl, trap_req); - break; } /* end if SPL */ - if (IR < 000260) { /* clear CC */ - if (IR & 010) N = 0; - if (IR & 004) Z = 0; - if (IR & 002) V = 0; - if (IR & 001) C = 0; - break; } /* end if clear CCs */ - if (IR & 010) N = 1; /* set CC */ - if (IR & 004) Z = 1; - if (IR & 002) V = 1; - if (IR & 001) C = 1; - break; /* end case RTS et al */ + if (IR < 000210) { /* RTS */ + dstspec = dstspec & 07; + JMP_PC (R[dstspec]); + R[dstspec] = ReadW (SP | dsenable); + if (dstspec != 6) SP = (SP + 2) & 0177777; + break; } /* end if RTS */ + if (IR < 000230) { + setTRAP (TRAP_ILL); + break; } + if (IR < 000240) { /* SPL */ + if (cm == KERNEL) ipl = IR & 07; + trap_req = calc_ints (ipl, trap_req); + break; } /* end if SPL */ + if (IR < 000260) { /* clear CC */ + if (IR & 010) N = 0; + if (IR & 004) Z = 0; + if (IR & 002) V = 0; + if (IR & 001) C = 0; + break; } /* end if clear CCs */ + if (IR & 010) N = 1; /* set CC */ + if (IR & 004) Z = 1; + if (IR & 002) V = 1; + if (IR & 001) C = 1; + break; /* end case RTS et al */ case 003: /* SWAB */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = ((dst & 0377) << 8) | ((dst >> 8) & 0377); - N = GET_SIGN_B (dst & 0377); - Z = GET_Z (dst & 0377); - V = C = 0; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; /* end SWAB */ + dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = ((dst & 0377) << 8) | ((dst >> 8) & 0377); + N = GET_SIGN_B (dst & 0377); + Z = GET_Z (dst & 0377); + V = C = 0; + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; /* end SWAB */ /* Opcode 0: branches, JSR */ case 004: case 005: /* BR */ - BRANCH_F (IR); - break; + BRANCH_F (IR); + break; case 006: case 007: /* BR */ - BRANCH_B (IR); - break; + BRANCH_B (IR); + break; case 010: case 011: /* BNE */ - if (Z == 0) { BRANCH_F (IR); } - break; + if (Z == 0) { BRANCH_F (IR); } + break; case 012: case 013: /* BNE */ - if (Z == 0) { BRANCH_B (IR); } - break; + if (Z == 0) { BRANCH_B (IR); } + break; case 014: case 015: /* BEQ */ - if (Z) { BRANCH_F (IR); } - break; + if (Z) { BRANCH_F (IR); } + break; case 016: case 017: /* BEQ */ - if (Z) { BRANCH_B (IR); } - break; + if (Z) { BRANCH_B (IR); } + break; case 020: case 021: /* BGE */ - if ((N ^ V) == 0) { BRANCH_F (IR); } - break; + if ((N ^ V) == 0) { BRANCH_F (IR); } + break; case 022: case 023: /* BGE */ - if ((N ^ V) == 0) { BRANCH_B (IR); } - break; + if ((N ^ V) == 0) { BRANCH_B (IR); } + break; case 024: case 025: /* BLT */ - if (N ^ V) { BRANCH_F (IR); } - break; + if (N ^ V) { BRANCH_F (IR); } + break; case 026: case 027: /* BLT */ - if (N ^ V) { BRANCH_B (IR); } - break; + if (N ^ V) { BRANCH_B (IR); } + break; case 030: case 031: /* BGT */ - if ((Z | (N ^ V)) == 0) { BRANCH_F (IR); } - break; + if ((Z | (N ^ V)) == 0) { BRANCH_F (IR); } + break; case 032: case 033: /* BGT */ - if ((Z | (N ^ V)) == 0) { BRANCH_B (IR); } - break; + if ((Z | (N ^ V)) == 0) { BRANCH_B (IR); } + break; case 034: case 035: /* BLE */ - if (Z | (N ^ V)) { BRANCH_F (IR); } - break; + if (Z | (N ^ V)) { BRANCH_F (IR); } + break; case 036: case 037: /* BLE */ - if (Z | (N ^ V)) { BRANCH_B (IR); } - break; + if (Z | (N ^ V)) { BRANCH_B (IR); } + break; case 040: case 041: case 042: case 043: /* JSR */ case 044: case 045: case 046: case 047: - if (dstreg) setTRAP (TRAP_ILL); - else { srcspec = srcspec & 07; - dst = GeteaW (dstspec); - SP = (SP - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0366); - WriteW (R[srcspec], SP | dsenable); - if ((SP < STKLIM) && (cm == KERNEL)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - R[srcspec] = PC; - JMP_PC (dst & 0177777); } - break; /* end JSR */ + if (dstreg) setTRAP (TRAP_ILL); + else { + srcspec = srcspec & 07; + dst = GeteaW (dstspec); + SP = (SP - 2) & 0177777; + if (update_MM) MMR1 = calc_MMR1 (0366); + WriteW (R[srcspec], SP | dsenable); + if ((SP < STKLIM) && (cm == KERNEL)) { + setTRAP (TRAP_YEL); + setCPUERR (CPUE_YEL); } + R[srcspec] = PC; + JMP_PC (dst & 0177777); } + break; /* end JSR */ /* Opcode 0: SOPs */ case 050: /* CLR */ - N = V = C = 0; - Z = 1; - if (dstreg) R[dstspec] = 0; - else WriteW (0, GeteaW (dstspec)); - break; + N = V = C = 0; + Z = 1; + if (dstreg) R[dstspec] = 0; + else WriteW (0, GeteaW (dstspec)); + break; case 051: /* COM */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = dst ^ 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - C = 1; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = dst ^ 0177777; + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = 0; + C = 1; + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; case 052: /* INC */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (dst + 1) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = (dst == 0100000); - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = (dst + 1) & 0177777; + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = (dst == 0100000); + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; case 053: /* DEC */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (dst - 1) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = (dst == 077777); - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = (dst - 1) & 0177777; + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = (dst == 077777); + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; case 054: /* NEG */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (-dst) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = (dst == 0100000); - C = Z ^ 1; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = (-dst) & 0177777; + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = (dst == 0100000); + C = Z ^ 1; + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; case 055: /* ADC */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (dst + C) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = (C && (dst == 0100000)); - C = C & Z; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = (dst + C) & 0177777; + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = (C && (dst == 0100000)); + C = C & Z; + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; /* Opcode 0: SOPs, continued */ case 056: /* SBC */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (dst - C) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = (C && (dst == 077777)); - C = (C && (dst == 0177777)); - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = (dst - C) & 0177777; + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = (C && (dst == 077777)); + C = (C && (dst == 0177777)); + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; case 057: /* TST */ - dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = C = 0; - break; + dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = C = 0; + break; case 060: /* ROR */ - src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (src >> 1) | (C << 15); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - C = (src & 1); - V = N ^ C; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = (src >> 1) | (C << 15); + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + C = (src & 1); + V = N ^ C; + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; case 061: /* ROL */ - src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = ((src << 1) | C) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - C = GET_SIGN_W (src); - V = N ^ C; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = ((src << 1) | C) & 0177777; + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + C = GET_SIGN_W (src); + V = N ^ C; + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; case 062: /* ASR */ - src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (src >> 1) | (src & 0100000); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - C = (src & 1); - V = N ^ C; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = (src >> 1) | (src & 0100000); + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + C = (src & 1); + V = N ^ C; + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; case 063: /* ASL */ - src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = (src << 1) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - C = GET_SIGN_W (src); - V = N ^ C; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = (src << 1) & 0177777; + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + C = GET_SIGN_W (src); + V = N ^ C; + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; /* Opcode 0: SOPS, continued @@ -1050,89 +1056,92 @@ case 000: */ case 064: /* MARK */ - i = (PC + dstspec + dstspec) & 0177777; - JMP_PC (R[5]); - R[5] = ReadW (i | dsenable); - SP = (i + 2) & 0177777; - break; + i = (PC + dstspec + dstspec) & 0177777; + JMP_PC (R[5]); + R[5] = ReadW (i | dsenable); + SP = (i + 2) & 0177777; + break; case 065: /* MFPI */ - if (dstreg) { - if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm]; - else dst = R[dstspec]; } - else { i = ((cm == pm) && (cm == USER))? - calc_ds (pm): calc_is (pm); - dst = ReadW ((GeteaW (dstspec) & 0177777) | i); } - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - SP = (SP - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0366); - WriteW (dst, SP | dsenable); - if ((cm == KERNEL) && (SP < STKLIM)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - break; + if (dstreg) { + if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm]; + else dst = R[dstspec]; } + else { + i = ((cm == pm) && (cm == USER))? calc_ds (pm): calc_is (pm); + dst = ReadW ((GeteaW (dstspec) & 0177777) | i); } + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = 0; + SP = (SP - 2) & 0177777; + if (update_MM) MMR1 = calc_MMR1 (0366); + WriteW (dst, SP | dsenable); + if ((cm == KERNEL) && (SP < STKLIM)) { + setTRAP (TRAP_YEL); + setCPUERR (CPUE_YEL); } + break; case 066: /* MTPI */ - dst = ReadW (SP | dsenable); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - SP = (SP + 2) & 0177777; - if (update_MM) MMR1 = 026; - if (dstreg) { - if ((dstspec == 6) && (cm != pm)) STACKFILE[pm] = dst; - else R[dstspec] = dst; } - else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_is (pm)); - break; + dst = ReadW (SP | dsenable); + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = 0; + SP = (SP + 2) & 0177777; + if (update_MM) MMR1 = 026; + if (dstreg) { + if ((dstspec == 6) && (cm != pm)) STACKFILE[pm] = dst; + else R[dstspec] = dst; } + else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_is (pm)); + break; case 067: /* SXT */ - dst = N? 0177777: 0; - Z = N ^ 1; - V = 0; - if (dstreg) R[dstspec] = dst; - else WriteW (dst, GeteaW (dstspec)); - break; + dst = N? 0177777: 0; + Z = N ^ 1; + V = 0; + if (dstreg) R[dstspec] = dst; + else WriteW (dst, GeteaW (dstspec)); + break; /* Opcode 0: SOPs, continued */ case 070: /* CSM */ - if (((MMR3 & MMR3_CSM) == 0) || (cm == KERNEL)) - setTRAP (TRAP_ILL); - else { dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - PSW = (cm << PSW_V_CM) | (pm << PSW_V_PM) | - (rs << PSW_V_RS) | (ipl << PSW_V_IPL) | - (tbit << PSW_V_TBIT); - STACKFILE[cm] = SP; - WriteW (PSW, ((SP - 2) & 0177777) | calc_ds (SUPER)); - WriteW (PC, ((SP - 4) & 0177777) | calc_ds (SUPER)); - WriteW (dst, ((SP - 6) & 0177777) | calc_ds (SUPER)); - SP = (SP - 6) & 0177777; - pm = cm; - cm = SUPER; - tbit = 0; - isenable = calc_is (cm); - dsenable = calc_ds (cm); - PC = ReadW (010 | isenable); } - break; + if (((MMR3 & MMR3_CSM) == 0) || (cm == KERNEL)) + setTRAP (TRAP_ILL); + else { + dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); + PSW = (cm << PSW_V_CM) | (pm << PSW_V_PM) | + (rs << PSW_V_RS) | (ipl << PSW_V_IPL) | + (tbit << PSW_V_TBIT); + STACKFILE[cm] = SP; + WriteW (PSW, ((SP - 2) & 0177777) | calc_ds (SUPER)); + WriteW (PC, ((SP - 4) & 0177777) | calc_ds (SUPER)); + WriteW (dst, ((SP - 6) & 0177777) | calc_ds (SUPER)); + SP = (SP - 6) & 0177777; + pm = cm; + cm = SUPER; + tbit = 0; + isenable = calc_is (cm); + dsenable = calc_ds (cm); + PC = ReadW (010 | isenable); } + break; case 072: /* TSTSET */ - if (dstreg) setTRAP (TRAP_ILL); - else { dst = ReadMW (GeteaW (dstspec)); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - C = (dst & 1); - R[0] = dst; /* R[0] <- dst */ - PWriteW (R[0] | 1, last_pa); } /* dst <- R[0] | 1 */ - break; + if (dstreg) setTRAP (TRAP_ILL); + else { + dst = ReadMW (GeteaW (dstspec)); + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = 0; + C = (dst & 1); + R[0] = dst; /* R[0] <- dst */ + PWriteW (R[0] | 1, last_pa); } /* dst <- R[0] | 1 */ + break; case 073: /* WRTLCK */ - if (dstreg) setTRAP (TRAP_ILL); - else { N = GET_SIGN_W (R[0]); - Z = GET_Z (R[0]); - V = 0; - WriteW (R[0], GeteaW (dstspec)); } + if (dstreg) setTRAP (TRAP_ILL); + else { + N = GET_SIGN_W (R[0]); + Z = GET_Z (R[0]); + V = 0; + WriteW (R[0], GeteaW (dstspec)); } break; default: - setTRAP (TRAP_ILL); - break; } /* end switch SOPs */ + setTRAP (TRAP_ILL); + break; } /* end switch SOPs */ break; /* end case 000 */ /* Opcodes 01 - 06: double operand word instructions @@ -1148,10 +1157,11 @@ case 000: case 001: /* MOV */ if (srcreg && !dstreg) { /* R,not R */ - ea = GeteaW (dstspec); - dst = R[srcspec]; } - else { dst = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - if (!dstreg) ea = GeteaW (dstspec); } + ea = GeteaW (dstspec); + dst = R[srcspec]; } + else { + dst = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); + if (!dstreg) ea = GeteaW (dstspec); } N = GET_SIGN_W (dst); Z = GET_Z (dst); V = 0; @@ -1160,10 +1170,11 @@ case 001: /* MOV */ break; case 002: /* CMP */ if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadW (GeteaW (dstspec)); - src = R[srcspec]; } - else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); } + src2 = ReadW (GeteaW (dstspec)); + src = R[srcspec]; } + else { + src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); + src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); } dst = (src - src2) & 0177777; N = GET_SIGN_W (dst); Z = GET_Z (dst); @@ -1172,10 +1183,11 @@ case 002: /* CMP */ break; case 003: /* BIT */ if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadW (GeteaW (dstspec)); - src = R[srcspec]; } - else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); } + src2 = ReadW (GeteaW (dstspec)); + src = R[srcspec]; } + else { + src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); + src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); } dst = src2 & src; N = GET_SIGN_W (dst); Z = GET_Z (dst); @@ -1183,10 +1195,11 @@ case 003: /* BIT */ break; case 004: /* BIC */ if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMW (GeteaW (dstspec)); - src = R[srcspec]; } - else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } + src2 = ReadMW (GeteaW (dstspec)); + src = R[srcspec]; } + else { + src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); + src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } dst = src2 & ~src; N = GET_SIGN_W (dst); Z = GET_Z (dst); @@ -1196,10 +1209,11 @@ case 004: /* BIC */ break; case 005: /* BIS */ if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMW (GeteaW (dstspec)); - src = R[srcspec]; } - else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } + src2 = ReadMW (GeteaW (dstspec)); + src = R[srcspec]; } + else { + src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); + src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } dst = src2 | src; N = GET_SIGN_W (dst); Z = GET_Z (dst); @@ -1209,10 +1223,11 @@ case 005: /* BIS */ break; case 006: /* ADD */ if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMW (GeteaW (dstspec)); - src = R[srcspec]; } - else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } + src2 = ReadMW (GeteaW (dstspec)); + src = R[srcspec]; } + else { + src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); + src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } dst = (src2 + src) & 0177777; N = GET_SIGN_W (dst); Z = GET_Z (dst); @@ -1243,123 +1258,123 @@ case 007: srcspec = srcspec & 07; switch ((IR >> 9) & 07) { /* decode IR<11:9> */ case 0: /* MUL */ - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - src = R[srcspec]; - if (GET_SIGN_W (src2)) src2 = src2 | ~077777; - if (GET_SIGN_W (src)) src = src | ~077777; - dst = src * src2; - R[srcspec] = (dst >> 16) & 0177777; - R[srcspec | 1] = dst & 0177777; - N = (dst < 0); - Z = GET_Z (dst); - V = 0; - C = ((dst > 077777) || (dst < -0100000)); - break; + src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); + src = R[srcspec]; + if (GET_SIGN_W (src2)) src2 = src2 | ~077777; + if (GET_SIGN_W (src)) src = src | ~077777; + dst = src * src2; + R[srcspec] = (dst >> 16) & 0177777; + R[srcspec | 1] = dst & 0177777; + N = (dst < 0); + Z = GET_Z (dst); + V = 0; + C = ((dst > 077777) || (dst < -0100000)); + break; case 1: /* DIV */ - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1]; - if (src2 == 0) { - N = 0; /* J11,11/70 compat */ - Z = V = C = 1; /* N = 0, Z = 1 */ - break; } - if ((src == 020000000000) && (src2 == 0177777)) { - V = 1; /* J11,11/70 compat */ - N = Z = C = 0; /* N = Z = 0 */ - break; } - if (GET_SIGN_W (src2)) src2 = src2 | ~077777; - if (GET_SIGN_W (R[srcspec])) src = src | ~017777777777; - dst = src / src2; - N = (dst < 0); /* N set on 32b result */ - if ((dst > 077777) || (dst < -0100000)) { - V = 1; /* J11,11/70 compat */ - Z = C = 0; /* Z = C = 0 */ - break; } - R[srcspec] = dst & 0177777; - R[srcspec | 1] = (src - (src2 * dst)) & 0177777; - Z = GET_Z (dst); - V = C = 0; - break; + src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); + src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1]; + if (src2 == 0) { + N = 0; /* J11,11/70 compat */ + Z = V = C = 1; /* N = 0, Z = 1 */ + break; } + if ((src == 020000000000) && (src2 == 0177777)) { + V = 1; /* J11,11/70 compat */ + N = Z = C = 0; /* N = Z = 0 */ + break; } + if (GET_SIGN_W (src2)) src2 = src2 | ~077777; + if (GET_SIGN_W (R[srcspec])) src = src | ~017777777777; + dst = src / src2; + N = (dst < 0); /* N set on 32b result */ + if ((dst > 077777) || (dst < -0100000)) { + V = 1; /* J11,11/70 compat */ + Z = C = 0; /* Z = C = 0 */ + break; } + R[srcspec] = dst & 0177777; + R[srcspec | 1] = (src - (src2 * dst)) & 0177777; + Z = GET_Z (dst); + V = C = 0; + break; /* Opcode 7: EIS, continued */ case 2: /* ASH */ - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - src2 = src2 & 077; - sign = GET_SIGN_W (R[srcspec]); - src = sign? R[srcspec] | ~077777: R[srcspec]; - if (src2 == 0) { /* [0] */ - dst = src; - V = C = 0; } - else if (src2 <= 15) { /* [1,15] */ - dst = src << src2; - i = (src >> (16 - src2)) & 0177777; - V = (i != ((dst & 0100000)? 0177777: 0)); - C = (i & 1); } - else if (src2 <= 31) { /* [16,31] */ - dst = 0; - V = (src != 0); - C = (src << (src2 - 16)) & 1; } - else if (src2 == 32) { /* [32] = -32 */ - dst = -sign; - V = C = 0; } - else { /* [33,63] = -31,-1 */ - dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); - V = 0; - C = ((src >> (63 - src2)) & 1); } - dst = R[srcspec] = dst & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - break; + src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); + src2 = src2 & 077; + sign = GET_SIGN_W (R[srcspec]); + src = sign? R[srcspec] | ~077777: R[srcspec]; + if (src2 == 0) { /* [0] */ + dst = src; + V = C = 0; } + else if (src2 <= 15) { /* [1,15] */ + dst = src << src2; + i = (src >> (16 - src2)) & 0177777; + V = (i != ((dst & 0100000)? 0177777: 0)); + C = (i & 1); } + else if (src2 <= 31) { /* [16,31] */ + dst = 0; + V = (src != 0); + C = (src << (src2 - 16)) & 1; } + else if (src2 == 32) { /* [32] = -32 */ + dst = -sign; + V = C = 0; } + else { /* [33,63] = -31,-1 */ + dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); + V = 0; + C = ((src >> (63 - src2)) & 1); } + dst = R[srcspec] = dst & 0177777; + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + break; case 3: /* ASHC */ - src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - src2 = src2 & 077; - sign = GET_SIGN_W (R[srcspec]); - src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1]; - if (src2 == 0) { /* [0] */ - dst = src; - V = C = 0; } - else if (src2 <= 31) { /* [1,31] */ - dst = ((uint32) src) << src2; - i = (src >> (32 - src2)) | (-sign << src2); - V = (i != ((dst & 020000000000)? -1: 0)); - C = (i & 1); } - else if (src2 == 32) { /* [32] = -32 */ - dst = -sign; - V = 0; - C = (src >> 31) & 1; } - else { /* [33,63] = -31,-1 */ - dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); - V = 0; - C = ((src >> (63 - src2)) & 1); } - i = R[srcspec] = (dst >> 16) & 0177777; - dst = R[srcspec | 1] = dst & 0177777; - N = GET_SIGN_W (i); - Z = GET_Z (dst | i); - break; + src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); + src2 = src2 & 077; + sign = GET_SIGN_W (R[srcspec]); + src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1]; + if (src2 == 0) { /* [0] */ + dst = src; + V = C = 0; } + else if (src2 <= 31) { /* [1,31] */ + dst = ((uint32) src) << src2; + i = (src >> (32 - src2)) | (-sign << src2); + V = (i != ((dst & 020000000000)? -1: 0)); + C = (i & 1); } + else if (src2 == 32) { /* [32] = -32 */ + dst = -sign; + V = 0; + C = (src >> 31) & 1; } + else { /* [33,63] = -31,-1 */ + dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); + V = 0; + C = ((src >> (63 - src2)) & 1); } + i = R[srcspec] = (dst >> 16) & 0177777; + dst = R[srcspec | 1] = dst & 0177777; + N = GET_SIGN_W (i); + Z = GET_Z (dst | i); + break; /* Opcode 7: EIS, continued */ case 4: /* XOR */ - dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); - dst = dst ^ R[srcspec]; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); + dst = dst ^ R[srcspec]; + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = 0; + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; case 5: /* FIS - not impl */ - setTRAP (TRAP_ILL); - break; + setTRAP (TRAP_ILL); + break; case 6: /* CIS - not impl */ - if (cpu_unit.flags & UNIT_CIS) cis11 (IR); - else setTRAP (TRAP_ILL); - break; + if (cpu_unit.flags & UNIT_CIS) cis11 (IR); + else setTRAP (TRAP_ILL); + break; case 7: /* SOB */ - R[srcspec] = (R[srcspec] - 1) & 0177777; - if (R[srcspec]) { - JMP_PC ((PC - dstspec - dstspec) & 0177777); } - break; } /* end switch EIS */ + R[srcspec] = (R[srcspec] - 1) & 0177777; + if (R[srcspec]) { + JMP_PC ((PC - dstspec - dstspec) & 0177777); } + break; } /* end switch EIS */ break; /* end case 007 */ /* Opcode 10: branches, traps, SOPs */ @@ -1367,175 +1382,175 @@ case 007: case 010: switch ((IR >> 6) & 077) { /* decode IR<11:6> */ case 000: case 001: /* BPL */ - if (N == 0) { BRANCH_F (IR); } - break; + if (N == 0) { BRANCH_F (IR); } + break; case 002: case 003: /* BPL */ - if (N == 0) { BRANCH_B (IR); } - break; + if (N == 0) { BRANCH_B (IR); } + break; case 004: case 005: /* BMI */ - if (N) { BRANCH_F (IR); } - break; + if (N) { BRANCH_F (IR); } + break; case 006: case 007: /* BMI */ - if (N) { BRANCH_B (IR); } - break; + if (N) { BRANCH_B (IR); } + break; case 010: case 011: /* BHI */ - if ((C | Z) == 0) { BRANCH_F (IR); } - break; + if ((C | Z) == 0) { BRANCH_F (IR); } + break; case 012: case 013: /* BHI */ - if ((C | Z) == 0) { BRANCH_B (IR); } - break; + if ((C | Z) == 0) { BRANCH_B (IR); } + break; case 014: case 015: /* BLOS */ - if (C | Z) { BRANCH_F (IR); } - break; + if (C | Z) { BRANCH_F (IR); } + break; case 016: case 017: /* BLOS */ - if (C | Z) { BRANCH_B (IR); } - break; + if (C | Z) { BRANCH_B (IR); } + break; case 020: case 021: /* BVC */ - if (V == 0) { BRANCH_F (IR); } - break; + if (V == 0) { BRANCH_F (IR); } + break; case 022: case 023: /* BVC */ - if (V == 0) { BRANCH_B (IR); } - break; + if (V == 0) { BRANCH_B (IR); } + break; case 024: case 025: /* BVS */ - if (V) { BRANCH_F (IR); } - break; + if (V) { BRANCH_F (IR); } + break; case 026: case 027: /* BVS */ - if (V) { BRANCH_B (IR); } - break; + if (V) { BRANCH_B (IR); } + break; case 030: case 031: /* BCC */ - if (C == 0) { BRANCH_F (IR); } - break; + if (C == 0) { BRANCH_F (IR); } + break; case 032: case 033: /* BCC */ - if (C == 0) { BRANCH_B (IR); } - break; + if (C == 0) { BRANCH_B (IR); } + break; case 034: case 035: /* BCS */ - if (C) { BRANCH_F (IR); } - break; + if (C) { BRANCH_F (IR); } + break; case 036: case 037: /* BCS */ - if (C) { BRANCH_B (IR); } - break; + if (C) { BRANCH_B (IR); } + break; case 040: case 041: case 042: case 043: /* EMT */ - setTRAP (TRAP_EMT); - break; + setTRAP (TRAP_EMT); + break; case 044: case 045: case 046: case 047: /* TRAP */ - setTRAP (TRAP_TRAP); - break; + setTRAP (TRAP_TRAP); + break; /* Opcode 10, continued: SOPs */ case 050: /* CLRB */ - N = V = C = 0; - Z = 1; - if (dstreg) R[dstspec] = R[dstspec] & 0177400; - else WriteB (0, GeteaB (dstspec)); - break; + N = V = C = 0; + Z = 1; + if (dstreg) R[dstspec] = R[dstspec] & 0177400; + else WriteB (0, GeteaB (dstspec)); + break; case 051: /* COMB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (dst ^ 0377) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - C = 1; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); + dst = (dst ^ 0377) & 0377; + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + V = 0; + C = 1; + if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + else PWriteB (dst, last_pa); + break; case 052: /* INCB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (dst + 1) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = (dst == 0200); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); + dst = (dst + 1) & 0377; + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + V = (dst == 0200); + if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + else PWriteB (dst, last_pa); + break; case 053: /* DECB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (dst - 1) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = (dst == 0177); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); + dst = (dst - 1) & 0377; + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + V = (dst == 0177); + if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + else PWriteB (dst, last_pa); + break; case 054: /* NEGB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (-dst) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = (dst == 0200); - C = (Z ^ 1); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); + dst = (-dst) & 0377; + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + V = (dst == 0200); + C = (Z ^ 1); + if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + else PWriteB (dst, last_pa); + break; case 055: /* ADCB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (dst + C) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = (C && (dst == 0200)); - C = C & Z; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); + dst = (dst + C) & 0377; + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + V = (C && (dst == 0200)); + C = C & Z; + if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + else PWriteB (dst, last_pa); + break; /* Opcode 10: SOPs, continued */ case 056: /* SBCB */ - dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (dst - C) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = (C && (dst == 0177)); - C = (C && (dst == 0377)); - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; + dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); + dst = (dst - C) & 0377; + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + V = (C && (dst == 0177)); + C = (C && (dst == 0377)); + if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + else PWriteB (dst, last_pa); + break; case 057: /* TSTB */ - dst = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = C = 0; - break; + dst = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + V = C = 0; + break; case 060: /* RORB */ - src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = ((src & 0377) >> 1) | (C << 7); - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - C = (src & 1); - V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; + src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); + dst = ((src & 0377) >> 1) | (C << 7); + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + C = (src & 1); + V = N ^ C; + if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + else PWriteB (dst, last_pa); + break; case 061: /* ROLB */ - src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = ((src << 1) | C) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - C = GET_SIGN_B (src & 0377); - V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; + src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); + dst = ((src << 1) | C) & 0377; + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + C = GET_SIGN_B (src & 0377); + V = N ^ C; + if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + else PWriteB (dst, last_pa); + break; case 062: /* ASRB */ - src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = ((src & 0377) >> 1) | (src & 0200); - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - C = (src & 1); - V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; + src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); + dst = ((src & 0377) >> 1) | (src & 0200); + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + C = (src & 1); + V = N ^ C; + if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + else PWriteB (dst, last_pa); + break; case 063: /* ASLB */ - src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); - dst = (src << 1) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - C = GET_SIGN_B (src & 0377); - V = N ^ C; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - break; + src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); + dst = (src << 1) & 0377; + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + C = GET_SIGN_B (src & 0377); + V = N ^ C; + if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; + else PWriteB (dst, last_pa); + break; /* Opcode 10: SOPs, continued @@ -1546,55 +1561,55 @@ case 010: */ case 064: /* MTPS */ - dst = dstreg? R[dstspec]: ReadB (GeteaB (dstspec)); - if (cm == KERNEL) { - ipl = (dst >> PSW_V_IPL) & 07; - trap_req = calc_ints (ipl, trap_req); } - N = (dst >> PSW_V_N) & 01; - Z = (dst >> PSW_V_Z) & 01; - V = (dst >> PSW_V_V) & 01; - C = (dst >> PSW_V_C) & 01; - break; + dst = dstreg? R[dstspec]: ReadB (GeteaB (dstspec)); + if (cm == KERNEL) { + ipl = (dst >> PSW_V_IPL) & 07; + trap_req = calc_ints (ipl, trap_req); } + N = (dst >> PSW_V_N) & 01; + Z = (dst >> PSW_V_Z) & 01; + V = (dst >> PSW_V_V) & 01; + C = (dst >> PSW_V_C) & 01; + break; case 065: /* MFPD */ - if (dstreg) { - if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm]; - else dst = R[dstspec]; } - else dst = ReadW ((GeteaW (dstspec) & 0177777) | calc_ds (pm)); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - SP = (SP - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0366); - WriteW (dst, SP | dsenable); - if ((cm == KERNEL) && (SP < STKLIM)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - break; + if (dstreg) { + if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm]; + else dst = R[dstspec]; } + else dst = ReadW ((GeteaW (dstspec) & 0177777) | calc_ds (pm)); + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = 0; + SP = (SP - 2) & 0177777; + if (update_MM) MMR1 = calc_MMR1 (0366); + WriteW (dst, SP | dsenable); + if ((cm == KERNEL) && (SP < STKLIM)) { + setTRAP (TRAP_YEL); + setCPUERR (CPUE_YEL); } + break; case 066: /* MTPD */ - dst = ReadW (SP | dsenable); - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - SP = (SP + 2) & 0177777; - if (update_MM) MMR1 = 026; - if (dstreg) { - if ((dstspec == 6) && (cm != pm)) STACKFILE[pm] = dst; - else R[dstspec] = dst; } - else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_ds (pm)); - break; + dst = ReadW (SP | dsenable); + N = GET_SIGN_W (dst); + Z = GET_Z (dst); + V = 0; + SP = (SP + 2) & 0177777; + if (update_MM) MMR1 = 026; + if (dstreg) { + if ((dstspec == 6) && (cm != pm)) STACKFILE[pm] = dst; + else R[dstspec] = dst; } + else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_ds (pm)); + break; case 067: /* MFPS */ - dst = (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) | - (N << PSW_V_N) | (Z << PSW_V_Z) | - (V << PSW_V_V) | (C << PSW_V_C); - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = (dst & 0200)? 0177400 | dst: dst; - else WriteB (dst, GeteaB (dstspec)); - break; + dst = (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) | + (N << PSW_V_N) | (Z << PSW_V_Z) | + (V << PSW_V_V) | (C << PSW_V_C); + N = GET_SIGN_B (dst); + Z = GET_Z (dst); + V = 0; + if (dstreg) R[dstspec] = (dst & 0200)? 0177400 | dst: dst; + else WriteB (dst, GeteaB (dstspec)); + break; default: - setTRAP (TRAP_ILL); - break; } /* end switch SOPs */ + setTRAP (TRAP_ILL); + break; } /* end switch SOPs */ break; /* end case 010 */ /* Opcodes 11 - 16: double operand byte instructions @@ -1605,10 +1620,11 @@ case 010: case 011: /* MOVB */ if (srcreg && !dstreg) { /* R,not R */ - ea = GeteaB (dstspec); - dst = R[srcspec] & 0377; } - else { dst = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); - if (!dstreg) ea = GeteaB (dstspec); } + ea = GeteaB (dstspec); + dst = R[srcspec] & 0377; } + else { + dst = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); + if (!dstreg) ea = GeteaB (dstspec); } N = GET_SIGN_B (dst); Z = GET_Z (dst); V = 0; @@ -1617,10 +1633,11 @@ case 011: /* MOVB */ break; case 012: /* CMPB */ if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadB (GeteaB (dstspec)); - src = R[srcspec] & 0377; } - else { src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); - src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); } + src2 = ReadB (GeteaB (dstspec)); + src = R[srcspec] & 0377; } + else { + src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); + src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); } dst = (src - src2) & 0377; N = GET_SIGN_B (dst); Z = GET_Z (dst); @@ -1629,10 +1646,11 @@ case 012: /* CMPB */ break; case 013: /* BITB */ if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadB (GeteaB (dstspec)); - src = R[srcspec] & 0377; } - else { src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); - src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); } + src2 = ReadB (GeteaB (dstspec)); + src = R[srcspec] & 0377; } + else { + src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); + src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); } dst = (src2 & src) & 0377; N = GET_SIGN_B (dst); Z = GET_Z (dst); @@ -1640,10 +1658,11 @@ case 013: /* BITB */ break; case 014: /* BICB */ if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMB (GeteaB (dstspec)); - src = R[srcspec]; } - else { src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec)); - src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); } + src2 = ReadMB (GeteaB (dstspec)); + src = R[srcspec]; } + else { + src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec)); + src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); } dst = (src2 & ~src) & 0377; N = GET_SIGN_B (dst); Z = GET_Z (dst); @@ -1653,10 +1672,11 @@ case 014: /* BICB */ break; case 015: /* BISB */ if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMB (GeteaB (dstspec)); - src = R[srcspec]; } - else { src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec)); - src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); } + src2 = ReadMB (GeteaB (dstspec)); + src = R[srcspec]; } + else { + src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec)); + src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); } dst = (src2 | src) & 0377; N = GET_SIGN_B (dst); Z = GET_Z (dst); @@ -1666,10 +1686,11 @@ case 015: /* BISB */ break; case 016: /* SUB */ if (srcreg && !dstreg) { /* R,not R */ - src2 = ReadMW (GeteaW (dstspec)); - src = R[srcspec]; } - else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } + src2 = ReadMW (GeteaW (dstspec)); + src = R[srcspec]; } + else { + src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); + src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); } dst = (src2 - src) & 0177777; N = GET_SIGN_W (dst); Z = GET_Z (dst); @@ -1770,15 +1791,15 @@ case 4: /* -(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; if (update_MM) MMR1 = calc_MMR1 (0360 | reg); if ((adr < STKLIM) && (reg == 6) && (cm == KERNEL)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } + setTRAP (TRAP_YEL); + setCPUERR (CPUE_YEL); } return (adr | ds); case 5: /* @-(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; if (update_MM) MMR1 = calc_MMR1 (0360 | reg); if ((adr < STKLIM) && (reg == 6) && (cm == KERNEL)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } + setTRAP (TRAP_YEL); + setCPUERR (CPUE_YEL); } adr = ReadW (adr | ds); return (adr | dsenable); case 6: /* d(r) */ @@ -1820,15 +1841,15 @@ case 4: /* -(R) */ adr = R[reg] = (R[reg] - delta) & 0177777; if (update_MM) MMR1 = calc_MMR1 ((((-delta) & 037) << 3) | reg); if ((adr < STKLIM) && (reg == 6) && (cm == KERNEL)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } + setTRAP (TRAP_YEL); + setCPUERR (CPUE_YEL); } return (adr | ds); case 5: /* @-(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; if (update_MM) MMR1 = calc_MMR1 (0360 | reg); if ((adr < STKLIM) && (reg == 6) && (cm == KERNEL)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } + setTRAP (TRAP_YEL); + setCPUERR (CPUE_YEL); } adr = ReadW (adr | ds); return (adr | dsenable); case 6: /* d(r) */ @@ -2018,19 +2039,19 @@ if (MMR0 & MMR0_MME) { /* if mmgt */ dbn = va & VA_BN; /* extr block num */ plf = (apr & PDR_PLF) >> 2; /* extr page length */ if ((apr & PDR_PRD) == 0) { /* not readable? */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_NR; /* err non-resident */ - ABORT (TRAP_MME); } /* abort ref */ + if (update_MM) MMR0 = /* update MMR0 */ + (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); + MMR0 = MMR0 | MMR0_NR; /* err non-resident */ + ABORT (TRAP_MME); } /* abort ref */ if ((apr & PDR_ED)? dbn < plf: dbn > plf) { /* if pg lnt error */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_PL; - ABORT (TRAP_MME); } /* abort ref */ + if (update_MM) MMR0 = /* update MMR0 */ + (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); + MMR0 = MMR0 | MMR0_PL; + ABORT (TRAP_MME); } /* abort ref */ pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK; if ((MMR3 & MMR3_M22E) == 0) { - pa = pa & 0777777; - if (pa >= 0760000) pa = 017000000 | pa; } } + pa = pa & 0777777; + if (pa >= 0760000) pa = 017000000 | pa; } } else { pa = va & 0177777; /* mmgt off */ if (pa >= 0160000) pa = 017600000 | pa; } return pa; @@ -2060,25 +2081,25 @@ if (MMR0 & MMR0_MME) { /* if mmgt */ dbn = va & VA_BN; /* extr block num */ plf = (apr & PDR_PLF) >> 2; /* extr page length */ if ((apr & PDR_PRD) == 0) { /* not readable? */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_NR; /* err non-resident */ - ABORT (TRAP_MME); } /* abort ref */ + if (update_MM) MMR0 = /* update MMR0 */ + (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); + MMR0 = MMR0 | MMR0_NR; /* err non-resident */ + ABORT (TRAP_MME); } /* abort ref */ if ((apr & PDR_ED)? dbn < plf: dbn > plf) { /* if pg lnt error */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_PL; - ABORT (TRAP_MME); } /* abort ref */ + if (update_MM) MMR0 = /* update MMR0 */ + (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); + MMR0 = MMR0 | MMR0_PL; + ABORT (TRAP_MME); } /* abort ref */ if ((apr & PDR_PWR) == 0) { /* not writeable? */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_RO; /* err read only */ - ABORT (TRAP_MME); } /* abort ref */ + if (update_MM) MMR0 = /* update MMR0 */ + (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); + MMR0 = MMR0 | MMR0_RO; /* err read only */ + ABORT (TRAP_MME); } /* abort ref */ APRFILE[apridx] = apr | PDR_W; /* set W */ pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK; if ((MMR3 & MMR3_M22E) == 0) { - pa = pa & 0777777; - if (pa >= 0760000) pa = 017000000 | pa; } } + pa = pa & 0777777; + if (pa >= 0760000) pa = 017000000 | pa; } } else { pa = va & 0177777; /* mmgt off */ if (pa >= 0160000) pa = 017600000 | pa; } return pa; @@ -2113,8 +2134,8 @@ if (MMR0 & MMR0_MME) { /* if mmgt */ if ((apr & PDR_ED)? dbn < plf: dbn > plf) return MAXMEMSIZE; pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK; if ((MMR3 & MMR3_M22E) == 0) { - pa = pa & 0777777; - if (pa >= 0760000) pa = 017000000 | pa; } } + pa = pa & 0777777; + if (pa >= 0760000) pa = 017000000 | pa; } } else { pa = va & 0177777; /* mmgt off */ if (pa >= 0160000) pa = 017600000 | pa; } return pa; @@ -2157,7 +2178,7 @@ case 0: /* DR */ return SCPE_OK; case 1: /* MMR0 */ if (access == WRITEB) data = (pa & 1)? - (MMR0 & 0377) | (data << 8): (MMR0 & ~0377) | data; + (MMR0 & 0377) | (data << 8): (MMR0 & ~0377) | data; MMR0 = (MMR0 & ~MMR0_RW) | (data & MMR0_RW); return SCPE_OK; default: /* MMR1, MMR2 */ @@ -2284,7 +2305,7 @@ case 2: /* MEMERR */ return SCPE_OK; case 3: /* CCR */ if (access == WRITEB) data = (pa & 1)? - (CCR & 0377) | (data << 8): (CCR & ~0377) | data; + (CCR & 0377) | (data << 8): (CCR & ~0377) | data; CCR = data; return SCPE_OK; case 4: /* MAINT */ @@ -2324,15 +2345,15 @@ case 015: /* PIRQ */ case 017: /* PSW */ if (access == WRITEC) { /* console access? */ - PSW = data & PSW_RW; - return SCPE_OK; } + PSW = data & PSW_RW; + return SCPE_OK; } curr = (cm << PSW_V_CM) | (pm << PSW_V_PM) | (rs << PSW_V_RS) | (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) | (N << PSW_V_N) | (Z << PSW_V_Z) | (V << PSW_V_V) | (C << PSW_V_C); STACKFILE[cm] = SP; if (access == WRITEB) data = (pa & 1)? - (curr & 0377) | (data << 8): (curr & ~0377) | data; + (curr & 0377) | (data << 8): (curr & ~0377) | data; curr = (curr & ~PSW_RW) | (data & PSW_RW); oldrs = rs; cm = (curr >> PSW_V_CM) & 03; /* call calc_is,ds */ @@ -2344,9 +2365,9 @@ case 017: /* PSW */ V = (curr >> PSW_V_V) & 01; C = (curr >> PSW_V_C) & 01; if (rs != oldrs) { - for (i = 0; i < 6; i++) { - REGFILE[i][oldrs] = R[i]; - R[i] = REGFILE[i][rs]; } } + for (i = 0; i < 6; i++) { + REGFILE[i][oldrs] = R[i]; + R[i] = REGFILE[i][rs]; } } SP = STACKFILE[cm]; isenable = calc_is (cm); dsenable = calc_ds (cm); diff --git a/PDP11/pdp11_doc.txt b/PDP11/pdp11_doc.txt index 8214fe3d..1b8b22c3 100644 --- a/PDP11/pdp11_doc.txt +++ b/PDP11/pdp11_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik Subj: PDP-11 Simulator Usage -Date: 15-Nov-2002 +Date: 15-Jan-2003 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2002, written by Robert M Supnik - Copyright (c) 1993-2002, Robert M Supnik + Original code published in 1993-2003, written by Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -73,7 +73,8 @@ sim/pdp11/ pdp11_defs.h pdp11_tc.c pdp11_tm.c pdp11_ts.c - pdp11_xp.c + pdp11_xq.c + pdp11_xu.c 2. PDP-11 Features @@ -106,10 +107,12 @@ TC TC11/TU56 DECtape controller with eight drives TM TM11/TU10 magnetic tape controller with eight drives TS TS11/TSV05 magnetic tape controller with one drive TQ TQK50 TMSCP magnetic tape controller with four drives -XQ DELQA/DEQNA Ethernet controller +XQ DELQA/DEQNA Qbus Ethernet controller +XU DEUNA/DELUA Unibus Ethernet controller -The DZ, RK, HK, RL, RP, RQ, RQB, RQC, RQD, RX, RY, TC, TM, TS, TQ, and XQ -devices can be set DISABLED. RQB, RQC, RQD, RY, and TS are disabled by default. +The DZ, RK, HK, RL, RP, RQ, RQB, RQC, RQD, RX, RY, TC, TM, TS, TQ, XQ, and XU +devices can be set DISABLED. RQB, RQC, RQD, RY, TS, and XU are disabled by +default. The PDP-11 simulator implements several unique stop conditions: @@ -1140,9 +1143,9 @@ Error handling is as follows: OS I/O error fatal tape error -2.10 DELQA/DEQNA Ethernet Controller (XQ) +2.10 DELQA/DEQNA Qbus Ethernet Controller (XQ) -XQ simulates the DELQA/DEQNA 10Mbps Ethernet controller. Options allow +XQ simulates the DELQA/DEQNA Qbus Ethernet controller. Options allow control of the MAC address, the controller mode, and the sanity timer. SET XQ MAC= ex. 08-00-2B-AA-BB-CC @@ -1209,7 +1212,12 @@ not limited to the ~1.5Mbit/sec of the real DEQNA/DELQA controllers, nor the 10Mbit/sec of a standard Ethernet. Attach it to a Fast Ethernet (100 Mbit/sec) card, and "Feel the Power!" :-) -2.11 Symbolic Display and Input +2.11 DEUNA/DELUA Unibus Ethernet Controller (XU) + +XU simulates the DEUNA/DELUA Unibus Ethernet controller. THe current +implementation is a stub and is permanently disabled. + +2.12 Symbolic Display and Input The PDP-11 simulator implements symbolic display and input. Display is controlled by command line switches: diff --git a/PDP11/pdp11_fp.c b/PDP11/pdp11_fp.c index 3cb29322..676fa6d6 100644 --- a/PDP11/pdp11_fp.c +++ b/PDP11/pdp11_fp.c @@ -255,35 +255,35 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */ case 0: switch (ac) { /* decode IR<7:6> */ case 0: /* specials */ - if (IR == 0170000) { /* CFCC */ - N = (FPS >> PSW_V_N) & 1; - Z = (FPS >> PSW_V_Z) & 1; - V = (FPS >> PSW_V_V) & 1; - C = (FPS >> PSW_V_C) & 1; } - else if (IR == 0170001) /* SETF */ - FPS = FPS & ~FPS_D; - else if (IR == 0170002) /* SETI */ - FPS = FPS & ~FPS_L; - else if (IR == 0170011) /* SETD */ - FPS = FPS | FPS_D; - else if (IR == 0170012) /* SETL */ - FPS = FPS | FPS_L; - else fpnotrap (FEC_OP); - break; + if (IR == 0170000) { /* CFCC */ + N = (FPS >> PSW_V_N) & 1; + Z = (FPS >> PSW_V_Z) & 1; + V = (FPS >> PSW_V_V) & 1; + C = (FPS >> PSW_V_C) & 1; } + else if (IR == 0170001) /* SETF */ + FPS = FPS & ~FPS_D; + else if (IR == 0170002) /* SETI */ + FPS = FPS & ~FPS_L; + else if (IR == 0170011) /* SETD */ + FPS = FPS | FPS_D; + else if (IR == 0170012) /* SETL */ + FPS = FPS | FPS_L; + else fpnotrap (FEC_OP); + break; case 1: /* LDFPS */ - dst = (dstspec <= 07)? R[dstspec]: ReadW (GeteaW (dstspec)); - FPS = dst & FPS_RW; - break; + dst = (dstspec <= 07)? R[dstspec]: ReadW (GeteaW (dstspec)); + FPS = dst & FPS_RW; + break; case 2: /* STFPS */ - FPS = FPS & FPS_RW; - if (dstspec <= 07) R[dstspec] = FPS; - else WriteW (FPS, GeteaW (dstspec)); - break; + FPS = FPS & FPS_RW; + if (dstspec <= 07) R[dstspec] = FPS; + else WriteW (FPS, GeteaW (dstspec)); + break; case 3: /* STST */ - if (dstspec <= 07) R[dstspec] = FEC; - else WriteI ((FEC << 16) | FEA, GeteaFP (dstspec, LONG), - dstspec, LONG); - break; } /* end switch <7:6> */ + if (dstspec <= 07) R[dstspec] = FEC; + else WriteI ((FEC << 16) | FEA, GeteaFP (dstspec, LONG), + dstspec, LONG); + break; } /* end switch <7:6> */ break; /* end case 0 */ /* "Easy" instructions */ @@ -291,27 +291,27 @@ case 0: case 1: switch (ac) { /* decode IR<7:6> */ case 0: /* CLRf */ - WriteFP (&zero_fac, GeteaFP (dstspec, lenf), dstspec, lenf); - FPS = (FPS & ~FPS_CC) | FPS_Z; - break; + WriteFP (&zero_fac, GeteaFP (dstspec, lenf), dstspec, lenf); + FPS = (FPS & ~FPS_CC) | FPS_Z; + break; case 1: /* TSTf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - FPS = setfcc (FPS, fsrc.h, 0); - break; + ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); + FPS = setfcc (FPS, fsrc.h, 0); + break; case 2: /* ABSf */ - ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf); - if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; - else fsrc.h = fsrc.h & ~FP_SIGN; - WriteFP (&fsrc, ea, dstspec, lenf); - FPS = setfcc (FPS, fsrc.h, 0); - break; + ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf); + if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; + else fsrc.h = fsrc.h & ~FP_SIGN; + WriteFP (&fsrc, ea, dstspec, lenf); + FPS = setfcc (FPS, fsrc.h, 0); + break; case 3: /* NEGf */ - ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf); - if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; - else fsrc.h = fsrc.h ^ FP_SIGN; - WriteFP (&fsrc, ea, dstspec, lenf); - FPS = setfcc (FPS, fsrc.h, 0); - break; } /* end switch <7:6> */ + ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf); + if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; + else fsrc.h = fsrc.h ^ FP_SIGN; + WriteFP (&fsrc, ea, dstspec, lenf); + FPS = setfcc (FPS, fsrc.h, 0); + break; } /* end switch <7:6> */ break; /* end case 1 */ case 5: /* LDf */ ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); @@ -347,13 +347,13 @@ case 7: /* CMPf */ if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; if (GET_EXP (fac.h) == 0) fac = zero_fac; if ((fsrc.h == fac.h) && (fsrc.l == fac.l)) { /* equal? */ - FPS = (FPS & ~FPS_CC) | FPS_Z; - if ((fsrc.h | fsrc.l) == 0) { /* zero? */ - F_STORE (qdouble, zero_fac, FR[ac]); } - break; } + FPS = (FPS & ~FPS_CC) | FPS_Z; + if ((fsrc.h | fsrc.l) == 0) { /* zero? */ + F_STORE (qdouble, zero_fac, FR[ac]); } + break; } FPS = (FPS & ~FPS_CC) | ((fsrc.h >> (FP_V_SIGN - PSW_V_N)) & FPS_N); if ((GET_SIGN (fsrc.h ^ fac.h) == 0) && (fac.h != 0) && - F_LT (fsrc, fac)) FPS = FPS ^ FPS_N; + F_LT (fsrc, fac)) FPS = FPS ^ FPS_N; break; /* Load and store exponent instructions */ @@ -364,10 +364,11 @@ case 015: /* LDEXP */ fac.h = (fac.h & ~FP_EXP) | (((dst + FP_BIAS) & FP_M_EXP) << FP_V_EXP); newV = 0; if ((dst > 0177) && (dst <= 0177600)) { - if (dst < 0100000) { - if (fpnotrap (FEC_OVFLO)) fac = zero_fac; - newV = FPS_V; } - else { if (fpnotrap (FEC_UNFLO)) fac = zero_fac; } } + if (dst < 0100000) { + if (fpnotrap (FEC_OVFLO)) fac = zero_fac; + newV = FPS_V; } + else { + if (fpnotrap (FEC_UNFLO)) fac = zero_fac; } } F_STORE (qdouble, fac, FR[ac]); FPS = setfcc (FPS, fac.h, newV); break; @@ -390,13 +391,13 @@ case 016: /* LDCif */ else fac.l = ReadI (GeteaFP (dstspec, leni), dstspec, leni); fac.h = 0; if (fac.l) { - if (sign = GET_SIGN_L (fac.l)) fac.l = (fac.l ^ 0xFFFFFFFF) + 1; - for (i = 0; GET_SIGN_L (fac.l) == 0; i++) fac.l = fac.l << 1; - exp = ((FPS & FPS_L)? FP_BIAS + 32: FP_BIAS + 16) - i; - fac.h = (sign << FP_V_SIGN) | (exp << FP_V_EXP) | - ((fac.l >> (31 - FP_V_HB)) & FP_FRACH); - fac.l = (fac.l << (FP_V_HB + 1)) & FP_FRACL; - if ((FPS & (FPS_D + FPS_T)) == 0) roundfp11 (&fac); } + if (sign = GET_SIGN_L (fac.l)) fac.l = (fac.l ^ 0xFFFFFFFF) + 1; + for (i = 0; GET_SIGN_L (fac.l) == 0; i++) fac.l = fac.l << 1; + exp = ((FPS & FPS_L)? FP_BIAS + 32: FP_BIAS + 16) - i; + fac.h = (sign << FP_V_SIGN) | (exp << FP_V_EXP) | + ((fac.l >> (31 - FP_V_HB)) & FP_FRACH); + fac.l = (fac.l << (FP_V_HB + 1)) & FP_FRACL; + if ((FPS & (FPS_D + FPS_T)) == 0) roundfp11 (&fac); } F_STORE (qdouble, fac, FR[ac]); FPS = setfcc (FPS, fac.h, 0); break; @@ -405,28 +406,31 @@ case 013: /* STCfi */ exp = GET_EXP (FR[ac].h); /* exponent, */ F_LOAD_FRAC (qdouble, FR[ac], fac); /* fraction */ if (FPS & FPS_L) { - leni = LONG; - i = FP_BIAS + 32; } - else { leni = WORD; - i = FP_BIAS + 16; } + leni = LONG; + i = FP_BIAS + 32; } + else { + leni = WORD; + i = FP_BIAS + 16; } C = 0; if (exp <= FP_BIAS) dst = 0; else if (exp > i) { + dst = 0; + C = 1; } + else { + F_RSH_V (fac, FP_V_HB + 1 + i - exp, fsrc); + if (leni == WORD) fsrc.l = fsrc.l & ~0177777; + if (fsrc.l >= i_limit[leni == LONG][sign]) { dst = 0; - C = 1; } - else { F_RSH_V (fac, FP_V_HB + 1 + i - exp, fsrc); - if (leni == WORD) fsrc.l = fsrc.l & ~0177777; - if (fsrc.l >= i_limit[leni == LONG][sign]) { - dst = 0; - C = 1; } - else { dst = fsrc.l; - if (sign) dst = -dst; } } + C = 1; } + else { + dst = fsrc.l; + if (sign) dst = -dst; } } N = GET_SIGN_L (dst); Z = (dst == 0); V = 0; if (C) fpnotrap (FEC_ICVT); FPS = (FPS & ~FPS_CC) | (N << PSW_V_N) | - (Z << PSW_V_Z) | (C << PSW_V_C); + (Z << PSW_V_Z) | (C << PSW_V_C); if (dstspec <= 07) R[dstspec] = (dst >> 16) & 0177777; else WriteI (dst, GeteaFP (dstspec, leni), dstspec, leni); break; @@ -513,15 +517,15 @@ case 4: /* -(R) */ adr = R[reg] = (R[reg] - len) & 0177777; if (update_MM) MMR1 = (((-len) & 037) << 3) | reg; if ((adr < STKLIM) && (reg == 6) && (cm == KERNEL)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } + setTRAP (TRAP_YEL); + setCPUERR (CPUE_YEL); } return (adr | ds); case 5: /* @-(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; if (update_MM) MMR1 = 0360 | reg; if ((adr < STKLIM) && (reg == 6) && (cm == KERNEL)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } + setTRAP (TRAP_YEL); + setCPUERR (CPUE_YEL); } adr = ReadW (adr | ds); return (adr | dsenable); case 6: /* d(r) */ @@ -573,10 +577,10 @@ if (spec == 027) { fptr->l = 0; } else { exta = VA & ~0177777; fptr->h = (ReadW (VA) << FP_V_F0) | - (ReadW (exta | ((VA + 2) & 0177777)) << FP_V_F1); + (ReadW (exta | ((VA + 2) & 0177777)) << FP_V_F1); if (len == QUAD) fptr->l = - (ReadW (exta | ((VA + 4) & 0177777)) << FP_V_F2) | - (ReadW (exta | ((VA + 6) & 0177777)) << FP_V_F3); + (ReadW (exta | ((VA + 4) & 0177777)) << FP_V_F2) | + (ReadW (exta | ((VA + 6) & 0177777)) << FP_V_F3); else fptr->l = 0; } if ((GET_SIGN (fptr->h) != 0) && (GET_EXP (fptr->h) == 0) && (fpnotrap (FEC_UNDFV) == 0)) ABORT (TRAP_INT); @@ -662,26 +666,26 @@ if (GET_SIGN (facp->h) != GET_SIGN (fsrcp->h)) { /* signs different? */ if (ediff) { F_RSH_V (fsrcfrac, ediff, fsrcfrac); } /* sub, shf fsrc */ F_SUB (fsrcfrac, facfrac, facfrac); /* sub fsrc from fac */ if ((facfrac.h | facfrac.l) == 0) { /* result zero? */ - *facp = zero_fac; /* no overflow */ - return 0; } + *facp = zero_fac; /* no overflow */ + return 0; } if (ediff <= 1) { /* big normalize? */ - if ((facfrac.h & (0x00FFFFFF << FP_GUARD)) == 0) { - F_LSH_K (facfrac, 24, facfrac); - facexp = facexp - 24; } - if ((facfrac.h & (0x00FFF000 << FP_GUARD)) == 0) { - F_LSH_K (facfrac, 12, facfrac); - facexp = facexp - 12; } - if ((facfrac.h & (0x00FC0000 << FP_GUARD)) == 0) { - F_LSH_K (facfrac, 6, facfrac); - facexp = facexp - 6; } } + if ((facfrac.h & (0x00FFFFFF << FP_GUARD)) == 0) { + F_LSH_K (facfrac, 24, facfrac); + facexp = facexp - 24; } + if ((facfrac.h & (0x00FFF000 << FP_GUARD)) == 0) { + F_LSH_K (facfrac, 12, facfrac); + facexp = facexp - 12; } + if ((facfrac.h & (0x00FC0000 << FP_GUARD)) == 0) { + F_LSH_K (facfrac, 6, facfrac); + facexp = facexp - 6; } } while (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (facfrac); - facexp = facexp - 1; } } + F_LSH_1 (facfrac); + facexp = facexp - 1; } } else { if (ediff) { F_RSH_V (fsrcfrac, ediff, fsrcfrac); } /* add, shf fsrc */ F_ADD (fsrcfrac, facfrac, facfrac); /* add fsrc to fac */ if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD + 1)) { - F_RSH_1 (facfrac); /* carry out, shift */ - facexp = facexp + 1; } } + F_RSH_1 (facfrac); /* carry out, shift */ + facexp = facexp + 1; } } return round_and_pack (facp, facexp, &facfrac, 1); } @@ -770,30 +774,31 @@ if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { */ if (facexp <= FP_BIAS) { /* case 1 */ - *facp = zero_fac; - return round_and_pack (fracp, facexp, &facfrac, 1); } + *facp = zero_fac; + return round_and_pack (fracp, facexp, &facfrac, 1); } if (facexp > ((FPS & FPS_D)? FP_BIAS + 56: FP_BIAS + 24)) { - *fracp = zero_fac; /* case 2 */ - return round_and_pack (facp, facexp, &facfrac, 0); } + *fracp = zero_fac; /* case 2 */ + return round_and_pack (facp, facexp, &facfrac, 0); } F_RSH_V (fmask_fac, facexp - FP_BIAS, fmask); /* shift mask */ fsrcfrac.l = facfrac.l & fmask.l; /* extract fraction */ fsrcfrac.h = facfrac.h & fmask.h; if ((fsrcfrac.h | fsrcfrac.l) == 0) *fracp = zero_fac; - else { F_LSH_V (fsrcfrac, facexp - FP_BIAS, fsrcfrac); - fsrcexp = FP_BIAS; - if ((fsrcfrac.h & (0x00FFFFFF << FP_GUARD)) == 0) { - F_LSH_K (fsrcfrac, 24, fsrcfrac); - fsrcexp = fsrcexp - 24; } - if ((fsrcfrac.h & (0x00FFF000 << FP_GUARD)) == 0) { - F_LSH_K (fsrcfrac, 12, fsrcfrac); - fsrcexp = fsrcexp - 12; } - if ((fsrcfrac.h & (0x00FC0000 << FP_GUARD)) == 0) { - F_LSH_K (fsrcfrac, 6, fsrcfrac); - fsrcexp = fsrcexp - 6; } - while (GET_BIT (fsrcfrac.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (fsrcfrac); - fsrcexp = fsrcexp - 1; } - round_and_pack (fracp, fsrcexp, &fsrcfrac, 1); } + else { + F_LSH_V (fsrcfrac, facexp - FP_BIAS, fsrcfrac); + fsrcexp = FP_BIAS; + if ((fsrcfrac.h & (0x00FFFFFF << FP_GUARD)) == 0) { + F_LSH_K (fsrcfrac, 24, fsrcfrac); + fsrcexp = fsrcexp - 24; } + if ((fsrcfrac.h & (0x00FFF000 << FP_GUARD)) == 0) { + F_LSH_K (fsrcfrac, 12, fsrcfrac); + fsrcexp = fsrcexp - 12; } + if ((fsrcfrac.h & (0x00FC0000 << FP_GUARD)) == 0) { + F_LSH_K (fsrcfrac, 6, fsrcfrac); + fsrcexp = fsrcexp - 6; } + while (GET_BIT (fsrcfrac.h, FP_V_HB + FP_GUARD) == 0) { + F_LSH_1 (fsrcfrac); + fsrcexp = fsrcexp - 1; } + round_and_pack (fracp, fsrcexp, &fsrcfrac, 1); } facfrac.l = facfrac.l & ~fmask.l; facfrac.h = facfrac.h & ~fmask.h; return round_and_pack (facp, facexp, &facfrac, 0); @@ -835,18 +840,18 @@ mpc = *f2p; F_LSH_GUARD (mpc); /* guard multipicand */ if ((mpy.l | mpc.l) == 0) { /* 24b x 24b? */ for (i = 0; i < 24; i++) { - if (mpy.h & 1) result.h = result.h + mpc.h; - F_RSH_1 (result); - mpy.h = mpy.h >> 1; } } + if (mpy.h & 1) result.h = result.h + mpc.h; + F_RSH_1 (result); + mpy.h = mpy.h >> 1; } } else { if (mpy.l != 0) { /* 24b x 56b? */ - for (i = 0; i < 32; i++) { - if (mpy.l & 1) { F_ADD (mpc, result, result); } - F_RSH_1 (result); - mpy.l = mpy.l >> 1; } } - for (i = 0; i < 24; i++) { - if (mpy.h & 1) { F_ADD (mpc, result, result); } + for (i = 0; i < 32; i++) { + if (mpy.l & 1) { F_ADD (mpc, result, result); } F_RSH_1 (result); - mpy.h = mpy.h >> 1; } } + mpy.l = mpy.l >> 1; } } + for (i = 0; i < 24; i++) { + if (mpy.h & 1) { F_ADD (mpc, result, result); } + F_RSH_1 (result); + mpy.h = mpy.h >> 1; } } *f1p = result; return; } @@ -886,9 +891,9 @@ quo = zero_fac; for (i = count; (i > 0) && ((facfrac.h | facfrac.l) != 0); i--) { F_LSH_1 (quo); /* shift quotient */ if (!F_LT (facfrac, fsrcfrac)) { /* divd >= divr? */ - F_SUB (fsrcfrac, facfrac, facfrac); /* divd - divr */ - if (qd) quo.l = quo.l | 1; /* double or single? */ - else quo.h = quo.h | 1; } + F_SUB (fsrcfrac, facfrac, facfrac); /* divd - divr */ + if (qd) quo.l = quo.l | 1; /* double or single? */ + else quo.h = quo.h | 1; } F_LSH_1 (facfrac); } /* shift divd */ if (i > 0) { F_LSH_V (quo, i, quo); } /* early exit? */ @@ -967,8 +972,8 @@ if (r && ((FPS & FPS_T) == 0)) { if (FPS & FPS_D) { F_ADD (dround_guard_fac, frac, frac); } else { F_ADD (fround_guard_fac, frac, frac); } if (GET_BIT (frac.h, FP_V_HB + FP_GUARD + 1)) { - F_RSH_1 (frac); - exp = exp + 1; } } + F_RSH_1 (frac); + exp = exp + 1; } } F_RSH_GUARD (frac); facp->l = frac.l & FP_FRACL; facp->h = (facp->h & FP_SIGN) | ((exp & FP_M_EXP) << FP_V_EXP) | diff --git a/PDP11/pdp11_hk.c b/PDP11/pdp11_hk.c index 2f1d8a07..552025fc 100644 --- a/PDP11/pdp11_hk.c +++ b/PDP11/pdp11_hk.c @@ -478,7 +478,7 @@ case 006: /* HKER */ case 007: /* HKAS */ *data = hkof; for (i = 0; i < HK_NUMDR; i++) - if (hkds[i] & DS_ATA) *data = *data | (AS_U0 << i); + if (hkds[i] & DS_ATA) *data = *data | (AS_U0 << i); break; case 010: /* HKDC */ *data = hkdc = hkdc & ~DC_MBZ; @@ -526,27 +526,27 @@ if ((hkcs1 & CS1_GO) && /* busy? */ switch (j) { /* decode PA<4:1> */ case 000: /* HKCS1 */ if (data & CS1_CCLR) { /* controller reset? */ - hkcs1 = CS1_DONE; /* CS1 = done */ - hkcs2 = CS2_IR | CS2_OR; /* CS2 = ready */ - hkmr = hkmr2 = hkmr3 = 0; /* maint = 0 */ - hkda = hkdc = 0; - hkba = hkwc = 0; - hkspr = hkof = 0; - CLR_INT (HK); /* clr int */ - for (i = 0; i < HK_NUMDR; i++) { /* stop data xfr */ - if (sim_is_active (&hk_unit[i]) && - ((uptr->FNC & CS1_M_FNC) >= FNC_XFER)) - sim_cancel (&hk_unit[i]); } - drv = 0; - break; } + hkcs1 = CS1_DONE; /* CS1 = done */ + hkcs2 = CS2_IR | CS2_OR; /* CS2 = ready */ + hkmr = hkmr2 = hkmr3 = 0; /* maint = 0 */ + hkda = hkdc = 0; + hkba = hkwc = 0; + hkspr = hkof = 0; + CLR_INT (HK); /* clr int */ + for (i = 0; i < HK_NUMDR; i++) { /* stop data xfr */ + if (sim_is_active (&hk_unit[i]) && + ((uptr->FNC & CS1_M_FNC) >= FNC_XFER)) + sim_cancel (&hk_unit[i]); } + drv = 0; + break; } if (data & CS1_IE) { /* setting IE? */ - if (data & CS1_DONE) SET_INT (HK); } /* write to DONE+IE? */ + if (data & CS1_DONE) SET_INT (HK); } /* write to DONE+IE? */ else CLR_INT (HK); /* no, clr intr */ hkcs1 = (hkcs1 & ~CS1_RW) | (data & CS1_RW); /* merge data */ if (SC02C) hkspr = (hkspr & ~CS1_M_UAE) | GET_UAE (hkcs1); if (hkcs1 & CS1_GO) { /* go? */ - if (hkcs1 & CS1_ERR) hkcs1 = hkcs1 & ~CS1_GO; - else hk_go (drv); } + if (hkcs1 & CS1_ERR) hkcs1 = hkcs1 & ~CS1_GO; + else hk_go (drv); } break; case 001: /* HKWC */ hkwc = data; @@ -718,28 +718,30 @@ case FNC_NOP: /* select */ case FNC_OFFSET: /* offset */ if (uptr->FNC & FNC_2ND) { /* 2nd int? */ - hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */ - update_hkcs (CS1_DI, drv); } /* drive intr */ - else { uptr->FNC = uptr->FNC | FNC_2ND; /* second state */ - hk_off[drv] = hkof & AS_OF; /* save offset */ - sim_activate (uptr, hk_swait * 10); /* wait for compl */ - update_hkcs (CS1_DONE, drv); } /* done */ + hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */ + update_hkcs (CS1_DI, drv); } /* drive intr */ + else { + uptr->FNC = uptr->FNC | FNC_2ND; /* second state */ + hk_off[drv] = hkof & AS_OF; /* save offset */ + sim_activate (uptr, hk_swait * 10); /* wait for compl */ + update_hkcs (CS1_DONE, drv); } /* done */ break; case FNC_RECAL: /* recalibrate */ case FNC_SEEK: /* seek */ if (uptr->FNC & FNC_2ND) { /* 2nd int? */ - hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */ - update_hkcs (CS1_DI, drv); } /* drive intr */ - else { uptr->FNC = uptr->FNC | FNC_2ND; /* second state */ - hk_off[drv] = 0; /* clr offset */ - dc = (fnc == FNC_SEEK)? hkdc: 0; /* get cyl */ - hk_dif[drv] = dc - uptr->CYL; /* cyl diff */ - t = abs (hk_dif[drv]); /* |cyl diff| */ - if (t == 0) t = 1; /* min time */ - uptr->CYL = dc; /* save cyl */ - sim_activate (uptr, hk_swait * t); /* schedule */ - update_hkcs (CS1_DONE, drv); } /* done */ + hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */ + update_hkcs (CS1_DI, drv); } /* drive intr */ + else { + uptr->FNC = uptr->FNC | FNC_2ND; /* second state */ + hk_off[drv] = 0; /* clr offset */ + dc = (fnc == FNC_SEEK)? hkdc: 0; /* get cyl */ + hk_dif[drv] = dc - uptr->CYL; /* cyl diff */ + t = abs (hk_dif[drv]); /* |cyl diff| */ + if (t == 0) t = 1; /* min time */ + uptr->CYL = dc; /* save cyl */ + sim_activate (uptr, hk_swait * t); /* schedule */ + update_hkcs (CS1_DONE, drv); } /* done */ break; /* Data transfer commands only generate one interrupt */ @@ -747,15 +749,15 @@ case FNC_SEEK: /* seek */ case FNC_READH: hkdb[0] = uptr->CYL << RDH1_V_CYL; /* first word */ hkdb[1] = (GET_SC (hkda) << RDH2_V_SEC) | /* second word */ - (1 << (GET_SF (hkda) + RDH2_V_DHA)) | RDH2_GOOD; + (1 << (GET_SF (hkda) + RDH2_V_DHA)) | RDH2_GOOD; hkdb[2] = hkdb[0] ^ hkdb[1]; /* checksum */ update_hkcs (CS1_DONE, drv); /* done */ break; case FNC_WRITE: /* write */ if (uptr->flags & UNIT_WPRT) { /* write locked? */ - hk_cmderr (ER_WLE, drv); /* command error */ - return SCPE_OK; } + hk_cmderr (ER_WLE, drv); /* command error */ + return SCPE_OK; } case FNC_WCHK: /* write check */ case FNC_READ: /* read */ if (SC02C) ba = ((hkspr & XM_MMASK) << 16) | hkba; /* 22b addr? */ @@ -809,11 +811,11 @@ case FNC_READ: /* read */ awc = wc; for (wc = 0; wc < awc; wc++) { /* loop thru buf */ if (Map_ReadW (ba, 2, &comp, MAP)) { /* read word */ - hkcs2 = hkcs2 | CS2_NEM; /* set error */ - break; } + hkcs2 = hkcs2 | CS2_NEM; /* set error */ + break; } if (comp != hkxb[wc]) { /* compare wd */ - hkcs2 = hkcs2 | CS2_WCE; /* set error */ - break; } + hkcs2 = hkcs2 | CS2_WCE; /* set error */ + break; } if ((hkcs2 & CS2_UAI) == 0) ba = ba + 2; } } /* end else wchk */ @@ -821,7 +823,7 @@ case FNC_READ: /* read */ hkba = (ba & 0177777) & ~BA_MBZ; /* lower 16b */ hkcs1 = PUT_UAE (hkcs1, ba >> 16); /* upper 2b */ if (SC02C) /* SC02C? upper 6b */ - hkspr = (hkspr & ~XM_MMASK) | ((ba >> 16) & XM_MMASK); + hkspr = (hkspr & ~XM_MMASK) | ((ba >> 16) & XM_MMASK); da = da + wc + (HK_NUMWD - 1); da = da / HK_NUMWD; hkda = da % HK_NUMSC; @@ -830,10 +832,10 @@ case FNC_READ: /* read */ hkdc = da / HK_NUMSF; if (err != 0) { /* error? */ - hk_cmderr (ER_PAR, drv); /* set drive error */ - perror ("HK I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } + hk_cmderr (ER_PAR, drv); /* set drive error */ + perror ("HK I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; } case FNC_WRITEH: /* write headers stub */ update_hkcs (CS1_DONE, drv); /* set done */ @@ -858,7 +860,7 @@ if (flag & CS1_DONE) hkcs1 = hkcs1 & ~CS1_GO; /* clear go */ if (hkcs1 & CS1_IE) { /* intr enable? */ if (((flag & CS1_DONE) && ((hkcs1 & CS1_DONE) == 0)) || ((flag & CS1_DI) && (hkcs1 & CS1_DONE))) /* done 0->1 or DI? */ - SET_INT (HK); } + SET_INT (HK); } else CLR_INT (HK); hkcs1 = (hkcs1 & (CS1_DT|CS1_UAE|CS1_DONE|CS1_IE|CS1_SPA|CS1_FNC|CS1_GO)) | flag; for (i = 0; i < HK_NUMDR; i++) { /* if ATA, set DI */ @@ -878,11 +880,11 @@ if (hk_unit[drv].flags & UNIT_DIS) { /* disabled? */ hkds[drv] = (hkds[drv] & (DS_VV | DS_PIP | DS_ATA)) | DS_VLD | DS_DRA; if (hk_unit[drv].flags & UNIT_ATT) { /* attached? */ if (!sim_is_active (&hk_unit[drv])) /* not busy? */ - hkds[drv] = hkds[drv] | DS_RDY; /* set RDY */ + hkds[drv] = hkds[drv] | DS_RDY; /* set RDY */ if (hker[drv]) hkds[drv] = hkds[drv] | DS_ATA; /* err? set ATA */ if (hk_off[drv]) hkds[drv] = hkds[drv] | DS_OF; /* offset? set OF */ if (hk_unit[drv].flags & UNIT_WPRT) /* write locked? */ - hkds[drv] = hkds[drv] | DS_WRL; } /* set WRL */ + hkds[drv] = hkds[drv] | DS_WRL; } /* set WRL */ else { hkds[drv] = hkds[drv] & ~(DS_PIP | DS_VV); /* no, clr PIP,VV */ hker[drv] = 0; } /* no errors */ if (hk_unit[drv].flags & UNIT_RK07) hkds[drv] = hkds[drv] | DS_DT; @@ -1055,7 +1057,7 @@ if (sim_is_active (uptr)) { /* unit active? */ sim_cancel (uptr); /* cancel operation */ hker[drv] = hker[drv] | ER_OPI; /* set drive error */ if ((uptr->FNC & CS1_M_FNC) >= FNC_XFER) /* data transfer? */ - hkcs1 = hkcs1 | CS1_DONE | CS1_ERR; } /* set done, err */ + hkcs1 = hkcs1 | CS1_DONE | CS1_ERR; } /* set done, err */ update_hkcs (CS1_DI, drv); /* request intr */ return detach_unit (uptr); } diff --git a/PDP11/pdp11_io.c b/PDP11/pdp11_io.c index 3fc7e8c6..8703d515 100644 --- a/PDP11/pdp11_io.c +++ b/PDP11/pdp11_io.c @@ -90,9 +90,9 @@ t_stat stat; for (i = 0; dibp = dib_tab[i]; i++ ) { if ((pa >= dibp->ba) && (pa < (dibp->ba + dibp->lnt))) { - stat = dibp->rd (data, pa, access); - trap_req = calc_ints (ipl, trap_req); - return stat; } } + stat = dibp->rd (data, pa, access); + trap_req = calc_ints (ipl, trap_req); + return stat; } } return SCPE_NXM; } @@ -105,9 +105,9 @@ t_stat stat; for (i = 0; dibp = dib_tab[i]; i++ ) { if ((pa >= dibp->ba) && (pa < (dibp->ba + dibp->lnt))) { - stat = dibp->wr (data, pa, access); - trap_req = calc_ints (ipl, trap_req); - return stat; } } + stat = dibp->wr (data, pa, access); + trap_req = calc_ints (ipl, trap_req); + return stat; } } return SCPE_NXM; } @@ -168,12 +168,13 @@ t_stat ubm_wr (int32 data, int32 addr, int32 access) if (cpu_ubm) { int32 sc, pg = (addr >> 2) & UBM_M_PN; if (access == WRITEB) { - sc = (addr & 3) << 3; - ub_map[pg] = (ub_map[pg] & ~(0377 << sc)) | - ((data & 0377) << sc); } - else { sc = (addr & 2) << 3; - ub_map[pg] = (ub_map[pg] & ~(0177777 << sc)) | - ((data & 0177777) << sc); } + sc = (addr & 3) << 3; + ub_map[pg] = (ub_map[pg] & ~(0377 << sc)) | + ((data & 0377) << sc); } + else { + sc = (addr & 2) << 3; + ub_map[pg] = (ub_map[pg] & ~(0177777 << sc)) | + ((data & 0177777) << sc); } ub_map[pg] = ub_map[pg] & 017777776; return SCPE_OK; } return SCPE_NXM; @@ -191,7 +192,7 @@ if (cpu_bme) { /* bus map on? */ int32 pg = UBM_GETPN (ba); /* map entry */ int32 off = UBM_GETOFF (ba); /* offset */ if (pg != UBM_M_PN) /* last page? */ - *ma = (ub_map[pg] + off) & PAMASK; /* no, use map */ + *ma = (ub_map[pg] + off) & PAMASK; /* no, use map */ else *ma = (IOPAGEBASE + off) & PAMASK; } /* yes, use fixed */ else *ma = ba; /* else physical */ return TRUE; diff --git a/PDP11/pdp11_lp.c b/PDP11/pdp11_lp.c index e0b62744..78b16b14 100644 --- a/PDP11/pdp11_lp.c +++ b/PDP11/pdp11_lp.c @@ -126,7 +126,7 @@ if ((PA & 02) == 0) { /* csr */ if (PA & 1) return SCPE_OK; if ((data & CSR_IE) == 0) CLR_INT (LPT); else if ((lpt_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (LPT); + SET_INT (LPT); lpt_csr = (lpt_csr & ~LPTCSR_RW) | (data & LPTCSR_RW); } else { if ((PA & 1) == 0) lpt_unit.buf = data & 0177; /* buffer */ lpt_csr = lpt_csr & ~CSR_DONE; diff --git a/PDP11/pdp11_mscp.h b/PDP11/pdp11_mscp.h index e8d0401d..145aac61 100644 --- a/PDP11/pdp11_mscp.h +++ b/PDP11/pdp11_mscp.h @@ -1,6 +1,6 @@ /* pdp11_mscp.h: DEC MSCP and TMSCP definitions - Copyright (c) 2001-2002, Robert M Supnik + Copyright (c) 2001-2003, Robert M Supnik Derived from work by Stephen F. Shirron Permission is hereby granted, free of charge, to any person obtaining a @@ -24,6 +24,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 09-Jan-03 RMS Tape read/write end pkt is longer than disk read/write 20-Sep-02 RMS Merged TMSCP definitions */ @@ -251,21 +252,21 @@ #define ERG_LNT 12 -/* Flush - 10 W of status (8 undefined) */ +/* Flush - 10 W status (8 undefined) */ #define FLU_LNT 32 /* 8 - 15 /* reserved */ #define FLU_POSL 16 /* position */ #define FLU_POSH 17 -/* Write tape mark - 10W of status (8 undefined) */ +/* Write tape mark - 10W status (8 undefined) */ #define WTM_LNT 32 /* 8 - 15 /* reserved */ #define WTM_POSL 16 /* position */ #define WTM_POSH 17 -/* Get command status packet - 2 W parameter, 4 W of status */ +/* Get command status packet - 2 W parameter, 4 W status */ #define GCS_LNT 20 #define GCS_REFL 8 /* ref # */ @@ -386,9 +387,11 @@ #define POS_POSL 16 /* position */ #define POS_POSH 17 -/* Data transfer packet - 10 W parameters (disk), 6W parameters (tape), 10 W status */ +/* Data transfer packet - 10 W parameters (disk), 6W parameters (tape), + 10 W status (disk), 12W status (tape) */ -#define RW_LNT 32 +#define RW_LNT_D 32 +#define RW_LNT_T 36 #define RW_BCL 8 /* byte count */ #define RW_BCH 9 #define RW_BAL 10 /* buff desc */ diff --git a/PDP11/pdp11_pclk.c b/PDP11/pdp11_pclk.c index 6561bf96..30e134c0 100644 --- a/PDP11/pdp11_pclk.c +++ b/PDP11/pdp11_pclk.c @@ -219,13 +219,13 @@ case 00: /* CSR */ rv = CSR_GETRATE (pclk_csr); /* new rate */ pclk_unit.wait = xtim[rv]; /* new delay */ if ((pclk_csr & CSR_GO) == 0) { /* stopped? */ - sim_cancel (&pclk_unit); /* cancel */ - if (data & CSR_FIX) pclk_tick (); } /* fix? tick */ + sim_cancel (&pclk_unit); /* cancel */ + if (data & CSR_FIX) pclk_tick (); } /* fix? tick */ else if (((old_csr & CSR_GO) == 0) || /* run 0 -> 1? */ (rv != CSR_GETRATE (old_csr))) { /* rate change? */ - sim_cancel (&pclk_unit); /* cancel */ - sim_activate (&pclk_unit, /* start clock */ - sim_rtcn_init (pclk_unit.wait, TMR_PCLK)); + sim_cancel (&pclk_unit); /* cancel */ + sim_activate (&pclk_unit, /* start clock */ + sim_rtcn_init (pclk_unit.wait, TMR_PCLK)); } break; case 01: /* buffer */ @@ -247,12 +247,13 @@ if (pclk_csr & CSR_UPDN) /* up or down? */ else pclk_ctr = (pclk_ctr - 1) & DMASK; /* 0 = down */ if (pclk_ctr == 0) { /* reached zero? */ if (pclk_csr & CSR_DONE) /* done already set? */ - pclk_csr = pclk_csr | CSR_ERR; /* set error */ + pclk_csr = pclk_csr | CSR_ERR; /* set error */ else pclk_csr = pclk_csr | CSR_DONE; /* else set done */ if (pclk_csr & CSR_IE) SET_INT (PCLK); /* if IE, set int */ if (pclk_csr & CSR_MODE) pclk_ctr = pclk_csb; /* if rpt, reload */ - else { pclk_csb = 0; /* else clr ctr */ - pclk_csr = pclk_csr & ~CSR_GO; } } /* and clr go */ + else { + pclk_csb = 0; /* else clr ctr */ + pclk_csr = pclk_csr & ~CSR_GO; } } /* and clr go */ return; } diff --git a/PDP11/pdp11_rk.c b/PDP11/pdp11_rk.c index 255f1b24..55f5528c 100644 --- a/PDP11/pdp11_rk.c +++ b/PDP11/pdp11_rk.c @@ -284,7 +284,7 @@ UNIT *uptr; switch ((PA >> 1) & 07) { /* decode PA<3:1> */ case 0: /* RKDS: read only */ rkds = (rkds & RKDS_ID) | RKDS_RK05 | RKDS_SC_OK | - (rand () % RK_NUMSC); /* random sector */ + (rand () % RK_NUMSC); /* random sector */ uptr = rk_dev.units + GET_DRIVE (rkda); /* selected unit */ if (uptr->flags & UNIT_ATT) rkds = rkds | RKDS_RDY; /* attached? */ if (!sim_is_active (uptr)) rkds = rkds | RKDS_RWS; /* idle? */ @@ -325,30 +325,30 @@ case 1: /* RKER: read only */ case 2: /* RKCS */ rkcs = rkcs & RKCS_REAL; if (access == WRITEB) data = (PA & 1)? - (rkcs & 0377) | (data << 8): (rkcs & ~0377) | data; + (rkcs & 0377) | (data << 8): (rkcs & ~0377) | data; if ((data & CSR_IE) == 0) { /* int disable? */ - rkintq = 0; /* clr int queue */ - CLR_INT (RK); } /* clr int request */ + rkintq = 0; /* clr int queue */ + CLR_INT (RK); } /* clr int request */ else if ((rkcs & (CSR_DONE + CSR_IE)) == CSR_DONE) { - rkintq = rkintq | RK_CTLI; /* queue ctrl int */ - SET_INT (RK); } /* set int request */ + rkintq = rkintq | RK_CTLI; /* queue ctrl int */ + SET_INT (RK); } /* set int request */ rkcs = (rkcs & ~RKCS_RW) | (data & RKCS_RW); if ((rkcs & CSR_DONE) && (data & CSR_GO)) rk_go (); /* new function? */ return SCPE_OK; case 3: /* RKWC */ if (access == WRITEB) data = (PA & 1)? - (rkwc & 0377) | (data << 8): (rkwc & ~0377) | data; + (rkwc & 0377) | (data << 8): (rkwc & ~0377) | data; rkwc = data; return SCPE_OK; case 4: /* RKBA */ if (access == WRITEB) data = (PA & 1)? - (rkba & 0377) | (data << 8): (rkba & ~0377) | data; + (rkba & 0377) | (data << 8): (rkba & ~0377) | data; rkba = data & RKBA_IMP; return SCPE_OK; case 5: /* RKDA */ if ((rkcs & CSR_DONE) == 0) return SCPE_OK; if (access == WRITEB) data = (PA & 1)? - (rkda & 0377) | (data << 8): (rkda & ~0377) | data; + (rkda & 0377) | (data << 8): (rkda & ~0377) | data; rkda = data; return SCPE_OK; default: @@ -435,10 +435,11 @@ drv = uptr - rk_dev.units; /* get drv number */ if (uptr->FUNC == RKCS_SEEK) { /* seek */ rkcs = rkcs | RKCS_SCP; /* set seek done */ if (rkcs & CSR_IE) { /* ints enabled? */ - rkintq = rkintq | RK_SCPI (drv); /* queue request */ - if (rkcs & CSR_DONE) SET_INT (RK); } - else { rkintq = 0; /* clear queue */ - CLR_INT (RK); } /* clear interrupt */ + rkintq = rkintq | RK_SCPI (drv); /* queue request */ + if (rkcs & CSR_DONE) SET_INT (RK); } + else { + rkintq = 0; /* clear queue */ + CLR_INT (RK); } /* clear interrupt */ return SCPE_OK; } if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ @@ -455,19 +456,19 @@ if ((uptr->FUNC == RKCS_READ) && (err == 0)) { /* read? */ err = ferror (uptr->fileref); for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */ if (t = Map_WriteW (ma, wc << 1, rkxb, MAP)) { /* store buf */ - rker = rker | RKER_NXM; /* NXM? set flg */ - wc = wc - t; } /* adj wd cnt */ + rker = rker | RKER_NXM; /* NXM? set flg */ + wc = wc - t; } /* adj wd cnt */ } /* end read */ -if ((uptr->FUNC == RKCS_WRITE) && (err == 0)) { /* write? */ +if ((uptr->FUNC == RKCS_WRITE) && (err == 0)) { /* write? */ if (t = Map_ReadW (ma, wc << 1, rkxb, MAP)) { /* get buf */ - rker = rker | RKER_NXM; /* NXM? set flg */ - wc = wc - t; } /* adj wd cnt */ + rker = rker | RKER_NXM; /* NXM? set flg */ + wc = wc - t; } /* adj wd cnt */ if (wc) { /* any xfer? */ - awc = (wc + (RK_NUMWD - 1)) & ~(RK_NUMWD - 1); /* clr to */ - for (i = wc; i < awc; i++) rkxb[i] = 0; /* end of blk */ - fxwrite (rkxb, sizeof (int16), awc, uptr->fileref); - err = ferror (uptr->fileref); } + awc = (wc + (RK_NUMWD - 1)) & ~(RK_NUMWD - 1); /* clr to */ + for (i = wc; i < awc; i++) rkxb[i] = 0; /* end of blk */ + fxwrite (rkxb, sizeof (int16), awc, uptr->fileref); + err = ferror (uptr->fileref); } } /* end write */ if ((uptr->FUNC == RKCS_WCHK) && (err == 0)) { /* write check? */ @@ -476,12 +477,12 @@ if ((uptr->FUNC == RKCS_WCHK) && (err == 0)) { /* write check? */ for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */ awc = wc; /* save wc */ for (wc = 0; (err == 0) && (wc < awc); wc++) { /* loop thru buf */ - if (Map_ReadW (ma + (wc << 1), 2, &comp, MAP)) { /* mem wd */ - rker = rker | RKER_NXM; /* NXM? set flg */ - break; } - if (comp != rkxb[wc]) { /* match to disk? */ - rker = rker | RKER_WCE; /* no, err */ - if (rkcs & RKCS_SSE) break; } } + if (Map_ReadW (ma + (wc << 1), 2, &comp, MAP)) { /* mem wd */ + rker = rker | RKER_NXM; /* NXM? set flg */ + break; } + if (comp != rkxb[wc]) { /* match to disk? */ + rker = rker | RKER_WCE; /* no, err */ + if (rkcs & RKCS_SSE) break; } } } /* end wcheck */ rkwc = (rkwc + wc) & 0177777; /* final word count */ @@ -537,11 +538,11 @@ int32 i; for (i = 0; i <= RK_NUMDR; i++) { /* loop thru intq */ if (rkintq & (1u << i)) { /* bit i set? */ - rkintq = rkintq & ~(1u << i); /* clear bit i */ - if (rkintq) SET_INT (RK); /* queue next */ - rkds = (rkds & ~RKDS_ID) | /* id drive */ - (((i == 0)? last_drv: i - 1) << RKDS_V_ID); - return rk_dib.vec; } } /* return vector */ + rkintq = rkintq & ~(1u << i); /* clear bit i */ + if (rkintq) SET_INT (RK); /* queue next */ + rkds = (rkds & ~RKDS_ID) | /* id drive */ + (((i == 0)? last_drv: i - 1) << RKDS_V_ID); + return rk_dib.vec; } } /* return vector */ rkintq = 0; /* clear queue */ return 0; /* passive release */ } diff --git a/PDP11/pdp11_rl.c b/PDP11/pdp11_rl.c index 0afd3c38..1c623837 100644 --- a/PDP11/pdp11_rl.c +++ b/PDP11/pdp11_rl.c @@ -332,53 +332,54 @@ case 0: /* RLCS */ else rlcs = rlcs | RLCS_DRDY; /* see if ready */ if (access == WRITEB) data = (PA & 1)? - (rlcs & 0377) | (data << 8): (rlcs & ~0377) | data; + (rlcs & 0377) | (data << 8): (rlcs & ~0377) | data; rlcs = (rlcs & ~RLCS_RW) | (data & RLCS_RW); rlbae = (rlbae & ~RLCS_M_MEX) | ((rlcs >> RLCS_V_MEX) & RLCS_M_MEX); if (data & CSR_DONE) { /* ready set? */ - if ((data & CSR_IE) == 0) CLR_INT (RL); - else if ((rlcs & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (RL); - return SCPE_OK; } + if ((data & CSR_IE) == 0) CLR_INT (RL); + else if ((rlcs & (CSR_DONE + CSR_IE)) == CSR_DONE) + SET_INT (RL); + return SCPE_OK; } CLR_INT (RL); /* clear interrupt */ rlcs = rlcs & ~RLCS_ALLERR; /* clear errors */ switch (GET_FUNC (rlcs)) { /* case on RLCS<3:1> */ case RLCS_NOP: /* nop */ - rl_set_done (0); - break; + rl_set_done (0); + break; case RLCS_SEEK: /* seek */ - curr = GET_CYL (uptr->TRK); /* current cylinder */ - offs = GET_CYL (rlda); /* offset */ - if (rlda & RLDA_SK_DIR) { /* in or out? */ - newc = curr + offs; /* out */ - maxc = (uptr->flags & UNIT_RL02)? - RL_NUMCY * 2: RL_NUMCY; - if (newc >= maxc) newc = maxc - 1; } - else { newc = curr - offs; /* in */ - if (newc < 0) newc = 0; } - uptr->TRK = (newc << RLDA_V_CYL) | /* put on track */ - ((rlda & RLDA_SK_HD)? RLDA_HD1: RLDA_HD0); - sim_activate (uptr, rl_swait * abs (newc - curr)); - break; + curr = GET_CYL (uptr->TRK); /* current cylinder */ + offs = GET_CYL (rlda); /* offset */ + if (rlda & RLDA_SK_DIR) { /* in or out? */ + newc = curr + offs; /* out */ + maxc = (uptr->flags & UNIT_RL02)? + RL_NUMCY * 2: RL_NUMCY; + if (newc >= maxc) newc = maxc - 1; } + else { + newc = curr - offs; /* in */ + if (newc < 0) newc = 0; } + uptr->TRK = (newc << RLDA_V_CYL) | /* put on track */ + ((rlda & RLDA_SK_HD)? RLDA_HD1: RLDA_HD0); + sim_activate (uptr, rl_swait * abs (newc - curr)); + break; default: /* data transfer */ - sim_activate (uptr, rl_swait); /* activate unit */ - break; } /* end switch func */ + sim_activate (uptr, rl_swait); /* activate unit */ + break; } /* end switch func */ break; /* end case RLCS */ case 1: /* RLBA */ if (access == WRITEB) data = (PA & 1)? - (rlba & 0377) | (data << 8): (rlba & ~0377) | data; + (rlba & 0377) | (data << 8): (rlba & ~0377) | data; rlba = data & RLBA_IMP; break; case 2: /* RLDA */ if (access == WRITEB) data = (PA & 1)? - (rlda & 0377) | (data << 8): (rlda & ~0377) | data; + (rlda & 0377) | (data << 8): (rlda & ~0377) | data; rlda = data; break; case 3: /* RLMP */ if (access == WRITEB) data = (PA & 1)? - (rlmp & 0377) | (data << 8): (rlmp & ~0377) | data; + (rlmp & 0377) | (data << 8): (rlmp & ~0377) | data; rlmp = rlmp1 = rlmp2 = data; break; case 4: /* RLBAE */ @@ -410,7 +411,7 @@ func = GET_FUNC (rlcs); /* get function */ if (func == RLCS_GSTA) { /* get status */ if (rlda & RLDA_GS_CLR) uptr->STAT = uptr->STAT & ~RLDS_ERR; rlmp = uptr->STAT | (uptr->TRK & RLDS_HD) | - ((uptr->flags & UNIT_ATT)? RLDS_ATT: RLDS_UNATT); + ((uptr->flags & UNIT_ATT)? RLDS_ATT: RLDS_UNATT); if (uptr->flags & UNIT_RL02) rlmp = rlmp | RLDS_RL02; if (uptr->flags & UNIT_WPRT) rlmp = rlmp | RLDS_WLK; rlmp2 = rlmp1 = rlmp; @@ -456,19 +457,19 @@ if ((func >= RLCS_READ) && (err == 0)) { /* read (no hdr)? */ err = ferror (uptr->fileref); for ( ; i < wc; i++) rlxb[i] = 0; /* fill buffer */ if (t = Map_WriteW (ma, wc << 1, rlxb, MAP)) { /* store buffer */ - rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ - wc = wc - t; } /* adjust wc */ + rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ + wc = wc - t; } /* adjust wc */ } /* end read */ if ((func == RLCS_WRITE) && (err == 0)) { /* write? */ if (t = Map_ReadW (ma, wc << 1, rlxb, MAP)) { /* fetch buffer */ - rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ - wc = wc - t; } /* adj xfer lnt */ + rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ + wc = wc - t; } /* adj xfer lnt */ if (wc) { /* any xfer? */ - awc = (wc + (RL_NUMWD - 1)) & ~(RL_NUMWD - 1); /* clr to */ - for (i = wc; i < awc; i++) rlxb[i] = 0; /* end of blk */ - fxwrite (rlxb, sizeof (int16), awc, uptr->fileref); - err = ferror (uptr->fileref); } + awc = (wc + (RL_NUMWD - 1)) & ~(RL_NUMWD - 1); /* clr to */ + for (i = wc; i < awc; i++) rlxb[i] = 0; /* end of blk */ + fxwrite (rlxb, sizeof (int16), awc, uptr->fileref); + err = ferror (uptr->fileref); } } /* end write */ if ((func == RLCS_WCHK) && (err == 0)) { /* write check? */ @@ -477,12 +478,12 @@ if ((func == RLCS_WCHK) && (err == 0)) { /* write check? */ for ( ; i < wc; i++) rlxb[i] = 0; /* fill buffer */ awc = wc; /* save wc */ for (wc = 0; (err == 0) && (wc < awc); wc++) { /* loop thru buf */ - if (Map_ReadW (ma + (wc << 1), 2, &comp, MAP)) { /* mem wd */ - rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ - break; } - if (comp != rlxb[wc]) /* check to buf */ - rlcs = rlcs | RLCS_ERR | RLCS_CRC; - } /* end for */ + if (Map_ReadW (ma + (wc << 1), 2, &comp, MAP)) { /* mem wd */ + rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ + break; } + if (comp != rlxb[wc]) /* check to buf */ + rlcs = rlcs | RLCS_ERR | RLCS_CRC; + } /* end for */ } /* end wcheck */ rlmp = (rlmp + wc) & 0177777; /* final word count */ diff --git a/PDP11/pdp11_rp.c b/PDP11/pdp11_rp.c index 0d2ee4a8..4399a108 100644 --- a/PDP11/pdp11_rp.c +++ b/PDP11/pdp11_rp.c @@ -571,7 +571,7 @@ case 006: /* RPER1 */ case 007: /* RPAS */ *data = 0; for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) *data = *data | (AS_U0 << i); + if (rpds[i] & DS_ATA) *data = *data | (AS_U0 << i); break; case 010: /* RPLA */ *data = GET_SECTOR (rp_rwait, dtype) << LA_V_SC; @@ -646,52 +646,53 @@ switch (j) { /* decode PA<5:1> */ case 000: /* RPCS1 */ if ((access == WRITEB) && (PA & 1)) data = data << 8; if (data & CS1_TRE) { /* error clear? */ - rpcs1 = rpcs1 & ~CS1_TRE; /* clr CS1 */ - rpcs2 = rpcs2 & ~CS2_ERR; } /* clr CS2<15:8> */ + rpcs1 = rpcs1 & ~CS1_TRE; /* clr CS1 */ + rpcs2 = rpcs2 & ~CS2_ERR; } /* clr CS2<15:8> */ if ((access == WRITE) || (PA & 1)) { /* hi byte write? */ - if (rpcs1 & CS1_DONE) /* done set? */ - rpcs1 = (rpcs1 & ~CS1_UAE) | (data & CS1_UAE); } + if (rpcs1 & CS1_DONE) /* done set? */ + rpcs1 = (rpcs1 & ~CS1_UAE) | (data & CS1_UAE); } if ((access == WRITE) || !(PA & 1)) { /* lo byte write? */ - if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */ - rpiff = 1; /* set CSTB INTR */ - rpcs1 = (rpcs1 & ~CS1_IE) | (data & CS1_IE); - if (uptr->flags & UNIT_DIS) { /* nx disk? */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - cs1f = CS1_SC; } /* req interrupt */ - else if (sim_is_active (uptr)) - rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */ - else if (data & CS1_GO) { /* start op */ - uptr->FUNC = GET_FNC (data); /* set func */ - if ((uptr->FUNC >= FNC_XFER) && /* data xfer and */ - ((rpcs1 & CS1_DONE) == 0)) /* ~rdy? PGE */ - rpcs2 = rpcs2 | CS2_PGE; - else rp_go (drv, uptr->FUNC); } } + if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */ + rpiff = 1; /* set CSTB INTR */ + rpcs1 = (rpcs1 & ~CS1_IE) | (data & CS1_IE); + if (uptr->flags & UNIT_DIS) { /* nx disk? */ + rpcs2 = rpcs2 | CS2_NED; /* set error flag */ + cs1f = CS1_SC; } /* req interrupt */ + else if (sim_is_active (uptr)) + rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */ + else if (data & CS1_GO) { /* start op */ + uptr->FUNC = GET_FNC (data); /* set func */ + if ((uptr->FUNC >= FNC_XFER) && /* data xfer and */ + ((rpcs1 & CS1_DONE) == 0)) /* ~rdy? PGE */ + rpcs2 = rpcs2 | CS2_PGE; + else rp_go (drv, uptr->FUNC); } } rpcs3 = (rpcs3 & ~CS1_IE) | (rpcs1 & CS1_IE); rpbae = (rpbae & ~CS1_M_UAE) | ((rpcs1 >> CS1_V_UAE) & CS1_M_UAE); break; case 001: /* RPWC */ if (access == WRITEB) data = (PA & 1)? - (rpwc & 0377) | (data << 8): (rpwc & ~0377) | data; + (rpwc & 0377) | (data << 8): (rpwc & ~0377) | data; rpwc = data; break; case 002: /* RPBA */ if (access == WRITEB) data = (PA & 1)? - (rpba & 0377) | (data << 8): (rpba & ~0377) | data; + (rpba & 0377) | (data << 8): (rpba & ~0377) | data; rpba = data & ~BA_MBZ; break; case 003: /* RPDA */ if (access == WRITEB) data = (PA & 1)? - (rpda & 0377) | (data << 8): (rpda & ~0377) | data; + (rpda & 0377) | (data << 8): (rpda & ~0377) | data; rpda = data & ~DA_MBZ; break; case 004: /* RPCS2 */ if ((access == WRITEB) && (PA & 1)) data = data << 8; if (data & CS2_CLR) rp_reset (&rp_dev); /* init? */ - else { if ((data & ~rpcs2) & (CS2_PE | CS2_MXF)) - cs1f = CS1_SC; /* diagn intr */ - if (access == WRITEB) data = (rpcs2 & /* merge data */ - ((PA & 1)? 0377: 0177400)) | data; - rpcs2 = (rpcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; } + else { + if ((data & ~rpcs2) & (CS2_PE | CS2_MXF)) + cs1f = CS1_SC; /* diagn intr */ + if (access == WRITEB) data = (rpcs2 & /* merge data */ + ((PA & 1)? 0377: 0177400)) | data; + rpcs2 = (rpcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; } drv = GET_UNIT (rpcs2); break; case 006: /* RPER1 */ @@ -701,26 +702,26 @@ case 006: /* RPER1 */ case 007: /* RPAS */ if ((access == WRITEB) && (PA & 1)) break; for (i = 0; i < RP_NUMDR; i++) - if (data & (AS_U0 << i)) rpds[i] = rpds[i] & ~DS_ATA; + if (data & (AS_U0 << i)) rpds[i] = rpds[i] & ~DS_ATA; break; case 011: /* RPDB */ if (access == WRITEB) data = (PA & 1)? - (rpdb & 0377) | (data << 8): (rpdb & ~0377) | data; + (rpdb & 0377) | (data << 8): (rpdb & ~0377) | data; rpdb = data; break; case 012: /* RPMR */ if (access == WRITEB) data = (PA & 1)? - (rpmr & 0377) | (data << 8): (rpmr & ~0377) | data; + (rpmr & 0377) | (data << 8): (rpmr & ~0377) | data; rpmr = data; break; case 015: /* RPOF */ if (access == WRITEB) data = (PA & 1)? - (rpof & 0377) | (data << 8): (rpof & ~0377) | data; + (rpof & 0377) | (data << 8): (rpof & ~0377) | data; rpof = data & ~OF_MBZ; break; case 016: /* RPDC */ if (access == WRITEB) data = (PA & 1)? - (rpdc & 0377) | (data << 8): (rpdc & ~0377) | data; + (rpdc & 0377) | (data << 8): (rpdc & ~0377) | data; rpdc = data & ~DC_MBZ; break; case 024: /* RPBAE */ @@ -796,8 +797,8 @@ case FNC_PACK: /* pack acknowledge */ case FNC_OFFSET: /* offset mode */ case FNC_RETURN: if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } + rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ + break; } rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ sim_activate (uptr, rp_swait); /* time operation */ return; @@ -808,13 +809,13 @@ case FNC_RECAL: /* recalibrate */ case FNC_SEEK: /* seek */ case FNC_SEARCH: /* search */ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } + rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ + break; } if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ (GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */ (GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */ - rper1[drv] = rper1[drv] | ER1_IAE; - break; } + rper1[drv] = rper1[drv] | ER1_IAE; + break; } rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ t = abs (dc - uptr->CYL); /* cyl diff */ if (t == 0) t = 1; /* min time */ @@ -828,15 +829,15 @@ case FNC_WCHK: /* write check */ case FNC_READ: /* read */ case FNC_READH: /* read headers */ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ - break; } + rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */ + break; } rpcs2 = rpcs2 & ~CS2_ERR; /* clear errors */ rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE); if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ (GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */ (GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */ - rper1[drv] = rper1[drv] | ER1_IAE; - break; } + rper1[drv] = rper1[drv] | ER1_IAE; + break; } rpds[drv] = rpds[drv] & ~DS_RDY; /* clear drive rdy */ sim_activate (uptr, rp_rwait + (rp_swait * abs (dc - uptr->CYL))); uptr->CYL = dc; /* save cylinder */ @@ -890,9 +891,9 @@ case FNC_SEEK: /* seek */ case FNC_WRITE: /* write */ if (uptr->flags & UNIT_WPRT) { /* write locked? */ - rper1[drv] = rper1[drv] | ER1_WLE; /* set drive error */ - update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ - break; } + rper1[drv] = rper1[drv] | ER1_WLE; /* set drive error */ + update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ + break; } case FNC_WCHK: /* write check */ case FNC_READ: /* read */ case FNC_READH: /* read headers */ @@ -947,11 +948,11 @@ case FNC_READH: /* read headers */ awc = wc; for (wc = 0; wc < awc; wc++) { /* loop thru buf */ if (Map_ReadW (ba, 2, &comp, RH)) { /* read word */ - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - break; } + rpcs2 = rpcs2 | CS2_NEM; /* set error */ + break; } if (comp != rpxb[wc]) { /* compare wd */ - rpcs2 = rpcs2 | CS2_WCE; /* set error */ - break; } + rpcs2 = rpcs2 | CS2_WCE; /* set error */ + break; } if ((rpcs2 & CS2_UAI) == 0) ba = ba + 2; } } /* end else wchk */ @@ -968,11 +969,11 @@ case FNC_READH: /* read headers */ rpdc = da / drv_tab[dtype].surf; if (err != 0) { /* error? */ - rper1[drv] = rper1[drv] | ER1_PAR; /* set drive error */ - update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ - perror ("RP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } + rper1[drv] = rper1[drv] | ER1_PAR; /* set drive error */ + update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ + perror ("RP I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; } case FNC_WRITEH: /* write headers stub */ update_rpcs (CS1_DONE, drv); /* set done */ break; } /* end case func */ @@ -1046,7 +1047,7 @@ for (i = 0; i < RP_NUMDR; i++) { sim_cancel (uptr); uptr->CYL = uptr->FUNC = 0; if (uptr->flags & UNIT_ATT) rpds[i] = (rpds[i] & DS_VV) | - DS_DPR | DS_RDY | DS_MOL | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); + DS_DPR | DS_RDY | DS_MOL | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); else if (uptr->flags & UNIT_DIS) rpds[i] = 0; else rpds[i] = DS_DPR; rper1[i] = 0; } @@ -1076,7 +1077,7 @@ if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; if ((p = ftell (uptr->fileref)) == 0) { if (uptr->flags & UNIT_RO) return SCPE_OK; return pdp11_bad_block (uptr, - drv_tab[GET_DTYPE (uptr->flags)].sect, RP_NUMWD); } + drv_tab[GET_DTYPE (uptr->flags)].sect, RP_NUMWD); } for (i = 0; drv_tab[i].sect != 0; i++) { if (p <= (drv_tab[i].size * (int) sizeof (int16))) { uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); @@ -1098,7 +1099,7 @@ if (sim_is_active (uptr)) { /* unit active? */ sim_cancel (uptr); /* cancel operation */ rper1[drv] = rper1[drv] | ER1_OPI; /* set drive error */ if (uptr->FUNC >= FNC_WCHK) /* data transfer? */ - rpcs1 = rpcs1 | CS1_DONE | CS1_TRE; } /* set done, err */ + rpcs1 = rpcs1 | CS1_DONE | CS1_TRE; } /* set done, err */ update_rpcs (CS1_SC, drv); /* request intr */ return detach_unit (uptr); } diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c index d6b7951d..f3897376 100644 --- a/PDP11/pdp11_rq.c +++ b/PDP11/pdp11_rq.c @@ -1359,7 +1359,7 @@ if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ return OK; } } /* done */ else sts = ST_OFL; /* offline */ cp->pak[pkt].d[RW_BCL] = cp->pak[pkt].d[RW_BCH] = 0; /* bad packet */ -rq_putr (cp, pkt, cmd | OP_END, 0, sts, RW_LNT, UQ_TYP_SEQ); +rq_putr (cp, pkt, cmd | OP_END, 0, sts, RW_LNT_D, UQ_TYP_SEQ); return rq_putpkt (cp, pkt, TRUE); } @@ -1517,7 +1517,7 @@ cp->pak[pkt].d[RW_WBCL] = 0; cp->pak[pkt].d[RW_WBCH] = 0; cp->pak[pkt].d[RW_WBLL] = 0; cp->pak[pkt].d[RW_WBLH] = 0; -rq_putr (cp, pkt, cmd | OP_END, flg, sts, RW_LNT, UQ_TYP_SEQ); /* fill pkt */ +rq_putr (cp, pkt, cmd | OP_END, flg, sts, RW_LNT_D, UQ_TYP_SEQ); /* fill pkt */ if (!rq_putpkt (cp, pkt, TRUE)) return ERR; /* send pkt */ if (uptr->pktq) /* more to do? */ sim_activate (dptr->units + RQ_QUEUE, rq_qtime); /* activate thread */ diff --git a/PDP11/pdp11_rx.c b/PDP11/pdp11_rx.c index 1c5b1797..8f56f7bf 100644 --- a/PDP11/pdp11_rx.c +++ b/PDP11/pdp11_rx.c @@ -205,8 +205,8 @@ case 0: /* RXCS */ break; case 1: /* RXDB */ if ((rx_state == EMPTY) && (rx_csr & RXCS_TR)) {/* empty? */ - sim_activate (&rx_unit[0], rx_xwait); - rx_csr = rx_csr & ~RXCS_TR; } /* clear xfer */ + sim_activate (&rx_unit[0], rx_xwait); + rx_csr = rx_csr & ~RXCS_TR; } /* clear xfer */ *data = rx_dbr; /* return data */ break; } /* end switch PA */ return SCPE_OK; @@ -230,36 +230,36 @@ switch ((PA >> 1) & 1) { /* decode PA<1> */ case 0: /* RXCS */ rx_csr = rx_csr & RXCS_IMP; /* clear junk */ if (access == WRITEB) data = (PA & 1)? /* write byte? */ - (rx_csr & 0377) | (data << 8): (rx_csr & ~0377) | data; + (rx_csr & 0377) | (data << 8): (rx_csr & ~0377) | data; if (data & RXCS_INIT) { /* initialize? */ - rx_reset (&rx_dev); /* reset device */ - return SCPE_OK; } /* end if init */ + rx_reset (&rx_dev); /* reset device */ + return SCPE_OK; } /* end if init */ if ((data & CSR_GO) && (rx_state == IDLE)) { /* new function? */ - rx_csr = data & (RXCS_IE + RXCS_DRV + RXCS_FUNC); - drv = ((rx_csr & RXCS_DRV)? 1: 0); /* reselect drive */ - bptr = 0; /* clear buf pointer */ - switch (RXCS_GETFNC (data)) { /* case on func */ - case RXCS_FILL: - rx_state = FILL; /* state = fill */ - rx_csr = rx_csr | RXCS_TR; /* xfer is ready */ - break; - case RXCS_EMPTY: - rx_state = EMPTY; /* state = empty */ - sim_activate (&rx_unit[drv], rx_xwait); - break; - case RXCS_READ: case RXCS_WRITE: case RXCS_WRDEL: - rx_state = RWDS; /* state = get sector */ - rx_csr = rx_csr | RXCS_TR; /* xfer is ready */ - rx_esr = rx_esr & RXES_ID; /* clear errors */ - break; - default: - rx_state = CMD_COMPLETE; /* state = cmd compl */ - sim_activate (&rx_unit[drv], rx_cwait); - break; } /* end switch func */ - return SCPE_OK; } /* end if GO */ + rx_csr = data & (RXCS_IE + RXCS_DRV + RXCS_FUNC); + drv = ((rx_csr & RXCS_DRV)? 1: 0); /* reselect drive */ + bptr = 0; /* clear buf pointer */ + switch (RXCS_GETFNC (data)) { /* case on func */ + case RXCS_FILL: + rx_state = FILL; /* state = fill */ + rx_csr = rx_csr | RXCS_TR; /* xfer is ready */ + break; + case RXCS_EMPTY: + rx_state = EMPTY; /* state = empty */ + sim_activate (&rx_unit[drv], rx_xwait); + break; + case RXCS_READ: case RXCS_WRITE: case RXCS_WRDEL: + rx_state = RWDS; /* state = get sector */ + rx_csr = rx_csr | RXCS_TR; /* xfer is ready */ + rx_esr = rx_esr & RXES_ID; /* clear errors */ + break; + default: + rx_state = CMD_COMPLETE; /* state = cmd compl */ + sim_activate (&rx_unit[drv], rx_cwait); + break; } /* end switch func */ + return SCPE_OK; } /* end if GO */ if ((data & RXCS_IE) == 0) CLR_INT (RX); else if ((rx_csr & (RXCS_DONE + RXCS_IE)) == RXCS_DONE) - SET_INT (RX); + SET_INT (RX); rx_csr = (rx_csr & ~RXCS_RW) | (data & RXCS_RW); break; /* end case RXCS */ @@ -270,12 +270,12 @@ case 0: /* RXCS */ case 1: /* RXDB */ if ((PA & 1) || ((rx_state != IDLE) && ((rx_csr & RXCS_TR) == 0))) - return SCPE_OK; /* if ~IDLE, need tr */ + return SCPE_OK; /* if ~IDLE, need tr */ rx_dbr = data & 0377; /* save data */ if ((rx_state != IDLE) && (rx_state != EMPTY)) { - drv = ((rx_csr & RXCS_DRV)? 1: 0); /* select drive */ - sim_activate (&rx_unit[drv], rx_xwait); /* sched event */ - rx_csr = rx_csr & ~RXCS_TR; } /* clear xfer */ + drv = ((rx_csr & RXCS_DRV)? 1: 0); /* select drive */ + sim_activate (&rx_unit[drv], rx_xwait); /* sched event */ + rx_csr = rx_csr & ~RXCS_TR; } /* clear xfer */ break; /* end case RXDB */ } /* end switch PA */ return SCPE_OK; @@ -311,9 +311,10 @@ case IDLE: /* idle */ case EMPTY: /* empty buffer */ if (bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */ - else { rx_dbr = rx_buf[bptr]; /* get next */ - bptr = bptr + 1; - rx_csr = rx_csr | RXCS_TR; } /* set xfer */ + else { + rx_dbr = rx_buf[bptr]; /* get next */ + bptr = bptr + 1; + rx_csr = rx_csr | RXCS_TR; } /* set xfer */ break; case FILL: /* fill buffer */ @@ -336,34 +337,35 @@ case RWDT: /* wait for track */ return SCPE_OK; case RWXFR: if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ - rx_done (0, 0110); /* done, error */ - return IORETURN (rx_stopioe, SCPE_UNATT); } + rx_done (0, 0110); /* done, error */ + return IORETURN (rx_stopioe, SCPE_UNATT); } if (rx_track >= RX_NUMTR) { /* bad track? */ - rx_done (0, 0040); /* done, error */ - break; } + rx_done (0, 0040); /* done, error */ + break; } uptr->TRACK = rx_track; /* now on track */ if ((rx_sector == 0) || (rx_sector > RX_NUMSC)) { /* bad sect? */ - rx_done (0, 0070); /* done, error */ - break; } + rx_done (0, 0070); /* done, error */ + break; } da = CALC_DA (rx_track, rx_sector); /* get disk address */ if (func == RXCS_WRDEL) rx_esr = rx_esr | RXES_DD; /* del data? */ if (func == RXCS_READ) { /* read? */ - for (i = 0; i < RX_NUMBY; i++) - rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); } - else { if (uptr->flags & UNIT_WPRT) { /* write and locked? */ - rx_done (RXES_WLK, 0100); /* done, error */ - break; } - for (i = 0; i < RX_NUMBY; i++) /* write */ - *(((int8 *) uptr->filebuf) + da + i) = rx_buf[i]; - da = da + RX_NUMBY; - if (da > uptr->hwmark) uptr->hwmark = da; } + for (i = 0; i < RX_NUMBY; i++) + rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); } + else { + if (uptr->flags & UNIT_WPRT) { /* write and locked? */ + rx_done (RXES_WLK, 0100); /* done, error */ + break; } + for (i = 0; i < RX_NUMBY; i++) /* write */ + *(((int8 *) uptr->filebuf) + da + i) = rx_buf[i]; + da = da + RX_NUMBY; + if (da > uptr->hwmark) uptr->hwmark = da; } rx_done (0, 0); /* done */ break; case CMD_COMPLETE: /* command complete */ if (func == RXCS_ECODE) { /* read ecode? */ - rx_dbr = rx_ecode; /* set dbr */ - rx_done (0, -1); } /* don't update */ + rx_dbr = rx_ecode; /* set dbr */ + rx_done (0, -1); } /* don't update */ else rx_done (0, 0); break; @@ -371,11 +373,11 @@ case INIT_COMPLETE: /* init complete */ rx_unit[0].TRACK = 1; /* drive 0 to trk 1 */ rx_unit[1].TRACK = 0; /* drive 1 to trk 0 */ if ((rx_unit[0].flags & UNIT_BUF) == 0) { /* not buffered? */ - rx_done (RXES_ID, 0010); /* init done, error */ - break; } + rx_done (RXES_ID, 0010); /* init done, error */ + break; } da = CALC_DA (1, 1); /* track 1, sector 1 */ for (i = 0; i < RX_NUMBY; i++) /* read sector */ - rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); + rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); rx_done (RXES_ID, 0); /* set done */ if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020; break; } /* end case state */ diff --git a/PDP11/pdp11_stddev.c b/PDP11/pdp11_stddev.c index f7bff9e8..0b15f6ed 100644 --- a/PDP11/pdp11_stddev.c +++ b/PDP11/pdp11_stddev.c @@ -26,6 +26,7 @@ tti,tto DL11 terminal input/output clk KW11L line frequency clock + 22-Nov-02 RMS Changed terminal default to 7B for UNIX 01-Nov-02 RMS Added 7B/8B support to terminal 29-Sep-02 RMS Added vector display support Split out paper tape @@ -93,7 +94,7 @@ t_stat clk_reset (DEVICE *dptr); DIB tti_dib = { IOBA_TTI, IOLN_TTI, &tti_rd, &tti_wr, 1, IVCL (TTI), VEC_TTI, { NULL } }; -UNIT tti_unit = { UDATA (&tti_svc, UNIT_8B, 0), KBD_POLL_WAIT }; +UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; REG tti_reg[] = { { ORDATA (BUF, tti_unit.buf, 8) }, @@ -132,7 +133,7 @@ DEVICE tti_dev = { DIB tto_dib = { IOBA_TTO, IOLN_TTO, &tto_rd, &tto_wr, 1, IVCL (TTO), VEC_TTO, { NULL } }; -UNIT tto_unit = { UDATA (&tto_svc, UNIT_8B, 0), SERIAL_OUT_WAIT }; +UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; REG tto_reg[] = { { ORDATA (BUF, tto_unit.buf, 8) }, @@ -219,7 +220,7 @@ case 00: /* tti csr */ if (PA & 1) return SCPE_OK; if ((data & CSR_IE) == 0) CLR_INT (TTI); else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (TTI); + SET_INT (TTI); tti_csr = (tti_csr & ~TTICSR_RW) | (data & TTICSR_RW); return SCPE_OK; case 01: /* tti buf */ @@ -235,7 +236,8 @@ int32 c; sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); +if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */ +else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); tti_unit.pos = tti_unit.pos + 1; tti_csr = tti_csr | CSR_DONE; if (tti_csr & CSR_IE) SET_INT (TTI); @@ -274,7 +276,7 @@ case 00: /* tto csr */ if (PA & 1) return SCPE_OK; if ((data & CSR_IE) == 0) CLR_INT (TTO); else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (TTO); + SET_INT (TTO); tto_csr = (tto_csr & ~TTOCSR_RW) | (data & TTOCSR_RW); return SCPE_OK; case 01: /* tto buf */ diff --git a/PDP11/pdp11_sys.c b/PDP11/pdp11_sys.c index bcad0261..ecc8c78c 100644 --- a/PDP11/pdp11_sys.c +++ b/PDP11/pdp11_sys.c @@ -1,6 +1,6 @@ /* pdp11_sys.c: PDP-11 simulator interface - Copyright (c) 1993-2002, Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 09-Jan-03 RMS Added DELUA support 17-Oct-02 RMS Fixed bugs in branch, SOB address parsing 09-Oct-02 RMS Added DELQA support 12-Sep-02 RMS Added TMSCP, KW11P, RX211 support, RAD50 examine @@ -61,7 +62,7 @@ extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; extern DEVICE dt_dev; extern DEVICE tm_dev, ts_dev; extern DEVICE tq_dev; -extern DEVICE xq_dev; +extern DEVICE xq_dev, xu_dev; extern UNIT cpu_unit; extern REG cpu_reg[]; extern uint16 *M; @@ -108,6 +109,7 @@ DEVICE *sim_devices[] = { &ts_dev, &tq_dev, &xq_dev, + &xu_dev, NULL }; const char *sim_stop_messages[] = { diff --git a/PDP11/pdp11_tc.c b/PDP11/pdp11_tc.c index 365306f6..64c02bbb 100644 --- a/PDP11/pdp11_tc.c +++ b/PDP11/pdp11_tc.c @@ -400,7 +400,7 @@ case 003: /* TCBA */ case 004: /* TCDT */ fnc = DTS_GETFNC (dt_unit[unum].STATE); /* get function */ if (fnc == FNC_RALL) { /* read all? */ - DT_CLRDONE; } /* clear done */ + DT_CLRDONE; } /* clear done */ *data = tcdt; break; } return SCPE_OK; @@ -420,34 +420,34 @@ case 000: /* TCST */ case 001: /* TCCM */ old_tccm = tccm; /* save prior */ if (access == WRITEB) data = (PA & 1)? - (tccm & 0377) | (data << 8): (tccm & ~0377) | data; + (tccm & 0377) | (data << 8): (tccm & ~0377) | data; if ((data & CSR_IE) == 0) CLR_INT (DTA); else if ((((tccm & CSR_IE) == 0) && (tccm & CSR_DONE)) || - (data & CSR_DONE)) SET_INT (DTA); + (data & CSR_DONE)) SET_INT (DTA); tccm = (tccm & ~CSR_RW) | (data & CSR_RW); if ((data & CSR_GO) && (tccm & CSR_DONE)) { /* new cmd? */ - tcst = tcst & ~STA_ALLERR; /* clear errors */ - tccm = tccm & ~(CSR_ERR | CSR_DONE); /* clear done, err */ - CLR_INT (DTA); /* clear int */ - if ((old_tccm ^ tccm) & CSR_UNIT) dt_deselect (old_tccm); - unum = CSR_GETUNIT (tccm); /* get drive */ - fnc = CSR_GETFNC (tccm); /* get function */ - if (fnc == FNC_STOP) { /* stop all? */ - sim_activate (&dt_dev.units[DT_TIMER], dt_ctime); - for (i = 0; i < DT_NUMDR; i++) - dt_stopunit (dt_dev.units + i); /* stop unit */ - break; } - uptr = dt_dev.units + unum; - if (uptr->flags & UNIT_DIS) /* disabled? */ - dt_seterr (uptr, STA_SEL); /* select err */ - if ((fnc == FNC_WMRK) || /* write mark? */ - ((fnc == FNC_WALL) && (uptr->flags & UNIT_WPRT)) || - ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WPRT))) - dt_seterr (uptr, STA_ILO); /* illegal op */ - if (!(tccm & CSR_ERR)) dt_newsa (tccm); } + tcst = tcst & ~STA_ALLERR; /* clear errors */ + tccm = tccm & ~(CSR_ERR | CSR_DONE); /* clear done, err */ + CLR_INT (DTA); /* clear int */ + if ((old_tccm ^ tccm) & CSR_UNIT) dt_deselect (old_tccm); + unum = CSR_GETUNIT (tccm); /* get drive */ + fnc = CSR_GETFNC (tccm); /* get function */ + if (fnc == FNC_STOP) { /* stop all? */ + sim_activate (&dt_dev.units[DT_TIMER], dt_ctime); + for (i = 0; i < DT_NUMDR; i++) + dt_stopunit (dt_dev.units + i); /* stop unit */ + break; } + uptr = dt_dev.units + unum; + if (uptr->flags & UNIT_DIS) /* disabled? */ + dt_seterr (uptr, STA_SEL); /* select err */ + if ((fnc == FNC_WMRK) || /* write mark? */ + ((fnc == FNC_WALL) && (uptr->flags & UNIT_WPRT)) || + ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WPRT))) + dt_seterr (uptr, STA_ILO); /* illegal op */ + if (!(tccm & CSR_ERR)) dt_newsa (tccm); } else if ((tccm & CSR_ERR) == 0) { /* clear err? */ - tcst = tcst & ~STA_RWERR; - if (tcst & STA_ALLERR) tccm = tccm | CSR_ERR; } + tcst = tcst & ~STA_RWERR; + if (tcst & STA_ALLERR) tccm = tccm | CSR_ERR; } break; case 002: /* TCWC */ tcwc = data; /* word write only! */ @@ -459,7 +459,7 @@ case 004: /* TCDT */ unum = CSR_GETUNIT (tccm); /* get drive */ fnc = DTS_GETFNC (dt_unit[unum].STATE); /* get function */ if (fnc == FNC_WALL) { /* write all? */ - DT_CLRDONE; } /* clear done */ + DT_CLRDONE; } /* clear done */ tcdt = data; /* word write only! */ break; } return SCPE_OK; @@ -587,49 +587,50 @@ case DTS_OFR: /* off reel */ break; case FNC_SRCH: /* search */ if (dir) newpos = DT_BLK2LN ((DT_QFEZ (uptr)? - DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; + DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; else newpos = DT_BLK2LN ((DT_QREZ (uptr)? - 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); + 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); if (DBG_LOG (LOG_TC_MS)) fprintf (sim_log, ">>DT%d: searching %s\n", - unum, (dir? "backward": "forward")); + unum, (dir? "backward": "forward")); break; case FNC_WRIT: /* write */ case FNC_READ: /* read */ if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); - break; } + if (dir) newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; + else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); + break; } relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - dt_seterr (uptr, STA_BLKM); - return; } + dt_seterr (uptr, STA_BLKM); + return; } if (dir) newpos = DT_BLK2LN (((relpos >= (DTU_LPERB (uptr) - DT_HTLIN))? - blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; + blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; else newpos = DT_BLK2LN (((relpos < DT_HTLIN)? - blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); + blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); if (DBG_LOG (LOG_TC_RW) || (DBG_LOG (LOG_TC_BL) && (blk == dt_logblk))) - fprintf (sim_log, ">>DT%d: %s block %d %s\n", - unum, ((fnc == FNC_READ)? "read": "write"), - blk, (dir? "backward": "forward")); + fprintf (sim_log, ">>DT%d: %s block %d %s\n", + unum, ((fnc == FNC_READ)? "read": "write"), + blk, (dir? "backward": "forward")); break; case FNC_RALL: /* read all */ case FNC_WALL: /* write all */ if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE; - else newpos = DT_EZLIN + (DT_WSIZE - 1); } - else { relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if (dir? (relpos < (DTU_LPERB (uptr) - DT_CSMLN)): /* switch in time? */ - (relpos >= DT_CSMLN)) { - dt_seterr (uptr, STA_BLKM); - return; } - if (dir) newpos = DT_BLK2LN (blk + 1, uptr) - DT_CSMLN - DT_WSIZE; - else newpos = DT_BLK2LN (blk, uptr) + DT_CSMLN + (DT_WSIZE - 1); } + if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE; + else newpos = DT_EZLIN + (DT_WSIZE - 1); } + else { + relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ + if (dir? (relpos < (DTU_LPERB (uptr) - DT_CSMLN)): /* switch in time? */ + (relpos >= DT_CSMLN)) { + dt_seterr (uptr, STA_BLKM); + return; } + if (dir) newpos = DT_BLK2LN (blk + 1, uptr) - DT_CSMLN - DT_WSIZE; + else newpos = DT_BLK2LN (blk, uptr) + DT_CSMLN + (DT_WSIZE - 1); } if (fnc == FNC_WALL) sim_activate /* write all? */ - (&dt_dev.units[DT_TIMER], dt_ctime); /* sched done */ + (&dt_dev.units[DT_TIMER], dt_ctime); /* sched done */ if (DBG_LOG (LOG_TC_RW) || (DBG_LOG (LOG_TC_BL) && (blk == dt_logblk))) - fprintf (sim_log, ">>DT%d: read all block %d %s\n", - unum, blk, (dir? "backward": "forward")); + fprintf (sim_log, ">>DT%d: read all block %d %s\n", + unum, blk, (dir? "backward": "forward")); break; default: dt_seterr (uptr, STA_SEL); /* bad state */ @@ -689,7 +690,7 @@ if (((int32) uptr->pos < 0) || uptr->STATE = uptr->pos = 0; unum = uptr - dt_dev.units; if ((unum == CSR_GETUNIT (tccm)) && (CSR_GETFNC (tccm) != FNC_STOP)) - dt_seterr (uptr, STA_SEL); /* error */ + dt_seterr (uptr, STA_SEL); /* error */ return TRUE; } return FALSE; } @@ -728,7 +729,7 @@ case DTS_DECF: case DTS_DECR: /* decelerating */ if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ + sim_activate (uptr, dt_actime); /* must be reversing */ return SCPE_OK; case DTS_ACCF: case DTS_ACCR: /* accelerating */ dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ @@ -774,24 +775,24 @@ case DTS_OFR: /* off reel */ case FNC_READ: /* read */ wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ if (!dt_substate) { /* !wc ovf? */ - tcwc = tcwc & DMASK; /* incr MA, WC */ - tcba = tcba & DMASK; - ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */ - if (!Map_Addr (ma, &mma) || /* map addr */ - !ADDR_IS_MEM (mma)) { /* nx mem? */ - dt_seterr (uptr, STA_NXM); - break; } - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - M[mma >> 1] = tcdt = bptr[ba] & DMASK; /* read word */ - tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */ - tcba = (tcba + 2) & DMASK; - if (tcba <= 1) tccm = CSR_INCMEX (tccm); - if (tcwc == 0) dt_substate = 1; } + tcwc = tcwc & DMASK; /* incr MA, WC */ + tcba = tcba & DMASK; + ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */ + if (!Map_Addr (ma, &mma) || /* map addr */ + !ADDR_IS_MEM (mma)) { /* nx mem? */ + dt_seterr (uptr, STA_NXM); + break; } + ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ + M[mma >> 1] = tcdt = bptr[ba] & DMASK; /* read word */ + tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */ + tcba = (tcba + 2) & DMASK; + if (tcba <= 1) tccm = CSR_INCMEX (tccm); + if (tcwc == 0) dt_substate = 1; } if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not end blk? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); + sim_activate (uptr, DT_WSIZE * dt_ltime); else if (dt_substate) { /* wc ovf? */ - dt_schedez (uptr, dir); /* sched end zone */ - DT_SETDONE; } /* set done */ + dt_schedez (uptr, dir); /* sched end zone */ + DT_SETDONE; } /* set done */ else sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); break; @@ -808,24 +809,25 @@ case FNC_READ: /* read */ case FNC_WRIT: /* write */ wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ if (dt_substate) tcdt = 0; /* wc ovf? fill */ - else { ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */ - if (!Map_Addr (ma, &mma) || /* map addr */ - !ADDR_IS_MEM (mma)) { /* nx mem? */ - dt_seterr (uptr, STA_NXM); - break; } - else tcdt = M[mma >> 1]; /* get word */ - tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */ - tcba = (tcba + 2) & DMASK; - if (tcba <= 1) tccm = CSR_INCMEX (tccm); } + else { + ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */ + if (!Map_Addr (ma, &mma) || /* map addr */ + !ADDR_IS_MEM (mma)) { /* nx mem? */ + dt_seterr (uptr, STA_NXM); + break; } + else tcdt = M[mma >> 1]; /* get word */ + tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */ + tcba = (tcba + 2) & DMASK; + if (tcba <= 1) tccm = CSR_INCMEX (tccm); } ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ bptr[ba] = tcdt; /* write word */ if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; if (tcwc == 0) dt_substate = 1; if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not end blk? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); + sim_activate (uptr, DT_WSIZE * dt_ltime); else if (dt_substate) { /* wc ovf? */ - dt_schedez (uptr, dir); /* sched end zone */ - DT_SETDONE; } + dt_schedez (uptr, dir); /* sched end zone */ + DT_SETDONE; } else sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); break; @@ -833,14 +835,14 @@ case FNC_WRIT: /* write */ case FNC_RALL: if (tccm & CSR_DONE) { /* done set? */ - dt_seterr (uptr, STA_DATM); /* data miss */ - break; } + dt_seterr (uptr, STA_DATM); /* data miss */ + break; } relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - dat = bptr[ba]; } /* get tape word */ + (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { + wrd = DT_LIN2WD (uptr->pos, uptr); + ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ + dat = bptr[ba]; } /* get tape word */ else dat = dt_gethdr (uptr, blk, relpos); /* get hdr */ if (dir) dat = dt_comobv (dat); /* rev? comp obv */ tcdt = dat & DMASK; /* low 16b */ @@ -853,17 +855,17 @@ case FNC_RALL: case FNC_WALL: if (tccm & CSR_DONE) { /* done set? */ - dt_seterr (uptr, STA_DATM); /* data miss */ - break; } + dt_seterr (uptr, STA_DATM); /* data miss */ + break; } relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - dat = (STA_GETXD (tcst) << 16) | tcdt; /* get data word */ - if (dir) dat = dt_comobv (dat); /* rev? comp obv */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - bptr[ba] = dat; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } + (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { + wrd = DT_LIN2WD (uptr->pos, uptr); + dat = (STA_GETXD (tcst) << 16) | tcdt; /* get data word */ + if (dir) dat = dt_comobv (dat); /* rev? comp obv */ + ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ + bptr[ba] = dat; /* write word */ + if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } /* else /* ignore hdr */ sim_activate (uptr, DT_WSIZE * dt_ltime); DT_SETDONE; /* set done */ @@ -972,16 +974,17 @@ UNIT *uptr; for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ uptr = dt_dev.units + i; if (sim_is_running) { /* RESET? */ - prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ - if (dt_setpos (uptr)) continue; /* update pos */ - sim_cancel (uptr); - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); - } } - else { sim_cancel (uptr); /* sim reset */ - uptr->STATE = 0; - uptr->LASTT = sim_grtime (); } } + prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ + if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ + if (dt_setpos (uptr)) continue; /* update pos */ + sim_cancel (uptr); + sim_activate (uptr, dt_dctime); /* sched decel */ + DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); + } } + else { + sim_cancel (uptr); /* sim reset */ + uptr->STATE = 0; + uptr->LASTT = sim_grtime (); } } tcst = tcwc = tcba = tcdt = 0; /* clear reg */ tccm = CSR_DONE; CLR_INT (DTA); /* clear int req */ @@ -1077,7 +1080,7 @@ else if (!(sim_switches & SWMASK ('S')) && /* autosize? */ (fseek (uptr->fileref, 0, SEEK_END) == 0) && ((p = ftell (uptr->fileref)) > D16_FILSIZ)) { if (p <= D8_FILSIZ) - uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; + uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; else uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); } uptr->capac = DTU_CAPAC (uptr); /* set capacity */ uptr->filebuf = calloc (uptr->capac, sizeof (int32)); diff --git a/PDP11/pdp11_tm.c b/PDP11/pdp11_tm.c index 58b78192..6269b366 100644 --- a/PDP11/pdp11_tm.c +++ b/PDP11/pdp11_tm.c @@ -284,29 +284,30 @@ case 0: /* MTS: read only */ case 1: /* MTC */ uptr = tm_dev.units + GET_UNIT (tm_cmd); /* select unit */ if ((tm_cmd & MTC_DONE) == 0) tm_sta = tm_sta | STA_ILL; - else { if (access == WRITEB) data = (PA & 1)? - (tm_cmd & 0377) | (data << 8): - (tm_cmd & ~0377) | data; - if (data & MTC_INIT) { /* init? */ - tm_reset (&tm_dev); /* reset device */ - return SCPE_OK; } - if ((data & MTC_IE) == 0) /* int disable? */ - CLR_INT (TM); /* clr int request */ - else if ((tm_cmd & (MTC_ERR + MTC_DONE)) && !(tm_cmd & MTC_IE)) - SET_INT (TM); /* set int request */ - tm_cmd = (tm_cmd & ~MTC_RW) | (data & MTC_RW); - uptr = tm_dev.units + GET_UNIT (tm_cmd); /* new unit */ - if (data & MTC_GO) tm_go (uptr); } /* new function? */ + else { + if (access == WRITEB) data = (PA & 1)? + (tm_cmd & 0377) | (data << 8): + (tm_cmd & ~0377) | data; + if (data & MTC_INIT) { /* init? */ + tm_reset (&tm_dev); /* reset device */ + return SCPE_OK; } + if ((data & MTC_IE) == 0) /* int disable? */ + CLR_INT (TM); /* clr int request */ + else if ((tm_cmd & (MTC_ERR + MTC_DONE)) && !(tm_cmd & MTC_IE)) + SET_INT (TM); /* set int request */ + tm_cmd = (tm_cmd & ~MTC_RW) | (data & MTC_RW); + uptr = tm_dev.units + GET_UNIT (tm_cmd); /* new unit */ + if (data & MTC_GO) tm_go (uptr); } /* new function? */ tm_updcsta (uptr); /* update status */ break; case 2: /* MTBRC */ if (access == WRITEB) data = (PA & 1)? - (tm_bc & 0377) | (data << 8): (tm_bc & ~0377) | data; + (tm_bc & 0377) | (data << 8): (tm_bc & ~0377) | data; tm_bc = data; break; case 3: /* MTCMA */ if (access == WRITEB) data = (PA & 1)? - (tm_ca & 0377) | (data << 8): (tm_ca & ~0377) | data; + (tm_ca & 0377) | (data << 8): (tm_ca & ~0377) | data; tm_ca = data; break; case 4: /* MTD */ @@ -363,12 +364,12 @@ MT_CLR_PNU (uptr); /* and clear */ if (uptr->USTAT & STA_REW) { /* rewind? */ uptr->pos = 0; /* update position */ if (uptr->flags & UNIT_ATT) /* still on line? */ - uptr->USTAT = STA_ONL | STA_BOT | - ((uptr->flags & UNIT_WPRT)? STA_WLK: 0); + uptr->USTAT = STA_ONL | STA_BOT | + ((uptr->flags & UNIT_WPRT)? STA_WLK: 0); else uptr->USTAT = 0; if (u == GET_UNIT (tm_cmd)) { /* selected? */ - tm_set_done (); /* set done */ - tm_updcsta (uptr); } /* update status */ + tm_set_done (); /* set done */ + tm_updcsta (uptr); } /* update status */ return SCPE_OK; } if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ @@ -400,34 +401,35 @@ case MTC_READ: /* read */ if (tbc < cbc) cbc = tbc; /* use smaller */ abc = fxread (tmxb, sizeof (int8), cbc, uptr->fileref); if (err = ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); /* pos not upd */ - break; } + MT_SET_PNU (uptr); /* pos not upd */ + break; } for ( ; abc < cbc; abc++) tmxb[abc] = 0; /* fill with 0's */ if (t = Map_WriteB (xma, cbc, tmxb, MAP)) { /* copy buf to mem */ - tm_sta = tm_sta | STA_NXM; /* NXM, set err */ - cbc = cbc - t; } /* adj byte cnt */ + tm_sta = tm_sta | STA_NXM; /* NXM, set err */ + cbc = cbc - t; } /* adj byte cnt */ xma = (xma + cbc) & 0777777; /* inc bus addr */ tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */ uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* upd position */ - (2 * sizeof (t_mtrlnt)); + (2 * sizeof (t_mtrlnt)); break; case MTC_WRITE: /* write */ case MTC_WREXT: /* write ext gap */ if (t = Map_ReadB (xma, cbc, tmxb, MAP)) { /* copy mem to buf */ - tm_sta = tm_sta | STA_NXM; /* NXM, set err */ - cbc = cbc - t; /* adj byte cnt */ - if (cbc == 0) break; } /* no xfr? done */ + tm_sta = tm_sta | STA_NXM; /* NXM, set err */ + cbc = cbc - t; /* adj byte cnt */ + if (cbc == 0) break; } /* no xfr? done */ ebc = (cbc + 1) & ~1; /* force even */ fseek (uptr->fileref, uptr->pos, SEEK_SET); fxwrite (&cbc, sizeof (t_mtrlnt), 1, uptr->fileref); fxwrite (tmxb, sizeof (int8), ebc, uptr->fileref); fxwrite (&cbc, sizeof (t_mtrlnt), 1, uptr->fileref); if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */ - else { xma = (xma + cbc) & 0777777; /* inc bus addr */ - tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */ - uptr->pos = uptr->pos + ebc + /* upd pos */ - (2 * sizeof (t_mtrlnt)); } + else { + xma = (xma + cbc) & 0777777; /* inc bus addr */ + tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */ + uptr->pos = uptr->pos + ebc + /* upd pos */ + (2 * sizeof (t_mtrlnt)); } break; /* Unit service, continued */ @@ -440,19 +442,22 @@ case MTC_WREOF: break; case MTC_SPACEF: /* space forward */ - do { tm_bc = (tm_bc + 1) & 0177777; /* incr wc */ - if (tm_rdlntf (uptr, &tbc, &err)) break;/* read rec lnt, err? */ - uptr->pos = uptr->pos + ((tbc + 1) & ~1) + - (2 * sizeof (t_mtrlnt)); } + do { + tm_bc = (tm_bc + 1) & 0177777; /* incr wc */ + if (tm_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */ + uptr->pos = uptr->pos + ((tbc + 1) & ~1) + + (2 * sizeof (t_mtrlnt)); } while (tm_bc != 0); break; case MTC_SPACER: /* space reverse */ - do { tm_bc = (tm_bc + 1) & 0177777; /* incr wc */ - if (pnu) pnu = 0; /* pos not upd? */ - else { if (tm_rdlntr (uptr, &tbc, &err)) break; - uptr->pos = uptr->pos - ((tbc + 1) & ~1) - - (2 * sizeof (t_mtrlnt)); } } + do { + tm_bc = (tm_bc + 1) & 0177777; /* incr wc */ + if (pnu) pnu = 0; /* pos not upd? */ + else { + if (tm_rdlntr (uptr, &tbc, &err)) break; + uptr->pos = uptr->pos - ((tbc + 1) & ~1) - + (2 * sizeof (t_mtrlnt)); } } while (tm_bc != 0); break; } /* end case */ diff --git a/PDP11/pdp11_tq.c b/PDP11/pdp11_tq.c index aeb20ba3..e90273d5 100644 --- a/PDP11/pdp11_tq.c +++ b/PDP11/pdp11_tq.c @@ -1,6 +1,6 @@ /* pdp11_tq.c: TQK50 tape controller simulator - Copyright (c) 2002, Robert M Supnik + Copyright (c) 2002-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ tq TQK50 tape controller + 09-Jan-03 RMS Fixed bug in transfer end packet status 17-Oct-02 RMS Fixed bug in read reverse (found by Hans Pufal) */ @@ -548,7 +549,8 @@ if (tq_pip) { /* polling? */ tq_pkt[pkt].d[RW_BCH], tq_pkt[pkt].d[RW_BCL], tq_pkt[pkt].d[RW_BAH], tq_pkt[pkt].d[RW_BAL]); if (up) fprintf (sim_log, ", pos=%d, obj=%d\n", up->pos, up->objp); - else fprintf (sim_log, "\n"); } + else fprintf (sim_log, "\n"); + fflush (sim_log); } if (GETP (pkt, UQ_HCTC, TYP) != UQ_TYP_SEQ) /* seq packet? */ return tq_fatal (PE_PIE); /* no, term thread */ cnid = GETP (pkt, UQ_HCTC, CID); /* get conn ID */ @@ -946,7 +948,7 @@ else sts = ST_OFL; /* offline */ PUTP32 (pkt, RW_BCL, 0); /* no bytes processed */ PUTP32 (pkt, RW_POSL, objp); /* set obj pos */ PUTP32 (pkt, RW_RSZL, 0); /* clr rec size */ -tq_putr (pkt, cmd | OP_END, tq_efl (uptr), sts, RW_LNT, UQ_TYP_SEQ); +tq_putr (pkt, cmd | OP_END, tq_efl (uptr), sts, RW_LNT_T, UQ_TYP_SEQ); return tq_putpkt (pkt, TRUE); } @@ -1139,7 +1141,7 @@ t_bool tq_mot_end (UNIT *uptr, uint32 flg, uint32 sts, uint32 rsiz) { int32 pkt = uptr->cpkt; /* packet */ uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */ -uint32 lnt = RW_LNT; /* assume rw */ +uint32 lnt = RW_LNT_T; /* assume rw */ if (cmd == OP_ERG) lnt = ERG_LNT; /* set pkt lnt */ else if (cmd == OP_ERS) lnt = ERS_LNT; @@ -1148,8 +1150,7 @@ else if (cmd == OP_POS) lnt = POS_LNT; uptr->cpkt = 0; /* done */ if (lnt > ERG_LNT) { /* xfer cmd? */ - PUTP32 (pkt, RW_POSL, uptr->objp); } /* position */ -if (lnt > POS_LNT) { /* read or write? */ + PUTP32 (pkt, RW_POSL, uptr->objp); /* position */ PUTP32 (pkt, RW_RSZL, rsiz); } /* record size */ tq_putr (pkt, cmd | OP_END, flg | tq_efl (uptr), sts, lnt, UQ_TYP_SEQ); if (!tq_putpkt (pkt, TRUE)) return ERR; /* send pkt */ @@ -1495,7 +1496,8 @@ if (DBG_LOG (LOG_TQ)) { fprintf (sim_log, ">>TQ: rsp=%04X, sts=%04X", tq_pkt[pkt].d[RSP_OPF], tq_pkt[pkt].d[RSP_STS]); if (up) fprintf (sim_log, ", pos=%d, obj=%d\n", up->pos, up->objp); - else fprintf (sim_log, "\n"); } + else fprintf (sim_log, "\n"); + fflush (sim_log); } if (!tq_getdesc (&tq_rq, &desc)) return ERR; /* get rsp desc */ if ((desc & UQ_DESC_OWN) == 0) { /* not valid? */ if (qt) tq_enqt (&tq_rspq, pkt); /* normal? q tail */ diff --git a/PDP11/pdp11_ts.c b/PDP11/pdp11_ts.c index 58a3ba96..eceb4964 100644 --- a/PDP11/pdp11_ts.c +++ b/PDP11/pdp11_ts.c @@ -383,8 +383,8 @@ t_addr pa; switch ((PA >> 1) & 01) { /* decode PA<1> */ case 0: /* TSDB */ if ((tssr & TSSR_SSR) == 0) { /* ready? */ - tssr = tssr | TSSR_RMR; /* no, refuse */ - break; } + tssr = tssr | TSSR_RMR; /* no, refuse */ + break; } tsba = ((tsdbx & TSDBX_M_XA) << 18) | /* form pkt addr */ ((data & 03) << 16) | (data & 0177774); tsdbx = 0; /* clr tsdbx */ @@ -393,23 +393,24 @@ case 0: /* TSDB */ msgrfc = msgxs1 = msgxs2 = msgxs3 = msgxs4 = 0; /* clr status */ CLR_INT (TS); /* clr int req */ for (i = 0; i < CMD_PLNT; i++) { /* get cmd pkt */ - if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa)) - tscmdp[i] = ReadW (pa); - else { ts_endcmd (TSSR_NXM + TC5, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL); - return SCPE_OK; } - tsba = tsba + 2; } /* incr tsba */ + if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa)) + tscmdp[i] = ReadW (pa); + else { + ts_endcmd (TSSR_NXM + TC5, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL); + return SCPE_OK; } + tsba = tsba + 2; } /* incr tsba */ ts_ownc = ts_ownm = 1; /* tape owns all */ sim_activate (&ts_unit, ts_time); /* activate */ break; case 1: /* TSSR */ if (PA & 1) { /* TSDBX */ - if (UNIBUS) return SCPE_OK; /* not in TS11 */ - if (tssr & TSSR_SSR) { /* ready? */ - tsdbx = data; /* save */ - if (data & TSDBX_BOOT) { - ts_bcmd = 1; - sim_activate (&ts_unit, ts_time); } } - else tssr = tssr | TSSR_RMR; } /* no, err */ + if (UNIBUS) return SCPE_OK; /* not in TS11 */ + if (tssr & TSSR_SSR) { /* ready? */ + tsdbx = data; /* save */ + if (data & TSDBX_BOOT) { + ts_bcmd = 1; + sim_activate (&ts_unit, ts_time); } } + else tssr = tssr | TSSR_RMR; } /* no, err */ else if (access == WRITE) ts_reset (&ts_dev); /* reset */ break; } return SCPE_OK; @@ -445,7 +446,7 @@ do { fc = (fc - 1) & DMASK; /* decr wc */ uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */ msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ if (tbc == MTR_TMK) /* tape mark? */ - return (XTC (XS0_TMK | XS0_RLS, TC2)); + return (XTC (XS0_TMK | XS0_RLS, TC2)); uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) + sizeof (t_mtrlnt); } while (fc != 0); @@ -463,14 +464,15 @@ if ((uptr->pos == 0) && (wchopt & WCH_ENB)) tmkprv = TRUE; do { prvp = uptr->pos; /* save cur pos */ tc = ts_spacef (uptr, 0, FALSE); /* space fwd */ if (GET_X (tc) & XS0_TMK) { /* tape mark? */ - msgrfc = (msgrfc - 1) & DMASK; /* decr count */ - if (tmkprv && (wchopt & WCH_ESS) && - (uptr->pos - prvp == sizeof (t_mtrlnt))) - return (XTC ((msgrfc? XS0_RLS: 0) | - XS0_TMK | XS0_LET, TC2)); - tmkprv = TRUE; } - else { if (tc) return tc; /* other err? */ - tmkprv = FALSE; } } + msgrfc = (msgrfc - 1) & DMASK; /* decr count */ + if (tmkprv && (wchopt & WCH_ESS) && + (uptr->pos - prvp == sizeof (t_mtrlnt))) + return (XTC ((msgrfc? XS0_RLS: 0) | + XS0_TMK | XS0_LET, TC2)); + tmkprv = TRUE; } + else { + if (tc) return tc; /* other err? */ + tmkprv = FALSE; } } while (msgrfc != 0); return 0; } @@ -508,7 +510,7 @@ do { fc = (fc - 1) & DMASK; /* decr wc */ uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */ msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ if (tbc == MTR_TMK) /* tape mark? */ - return (XTC (XS0_TMK | XS0_RLS, TC2)); + return (XTC (XS0_TMK | XS0_RLS, TC2)); uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) - sizeof (t_mtrlnt); } while (fc != 0); @@ -525,14 +527,15 @@ msgrfc = fc; do { prvp = uptr->pos; /* save cur pos */ tc = ts_spacer (uptr, 0, FALSE); /* space rev */ if (GET_X (tc) & XS0_TMK) { /* tape mark? */ - msgrfc = (msgrfc - 1) & DMASK; /* decr wc */ - if (tmkprv && (wchopt & WCH_ESS) && - (prvp - uptr->pos == sizeof (t_mtrlnt))) - return (XTC ((msgrfc? XS0_RLS: 0) | - XS0_TMK | XS0_LET, TC2)); - tmkprv = TRUE; } - else { if (tc) return tc; /* other err? */ - tmkprv = FALSE; } } + msgrfc = (msgrfc - 1) & DMASK; /* decr wc */ + if (tmkprv && (wchopt & WCH_ESS) && + (prvp - uptr->pos == sizeof (t_mtrlnt))) + return (XTC ((msgrfc? XS0_RLS: 0) | + XS0_TMK | XS0_LET, TC2)); + tmkprv = TRUE; } + else { + if (tc) return tc; /* other err? */ + tmkprv = FALSE; } } while (msgrfc != 0); return 0; } @@ -566,9 +569,10 @@ msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ for (i = 0; i < wbc; i++) { /* copy buffer */ wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */ if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */ - WriteB (pa, tsxb[i]); /* no, store */ - else { tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */ - return (XTC (XS0_RLS, TC4)); } + WriteB (pa, tsxb[i]); /* no, store */ + else { + tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */ + return (XTC (XS0_RLS, TC4)); } tsba = tsba + 1; msgrfc = (msgrfc - 1) & DMASK; } if (msgrfc) return (XTC (XS0_RLS, TC2)); /* buf too big? */ @@ -607,9 +611,10 @@ for (i = wbc; i > 0; i--) { /* copy buffer */ tsba = tsba - 1; wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */ if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */ - WriteB (pa, tsxb[i - 1]); /* no, store */ - else { tssr = ts_updtssr (tssr | TSSR_NXM); - return (XTC (XS0_RLS, TC4)); } + WriteB (pa, tsxb[i - 1]); /* no, store */ + else { + tssr = ts_updtssr (tssr | TSSR_NXM); + return (XTC (XS0_RLS, TC4)); } msgrfc = (msgrfc - 1) & DMASK; } if (msgrfc) return (XTC (XS0_RLS, TC2)); /* buf too big? */ if (tbc > wbc) return (XTC (XS0_RLL, TC2)); /* rec too big? */ @@ -628,8 +633,9 @@ for (i = 0; i < fc; i++) { /* copy mem to buf */ wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */ if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */ tsxb[i] = ReadB (pa); /* no, store */ - else { tssr = ts_updtssr (tssr | TSSR_NXM); - return TC5; } + else { + tssr = ts_updtssr (tssr | TSSR_NXM); + return TC5; } tsba = tsba + 1; } ebc = (fc + 1) & ~1; /* force even */ fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */ @@ -679,10 +685,10 @@ if (ts_bcmd) { /* boot? */ ts_bcmd = 0; /* clear flag */ uptr->pos = 0; /* rewind */ if (uptr->flags & UNIT_ATT) { /* attached? */ - cmdlnt = cmdadh = cmdadl = 0; /* defang rd */ - ts_spacef (uptr, 1, FALSE); /* space fwd */ - ts_readf (uptr, 512); /* read blk */ - tssr = ts_updtssr (tssr | TSSR_SSR); } + cmdlnt = cmdadh = cmdadl = 0; /* defang rd */ + ts_spacef (uptr, 1, FALSE); /* space fwd */ + ts_readf (uptr, 512); /* read blk */ + tssr = ts_updtssr (tssr | TSSR_SSR); } else tssr = ts_updtssr (tssr | TSSR_SSR | TC3); if (cmdhdr & CMD_IE) SET_INT (TS); return SCPE_OK; } @@ -696,7 +702,7 @@ fnc = GET_FNC (cmdhdr); /* get fnc+mode */ mod = GET_MOD (cmdhdr); if (DBG_LOG (LOG_TS)) fprintf (sim_log, ">>TS: cmd=%o, mod=%o, buf=%o, lnt=%d, pos=%d\n", - fnc, mod, cmdadl, cmdlnt, ts_unit.pos); + fnc, mod, cmdadl, cmdlnt, ts_unit.pos); if ((fnc != FNC_WCHR) && (tssr & TSSR_NBA)) { /* ~wr chr & nba? */ ts_endcmd (TC3, 0, 0); /* error */ return SCPE_OK; } @@ -738,112 +744,116 @@ case FNC_GSTA: /* get status */ return SCPE_OK; case FNC_WCHR: /* write char */ if ((cmdadh & ADDRTEST) || (cmdadl & 1) || (cmdlnt < 6)) { - ts_endcmd (TSSR_NBA | TC3, XS0_ILA, 0); - break; } + ts_endcmd (TSSR_NBA | TC3, XS0_ILA, 0); + break; } tsba = (cmdadh << 16) | cmdadl; for (i = 0; (i < WCH_PLNT) && (i < (cmdlnt / 2)); i++) { - if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa)) - tswchp[i] = ReadW (pa); - else { ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0); - return SCPE_OK; } - tsba = tsba + 2; } + if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa)) + tswchp[i] = ReadW (pa); + else { + ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0); + return SCPE_OK; } + tsba = tsba + 2; } if ((wchlnt < ((MSG_PLNT - 1) * 2)) || (wchadh & 0177700) || (wchadl & 1)) ts_endcmd (TSSR_NBA | TC3, 0, 0); - else { msgxs2 = msgxs2 | XS2_XTF | 1; - tssr = ts_updtssr (tssr & ~TSSR_NBA); - ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); } + else { + msgxs2 = msgxs2 | XS2_XTF | 1; + tssr = ts_updtssr (tssr & ~TSSR_NBA); + ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); } return SCPE_OK; case FNC_CTL: /* control */ switch (mod) { /* case mode */ case 00: /* msg buf rls */ - tssr = ts_updtssr (tssr | TSSR_SSR); /* set SSR */ - if (wchopt & WCH_ERI) SET_INT (TS); - ts_ownc = 0; ts_ownm = 1; /* keep msg */ - break; + tssr = ts_updtssr (tssr | TSSR_SSR); /* set SSR */ + if (wchopt & WCH_ERI) SET_INT (TS); + ts_ownc = 0; ts_ownm = 1; /* keep msg */ + break; case 01: /* rewind and unload */ - if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ - detach_unit (uptr); /* unload */ - ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); - break; + if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ + detach_unit (uptr); /* unload */ + ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); + break; case 02: /* clean */ - ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); /* nop */ - break; + ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); /* nop */ + break; case 03: /* undefined */ - ts_endcmd (TC3, XS0_ILC, MSG_ACK | MSG_MILL | MSG_CFAIL); - return SCPE_OK; + ts_endcmd (TC3, XS0_ILC, MSG_ACK | MSG_MILL | MSG_CFAIL); + return SCPE_OK; case 04: /* rewind */ - if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ - uptr->pos = 0; - ts_endcmd (TC0, XS0_BOT, MSG_ACK | MSG_CEND); - break; } + if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ + uptr->pos = 0; + ts_endcmd (TC0, XS0_BOT, MSG_ACK | MSG_CEND); + break; } break; case FNC_READ: /* read */ switch (mod) { /* case mode */ case 00: /* fwd */ - st0 = ts_readf (uptr, cmdlnt); /* read */ - break; + st0 = ts_readf (uptr, cmdlnt); /* read */ + break; case 01: /* back */ - st0 = ts_readr (uptr, cmdlnt); /* read */ - break; + st0 = ts_readr (uptr, cmdlnt); /* read */ + break; case 02: /* reread fwd */ - if (cmdhdr & CMD_OPP) { /* opposite? */ - st0 = ts_readr (uptr, cmdlnt); - st1 = ts_spacef (uptr, 1, FALSE); } - else { st0 = ts_spacer (uptr, 1, FALSE); - st1 = ts_readf (uptr, cmdlnt); } - break; + if (cmdhdr & CMD_OPP) { /* opposite? */ + st0 = ts_readr (uptr, cmdlnt); + st1 = ts_spacef (uptr, 1, FALSE); } + else { + st0 = ts_spacer (uptr, 1, FALSE); + st1 = ts_readf (uptr, cmdlnt); } + break; case 03: /* reread back */ - if (cmdhdr & CMD_OPP) { /* opposite */ - st0 = ts_readf (uptr, cmdlnt); - st1 = ts_spacer (uptr, 1, FALSE); } - else { st0 = ts_spacef (uptr, 1, FALSE); - st1 = ts_readr (uptr, cmdlnt); } - break; } + if (cmdhdr & CMD_OPP) { /* opposite */ + st0 = ts_readf (uptr, cmdlnt); + st1 = ts_spacer (uptr, 1, FALSE); } + else { + st0 = ts_spacef (uptr, 1, FALSE); + st1 = ts_readr (uptr, cmdlnt); } + break; } ts_cmpendcmd (st0, st1); break; case FNC_WRIT: /* write */ switch (mod) { /* case mode */ case 00: /* write */ - st0 = ts_write (uptr, cmdlnt); - break; + st0 = ts_write (uptr, cmdlnt); + break; case 01: /* rewrite */ - st0 = ts_spacer (uptr, 1, FALSE); - st1 = ts_write (uptr, cmdlnt); - break; } + st0 = ts_spacer (uptr, 1, FALSE); + st1 = ts_write (uptr, cmdlnt); + break; } ts_cmpendcmd (st0, st1); break; case FNC_FMT: /* format */ switch (mod) { /* case mode */ case 00: /* write tmk */ - st0 = ts_wtmk (uptr); - break; + st0 = ts_wtmk (uptr); + break; case 01: /* erase */ - break; + break; case 02: /* retry tmk */ - st0 = ts_spacer (uptr, 1, FALSE); - st1 = ts_wtmk (uptr); - break; } + st0 = ts_spacer (uptr, 1, FALSE); + st1 = ts_wtmk (uptr); + break; } ts_cmpendcmd (st0, st1); break; case FNC_POS: switch (mod) { /* case mode */ case 00: /* space fwd */ - st0 = ts_spacef (uptr, cmdadl, TRUE); - break; + st0 = ts_spacef (uptr, cmdadl, TRUE); + break; case 01: /* space rev */ - st0 = ts_spacer (uptr, cmdadl, TRUE); - break; + st0 = ts_spacer (uptr, cmdadl, TRUE); + break; case 02: /* space ffwd */ - st0 = ts_skipf (uptr, cmdadl); - break; + st0 = ts_skipf (uptr, cmdadl); + break; case 03: /* space frev */ - st0 = ts_skipr (uptr, cmdadl); - break; + st0 = ts_skipr (uptr, cmdadl); + break; case 04: /* rewind */ - if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ - uptr->pos = 0; - break; } + if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ + uptr->pos = 0; + break; } ts_cmpendcmd (st0, 0); break; } return SCPE_OK; @@ -901,18 +911,19 @@ if (msg && !(tssr & TSSR_NBA)) { /* send end pkt */ msglnt = wchlnt - 4; /* exclude hdr, bc */ tsba = (wchadh << 16) | wchadl; for (i = 0; (i < MSG_PLNT) && (i < (wchlnt / 2)); i++) { - if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa)) - WriteW (pa, tsmsgp[i]); - else { tssr = tssr | TSSR_NXM; - tc = (tc & ~TSSR_TC) | TC4; - break; } - tsba = tsba + 2; } } + if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa)) + WriteW (pa, tsmsgp[i]); + else { + tssr = tssr | TSSR_NXM; + tc = (tc & ~TSSR_TC) | TC4; + break; } + tsba = tsba + 2; } } tssr = ts_updtssr (tssr | tc | TSSR_SSR | (tc? TSSR_SC: 0)); if (cmdhdr & CMD_IE) SET_INT (TS); ts_ownm = 0; ts_ownc = 0; if (DBG_LOG (LOG_TS)) fprintf (sim_log, ">>TS: sta=%o, tc=%o, rfc=%d, pos=%d\n", - msgxs0, GET_TC (tssr), msgrfc, ts_unit.pos); + msgxs0, GET_TC (tssr), msgrfc, ts_unit.pos); return; } diff --git a/PDP11/pdp11_xq.c b/PDP11/pdp11_xq.c index 7976f9b1..a551b6a0 100644 --- a/PDP11/pdp11_xq.c +++ b/PDP11/pdp11_xq.c @@ -26,9 +26,11 @@ ------------------------------------------------------------------------------ - This DELQA/DEQNA simulation is based on: + This DEQNA/DELQA simulation is based on: Digital DELQA Users Guide, Part# EK-DELQA-UG-002 Digital DEQNA Users Guide, Part# EK-DEQNA-UG-001 + These manuals can be found online at: + http://www.spies.com/~aek/pdf/dec/qbus Certain adaptations have been made because this is an emulation: The default MAC address is 08-00-2B-AA-BB-CC unless set otherwise. @@ -37,17 +39,85 @@ implemented more like an extended Internal Loopback Time Domain Reflectometry (TDR) numbers are faked The 10-second approx. hardware/software reset delay does not exist - Some physical ethernet receive events like Runts, Overruns, etc. are never - reported back, since the packet-level driver never sees them + Some physical ethernet receive events like Runts, Overruns, etc. are + never reported back, since the packet-level driver never sees them Certain advantages are derived from this emulation: If the real ethernet controller is faster than 10Mbit, the speed is passed on since there are no minimum response times. + Known Bugs or Unsupported features: + 1) DEQNA and DEQNA-LOCK modes not implemented fully [done! 07-Jan-03] + 2) Sanity Timer not implemented [done! 16-Oct-02] + 3) MOP functionality not implemented + 4) Multicast support is weak [done! 22-Oct-02] + 5) Promiscuous mode not implemented [done! 22-Oct-02] + 6) Cannot VMScluster node [done! 27-Dec-02] + 7) Cannot bootstrap module on VAX (>>> B XQA0) [done! 12-Oct-02] + 8) PDP11 bootstrap code missing + 9) Automatic ID broadcast every 8-10 minutes [done! 30-Dec-02] + 10) External loopback packet processing [done! 02-Jan-03] + 11) NXM detection/protection [done! 21-Oct-02] + ------------------------------------------------------------------------------ Modification history: + 16-Jan-03 DTH Merged Mark Pizzolato's enhancements with main source + Corrected PDP11 XQ_DEBUG compilation + 15-Jan-03 MP Fixed the number of units in the xq device structure. + 13-Jan-03 MP Reworked the timer management logic which initiated + the system id broadcast messages. The original + implementation triggered this on the CSR transition + of Receiver Enabled. This was an issue since the + it seems that at least VMS's XQ driver makes this + transition often and the resulting overhead reduces + the simulated CPU instruction execution thruput by + about 40%. I start the system id timer on device + reset and it fires once a second so that it can + leverage the reasonably recalibrated tmr_poll value. + 13-Jan-03 MP Changed the scheduling of xq_svc to leverage the + dynamically computed clock values to achieve an + approximate interval of 100 per second. This is + more than sufficient for normal system behaviour + expecially since we service recieves with every + transmit. The previous fixed value of 2500 + attempted to get 200/sec but it was a guess that + didn't adapt. On faster host systems (possibly + most of them) the 2500 number spends too much time + polling. + 10-Jan-03 DTH Removed XQ_DEBUG dependency from Borland #pragmas + Added SET XQ BOOTROM command for PDP11s + 07-Jan-03 DTH Added pointer to online manuals + 02-Jan-03 DTH Added local packet processing + 30-Dec-02 DTH Added automatic system id broadcast + 27-Dec-02 DTH Merged Mark Pizzolato's enhancements with main source + 20-Dec-02 MP Fix bug that caused VMS system crashes when attempting cluster + operations. Added additional conditionally compiled debug + info needed to track down the issue. + 17-Dec-02 MP Added SIMH "registers" describing the Ethernet state + so this information can be recorded in a "saved" snapshot. + 05-Dec-02 MP Adjusted the rtime value from 100 to 2500 which increased the + available CPU cycles for Instruction execution by almost 100%. + This made sense after the below enhancements which, in general + caused the draining of the received data stream much more + agressively with less overhead. + 05-Dec-02 MP Added a call to xq_svc after all successful calls to eth_write + to allow receive processing to happen before the next event + service time. + 05-Dec-02 MP Restructured the flow of processing in xq_svc so that eth_read + is called repeatedly until either a packet isn't found or + there is no room for another one in the queue. Once that has + been done, xq_processrdbl is called to pass the queued packets + into the simulated system as space is available there. + xq_process_rdbl is also called at the beginning of xq_svc to + drain the queue into the simulated system, making more room + available in the queue. No processing is done at all in + xq_svc if the receiver is disabled. + 04-Dec-02 MP Changed interface and usage to xq_insert_queue to pass + the packet to be inserted by reference. This avoids 3K bytes + of buffer copy operations for each packet received. Now only + copy actual received packet data. 31-Oct-02 DTH Cleaned up pointer warnings (found by Federico Schwindt) Corrected unattached and no network behavior Added message when SHOW XQ ETH finds no devices @@ -60,7 +130,7 @@ Added and debugged Sanity Timer code Corrected copyright 15-Oct-02 DTH Rollback to known good Beta3 and roll forward; TCP broken - 12-Oct-02 DTH Fixed VAX network bootstrap; setup packets must return non-zero TDR + 12-Oct-02 DTH Fixed VAX network bootstrap; setup packets must return TDR > 0 11-Oct-02 DTH Added SET/SHOW XQ TYPE and SET/SHOW XQ SANITY commands 10-Oct-02 DTH Beta 3 released; Integrated with 2.10-0b1 Fixed off-by-1 bug on xq.setup.macs[7..13] @@ -82,32 +152,16 @@ 15-Aug-02 DTH Started XQ simulation ------------------------------------------------------------------------------ - - Known Bugs or Unsupported features: - - 1) DEQNA and DEQNA-LOCK modes not implemented fully - 2) Sanity Timer not implemented [done! 16-Oct-02] - 3) MOP functionality not implemented - 4) Multicast support is weak [done! 22-Oct-02] - 5) Promiscuous mode not implemented [done! 22-Oct-02] - 6) Cannot VMScluster node - 7) Cannot bootstrap module on VAX (>>> B XQA0) - 8) PDP11 bootstrap code missing - 9) Automatic ID broadcast every 8-10 minutes - 10) External loopback packet processing - 11) NXM detection/protection [done! 21-Oct-02] - - ------------------------------------------------------------------------------ */ /* compiler directives to help the Author keep the code clean :-) */ -#if defined (__BORLANDC__) && defined (XQ_DEBUG) +#if defined (__BORLANDC__) #pragma warn +8070 /* function should return value */ -/* #pragma warn +8071 */ /* conversion may lose significant digits */ +/* #pragma warn +8071 *//* conversion may lose significant digits */ #pragma warn +8075 /* suspicious pointer conversion */ #pragma warn +8079 /* mixing different char pointers */ #pragma warn +8080 /* variable declared but not used */ -#endif /* __BORLANDC__ && XQ_DEBUG */ +#endif /* __BORLANDC__ */ #include #include "pdp11_xq.h" @@ -116,7 +170,7 @@ extern int32 int_req[IPL_HLVL]; extern int32 tmr_poll, clk_tps; struct xq_device xq = { - 100, /* rtime */ + 2500, /* rtime */ {0x08, 0x00, 0x2B, 0xAA, 0xBB, 0xCC}, /* mac */ XQ_T_DELQA, /* type */ {0} /* sanity */ @@ -128,6 +182,7 @@ t_stat xq_rd(int32* data, int32 PA, int32 access); t_stat xq_wr(int32 data, int32 PA, int32 access); t_stat xq_svc(UNIT * uptr); t_stat xq_sansvc(UNIT * uptr); +t_stat xq_idsvc(UNIT * uptr); t_stat xq_reset (DEVICE * dptr); t_stat xq_attach (UNIT * uptr, char * cptr); t_stat xq_detach (UNIT * uptr); @@ -137,6 +192,8 @@ t_stat xq_show_type (FILE* st, UNIT* uptr, int32 val, void* desc); t_stat xq_set_type (UNIT* uptr, int32 val, char* cptr, void* desc); t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc); t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc); +t_stat xq_show_bootrom (FILE* st, UNIT* uptr, int32 val, void* desc); +t_stat xq_set_bootrom (UNIT* uptr, int32 val, char* cptr, void* desc); t_stat xq_showeth (FILE* st, UNIT* uptr, int32 val, void* desc); t_stat xq_process_xbdl(void); t_stat xq_dispatch_xbdl(void); @@ -148,15 +205,18 @@ t_stat xq_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); void xq_start_santmr(void); void xq_cancel_santmr(void); void xq_reset_santmr(void); - +t_stat xq_boot_host(void); +void xq_start_idtmr(void); +t_stat xq_system_id(const ETH_MAC dst, uint16 receipt_id); /* SIMH device structures */ DIB xq_dib = { IOBA_XQ, IOLN_XQ, &xq_rd, &xq_wr, 1, IVCL (XQ), 0, { &xq_inta } }; UNIT xq_unit[] = { - { UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&xq_sansvc, UNIT_DIS, 0) } /* sanity timer */ + { UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, /* receive timer */ + { UDATA (&xq_sansvc, UNIT_DIS, 0) }, /* sanity timer */ + { UDATA (&xq_idsvc, UNIT_DIS, 0) } /* system id timer */ }; REG xq_reg[] = { @@ -170,6 +230,13 @@ REG xq_reg[] = { { GRDATA ( XBDL, xq.xbdl, XQ_RDX, 32, 0) }, { GRDATA ( VAR, xq.var, XQ_RDX, 16, 0) }, { GRDATA ( CSR, xq.csr, XQ_RDX, 16, 0) }, + { GRDATA ( SETUP_PRM, xq.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO}, + { GRDATA ( SETUP_MLT, xq.setup.multicast, XQ_RDX, 32, 0), REG_HRO}, + { GRDATA ( SETUP_L1, xq.setup.l1, XQ_RDX, 32, 0), REG_HRO}, + { GRDATA ( SETUP_L2, xq.setup.l2, XQ_RDX, 32, 0), REG_HRO}, + { GRDATA ( SETUP_L3, xq.setup.l3, XQ_RDX, 32, 0), REG_HRO}, + { GRDATA ( SETUP_SAN, xq.setup.sanity_timer, XQ_RDX, 32, 0), REG_HRO}, + { BRDATA ( SETUP_MACS, &xq.setup.macs, XQ_RDX, 8, sizeof(xq.setup.macs)), REG_HRO}, { NULL }, }; @@ -177,6 +244,8 @@ MTAB xq_mod[] = { #if defined (VM_PDP11) { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", &set_addr, &show_addr, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_NC, 0, "BOOTROM", "BOOTROM", + &xq_set_bootrom, &xq_show_bootrom, NULL }, #else { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL, NULL, &show_addr, NULL }, @@ -185,24 +254,37 @@ MTAB xq_mod[] = { NULL, &show_vec, NULL }, { MTAB_XTD | MTAB_VDV, 0, "MAC", "MAC", &xq_setmac, &xq_showmac, &xq.mac }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "ETH", "ETH", - 0, &xq_showeth, 0 }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "ETH", NULL, + NULL, &xq_showeth, NULL }, { MTAB_XTD | MTAB_VDV, 0, "TYPE", "TYPE", - &xq_set_type, &xq_show_type, 0 }, - { MTAB_XTD | MTAB_VDV, 0, "SANITY", "SANITY", - &xq_set_sanity, &xq_show_sanity, 0 }, + &xq_set_type, &xq_show_type, NULL }, + { MTAB_XTD | MTAB_VDV|MTAB_NMO, 0, "SANITY", "SANITY", + &xq_set_sanity, &xq_show_sanity, NULL }, { 0 }, }; DEVICE xq_dev = { "XQ", xq_unit, xq_reg, xq_mod, - 2, XQ_RDX, 0, 1, XQ_RDX, 8, + 3, XQ_RDX, 0, 1, XQ_RDX, 8, &xq_ex, &xq_dep, &xq_reset, NULL, &xq_attach, &xq_detach, &xq_dib, DEV_DISABLE | DEV_QBUS }; #ifdef XQ_DEBUG +#if defined(VM_VAX) +extern int32 PSL; /* PSL */ +extern int32 fault_PC; /* fault PC */ +#endif + +const char* const xq_recv_regnames[] = { + "MAC0", "MAC1", "MAC2", "MAC3", "MAC4", "MAC5", "VAR", "CSR" +}; + +const char* const xq_xmit_regnames[] = { + "", "", "RBDL-Lo", "RBDL-Hi", "XBDL-Lo", "XBDL-Hi", "VAR", "CSR" +}; + const char* const xq_csr_bits[] = { "RE ", "SR ", "NI ", "BD ", "XL ", "RL ", "IE ", "XI ", "IL ", "EL ", "SE ", "RR ", "OK ", "CA ", "PE ", "RI" @@ -255,7 +337,7 @@ void xq_remove_queue(struct xq_msg_que* que) } } -void xq_insert_queue(struct xq_msg_que* que, int32 type, ETH_PACK packet, int32 status) +void xq_insert_queue(struct xq_msg_que* que, int32 type, ETH_PACK* packet, int32 status) { struct xq_msg_itm* item; @@ -274,12 +356,16 @@ void xq_insert_queue(struct xq_msg_que* que, int32 type, ETH_PACK packet, int32 if (++que->head == XQ_QUE_MAX) que->head = 0; que->loss++; +#ifdef XQ_DEBUG + fprintf(stderr, "Packet Lost\n"); +#endif } /* set information in (new) tail item */ item = &que->item[que->tail]; - item->type = type; - item->packet = packet; + item->type = type; + item->packet.len = packet->len; + memcpy(item->packet.msg, packet->msg, packet->len); item->status = status; } @@ -289,13 +375,13 @@ void xq_insert_queue(struct xq_msg_que* que, int32 type, ETH_PACK packet, int32 /* stop simh from reading non-existant unit data stream */ -t_stat xq_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) +t_stat xq_ex (t_value* vptr, t_addr addr, UNIT* uptr, int32 sw) { return SCPE_NOFNC; } /* stop simh from writing non-existant unit data stream */ -t_stat xq_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) +t_stat xq_dep (t_value val, t_addr addr, UNIT* uptr, int32 sw) { return SCPE_NOFNC; } @@ -432,8 +518,29 @@ t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc) return SCPE_OK; } +t_stat xq_show_bootrom (FILE* st, UNIT* uptr, int32 val, void* desc) +{ + /* format includes \n for MTAB_NMO compatibility */ + fprintf(st, "bootrom=%s\n", xq.bootrom); + return SCPE_OK; +} + +t_stat xq_set_bootrom (UNIT* uptr, int32 val, char* cptr, void* desc) +{ + size_t len; + if (!cptr) return SCPE_IERR; + len = strlen(cptr) + 1; + if (len > sizeof(xq.bootrom)) return SCPE_ARG; + + memcpy(xq.bootrom, cptr, strlen(cptr)+1); + return SCPE_OK; +} + t_stat xq_nxm_error(void) { +#ifdef XQ_DEBUG + fprintf(stderr,"XQ: Non Existent Memory Error\n"); +#endif /* set NXM and associated bits in CSR */ xq.csr |= (XQ_CSR_NI | XQ_CSR_XI | XQ_CSR_XL | XQ_CSR_RL); @@ -454,18 +561,16 @@ void xq_write_callback (int status) const uint16 TDR = 100 + xq.write_buffer.len * 8; /* arbitrary value */ uint16 write_success[2] = {0}; uint16 write_failure[2] = {XQ_DSC_C}; -#if 0 - write_success[1] = TDR; - write_failure[1] = TDR; -#else write_success[1] = TDR & 0x03FF; /* Does TDR get set on successful packets ?? */ write_failure[1] = TDR & 0x03FF; /* TSW2<09:00> */ -#endif /* update write status words */ if (status == 0) { /* success */ wstatus = Map_WriteW(xq.xbdl_ba + 8, 4, write_success, NOMAP); } else { /* failure */ +#ifdef XQ_DEBUG + fprintf(stderr, "XQ: Packet Write Error\n"); +#endif wstatus = Map_WriteW(xq.xbdl_ba + 8, 4, write_failure, NOMAP); } if (wstatus) { @@ -492,11 +597,19 @@ void xq_write_callback (int status) } /* read registers: */ - t_stat xq_rd(int32* data, int32 PA, int32 access) { int index = (PA >> 1) & 07; /* word index */ +#ifdef XQ_DEBUG + if (index != 7) +#if defined(VM_VAX) + fprintf (stderr,"XQ: %s %08X %08X read: %X\n", xq_recv_regnames[index], fault_PC, PSL, *data); +#else + fprintf (stderr,"XQ: %s read: %X\n", xq_recv_regnames[index], *data); +#endif /* VM_VAX */ +#endif + switch (index) { case 0: case 1: @@ -542,7 +655,7 @@ t_stat xq_process_rbdl(void) struct xq_msg_itm* item; #ifdef XQ_DEBUG - printf("CSR: Processing read\n"); + fprintf(stderr,"XQ: CSR - Processing read\n"); #endif /* process buffer descriptors */ while(1) { @@ -612,6 +725,9 @@ t_stat xq_process_rbdl(void) } xq.rbdl_buf[5] = ((rbl & 0x00FF) << 8) | (rbl & 0x00FF); if (xq.ReadQ.loss) { +#ifdef XQ_DEBUG + fprintf(stderr, "XQ: ReadQ overflow\n"); +#endif xq.rbdl_buf[4] |= 0x0001; /* set overflow bit */ xq.ReadQ.loss = 0; /* reset loss counter */ } @@ -647,6 +763,9 @@ t_stat xq_process_mop(void) struct xq_meb* meb = (struct xq_meb*) &xq.write_buffer.msg[0200]; const struct xq_meb* limit = (struct xq_meb*) &xq.write_buffer.msg[0400]; +#ifdef XQ_DEBUG + fprintf(stderr, "XQ: Processing MOP data\n"); +#endif if (xq.type == XQ_T_DEQNA) /* DEQNA's don't MOP */ return SCPE_NOFNC; @@ -657,7 +776,7 @@ t_stat xq_process_mop(void) /* MOP stuff here - NOT YET FULLY IMPLEMENTED */ #ifdef XQ_DEBUG - printf("Processing MEB type: %d\n", meb->type); + printf("XQ: Processing MEB type: %d\n", meb->type); #endif switch (meb->type) { case 0: /* MOP Termination */ @@ -701,6 +820,7 @@ t_stat xq_process_setup(void) ETH_MAC filters[XQ_FILTER_MAX + 1]; /* extract filter addresses from setup packet */ + memset(xq.setup.macs, '\0', sizeof(xq.setup.macs)); for (i = 0; i < 7; i++) for (j = 0; j < 6; j++) { xq.setup.macs[i] [j] = xq.write_buffer.msg[(i + 01) + (j * 8)]; @@ -756,6 +876,9 @@ t_stat xq_process_setup(void) if (xq.write_buffer.msg[0]) status = xq_process_mop(); + /* mark setup block valid */ + xq.setup.valid = 1; + #ifdef XQ_DEBUG xq_debug_setup(); #endif @@ -771,7 +894,7 @@ t_stat xq_process_setup(void) */ t_stat xq_process_xbdl() { - const uint16 implicit_chain_status[2] = {XQ_DSC_L | XQ_DSC_C, 0}; + const uint16 implicit_chain_status[2] = {XQ_DSC_V | XQ_DSC_C, 1}; const uint16 write_success[2] = {0, 1 /*Non-Zero TDR*/}; uint16 b_length, w_length; @@ -780,7 +903,7 @@ t_stat xq_process_xbdl() t_stat status; #ifdef XQ_DEBUG - printf("CSR: Processing write\n"); + fprintf(stderr,"XQ: xq_process_xbdl - Processing write\n"); #endif /* clear write buffer */ xq.write_buffer.len = 0; @@ -789,9 +912,9 @@ t_stat xq_process_xbdl() while (1) { /* Get transmit bdl from memory */ + rstatus = Map_ReadW (xq.xbdl_ba, 12, &xq.xbdl_buf[0], NOMAP); xq.xbdl_buf[0] = 0xFFFF; wstatus = Map_WriteW(xq.xbdl_ba, 2, &xq.xbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq.xbdl_ba + 2, 6, &xq.xbdl_buf[1], NOMAP); if (rstatus || wstatus) return xq_nxm_error(); /* invalid buffer? */ @@ -799,20 +922,17 @@ t_stat xq_process_xbdl() xq.csr |= XQ_CSR_XL; if (xq.csr & XQ_CSR_IE) SET_INT(XQ); +#ifdef XQ_DEBUG + fprintf(stderr,"XQ: xq_process_xbdl - List Empty - Done Processing write\n"); +#endif return SCPE_OK; } - /* explicit chain buffer? */ - if (xq.xbdl_buf[1] & XQ_DSC_C) { - xq.xbdl_ba = ((xq.xbdl_buf[1] & 0x3F) << 16) | xq.xbdl_buf[2]; - continue; - } - - /* get status words */ - rstatus = Map_ReadW(xq.xbdl_ba + 8, 4, &xq.xbdl_buf[4], NOMAP); - if (rstatus) return xq_nxm_error(); - - /* get host memory address */ +#ifdef XQ_DEBUG + fprintf(stderr,"XQ: xq_process_xbdl: Buffer Descriptor Information: %04X %04X %04X %04X %04X \n", + xq.xbdl_buf[1], xq.xbdl_buf[2], xq.xbdl_buf[3], xq.xbdl_buf[4], xq.xbdl_buf[5]); +#endif + /* compute host memory address */ address = ((xq.xbdl_buf[1] & 0x3F) << 16) | xq.xbdl_buf[2]; /* decode buffer length - two's complement (in words) */ @@ -821,6 +941,15 @@ t_stat xq_process_xbdl() if (xq.xbdl_buf[1] & XQ_DSC_H) b_length -= 1; if (xq.xbdl_buf[1] & XQ_DSC_L) b_length -= 1; + /* explicit chain buffer? */ + if (xq.xbdl_buf[1] & XQ_DSC_C) { + xq.xbdl_ba = address; +#ifdef XQ_DEBUG + fprintf(stderr,"XQ: xq_process_xbdl: Chained Buffer Encountered: %d\n", b_length); +#endif + continue; + } + /* add to transmit buffer, making sure it's not too big */ if ((xq.write_buffer.len + b_length) > sizeof(xq.write_buffer.msg)) b_length = sizeof(xq.write_buffer.msg) - xq.write_buffer.len; @@ -836,10 +965,10 @@ t_stat xq_process_xbdl() status = xq_process_setup(); /* put packet in read buffer */ - xq_insert_queue (&xq.ReadQ, 0, xq.write_buffer, status); + xq_insert_queue (&xq.ReadQ, 0, &xq.write_buffer, status); } else { /* loopback */ /* put packet in read buffer */ - xq_insert_queue (&xq.ReadQ, 1, xq.write_buffer, 0); + xq_insert_queue (&xq.ReadQ, 1, &xq.write_buffer, 0); } /* update write status */ @@ -866,11 +995,19 @@ t_stat xq_process_xbdl() status = eth_write(xq.etherface, &xq.write_buffer, &xq_write_callback); if (status != SCPE_OK) /* not implemented or unattached */ xq_write_callback(1); /* fake failure */ + else + xq_svc(&xq_unit[0]); /* service any received data */ +#ifdef XQ_DEBUG + fprintf(stderr,"XQ: xq_process_xbdl: Completed Processing write\n"); +#endif return SCPE_OK; } /* loopback/non-loopback */ } else { /* not at end-of-message */ +#ifdef XQ_DEBUG + fprintf(stderr,"XQ: xq_process_xbdl: Processing Implicit Chained Buffer Segment\n"); +#endif /* update bdl status words */ wstatus = Map_WriteW(xq.xbdl_ba + 8, 4, (uint16*) implicit_chain_status, NOMAP); if(wstatus) return xq_nxm_error(); @@ -889,7 +1026,7 @@ t_stat xq_dispatch_rbdl(void) t_stat status; #ifdef XQ_DEBUG - printf("CSR: Dispatching read\n"); + fprintf(stderr,"XQ: CSR - Dispatching read\n"); #endif /* mark receive bdl valid */ xq.csr &= ~XQ_CSR_RL; @@ -927,7 +1064,7 @@ t_stat xq_dispatch_xbdl() int i; t_stat status; #ifdef XQ_DEBUG - printf("CSR: Dispatching write\n"); + fprintf(stderr,"XQ: CSR - Dispatching write\n"); #endif /* mark transmit bdl valid */ xq.csr &= ~XQ_CSR_XL; @@ -948,20 +1085,110 @@ t_stat xq_dispatch_xbdl() return status; } +t_stat xq_process_loopback(ETH_PACK* pack) +{ + ETH_PACK reply; + ETH_MAC physical_address; + t_stat status; + int offset = pack->msg[14] | (pack->msg[15] << 8); + int function = pack->msg[offset] | (pack->msg[offset+1] << 8); + + if (function != 2 /*forward*/) + return SCPE_NOFNC; + + /* create reply packet */ + memcpy (&reply, pack, sizeof(ETH_PACK)); + memcpy (physical_address, xq.setup.valid ? xq.setup.macs[0] : xq.mac, sizeof(ETH_MAC)); + memcpy (&reply.msg[0], &reply.msg[offset+2], sizeof(ETH_MAC)); + memcpy (&reply.msg[6], physical_address, sizeof(ETH_MAC)); + memcpy (&reply.msg[offset+2], physical_address, sizeof(ETH_MAC)); + reply.msg[offset] = 0x01; + offset += 8; + reply.msg[14] = offset & 0xFF; + reply.msg[15] = (offset >> 8) & 0xFF; + + /* send reply packet */ + status = eth_write(xq.etherface, &reply, NULL); + + return status; +} + +t_stat xq_process_remote_console (ETH_PACK* pack) +{ + t_stat status; + ETH_MAC source; + uint16 receipt; + int code = pack->msg[16]; + + switch (code) { + case 0x05: /* request id */ + receipt = pack->msg[18] | (pack->msg[19] << 8); + memcpy(source, &pack->msg[6], sizeof(ETH_MAC)); + + /* send system id to requestor */ + status = xq_system_id (source, receipt); + return status; + break; + case 0x06: /* boot */ + /* + NOTE: the verification field should be checked here against the + verification value established in the setup packet. If they match the + reboot should occur, otherwise nothing happens, and the packet + is passed on to the host. + + Verification is not implemented, since the setup packet processing code + isn't complete yet. + + Various values are also passed: processor, control, and software id. + These control the various boot parameters, however SIMH does not + have a mechanism to pass these to the host, so just reboot. + */ + + status = xq_boot_host(); + return status; + break; + } /* switch */ + + return SCPE_NOFNC; +} + +t_stat xq_process_local (ETH_PACK* pack) +{ + /* returns SCPE_OK if local processing occurred, + otherwise returns SCPE_NOFNC or some other code */ + int protocol; + + /* DEQNA's have no local processing capability */ + if (xq.type == XQ_T_DEQNA) + return SCPE_NOFNC; + + protocol = pack->msg[12] | (pack->msg[13] << 8); + switch (protocol) { + case 0x0090: /* ethernet loopback */ + return xq_process_loopback(pack); + break; + case 0x0260: /* MOP remote console */ + return xq_process_remote_console(pack); + break; + } + return SCPE_NOFNC; +} + void xq_read_callback(int status) { - t_stat rstatus; - if (xq.csr & XQ_CSR_RE) { /* receiver enabled */ + /* process any packets locally that can be */ + t_stat status = xq_process_local (&xq.read_buffer); + /* add packet to read queue */ - xq_insert_queue(&xq.ReadQ, 2, xq.read_buffer, status); - - /* process packet if receive list is valid */ - if (~xq.csr & XQ_CSR_RL) - rstatus = xq_process_rbdl(); - + if (status != SCPE_OK) + xq_insert_queue(&xq.ReadQ, 2, &xq.read_buffer, status); } +#ifdef XQ_DEBUG + else + fprintf(stderr, "XQ: packet received with receiver disabled\n"); +#endif } void xq_sw_reset(void) @@ -972,6 +1199,9 @@ void xq_sw_reset(void) /* disconnect ethernet reception */ sim_cancel(&xq_unit[0]); + /* stop system_id timer */ + sim_cancel(&xq_unit[2]); + /* reset csr bits */ xq.csr = XQ_CSR_XL | XQ_CSR_RL; @@ -982,8 +1212,7 @@ void xq_sw_reset(void) xq_clear_queue(&xq.ReadQ); /* clear setup info */ - memset (&xq.setup, 0, 6 * XQ_FILTER_MAX); - xq.setup.promiscuous = 0; + memset (&xq.setup, 0, sizeof(xq.setup)); } @@ -1038,10 +1267,14 @@ t_stat xq_wr_csr(int32 data) if (data & XQ_CSR_XI) /* clearing XI clears NI too */ xq.csr &= ~XQ_CSR_NI; - /* start receiver when RE transitions to set */ + /* start receiver timer when RE transitions to set */ if (~saved_csr & XQ_CSR_RE & data) { - //xq_start_receiver(); - sim_activate(&xq_unit[0], xq.rtime); + sim_activate(&xq_unit[0], (clk_tps * tmr_poll)/100); + } + + /* stop receiver timer when RE transitions to clear */ + if (saved_csr & XQ_CSR_RE & ~data) { + sim_cancel(&xq_unit[0]); } return SCPE_OK; @@ -1050,8 +1283,18 @@ t_stat xq_wr_csr(int32 data) t_stat xq_wr(int32 data, int32 PA, int32 access) { t_stat status; + int index = (PA >> 1) & 07; /* word index */ - switch ((PA >> 1) & 07) { +#ifdef XQ_DEBUG + if (index != 7) +#if defined(VM_VAX) + fprintf (stderr,"XQ: %s %08X %08X write: %X\n", xq_xmit_regnames[index], fault_PC, PSL, data); +#else + fprintf (stderr,"XQ: %s write: %X\n", xq_xmit_regnames[index], data); +#endif /* VM_VAX */ +#endif + + switch (index) { case 0: /* these should not be written */ case 1: break; @@ -1121,6 +1364,7 @@ t_stat xq_reset(DEVICE* dptr) break; case XQ_T_DELQA: /* note that the DELQA in NORMAL mode has no power-on SANITY state! */ + xq_start_idtmr(); break; }; @@ -1134,7 +1378,7 @@ void xq_start_santmr(void) #if 0 #ifdef XQ_DEBUG - printf("SANITY TIMER: enabled, qsecs: %d, poll:%d\n", xq.sanity.quarter_secs, tmr_poll); + fprintf(stderr,"XQ: SANITY TIMER: enabled, qsecs: %d, poll:%d\n", xq.sanity.quarter_secs, tmr_poll); #endif #endif if (sim_is_active(&xq_unit[1])) /* cancel timer, just in case */ @@ -1149,7 +1393,7 @@ void xq_cancel_santmr(void) if (sim_is_active(&xq_unit[1]) && !xq.sanity.enabled) { #if 0 #ifdef XQ_DEBUG - printf("SANITY TIMER: cancelled, qsecs: %d\n", xq.sanity.quarter_secs); + fprintf(stderr,"XQ: SANITY TIMER: cancelled, qsecs: %d\n", xq.sanity.quarter_secs); #endif #endif sim_cancel(&xq_unit[1]); @@ -1161,7 +1405,7 @@ void xq_reset_santmr(void) #if 0 #ifdef XQ_DEBUG ftime(&start); - printf("SANITY TIMER: resetting, qsecs: %d\n", xq.sanity.quarter_secs); + fprintf(stderr,"XQ: SANITY TIMER: resetting, qsecs: %d\n", xq.sanity.quarter_secs); #endif #endif xq.sanity.countdown = xq.sanity.quarter_secs; @@ -1179,39 +1423,159 @@ t_stat xq_sansvc(UNIT* uptr) /* If this section is entered, it means that the sanity timer has expired without being reset, and the controller must reboot the processor. - - The manual says the hardware should force Qbus BDCOK low for - 3.6 microseconds, which will cause the host to reboot. - - Since the SIMH Qbus emulator does not have this functionality, we call - a special STOP_ code, and let the CPU stop dispatch routine decide - what the appropriate cpu-specific behavior should be. */ #if 0 #ifdef XQ_DEBUG ftime(&finish); - printf("SANITY TIMER: EXPIRED, qsecs: %d, poll: %d, elapsed: %d\n", + fprintf(stderr,"XQ: SANITY TIMER: EXPIRED, qsecs: %d, poll: %d, elapsed: %d\n", xq.sanity.quarter_secs, tmr_poll, finish.time - start.time); #endif #endif - return STOP_SANITY; + xq_boot_host(); } return SCPE_OK; } +t_stat xq_boot_host(void) +{ + /* + The manual says the hardware should force the Qbus BDCOK low for + 3.6 microseconds, which will cause the host to reboot. + + Since the SIMH Qbus emulator does not have this functionality, we call + a special STOP_ code, and let the CPU stop dispatch routine decide + what the appropriate cpu-specific behavior should be. + */ + return STOP_SANITY; +} + +void xq_start_idtmr(void) +{ + /* must be recalculated each time since tmr_poll is a dynamic number */ + const int32 one_sec = clk_tps * tmr_poll; + + if (sim_is_active(&xq_unit[2])) /* cancel timer, just in case */ + sim_cancel(&xq_unit[2]); + xq.id.enabled = 1; + /* every 8-10 minutes (9 in this case) the DELQA broadcasts a system id message */ + xq.id.countdown = 9 * 60; + sim_activate(&xq_unit[2], one_sec); +} + +t_stat xq_system_id (const ETH_MAC dest, uint16 receipt_id) +{ + static uint16 receipt = 0; + ETH_PACK system_id; + uint8* const msg = &system_id.msg[0]; + t_stat status; + + memset (&system_id, 0, sizeof(system_id)); + memcpy (&msg[0], dest, sizeof(ETH_MAC)); + memcpy (&msg[6], xq.setup.valid ? xq.setup.macs[0] : xq.mac, sizeof(ETH_MAC)); + msg[12] = 0x60; /* type */ + msg[13] = 0x02; /* type */ + msg[14] = 0x1C; /* character count */ + msg[15] = 0x00; /* character count */ + msg[16] = 0x07; /* code */ + msg[17] = 0x00; /* zero pad */ + if (receipt_id) { + msg[18] = receipt_id & 0xFF; /* receipt number */ + msg[19] = (receipt_id >> 8) & 0xFF; /* receipt number */ + } else { + msg[18] = receipt & 0xFF; /* receipt number */ + msg[19] = (receipt++ >> 8) & 0xFF; /* receipt number */ + } + + /* MOP VERSION */ + msg[20] = 0x01; /* type */ + msg[21] = 0x00; /* type */ + msg[22] = 0x03; /* length */ + msg[23] = 0x03; /* version */ + msg[24] = 0x01; /* eco */ + msg[25] = 0x00; /* user eco */ + + /* FUNCTION */ + msg[26] = 0x02; /* type */ + msg[27] = 0x00; /* type */ + msg[28] = 0x02; /* length */ + msg[29] = 0x00; /* value 1 ??? */ + msg[30] = 0x00; /* value 2 */ + + /* HARDWARE ADDRESS */ + msg[31] = 0x07; /* type */ + msg[32] = 0x00; /* type */ + msg[33] = 0x06; /* length */ + memcpy (&msg[34], xq.mac, sizeof(ETH_MAC)); /* ROM address */ + + /* DEVICE TYPE */ + msg[40] = 37; /* type */ + msg[41] = 0x00; /* type */ + msg[42] = 0x01; /* length */ + msg[43] = 0x11; /* value (0x11=DELQA) */ + + /* write system id */ + system_id.len = 60; + status = eth_write(xq.etherface, &system_id, NULL); + + return status; +} + +t_stat xq_idsvc(UNIT* uptr) +{ +/* must be recalculated each time since tmr_poll is a dynamic number */ +const int32 one_sec = clk_tps * tmr_poll; +const ETH_MAC mop_multicast = {0xAB, 0x00, 0x00, 0x02, 0x00, 0x00}; + + /* DEQNAs don't issue system id messages */ + if (xq.type == XQ_T_DEQNA) + return SCPE_NOFNC; + + if (--xq.id.countdown <= 0) { + /* + If this section is entered, it means that the 9 minute interval has elapsed + so broadcast system id to MOP multicast address + */ + xq_system_id(mop_multicast, 0); + /* every 8-10 minutes (9 in this case) the DELQA broadcasts a system id message */ + xq.id.countdown = 9 * 60; + } + + /* resubmit - for one second to get a well calibrated value of tmr_poll */ + sim_activate(&xq_unit[2], one_sec); + return SCPE_OK; +} + /* ** service routine - used for ethernet reading loop */ t_stat xq_svc(UNIT* uptr) { t_stat status; + int queue_size; - /* read a packet from the ethernet - processing is via the callback */ - status = eth_read (xq.etherface, &xq.read_buffer, &xq_read_callback); + /* Don't try a read if the receiver is disabled */ + if (!(xq.csr & XQ_CSR_RE)) return SCPE_OK; + + /* First pump any queued packets into the system */ + if ((xq.ReadQ.count > 0) && (~xq.csr & XQ_CSR_RL)) + status = xq_process_rbdl(); + + /* Now read and queue packets that have arrived */ + /* This is repeated as long as they are available and we have room */ + do + { + queue_size = xq.ReadQ.count; + /* read a packet from the ethernet - processing is via the callback */ + status = eth_read (xq.etherface, &xq.read_buffer, &xq_read_callback); + } while (queue_size != xq.ReadQ.count); + + /* Now pump any still queued packets into the system */ + if ((xq.ReadQ.count > 0) && (~xq.csr & XQ_CSR_RL)) + status = xq_process_rbdl(); /* resubmit if still receive enabled */ if (xq.csr & XQ_CSR_RE) - sim_activate(&xq_unit[0], xq.rtime); + sim_activate(&xq_unit[0], (clk_tps * tmr_poll)/100); return SCPE_OK; } @@ -1278,8 +1642,10 @@ int32 xq_inta (void) /=============================================================================*/ #ifdef XQ_DEBUG + void xq_dump_csr (void) { + static int cnt = 0; /* tell user what is changing in register */ int i; int mask = 1; @@ -1290,7 +1656,12 @@ void xq_dump_csr (void) if ((csr & mask)) strcat (hi, xq_csr_bits[i]); if ((~csr & mask)) strcat (lo, xq_csr_bits[i]); } - printf ("CSR read: %s %s\n", hi, lo); +#if defined (VM_VAX) + printf ("CSR %08X %08X read: %s %s\n", fault_PC, PSL, hi, lo); +#else +if (cnt < 20) + printf ("CSR read[%d]: %s %s\n", cnt++, hi, lo); +#endif /* VM_VAX */ } void xq_dump_var (void) @@ -1326,7 +1697,11 @@ void xq_csr_changes (uint16 data) /* write-one-to-clear bits*/ if (data & XQ_CSR_RI) strcat(lo, "RI "); if (data & XQ_CSR_XI) strcat(lo, "XI "); +#if defined(VM_VAX) + printf ("CSR %08X %08X write: %s %s\n", fault_PC, PSL, hi, lo); +#else printf ("CSR write: %s %s\n", hi, lo); +#endif /* VM_VAX */ } void xq_var_changes (uint16 data) @@ -1345,9 +1720,11 @@ void xq_var_changes (uint16 data) if (~var & XQ_VEC_ID & data) strcat (hi, "ID "); if (var & XQ_VEC_ID & ~data) strcat (lo, "ID "); - if ((var & XQ_VEC_IV) != (data & XQ_VEC_IV)) + if ((var & XQ_VEC_IV) != (data & XQ_VEC_IV)) { vec = (data & XQ_VEC_IV) >> 2; - printf ("VAR write: %s %s - Vec: %d\n", hi, lo, vec); + printf ("VAR write: %s %s - Vec: %d\n", hi, lo, vec); + } else + printf ("VAR write: %s %s\n", hi, lo); } void xq_debug_setup(void) @@ -1369,8 +1746,7 @@ void xq_debug_setup(void) if (len & XQ_SETUP_PM) strcat(buffer, "PM "); if (len & XQ_SETUP_LD) strcat(buffer, "LD "); if (len & XQ_SETUP_ST) strcat(buffer, "ST "); - printf ("Setup: Length [%d] info: %s\n", len, buffer); + printf ("Setup: Length [%d =0x%X, LD:%d, ST:%d] info: %s\n", len, len, (len & XQ_SETUP_LD) >> 2, (len & XQ_SETUP_ST) >> 4, buffer); } } #endif - diff --git a/PDP11/pdp11_xq.h b/PDP11/pdp11_xq.h index fdc8ad98..2b978bab 100644 --- a/PDP11/pdp11_xq.h +++ b/PDP11/pdp11_xq.h @@ -28,6 +28,11 @@ Modification history: + 15-Jan-03 DTH Merged Mark Pizzolato's changes into main source + 13-Jan-03 MP Added xq_id to countdown the triggering of the System Id + multicast packets + 10-Jan-03 DTH Added bootrom + 30-Dec-02 DTH Added setup valid field 21-Oct-02 DTH Corrected copyright again 15-Oct-02 DTH Fixed copyright, added sanity timer support 10-Oct-02 DTH Added more setup fields and bitmasks @@ -69,6 +74,11 @@ struct xq_sanity { int countdown; /* sanity timer countdown in 1/4 seconds */ }; +struct xq_id { + int enabled; /* System ID timer enabled ? */ + int countdown; /* System ID timer countdown in seconds */ +}; + struct xq_msg_itm { int type; /* receive (0=setup, 1=loopback, 2=normal) */ ETH_PACK packet; /* packet */ @@ -84,6 +94,7 @@ struct xq_msg_que { }; struct xq_setup { + int valid; /* is the setup block valid? */ int promiscuous; /* promiscuous mode enabled */ int multicast; /* enable all multicast addresses */ int l1; /* first diagnostic led state */ @@ -108,6 +119,7 @@ struct xq_device { ETH_MAC mac; /* MAC address */ enum xq_type type; /* controller type */ struct xq_sanity sanity; /* sanity timer information */ + struct xq_id id; /* System ID timer information */ /*- initialized values - DO NOT MOVE */ /* I/O register storage */ @@ -130,6 +142,7 @@ struct xq_device { ETH_PACK read_buffer; ETH_PACK write_buffer; struct xq_msg_que ReadQ; + uint8 bootrom[256]; }; #define XQ_CSR_RI 0x8000 /* Receive Interrupt Request (RI) [RO/W1] */ diff --git a/PDP11/pdp11_xu.c b/PDP11/pdp11_xu.c new file mode 100644 index 00000000..9c462781 --- /dev/null +++ b/PDP11/pdp11_xu.c @@ -0,0 +1,61 @@ +/* pdp11_xu.c: DEUNA/DELUA Unibus Ethernet interface (stub) + + Copyright (c) 2003, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + xu DEUNA/DELUNA Ethernet interface (stub) +*/ + +#if defined (USE_INT64) /* PDP-10 */ +#include "pdp10_defs.h" +#define VM_PDP10 1 +extern int32 int_req; +extern int32 int_vec[32]; +#else +#include "pdp11_defs.h" /* PDP-11 */ +#define VM_PDP11 1 +extern int32 int_req[IPL_HLVL]; +extern int32 int_vec[IPL_HLVL][32]; +#endif + +/* XU data structures + + xu_dev XU device descriptor + xu_unit XU unit list + xu_reg XU register list +*/ + +DIB xu_dib = { IOBA_XU, IOLN_XU, NULL, NULL, + 1, IVCL (XU), VEC_XU, { NULL } }; + +UNIT xu_unit = { UDATA (NULL, 0, 0) }; + +REG xu_reg[] = { + { NULL } }; + +DEVICE xu_dev = { + "XU", &xu_unit, xu_reg, NULL, + 1, 8, 8, 1, 8, 8, + NULL, NULL, NULL, + NULL, NULL, NULL, + &xu_dib, DEV_DIS | DEV_UBUS }; diff --git a/PDP18B/pdp18b_cpu.c b/PDP18B/pdp18b_cpu.c index 03e582ee..1e26ff1e 100644 --- a/PDP18B/pdp18b_cpu.c +++ b/PDP18B/pdp18b_cpu.c @@ -519,18 +519,18 @@ extern UNIT clk_unit; #if defined (PDP9) #define CHECK_AUTO_INC \ if ((IR & 017770) == 010) { \ - MA = MA & 017; \ - M[MA] = (M[MA] + 1) & 0777777; } + MA = MA & 017; \ + M[MA] = (M[MA] + 1) & 0777777; } #define INDIRECT \ MA = memm? M[MA] & IAMASK: (MA & epcmask) | (M[MA] & damask) #define CHECK_ADDR_R(x) \ if (usmd) { \ - if (!MEM_ADDR_OK (x)) { \ - nexm = prvn = trap_pending = 1; \ - break; } \ - if ((x) < BR) { \ - prvn = trap_pending = 1; \ - break; } } \ + if (!MEM_ADDR_OK (x)) { \ + nexm = prvn = trap_pending = 1; \ + break; } \ + if ((x) < BR) { \ + prvn = trap_pending = 1; \ + break; } } \ if (!MEM_ADDR_OK (x)) nexm = 1 #define CHECK_INDEX /* no indexing capability */ #define CHECK_ADDR_W(x) \ @@ -550,28 +550,28 @@ extern UNIT clk_unit; #if defined (PDP15) #define CHECK_AUTO_INC \ if ((IR & damask & ~07) == 00010) { \ - MA = MA & 017; \ - M[MA] = (M[MA] + 1) & 0777777; } + MA = MA & 017; \ + M[MA] = (M[MA] + 1) & 0777777; } #define INDIRECT \ if (rest_pending) { \ - rest_pending = 0; \ - LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777); \ - memm = (M[MA] >> 16) & 1; \ - usmd = (M[MA] >> 15) & 1; } \ + rest_pending = 0; \ + LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777); \ + memm = (M[MA] >> 16) & 1; \ + usmd = (M[MA] >> 15) & 1; } \ MA = ((IR & damask & ~07) != 00010)? \ - (PC & BLKMASK) | (M[MA] & IAMASK): (M[MA] & ADDRMASK); \ + (PC & BLKMASK) | (M[MA] & IAMASK): (M[MA] & ADDRMASK); \ damask = memm? 017777: 07777; \ epcmask = ADDRMASK & ~damask #define CHECK_INDEX \ if ((IR & 0010000) && (memm == 0)) MA = (MA + XR) & ADDRMASK #define CHECK_ADDR_R(x) \ if (usmd) { \ - if (!MEM_ADDR_OK (x)) { \ - nexm = prvn = trap_pending = 1; \ - break; } \ - if ((x) < BR) { \ - prvn = trap_pending = 1; \ - break; } } \ + if (!MEM_ADDR_OK (x)) { \ + nexm = prvn = trap_pending = 1; \ + break; } \ + if ((x) < BR) { \ + prvn = trap_pending = 1; \ + break; } } \ if (!MEM_ADDR_OK (x)) nexm = 1 #define CHECK_ADDR_W(x) \ CHECK_ADDR_R (x); \ @@ -644,16 +644,17 @@ if (api_int && !ion_defer) { /* API intr? */ int32 i, lvl = api_int - 1; /* get req level */ api_act = api_act | (0200 >> lvl); /* set level active */ if (lvl >= API_HLVL) { /* software req? */ - MA = ACH_SWRE + lvl - API_HLVL; /* vec = 40:43 */ - api_req = api_req & ~(0200 >> lvl); } /* remove request */ - else { MA = 0; /* assume fails */ - for (i = 0; i < 32; i++) { /* loop hi to lo */ - if ((int_hwre[lvl] >> i) & 1) { /* int req set? */ - MA = api_vec[lvl][i]; /* get vector */ - break; } } } /* and stop */ + MA = ACH_SWRE + lvl - API_HLVL; /* vec = 40:43 */ + api_req = api_req & ~(0200 >> lvl); } /* remove request */ + else { + MA = 0; /* assume fails */ + for (i = 0; i < 32; i++) { /* loop hi to lo */ + if ((int_hwre[lvl] >> i) & 1) { /* int req set? */ + MA = api_vec[lvl][i]; /* get vector */ + break; } } } /* and stop */ if (MA == 0) { /* bad channel? */ - reason = STOP_API; /* API error */ - break; } + reason = STOP_API; /* API error */ + break; } api_int = api_eval (&int_pend); /* no API int */ api_cycle = 1; /* in API cycle */ emir_pending = rest_pending = 0; /* emir, restore off */ @@ -687,11 +688,11 @@ if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ #if defined (PDP9) || defined (PDP15) if (usmd) { /* user mode? */ if (!MEM_ADDR_OK (PC)) { /* nxm? */ - nexm = prvn = trap_pending = 1; /* abort fetch */ - continue; } \ + nexm = prvn = trap_pending = 1; /* abort fetch */ + continue; } if (PC < BR) { /* bounds viol? */ - prvn = trap_pending = 1; /* abort fetch */ - continue; } } + prvn = trap_pending = 1; /* abort fetch */ + continue; } } else if (!MEM_ADDR_OK (PC)) nexm = 1; /* flag nxm */ if (!ion_defer) usmd = usmdbuf; /* no IOT? load usmd */ #endif @@ -819,11 +820,11 @@ case 020: /* XCT, dir */ CHECK_INDEX; CHECK_ADDR_R (MA); if (usmd && (xct_count != 0)) { /* trap and chained? */ - prvn = trap_pending = 1; - break; } + prvn = trap_pending = 1; + break; } if (xct_count >= xct_max) { /* too many XCT's? */ - reason = STOP_XCT; - break; } + reason = STOP_XCT; + break; } xct_count = xct_count + 1; /* count XCT's */ #if defined (PDP9) ion_defer = 1; /* defer intr */ @@ -848,8 +849,8 @@ case 001: case 000: /* CAL */ #if defined (PDP9) || defined (PDP15) usmd = 0; /* clear user mode */ if ((cpu_unit.flags & UNIT_NOAPI) == 0) { /* if API, act lvl 4 */ - api_act = api_act | 010; - api_int = api_eval (&int_pend); } + api_act = api_act | 010; + api_int = api_eval (&int_pend); } #endif if (IR & 0020000) { INDIRECT; } /* indirect? */ CHECK_ADDR_W (MA); @@ -885,9 +886,9 @@ CHECK_AUTO_INC; /* check auto inc */ #endif #if defined (PDP9) if (rest_pending) { /* restore pending? */ - LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777); - memm = (M[MA] >> 16) & 1; - usmd = (M[MA] >> 15) & 1; } + LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777); + memm = (M[MA] >> 16) & 1; + usmd = (M[MA] >> 15) & 1; } #endif INDIRECT; /* complete indirect */ emir_pending = rest_pending = 0; @@ -907,147 +908,147 @@ case 036: /* OPR, dir */ skp = 0; /* assume no skip */ switch ((IR >> 6) & 017) { /* decode IR<8:11> */ case 0: /* nop */ - break; + break; case 1: /* SMA */ - if ((LAC & 0400000) != 0) skp = 1; - break; + if ((LAC & 0400000) != 0) skp = 1; + break; case 2: /* SZA */ - if ((LAC & 0777777) == 0) skp = 1; - break; + if ((LAC & 0777777) == 0) skp = 1; + break; case 3: /* SZA | SMA */ - if (((LAC & 0777777) == 0) || ((LAC & 0400000) != 0)) - skp = 1; - break; + if (((LAC & 0777777) == 0) || ((LAC & 0400000) != 0)) + skp = 1; + break; case 4: /* SNL */ - if (LAC >= 01000000) skp = 1; - break; + if (LAC >= 01000000) skp = 1; + break; case 5: /* SNL | SMA */ - if (LAC >= 0400000) skp = 1; - break; + if (LAC >= 0400000) skp = 1; + break; case 6: /* SNL | SZA */ - if ((LAC >= 01000000) || (LAC == 0)) skp = 1; - break; + if ((LAC >= 01000000) || (LAC == 0)) skp = 1; + break; case 7: /* SNL | SZA | SMA */ - if ((LAC >= 0400000) || (LAC == 0)) skp = 1; - break; + if ((LAC >= 0400000) || (LAC == 0)) skp = 1; + break; case 010: /* SKP */ - skp = 1; - break; + skp = 1; + break; case 011: /* SPA */ - if ((LAC & 0400000) == 0) skp = 1; - break; + if ((LAC & 0400000) == 0) skp = 1; + break; case 012: /* SNA */ - if ((LAC & 0777777) != 0) skp = 1; - break; + if ((LAC & 0777777) != 0) skp = 1; + break; case 013: /* SNA & SPA */ - if (((LAC & 0777777) != 0) && ((LAC & 0400000) == 0)) - skp = 1; - break; + if (((LAC & 0777777) != 0) && ((LAC & 0400000) == 0)) + skp = 1; + break; case 014: /* SZL */ - if (LAC < 01000000) skp = 1; - break; + if (LAC < 01000000) skp = 1; + break; case 015: /* SZL & SPA */ - if (LAC < 0400000) skp = 1; - break; + if (LAC < 0400000) skp = 1; + break; case 016: /* SZL & SNA */ - if ((LAC < 01000000) && (LAC != 0)) skp = 1; - break; + if ((LAC < 01000000) && (LAC != 0)) skp = 1; + break; case 017: /* SZL & SNA & SPA */ - if ((LAC < 0400000) && (LAC != 0)) skp = 1; - break; } /* end switch skips */ + if ((LAC < 0400000) && (LAC != 0)) skp = 1; + break; } /* end switch skips */ /* OPR, continued */ switch (((IR >> 9) & 014) | (IR & 03)) { /* IR<5:6,16:17> */ case 0: /* NOP */ - break; + break; case 1: /* CMA */ - LAC = LAC ^ 0777777; - break; + LAC = LAC ^ 0777777; + break; case 2: /* CML */ - LAC = LAC ^ 01000000; - break; + LAC = LAC ^ 01000000; + break; case 3: /* CML CMA */ - LAC = LAC ^ 01777777; - break; + LAC = LAC ^ 01777777; + break; case 4: /* CLL */ - LAC = LAC & 0777777; - break; + LAC = LAC & 0777777; + break; case 5: /* CLL CMA */ - LAC = (LAC & 0777777) ^ 0777777; - break; + LAC = (LAC & 0777777) ^ 0777777; + break; case 6: /* CLL CML = STL */ - LAC = LAC | 01000000; - break; + LAC = LAC | 01000000; + break; case 7: /* CLL CML CMA */ - LAC = (LAC | 01000000) ^ 0777777; - break; + LAC = (LAC | 01000000) ^ 0777777; + break; case 010: /* CLA */ - LAC = LAC & 01000000; - break; + LAC = LAC & 01000000; + break; case 011: /* CLA CMA = STA */ - LAC = LAC | 0777777; - break; + LAC = LAC | 0777777; + break; case 012: /* CLA CML */ - LAC = (LAC & 01000000) ^ 01000000; - break; + LAC = (LAC & 01000000) ^ 01000000; + break; case 013: /* CLA CML CMA */ - LAC = (LAC | 0777777) ^ 01000000; - break; + LAC = (LAC | 0777777) ^ 01000000; + break; case 014: /* CLA CLL */ - LAC = 0; - break; + LAC = 0; + break; case 015: /* CLA CLL CMA */ - LAC = 0777777; - break; + LAC = 0777777; + break; case 016: /* CLA CLL CML */ - LAC = 01000000; - break; + LAC = 01000000; + break; case 017: /* CLA CLL CML CMA */ - LAC = 01777777; - break; } /* end decode */ + LAC = 01777777; + break; } /* end decode */ /* OPR, continued */ if (IR & 0000004) { /* OAS */ #if defined (PDP9) || defined (PDP15) - if (usmd) prvn = trap_pending = 1; - else + if (usmd) prvn = trap_pending = 1; + else #endif LAC = LAC | SR; } switch (((IR >> 8) & 04) | ((IR >> 3) & 03)) { /* decode IR<7,13:14> */ case 1: /* RAL */ - LAC = ((LAC << 1) | (LAC >> 18)) & 01777777; + LAC = ((LAC << 1) | (LAC >> 18)) & 01777777; break; case 2: /* RAR */ - LAC = ((LAC >> 1) | (LAC << 18)) & 01777777; - break; + LAC = ((LAC >> 1) | (LAC << 18)) & 01777777; + break; case 3: /* RAL RAR */ #if defined (PDP15) /* PDP-15 */ - LAC = (LAC + 1) & 01777777; /* IAC */ + LAC = (LAC + 1) & 01777777; /* IAC */ #else /* PDP-4,-7,-9 */ - reason = stop_inst; /* undefined */ + reason = stop_inst; /* undefined */ #endif - break; + break; case 5: /* RTL */ - LAC = ((LAC << 2) | (LAC >> 17)) & 01777777; - break; + LAC = ((LAC << 2) | (LAC >> 17)) & 01777777; + break; case 6: /* RTR */ - LAC = ((LAC >> 2) | (LAC << 17)) & 01777777; - break; + LAC = ((LAC >> 2) | (LAC << 17)) & 01777777; + break; case 7: /* RTL RTR */ #if defined (PDP15) /* PDP-15 */ - LAC = ((LAC >> 9) & 0777) | ((LAC & 0777) << 9) | - (LAC & 01000000); /* BSW */ + LAC = ((LAC >> 9) & 0777) | ((LAC & 0777) << 9) | + (LAC & 01000000); /* BSW */ #else /* PDP-4,-7,-9 */ - reason = stop_inst; /* undefined */ + reason = stop_inst; /* undefined */ #endif - break; } /* end switch rotate */ + break; } /* end switch rotate */ if (IR & 0000040) { /* HLT */ - if (usmd) prvn = trap_pending = 1; - else reason = STOP_HALT; } + if (usmd) prvn = trap_pending = 1; + else reason = STOP_HALT; } if (skp && !prvn) PC = INCR_ADDR (PC); /* if skip, inc PC */ break; /* end OPR */ @@ -1065,10 +1066,10 @@ case 036: /* OPR, dir */ case 033: case 032: /* EAE */ if (cpu_unit.flags & UNIT_NOEAE) break; /* disabled? */ if (IR & 0020000) /* IR<4>? AC0 to L */ - LAC = ((LAC << 1) & 01000000) | (LAC & 0777777); + LAC = ((LAC << 1) & 01000000) | (LAC & 0777777); if (IR & 0010000) MQ = 0; /* IR<5>? clear MQ */ if ((IR & 0004000) && (LAC & 0400000)) /* IR<6> and minus? */ - eae_ac_sign = 01000000; /* set eae_ac_sign */ + eae_ac_sign = 01000000; /* set eae_ac_sign */ else eae_ac_sign = 0; /* if not, unsigned */ if (IR & 0002000) MQ = (MQ | LAC) & 0777777; /* IR<7>? or AC */ else if (eae_ac_sign) LAC = LAC ^ 0777777; /* if not, |AC| */ @@ -1079,25 +1080,25 @@ case 033: case 032: /* EAE */ switch ((IR >> 6) & 07) { /* case on IR<9:11> */ case 0: /* setup */ - if (IR & 04) LAC = LAC ^ 0777777; /* IR<15>? ~AC */ - if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */ - if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */ - break; + if (IR & 04) LAC = LAC ^ 0777777; /* IR<15>? ~AC */ + if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */ + if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */ + break; case 1: /* multiply */ - CHECK_ADDR_R (PC); /* validate PC */ - MA = M[PC]; /* get next word */ - PC = INCR_ADDR (PC); /* increment PC */ - if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */ - LAC = LAC & 0777777; /* clear link */ - for (SC = esc; SC != 0; SC--) { /* loop per step cnt */ - if (MQ & 1) LAC = LAC + MA; /* MQ<17>? add */ - MQ = (MQ >> 1) | ((LAC & 1) << 17); - LAC = LAC >> 1; } /* shift AC'MQ right */ - if (eae_ac_sign ^ link_init) { /* result negative? */ - LAC = LAC ^ 0777777; - MQ = MQ ^ 0777777; } - break; + CHECK_ADDR_R (PC); /* validate PC */ + MA = M[PC]; /* get next word */ + PC = INCR_ADDR (PC); /* increment PC */ + if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */ + LAC = LAC & 0777777; /* clear link */ + for (SC = esc; SC != 0; SC--) { /* loop per step cnt */ + if (MQ & 1) LAC = LAC + MA; /* MQ<17>? add */ + MQ = (MQ >> 1) | ((LAC & 1) << 17); + LAC = LAC >> 1; } /* shift AC'MQ right */ + if (eae_ac_sign ^ link_init) { /* result negative? */ + LAC = LAC ^ 0777777; + MQ = MQ ^ 0777777; } + break; /* EAE, continued @@ -1111,26 +1112,26 @@ case 033: case 032: /* EAE */ */ case 3: /* divide */ - CHECK_ADDR_R (PC); /* validate PC */ - MA = M[PC]; /* get next word */ - PC = INCR_ADDR (PC); /* increment PC */ - if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */ - if ((LAC & 0777777) >= MA) { /* overflow? */ - LAC = (LAC - MA) | 01000000; /* set link */ - break; } - LAC = LAC & 0777777; /* clear link */ - t = 0; /* init loop */ - for (SC = esc; SC != 0; SC--) { /* loop per step cnt */ - if (t) LAC = (LAC + MA) & 01777777; - else LAC = (LAC - MA) & 01777777; - t = (LAC >> 18) & 1; /* quotient bit */ - if (SC > 1) LAC = /* skip if last */ - ((LAC << 1) | (MQ >> 17)) & 01777777; - MQ = ((MQ << 1) | t) & 0777777; } + CHECK_ADDR_R (PC); /* validate PC */ + MA = M[PC]; /* get next word */ + PC = INCR_ADDR (PC); /* increment PC */ + if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */ + if ((LAC & 0777777) >= MA) { /* overflow? */ + LAC = (LAC - MA) | 01000000; /* set link */ + break; } + LAC = LAC & 0777777; /* clear link */ + t = 0; /* init loop */ + for (SC = esc; SC != 0; SC--) { /* loop per step cnt */ if (t) LAC = (LAC + MA) & 01777777; - if (eae_ac_sign) LAC = LAC ^ 0777777; /* sgn rem = sgn divd */ - if (eae_ac_sign ^ link_init ^ 1) MQ = MQ ^ 0777777; - break; + else LAC = (LAC - MA) & 01777777; + t = (LAC >> 18) & 1; /* quotient bit */ + if (SC > 1) LAC = /* skip if last */ + ((LAC << 1) | (MQ >> 17)) & 01777777; + MQ = ((MQ << 1) | t) & 0777777; } + if (t) LAC = (LAC + MA) & 01777777; + if (eae_ac_sign) LAC = LAC ^ 0777777; /* sgn rem = sgn divd */ + if (eae_ac_sign ^ link_init ^ 1) MQ = MQ ^ 0777777; + break; /* EAE, continued @@ -1141,43 +1142,45 @@ case 033: case 032: /* EAE */ case 4: /* normalize */ #if defined (PDP15) - if (!usmd) ion_defer = 2; /* free cycles */ + if (!usmd) ion_defer = 2; /* free cycles */ #endif - for (SC = esc; (SC != 0) && ((LAC & 0400000) == - ((LAC << 1) & 0400000)); SC--) { - LAC = (LAC << 1) | ((MQ >> 17) & 1); - MQ = (MQ << 1) | (link_init >> 18); } - LAC = link_init | (LAC & 0777777); /* trim AC, restore L */ - MQ = MQ & 0777777; /* trim MQ */ - SC = SC & 077; /* trim SC */ - break; + for (SC = esc; (SC != 0) && ((LAC & 0400000) == + ((LAC << 1) & 0400000)); SC--) { + LAC = (LAC << 1) | ((MQ >> 17) & 1); + MQ = (MQ << 1) | (link_init >> 18); } + LAC = link_init | (LAC & 0777777); /* trim AC, restore L */ + MQ = MQ & 0777777; /* trim MQ */ + SC = SC & 077; /* trim SC */ + break; case 5: /* long right shift */ - if (esc < 18) { - MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & 0777777; - LAC = ((fill << (18 - esc)) | (LAC >> esc)) & 01777777; } - else { if (esc < 36) MQ = - ((fill << (36 - esc)) | (LAC >> (esc - 18))) & 0777777; - else MQ = fill; - LAC = link_init | fill; } - SC = 0; /* clear step count */ - break; + if (esc < 18) { + MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & 0777777; + LAC = ((fill << (18 - esc)) | (LAC >> esc)) & 01777777; } + else { + if (esc < 36) MQ = + ((fill << (36 - esc)) | (LAC >> (esc - 18))) & 0777777; + else MQ = fill; + LAC = link_init | fill; } + SC = 0; /* clear step count */ + break; case 6: /* long left shift */ - if (esc < 18) { - LAC = link_init | - (((LAC << esc) | (MQ >> (18 - esc))) & 0777777); - MQ = ((MQ << esc) | (fill >> (18 - esc))) & 0777777; } - else { if (esc < 36) LAC = link_init | - (((MQ << (esc - 18)) | (fill >> (36 - esc))) & 0777777); - else LAC = link_init | fill; - MQ = fill; } - SC = 0; /* clear step count */ - break; - case 7: /* AC left shift */ - if (esc < 18) LAC = link_init | - (((LAC << esc) | (fill >> (18 - esc))) & 0777777); + if (esc < 18) { + LAC = link_init | + (((LAC << esc) | (MQ >> (18 - esc))) & 0777777); + MQ = ((MQ << esc) | (fill >> (18 - esc))) & 0777777; } + else { + if (esc < 36) LAC = link_init | + (((MQ << (esc - 18)) | (fill >> (36 - esc))) & 0777777); else LAC = link_init | fill; - SC = 0; /* clear step count */ - break; } /* end switch IR */ + MQ = fill; } + SC = 0; /* clear step count */ + break; + case 7: /* AC left shift */ + if (esc < 18) LAC = link_init | + (((LAC << esc) | (fill >> (18 - esc))) & 0777777); + else LAC = link_init | fill; + SC = 0; /* clear step count */ + break; } /* end switch IR */ break; /* end case EAE */ /* PDP-15 index operates: opcode 72 */ @@ -1187,46 +1190,46 @@ case 035: /* index operates */ t = (IR & 0400)? IR | 0777000: IR & 0377; /* sext immediate */ switch ((IR >> 9) & 017) { /* case on IR<5:8> */ case 000: /* AAS */ - LAC = (LAC & 01000000) | ((LAC + t) & 0777777); - if (SEXT (LAC & 0777777) >= SEXT (LR)) - PC = INCR_ADDR (PC); + LAC = (LAC & 01000000) | ((LAC + t) & 0777777); + if (SEXT (LAC & 0777777) >= SEXT (LR)) + PC = INCR_ADDR (PC); case 001: /* PAX */ - XR = LAC & 0777777; - break; + XR = LAC & 0777777; + break; case 002: /* PAL */ - LR = LAC & 0777777; - break; + LR = LAC & 0777777; + break; case 003: /* AAC */ - LAC = (LAC & 01000000) | ((LAC + t) & 0777777); - break; + LAC = (LAC & 01000000) | ((LAC + t) & 0777777); + break; case 004: /* PXA */ - LAC = (LAC & 01000000) | XR; - break; + LAC = (LAC & 01000000) | XR; + break; case 005: /* AXS */ - XR = (XR + t) & 0777777; - if (SEXT (XR) >= SEXT (LR)) PC = INCR_ADDR (PC); - break; + XR = (XR + t) & 0777777; + if (SEXT (XR) >= SEXT (LR)) PC = INCR_ADDR (PC); + break; case 006: /* PXL */ - LR = XR; - break; + LR = XR; + break; case 010: /* PLA */ - LAC = (LAC & 01000000) | LR; - break; + LAC = (LAC & 01000000) | LR; + break; case 011: /* PLX */ - XR = LR; - break; + XR = LR; + break; case 014: /* CLAC */ - LAC = LAC & 01000000; - break; + LAC = LAC & 01000000; + break; case 015: /* CLX */ - XR = 0; - break; + XR = 0; + break; case 016: /* CLLR */ - LR = 0; - break; + LR = 0; + break; case 017: /* AXR */ - XR = (XR + t) & 0777777; - break; } /* end switch IR */ + XR = (XR + t) & 0777777; + break; } /* end switch IR */ break; /* end case */ #endif @@ -1267,12 +1270,12 @@ case 035: /* index operates */ case 034: /* IOT */ #if defined (PDP15) if (IR & 0010000) { /* floating point? */ -/* PC = fp15 (PC, IR); /* process */ - break; } +/* PC = fp15 (PC, IR); /* process */ + break; } #endif if (usmd) { /* user mode? */ - prvn = trap_pending = 1; /* trap */ - break; } + prvn = trap_pending = 1; /* trap */ + break; } device = (IR >> 6) & 077; /* device = IR<6:11> */ pulse = IR & 067; /* pulse = IR<12:17> */ if (IR & 0000010) LAC = LAC & 01000000; /* clear AC? */ @@ -1283,10 +1286,10 @@ case 034: /* IOT */ #if defined (PDP4) switch (device) { /* decode IR<6:11> */ case 0: /* CPU and clock */ - if (pulse == 002) ion = 0; /* IOF */ - else if (pulse == 042) ion = ion_defer = 1; /* ION */ - else iot_data = clk (pulse, iot_data); - break; + if (pulse == 002) ion = 0; /* IOF */ + else if (pulse == 042) ion = ion_defer = 1; /* ION */ + else iot_data = clk (pulse, iot_data); + break; #endif /* PDP-7 system IOT's */ @@ -1294,23 +1297,23 @@ case 034: /* IOT */ #if defined (PDP7) switch (device) { /* decode IR<6:11> */ case 0: /* CPU and clock */ - if (pulse == 002) ion = 0; /* IOF */ - else if (pulse == 042) ion = ion_defer = 1; /* ION */ - else if (pulse == 062) /* ITON */ - usmd = ion = ion_defer = 1; - else iot_data = clk (pulse, iot_data); - break; + if (pulse == 002) ion = 0; /* IOF */ + else if (pulse == 042) ion = ion_defer = 1; /* ION */ + else if (pulse == 062) /* ITON */ + usmd = ion = ion_defer = 1; + else iot_data = clk (pulse, iot_data); + break; case 033: /* CPU control */ - if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC); - else if (pulse == 002) reset_all (0); /* CAF */ - break; + if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC); + else if (pulse == 002) reset_all (0); /* CAF */ + break; case 077: /* extended memory */ - if ((pulse == 001) && memm) PC = INCR_ADDR (PC); - else if (pulse == 002) memm = 1; /* EEM */ - else if (pulse == 042) /* EMIR */ - memm = emir_pending = 1; /* ext on, restore */ - else if (pulse == 004) memm = 0; /* LEM */ - break; + if ((pulse == 001) && memm) PC = INCR_ADDR (PC); + else if (pulse == 002) memm = 1; /* EEM */ + else if (pulse == 042) /* EMIR */ + memm = emir_pending = 1; /* ext on, restore */ + else if (pulse == 004) memm = 0; /* LEM */ + break; #endif /* PDP-9 and PDP-15 system IOT's */ @@ -1319,73 +1322,73 @@ case 034: /* IOT */ ion_defer = 1; /* delay interrupts */ switch (device) { /* decode IR<6:11> */ case 000: /* CPU and clock */ - if (pulse == 002) ion = 0; /* IOF */ - else if (pulse == 042) ion = 1; /* ION */ - else iot_data = clk (pulse, iot_data); - break; + if (pulse == 002) ion = 0; /* IOF */ + else if (pulse == 042) ion = 1; /* ION */ + else iot_data = clk (pulse, iot_data); + break; case 017: /* mem protection */ - if ((pulse == 001) && prvn) PC = INCR_ADDR (PC); - else if ((pulse == 041) && nexm) PC = INCR_ADDR (PC); - else if (pulse == 002) prvn = 0; - else if (pulse == 042) usmdbuf = 1; - else if (pulse == 004) BR = LAC & BRMASK; - else if (pulse == 044) nexm = 0; - break; + if ((pulse == 001) && prvn) PC = INCR_ADDR (PC); + else if ((pulse == 041) && nexm) PC = INCR_ADDR (PC); + else if (pulse == 002) prvn = 0; + else if (pulse == 042) usmdbuf = 1; + else if (pulse == 004) BR = LAC & BRMASK; + else if (pulse == 044) nexm = 0; + break; case 032: /* power fail */ - if ((pulse == 001) && (TST_INT (PWRFL))) - PC = INCR_ADDR (PC); - break; + if ((pulse == 001) && (TST_INT (PWRFL))) + PC = INCR_ADDR (PC); + break; case 033: /* CPU control */ - if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC); - else if (pulse == 002) reset_all (0); /* CAF */ - else if (pulse == 044) rest_pending = 1; /* DBR */ - if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) { - int32 t = api_ffo[api_act & 0377]; - api_act = api_act & ~(0200 >> t); } - break; + if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC); + else if (pulse == 002) reset_all (0); /* CAF */ + else if (pulse == 044) rest_pending = 1; /* DBR */ + if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) { + int32 t = api_ffo[api_act & 0377]; + api_act = api_act & ~(0200 >> t); } + break; case 055: /* API control */ - if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst; - else if (pulse == 001) { /* SPI */ - if (((LAC & SIGN) && api_enb) || - ((LAC & 0377) > api_act)) - iot_data = iot_data | IOT_SKP; } - else if (pulse == 002) { /* RPL */ - iot_data = iot_data | (api_enb << 17) | - (api_req << 8) | api_act; } - else if (pulse == 004) { /* ISA */ - api_enb = (iot_data & SIGN)? 1: 0; - api_req = api_req | ((LAC >> 8) & 017); - api_act = api_act | (LAC & 0377); } - break; + if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst; + else if (pulse == 001) { /* SPI */ + if (((LAC & SIGN) && api_enb) || + ((LAC & 0377) > api_act)) + iot_data = iot_data | IOT_SKP; } + else if (pulse == 002) { /* RPL */ + iot_data = iot_data | (api_enb << 17) | + (api_req << 8) | api_act; } + else if (pulse == 004) { /* ISA */ + api_enb = (iot_data & SIGN)? 1: 0; + api_req = api_req | ((LAC >> 8) & 017); + api_act = api_act | (LAC & 0377); } + break; #endif #if defined (PDP9) case 077: /* extended memory */ - if ((pulse == 001) && memm) PC = INCR_ADDR (PC); - else if (pulse == 002) memm = 1; /* EEM */ - else if (pulse == 042) /* EMIR */ - memm = emir_pending = 1; /* ext on, restore */ - else if (pulse == 004) memm = 0; /* LEM */ - break; + if ((pulse == 001) && memm) PC = INCR_ADDR (PC); + else if (pulse == 002) memm = 1; /* EEM */ + else if (pulse == 042) /* EMIR */ + memm = emir_pending = 1; /* ext on, restore */ + else if (pulse == 004) memm = 0; /* LEM */ + break; #endif #if defined (PDP15) case 077: /* bank addressing */ - if ((pulse == 041) || ((pulse == 061) && memm)) - PC = INCR_ADDR (PC); /* SKP15, SBA */ - else if (pulse == 042) rest_pending = 1; /* RES */ - else if (pulse == 062) memm = 0; /* DBA */ - else if (pulse == 064) memm = 1; /* EBA */ - damask = memm? 017777: 07777; /* set dir addr mask */ - epcmask = ADDRMASK & ~damask; /* extended PC mask */ - break; + if ((pulse == 041) || ((pulse == 061) && memm)) + PC = INCR_ADDR (PC); /* SKP15, SBA */ + else if (pulse == 042) rest_pending = 1; /* RES */ + else if (pulse == 062) memm = 0; /* DBA */ + else if (pulse == 064) memm = 1; /* EBA */ + damask = memm? 017777: 07777; /* set dir addr mask */ + epcmask = ADDRMASK & ~damask; /* extended PC mask */ + break; #endif /* IOT, continued */ default: /* devices */ - if (dev_tab[device]) /* defined? */ - iot_data = dev_tab[device] (pulse, iot_data); - else reason = stop_inst; /* stop on flag */ - break; } /* end switch device */ + if (dev_tab[device]) /* defined? */ + iot_data = dev_tab[device] (pulse, iot_data); + else reason = stop_inst; /* stop on flag */ + break; } /* end switch device */ LAC = LAC | (iot_data & 0777777); if (iot_data & IOT_SKP) PC = INCR_ADDR (PC); if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON; @@ -1420,7 +1423,7 @@ if (api_enb == 0) return 0; /* off? no req */ api_req = api_req & ~0360; /* clr req<0:3> */ for (i = 0; i < API_HLVL; i++) { /* loop thru levels */ if (int_hwre[i]) /* req on level? */ - api_req = api_req | (0200 >> i); } /* set api req */ + api_req = api_req | (0200 >> i); } /* set api req */ hi = api_ffo[api_req & 0377]; /* find hi req */ if (hi < api_ffo[api_act & 0377]) return (hi + 1); return 0; diff --git a/PDP18B/pdp18b_defs.h b/PDP18B/pdp18b_defs.h index a2ce2d89..6cc81215 100644 --- a/PDP18B/pdp18b_defs.h +++ b/PDP18B/pdp18b_defs.h @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 22-Nov-02 RMS Added PDP-4 drum support 05-Oct-02 RMS Added DIB structure 25-Jul-02 RMS Added PDP-4 DECtape support 10-Feb-02 RMS Added PDP-7 DECtape support @@ -51,10 +52,11 @@ integral real time clock Type 62 line printer (Hollerith) Type 550/555 DECtape + Type 24 serial drum PDP7 32K Type 177 EAE Type 649 KSR-33 Teletype Type 148 mem extension Type 444 paper tape reader - Type 75 paper tape punch + ??KA70A bounds control Type 75 paper tape punch integral real time clock Type 647B line printer (sixbit) Type 550/555 DECtape @@ -103,6 +105,7 @@ #define KSR28 0 /* Baudot terminal */ #define TYPE62 0 /* Hollerith printer */ #define TYPE550 0 /* DECtape */ +#define DRM 0 /* drum */ #elif defined (PDP7) #define ADDRSIZE 15 #define TYPE647 0 /* sixbit printer */ diff --git a/PDP18B/pdp18b_doc.txt b/PDP18B/pdp18b_doc.txt index 9408f7cb..445c62ec 100644 --- a/PDP18B/pdp18b_doc.txt +++ b/PDP18B/pdp18b_doc.txt @@ -81,6 +81,7 @@ PDP-4 CPU PDP-4 CPU with 8KW of memory LPT Type 62 line printer (Hollerith code) CLK integral real-time clock DT Type 550/555 DECtape + DRM Type 24 serial drum PDP-7 CPU PDP-7 CPU with 32KW of memory - Type 177 extended arithmetic element (EAE) @@ -500,7 +501,7 @@ The serial drum (DRM) implements these registers: name size comments DA 9 drum address (sector number) - MA 15 current memory address + MA 16 current memory address INT 1 interrupt pending flag DONE 1 device done flag ERR 1 error flag diff --git a/PDP18B/pdp18b_drm.c b/PDP18B/pdp18b_drm.c index 1c338818..d65c2887 100644 --- a/PDP18B/pdp18b_drm.c +++ b/PDP18B/pdp18b_drm.c @@ -23,9 +23,10 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. - drm (PDP-7) Type 24 serial drum - (PDP-9) RM09 serial drum + drm (PDP-4,PDP-7) Type 24 serial drum + 05-Dec-02 RMS Updated from Type 24 documentation + 22-Nov-02 RMS Added PDP-4 support 05-Feb-02 RMS Added DIB, device number support 03-Feb-02 RMS Fixed bug in reset routine (found by Robert Alan Byer) 06-Jan-02 RMS Revised enable/disable support @@ -92,7 +93,7 @@ UNIT drm_unit = REG drm_reg[] = { { ORDATA (DA, drm_da, 9) }, - { ORDATA (MA, drm_ma, 15) }, + { ORDATA (MA, drm_ma, 16) }, { FLDATA (INT, int_hwre[API_DRM], INT_V_DRM) }, { FLDATA (DONE, int_hwre[API_DRM], INT_V_DRM) }, { FLDATA (ERR, drm_err, 0) }, @@ -118,8 +119,8 @@ DEVICE drm_dev = { int32 drm60 (int32 pulse, int32 AC) { if ((pulse & 027) == 06) { /* DRLR, DRLW */ - drm_ma = AC & ADDRMASK; /* load mem addr */ - drm_unit.FUNC = pulse & 040; } /* save function */ + drm_ma = AC & 0177777; /* load mem addr */ + drm_unit.FUNC = pulse & DRM_WRITE; } /* save function */ return AC; } @@ -135,7 +136,7 @@ if (pulse & 002) { /* DRCF */ if (pulse & 004) { /* DRSS */ drm_da = AC & DRM_SMASK; /* load sector # */ t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time); - if (t < 0) t = t + DRM_NUMWDT; /* wrap around? */ + if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */ sim_activate (&drm_unit, t * drm_time); } /* schedule op */ return AC; } @@ -150,7 +151,7 @@ if (pulse & 004) { /* DRCS */ CLR_INT (DRM); /* clear done */ drm_err = 0; /* clear error */ t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time); - if (t < 0) t = t + DRM_NUMWDT; /* wrap around? */ + if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */ sim_activate (&drm_unit, t * drm_time); } /* schedule op */ return AC; } @@ -173,13 +174,14 @@ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ da = drm_da * DRM_NUMWDS; /* compute dev addr */ for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */ if (uptr->FUNC == DRM_READ) { - if (MEM_ADDR_OK (drm_ma)) /* read, check nxm */ - M[drm_ma] = *(((int32 *) uptr->filebuf) + da); } - else { if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; - else { *(((int32 *) uptr->filebuf) + da) = M[drm_ma]; - if (da >= uptr->hwmark) - uptr->hwmark = da + 1; } } - drm_ma = (drm_ma + 1) & ADDRMASK; } /* incr mem addr */ + if (MEM_ADDR_OK (drm_ma)) /* read, check nxm */ + M[drm_ma] = *(((int32 *) uptr->filebuf) + da); } + else { + if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; + else { + *(((int32 *) uptr->filebuf) + da) = M[drm_ma]; + if (da >= uptr->hwmark) uptr->hwmark = da + 1; } } + drm_ma = (drm_ma + 1) & 0177777; } /* incr mem addr */ drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */ SET_INT (DRM); /* set done */ return SCPE_OK; diff --git a/PDP18B/pdp18b_dt.c b/PDP18B/pdp18b_dt.c index 809f1073..5a7f3956 100644 --- a/PDP18B/pdp18b_dt.c +++ b/PDP18B/pdp18b_dt.c @@ -430,9 +430,9 @@ if (((pulse & 060) == 040) && (pulse & 05)) { /* select */ if (pulse & 01) dtsa = 0; /* DTCA */ if (pulse & 02) AC = dtsa; /* DTRA!... */ if (pulse & 04) { /* DTXA */ - if ((AC & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; - if ((AC & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; - dtsa = dtsa ^ (AC & DTA_RW); } + if ((AC & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; + if ((AC & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; + dtsa = dtsa ^ (AC & DTA_RW); } if ((old_dtsa ^ dtsa) & DTA_UNIT) dt_deselect (old_dtsa); uptr = dt_dev.units + DTA_GETUNIT (dtsa); /* get unit */ fnc = DTA_GETFNC (dtsa); /* get fnc */ @@ -440,7 +440,7 @@ if (((pulse & 060) == 040) && (pulse & 05)) { /* select */ (fnc >= FNC_WMRK) || /* write mark? */ ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WPRT)) || ((fnc == FNC_WALL) && (uptr->flags & UNIT_WPRT))) - dt_seterr (uptr, DTB_SEL); /* select err */ + dt_seterr (uptr, DTB_SEL); /* select err */ else dt_newsa (dtsa); /* new func */ DT_UPDINT; return AC; } @@ -489,10 +489,10 @@ if ((pulse & 001) && (dtsb & DTB_BEF)) /* MMBF */ if (pulse & 002) { /* MMRS */ dtsb = dtsb & ~(DTB_REV | DTB_GO); /* clr rev, go */ if (uptr) { /* valid unit? */ - mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if (mot & DTS_DIR) dtsb = dtsb | DTB_REV; /* rev? set */ - if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700)) - dtsb = dtsb | DTB_GO; } /* accel? go */ + mot = DTS_GETMOT (uptr->STATE); /* get motion */ + if (mot & DTS_DIR) dtsb = dtsb | DTB_REV; /* rev? set */ + if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700)) + dtsb = dtsb | DTB_GO; } /* accel? go */ AC = (AC & ~DMASK) | dtsb; } if ((pulse & 044) == 044) { /* MMSE */ if ((dtsa ^ AC) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ @@ -507,7 +507,7 @@ else if ((pulse & 044) == 004) { /* MMLC */ (fnc >= FNC_WMRK) || /* write mark? */ ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WLK)) || ((fnc == FNC_WALL) && (uptr->flags & UNIT_WLK))) - dt_seterr (uptr, DTB_SEL); /* select err */ + dt_seterr (uptr, DTB_SEL); /* select err */ else dt_newsa (dtsa); } DT_UPDINT; return AC; @@ -584,17 +584,17 @@ if (new_mving & ~prev_mving) { /* start? */ if (prev_mving & ~new_mving) { /* stop? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, dt_dctime); } /* schedule decel */ DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ return; } if (prev_dir ^ new_dir) { /* dir chg? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, dt_dctime); } /* schedule decel */ DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ DTS_SET2ND (DTS_ACCF | new_dir, 0); /* next = accel */ DTS_SET3RD (DTS_ATSF | new_dir, new_fnc); /* next next = fnc */ @@ -656,45 +656,46 @@ case DTS_OFR: /* off reel */ case FNC_MOVE: /* move */ dt_schedez (uptr, dir); /* sched end zone */ if (dt_log & LOG_MS) printf ("[DT%d: moving %s]\n", unum, (dir? - "backward": "forward")); + "backward": "forward")); return; /* done */ case FNC_SRCH: /* search */ if (dir) newpos = DT_BLK2LN ((DT_QFEZ (uptr)? - DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; + DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; else newpos = DT_BLK2LN ((DT_QREZ (uptr)? - 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); + 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); if (dt_log & LOG_MS) printf ("[DT%d: searching %s]\n", unum, - (dir? "backward": "forward")); + (dir? "backward": "forward")); break; case FNC_WRIT: /* write */ case FNC_READ: /* read */ #if defined (TC02) /* TC02/TC15 */ if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); - break; } + if (dir) newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; + else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); + break; } relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - dt_seterr (uptr, DTB_SEL); - return; } + dt_seterr (uptr, DTB_SEL); + return; } if (dir) newpos = DT_BLK2LN (((relpos >= (DTU_LPERB (uptr) - DT_HTLIN))? - blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; + blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; else newpos = DT_BLK2LN (((relpos < DT_HTLIN)? - blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); + blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); break; #endif case FNC_RALL: /* read all */ case FNC_WALL: /* write all */ if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE; - else newpos = DT_EZLIN + (DT_WSIZE - 1); } - else { newpos = ((uptr->pos) / DT_WSIZE) * DT_WSIZE; - if (!dir) newpos = newpos + (DT_WSIZE - 1); } + if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE; + else newpos = DT_EZLIN + (DT_WSIZE - 1); } + else { + newpos = ((uptr->pos) / DT_WSIZE) * DT_WSIZE; + if (!dir) newpos = newpos + (DT_WSIZE - 1); } if ((dt_log & LOG_RA) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: read all block %d %s%s\n", - unum, blk, (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); + printf ("[DT%d: read all block %d %s%s\n", + unum, blk, (dir? "backward": "forward"), + ((dtsa & DTA_MODE)? " continuous]": "]")); break; default: dt_seterr (uptr, DTB_SEL); /* bad state */ @@ -759,7 +760,7 @@ if (((int32) uptr->pos < 0) || uptr->STATE = uptr->pos = 0; unum = uptr - dt_dev.units; if (unum == DTA_GETUNIT (dtsa)) /* if selected, */ - dt_seterr (uptr, DTB_SEL); /* error */ + dt_seterr (uptr, DTB_SEL); /* error */ return TRUE; } return FALSE; } @@ -789,9 +790,9 @@ t_addr ba; switch (mot) { case DTS_DECF: case DTS_DECR: /* decelerating */ if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ + uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ + sim_activate (uptr, dt_actime); /* must be reversing */ return SCPE_OK; case DTS_ACCF: case DTS_ACCR: /* accelerating */ dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ @@ -829,8 +830,8 @@ case DTS_OFR: /* off reel */ #if defined (TC02) /* TC02/TC15 */ case FNC_SRCH: /* search */ if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* inc WC */ ma = M[DT_CA] & ADDRMASK; /* get mem addr */ @@ -856,34 +857,35 @@ case FNC_READ: /* read */ wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ switch (dt_substate) { /* case on substate */ case DTO_SOB: /* start of block */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: reading block %d %s%s\n", - unum, blk, (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - dt_substate = 0; /* fall through */ + if (dtsb & DTB_DTF) { /* DTF set? */ + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } + if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) + printf ("[DT%d: reading block %d %s%s\n", + unum, blk, (dir? "backward": "forward"), + ((dtsa & DTA_MODE)? " continuous]": "]")); + dt_substate = 0; /* fall through */ case 0: /* normal read */ - M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & DMASK; - ma = M[DT_CA] & ADDRMASK; /* mem addr */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - dtdb = bptr[ba]; /* get tape word */ - if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ - if (MEM_ADDR_OK (ma)) M[ma] = dtdb; /* mem addr legal? */ - if (M[DT_WC] == 0) dt_substate = DTO_WCO; /* wc ovf? */ + M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ + M[DT_CA] = (M[DT_CA] + 1) & DMASK; + ma = M[DT_CA] & ADDRMASK; /* mem addr */ + ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ + dtdb = bptr[ba]; /* get tape word */ + if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ + if (MEM_ADDR_OK (ma)) M[ma] = dtdb; /* mem addr legal? */ + if (M[DT_WC] == 0) dt_substate = DTO_WCO; /* wc ovf? */ case DTO_WCO: /* wc ovf, not sob */ - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else { dt_substate = dt_substate | DTO_SOB; - sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; } /* set DTF */ + if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ + sim_activate (uptr, DT_WSIZE * dt_ltime); + else { + dt_substate = dt_substate | DTO_SOB; + sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); + if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) + dtsb = dtsb | DTB_DTF; } /* set DTF */ break; case DTO_WCO | DTO_SOB: /* next block */ if (wrd == (dir? 0: DTU_BSIZE (uptr))) /* end of block? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ + dt_seterr (uptr, DTB_TIM); /* timing error */ else sim_activate (uptr, DT_WSIZE * dt_ltime); break; } break; @@ -904,31 +906,32 @@ case FNC_WRIT: /* write */ wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ switch (dt_substate) { /* case on substate */ case DTO_SOB: /* start block */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: writing block %d %s%s\n", unum, blk, - (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - dt_substate = 0; /* fall through */ + if (dtsb & DTB_DTF) { /* DTF set? */ + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } + if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) + printf ("[DT%d: writing block %d %s%s\n", unum, blk, + (dir? "backward": "forward"), + ((dtsa & DTA_MODE)? " continuous]": "]")); + dt_substate = 0; /* fall through */ case 0: /* normal write */ - M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & DMASK; + M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ + M[DT_CA] = (M[DT_CA] + 1) & DMASK; case DTO_WCO: /* wc ovflo */ - ma = M[DT_CA] & ADDRMASK; /* mem addr */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - dtdb = dt_substate? 0: M[ma]; /* get word */ - if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ - bptr[ba] = dtdb; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else { dt_substate = dt_substate | DTO_SOB; - sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; } /* set DTF */ + ma = M[DT_CA] & ADDRMASK; /* mem addr */ + ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ + dtdb = dt_substate? 0: M[ma]; /* get word */ + if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ + bptr[ba] = dtdb; /* write word */ + if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; + if (M[DT_WC] == 0) dt_substate = DTO_WCO; + if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ + sim_activate (uptr, DT_WSIZE * dt_ltime); + else { + dt_substate = dt_substate | DTO_SOB; + sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); + if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) + dtsb = dtsb | DTB_DTF; } /* set DTF */ break; case DTO_WCO | DTO_SOB: /* all done */ dt_schedez (uptr, dir); /* sched end zone */ @@ -944,29 +947,29 @@ case FNC_WRIT: /* write */ case FNC_RALL: switch (dt_substate) { /* case on substate */ case 0: case DTO_SOB: /* read in progress */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & DMASK; - ma = M[DT_CA] & ADDRMASK; /* mem addr */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - dtdb = bptr[ba]; } /* get tape word */ - else dtdb = dt_gethdr (uptr, blk, relpos); /* get hdr */ - if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - if (MEM_ADDR_OK (ma)) M[ma] = dtdb; /* mem addr legal? */ - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ + if (dtsb & DTB_DTF) { /* DTF set? */ + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } + relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ + M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ + M[DT_CA] = (M[DT_CA] + 1) & DMASK; + ma = M[DT_CA] & ADDRMASK; /* mem addr */ + if ((relpos >= DT_HTLIN) && /* in data zone? */ + (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { + wrd = DT_LIN2WD (uptr->pos, uptr); + ba = (blk * DTU_BSIZE (uptr)) + wrd; + dtdb = bptr[ba]; } /* get tape word */ + else dtdb = dt_gethdr (uptr, blk, relpos); /* get hdr */ + if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ + sim_activate (uptr, DT_WSIZE * dt_ltime); + if (MEM_ADDR_OK (ma)) M[ma] = dtdb; /* mem addr legal? */ + if (M[DT_WC] == 0) dt_substate = DTO_WCO; + if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) + dtsb = dtsb | DTB_DTF; /* set DTF */ break; case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ + dt_schedez (uptr, dir); /* sched end zone */ + break; } /* end case substate */ break; /* Write all has two subcases @@ -978,30 +981,30 @@ case FNC_RALL: case FNC_WALL: switch (dt_substate) { /* case on substate */ case 0: case DTO_SOB: /* read in progress */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & DMASK; - ma = M[DT_CA] & ADDRMASK; /* mem addr */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - dtdb = M[ma]; /* get mem word */ - if (dir) dtdb = dt_comobv (dtdb); - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - bptr[ba] = dtdb; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } + if (dtsb & DTB_DTF) { /* DTF set? */ + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } + relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ + M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ + M[DT_CA] = (M[DT_CA] + 1) & DMASK; + ma = M[DT_CA] & ADDRMASK; /* mem addr */ + if ((relpos >= DT_HTLIN) && /* in data zone? */ + (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { + dtdb = M[ma]; /* get mem word */ + if (dir) dtdb = dt_comobv (dtdb); + wrd = DT_LIN2WD (uptr->pos, uptr); + ba = (blk * DTU_BSIZE (uptr)) + wrd; + bptr[ba] = dtdb; /* write word */ + if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } /* /* ignore hdr */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; + sim_activate (uptr, DT_WSIZE * dt_ltime); + if (M[DT_WC] == 0) dt_substate = DTO_WCO; + if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) + dtsb = dtsb | DTB_DTF; /* set DTF */ + break; case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ + dt_schedez (uptr, dir); /* sched end zone */ + break; } /* end case substate */ break; /* Type 550 service */ @@ -1010,8 +1013,8 @@ case FNC_WALL: #else /* Type 550 */ case FNC_SRCH: /* search */ if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ dtdb = blk; /* store block # */ dtsb = dtsb | DTB_DTF; /* set DTF */ @@ -1021,27 +1024,28 @@ case FNC_SRCH: /* search */ case FNC_READ: case FNC_RALL: if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } sim_activate (uptr, DT_WSIZE * dt_ltime); /* sched next word */ relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - dtdb = bptr[ba]; /* get tape word */ - dtsb = dtsb | DTB_DTF; } /* set flag */ - else { ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1; - wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ - if ((wrd == 0) || /* skip 1st, last */ - (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; - if ((fnc == FNC_READ) && /* read, skip if not */ - (wrd != DT_CSMWD) && /* fwd, rev cksum */ - (wrd != ma)) break; - dtdb = dt_gethdr (uptr, blk, relpos); - if (wrd == (dir? DT_CSMWD: ma)) /* at end csum? */ - dtsb = dtsb | DTB_BEF; /* end block */ - else dtsb = dtsb | DTB_DTF; } /* else next word */ + wrd = DT_LIN2WD (uptr->pos, uptr); + ba = (blk * DTU_BSIZE (uptr)) + wrd; + dtdb = bptr[ba]; /* get tape word */ + dtsb = dtsb | DTB_DTF; } /* set flag */ + else { + ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1; + wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ + if ((wrd == 0) || /* skip 1st, last */ + (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; + if ((fnc == FNC_READ) && /* read, skip if not */ + (wrd != DT_CSMWD) && /* fwd, rev cksum */ + (wrd != ma)) break; + dtdb = dt_gethdr (uptr, blk, relpos); + if (wrd == (dir? DT_CSMWD: ma)) /* at end csum? */ + dtsb = dtsb | DTB_BEF; /* end block */ + else dtsb = dtsb | DTB_DTF; } /* else next word */ if (dir) dtdb = dt_comobv (dtdb); break; @@ -1049,27 +1053,28 @@ case FNC_READ: case FNC_RALL: case FNC_WRIT: case FNC_WALL: if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } sim_activate (uptr, DT_WSIZE * dt_ltime); /* sched next word */ relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - if (dir) bptr[ba] = dt_comobv (dtdb); /* get data word */ - else bptr[ba] = dtdb; - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1)) - dtsb = dtsb | DTB_BEF; /* end block */ - else dtsb = dtsb | DTB_DTF; } /* else next word */ - else { wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ - if ((wrd == 0) || /* skip 1st, last */ - (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; - if ((fnc == FNC_WRIT) && /* wr, skip if !csm */ - (wrd != ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1))) - break; - dtsb = dtsb | DTB_DTF; } /* set flag */ + wrd = DT_LIN2WD (uptr->pos, uptr); + ba = (blk * DTU_BSIZE (uptr)) + wrd; + if (dir) bptr[ba] = dt_comobv (dtdb); /* get data word */ + else bptr[ba] = dtdb; + if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; + if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1)) + dtsb = dtsb | DTB_BEF; /* end block */ + else dtsb = dtsb | DTB_DTF; } /* else next word */ + else { + wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ + if ((wrd == 0) || /* skip 1st, last */ + (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; + if ((fnc == FNC_WRIT) && /* wr, skip if !csm */ + (wrd != ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1))) + break; + dtsb = dtsb | DTB_DTF; } /* set flag */ break; #endif @@ -1176,16 +1181,17 @@ UNIT *uptr; for (i = 0; i < DT_NUMDR; i++) { /* stop all drives */ uptr = dt_dev.units + i; if (sim_is_running) { /* CAF? */ - prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ - if (dt_setpos (uptr)) continue; /* update pos */ - sim_cancel (uptr); - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); - } } - else { sim_cancel (uptr); /* sim reset */ - uptr->STATE = 0; - uptr->LASTT = sim_grtime (); } } + prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ + if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ + if (dt_setpos (uptr)) continue; /* update pos */ + sim_cancel (uptr); + sim_activate (uptr, dt_dctime); /* sched decel */ + DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); + } } + else { + sim_cancel (uptr); /* sim reset */ + uptr->STATE = 0; + uptr->LASTT = sim_grtime (); } } dtsa = dtsb = 0; /* clear status */ DT_UPDINT; /* reset interrupt */ return SCPE_OK; @@ -1292,8 +1298,8 @@ if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; if (sim_is_active (uptr)) { sim_cancel (uptr); if ((unum == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) { - dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF; - DT_UPDINT; } + dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF; + DT_UPDINT; } uptr->STATE = uptr->pos = 0; } bptr = uptr->filebuf; /* file buffer */ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ diff --git a/PDP18B/pdp18b_lp.c b/PDP18B/pdp18b_lp.c index 15d6f356..bb23db34 100644 --- a/PDP18B/pdp18b_lp.c +++ b/PDP18B/pdp18b_lp.c @@ -154,22 +154,22 @@ static const char *lpt_cc[] = { if (lpt_iot & 020) { /* space? */ SET_INT (LPTSPC); /* set flag */ if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); + return IORETURN (lpt_stopioe, SCPE_UNATT); fputs (lpt_cc[lpt_iot & 07], lpt_unit.fileref); /* print cctl */ if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } + perror ("LPT I/O error"); + clearerr (lpt_unit.fileref); + return SCPE_IOERR; } lpt_iot = 0; } /* clear state */ else { SET_INT (LPT); /* print */ if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); + return IORETURN (lpt_stopioe, SCPE_UNATT); if (lpt_iot & 010) fputc ('\r', lpt_unit.fileref); fputs (lpt_buf, lpt_unit.fileref); /* print buffer */ if (ferror (lpt_unit.fileref)) { /* test error */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } + perror ("LPT I/O error"); + clearerr (lpt_unit.fileref); + return SCPE_IOERR; } bptr = 0; for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ lpt_iot = 010; } /* set state */ @@ -253,33 +253,33 @@ if (pulse & 002) { /* pulse 02 */ lpt_done = 0; /* clear done */ CLR_INT (LPT); /* clear int req */ if (subp == 0) { /* LPCB */ - for (i = 0; i < LPT_BSIZE; i++) lpt_buf[i] = 0; - bptr = 0; /* reset buf ptr */ - lpt_done = 1; /* set done */ - if (lpt_ie) SET_INT (LPT); } } /* set int */ + for (i = 0; i < LPT_BSIZE; i++) lpt_buf[i] = 0; + bptr = 0; /* reset buf ptr */ + lpt_done = 1; /* set done */ + if (lpt_ie) SET_INT (LPT); } } /* set int */ if (pulse & 004) { /* LPDI */ switch (subp) { /* case on subcode */ case 0: /* LPDI */ #if defined (PDP9) - lpt_ie = 0; /* clear int enable */ - CLR_INT (LPT); /* clear int req */ + lpt_ie = 0; /* clear int enable */ + CLR_INT (LPT); /* clear int req */ #endif - break; + break; case 2: /* LPB3 */ - if (bptr < LPT_BSIZE) { - lpt_buf[bptr] = lpt_buf[bptr] | ((AC >> 12) & 077); - bptr = bptr + 1; } + if (bptr < LPT_BSIZE) { + lpt_buf[bptr] = lpt_buf[bptr] | ((AC >> 12) & 077); + bptr = bptr + 1; } case 1: /* LPB2 */ - if (bptr < LPT_BSIZE) { - lpt_buf[bptr] = lpt_buf[bptr] | ((AC >> 6) & 077); - bptr = bptr + 1; } + if (bptr < LPT_BSIZE) { + lpt_buf[bptr] = lpt_buf[bptr] | ((AC >> 6) & 077); + bptr = bptr + 1; } case 3: /* LPB1 */ - if (bptr < LPT_BSIZE) { - lpt_buf[bptr] = lpt_buf[bptr] | (AC & 077); - bptr = bptr + 1; } - lpt_done = 1; /* set done */ - if (lpt_ie) SET_INT (LPT); /* set int */ - break; } /* end case */ + if (bptr < LPT_BSIZE) { + lpt_buf[bptr] = lpt_buf[bptr] | (AC & 077); + bptr = bptr + 1; } + lpt_done = 1; /* set done */ + if (lpt_ie) SET_INT (LPT); /* set int */ + break; } /* end case */ } /* end if pulse 4 */ return AC; } @@ -293,12 +293,12 @@ if (pulse & 002) { /* LPCF */ if (pulse & 004) { int32 subp = (pulse >> 4) & 03; /* get subpulse */ if (subp < 3) { /* LPLS, LPPB, LPPS */ - lpt_iot = (pulse & 060) | (AC & 07); /* save parameters */ - sim_activate (&lpt_unit, lpt_unit.wait); } /* activate */ + lpt_iot = (pulse & 060) | (AC & 07); /* save parameters */ + sim_activate (&lpt_unit, lpt_unit.wait); } /* activate */ #if defined (PDP9) else { /* LPEI */ - lpt_ie = 1; /* set int enable */ - if (lpt_done) SET_INT (LPT); } + lpt_ie = 1; /* set int enable */ + if (lpt_done) SET_INT (LPT); } #endif } /* end if pulse 4 */ return AC; @@ -332,22 +332,22 @@ if ((lpt_unit.flags & UNIT_ATT) == 0) { /* not attached? */ return IORETURN (lpt_stopioe, SCPE_UNATT); } if ((lpt_iot & 020) == 0) { /* print? */ for (i = 0; i < bptr; i++) /* translate buffer */ - pbuf[i] = lpt_buf[i] | ((lpt_buf[i] >= 040)? 0: 0100); + pbuf[i] = lpt_buf[i] | ((lpt_buf[i] >= 040)? 0: 0100); if ((lpt_iot & 060) == 0) pbuf[bptr++] = '\r'; for (i = 0; i < LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ fwrite (pbuf, 1, bptr, lpt_unit.fileref); /* print buffer */ if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - bptr = 0; - return SCPE_IOERR; } + perror ("LPT I/O error"); + clearerr (lpt_unit.fileref); + bptr = 0; + return SCPE_IOERR; } bptr = 0; } /* clear buffer ptr */ if (lpt_iot & 060) { /* space? */ fputs (lpt_cc[lpt_iot & 07], lpt_unit.fileref); /* write cctl */ if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } } + perror ("LPT I/O error"); + clearerr (lpt_unit.fileref); + return SCPE_IOERR; } } lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ return SCPE_OK; } @@ -505,29 +505,31 @@ for (more = 1; more != 0; ) { /* loop until ctrl */ w1 = M[(M[LPT_CA] + 2) & ADDRMASK]; /* get second word */ M[LPT_CA] = (M[LPT_CA] + 2) & 0777777; /* advance mem addr */ if (mode) { /* unpacked? */ - c[0] = w0 & 0177; - c[1] = w1 & 0177; - ccnt = 2; } - else { c[0] = (w0 >> 11) & 0177; /* packed */ - c[1] = (w0 >> 4) & 0177; - c[2] = (((w0 << 3) | (w1 >> 15))) & 0177; - c[3] = (w1 >> 8) & 0177; - c[4] = (w1 >> 1) & 0177; - ccnt = 5; } + c[0] = w0 & 0177; + c[1] = w1 & 0177; + ccnt = 2; } + else { + c[0] = (w0 >> 11) & 0177; /* packed */ + c[1] = (w0 >> 4) & 0177; + c[2] = (((w0 << 3) | (w1 >> 15))) & 0177; + c[3] = (w1 >> 8) & 0177; + c[4] = (w1 >> 1) & 0177; + ccnt = 5; } for (i = 0; i < ccnt; i++) { /* loop through */ - if ((c[i] <= 037) && ctrl[c[i]]) { /* control char? */ - fwrite (lpt_buf, 1, bptr, lpt_unit.fileref); - fputs (ctrl[c[i]], lpt_unit.fileref); - if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - bptr = 0; - lpt_updsta (STA_DON | STA_ALM); - return SCPE_IOERR; } - lpt_unit.pos = ftell (lpt_unit.fileref); - bptr = more = 0; } - else { if (bptr < LPT_BSIZE) lpt_buf[bptr++] = c[i]; - else lpt_sta = lpt_sta | STA_OVF; } } } + if ((c[i] <= 037) && ctrl[c[i]]) { /* control char? */ + fwrite (lpt_buf, 1, bptr, lpt_unit.fileref); + fputs (ctrl[c[i]], lpt_unit.fileref); + if (ferror (lpt_unit.fileref)) { /* error? */ + perror ("LPT I/O error"); + clearerr (lpt_unit.fileref); + bptr = 0; + lpt_updsta (STA_DON | STA_ALM); + return SCPE_IOERR; } + lpt_unit.pos = ftell (lpt_unit.fileref); + bptr = more = 0; } + else { + if (bptr < LPT_BSIZE) lpt_buf[bptr++] = c[i]; + else lpt_sta = lpt_sta | STA_OVF; } } } lcnt = lcnt - 1; /* decr line count */ if (lcnt) sim_activate (&lpt_unit, lpt_unit.wait); /* more to do? */ diff --git a/PDP18B/pdp18b_mt.c b/PDP18B/pdp18b_mt.c index 66d4daa2..060c8630 100644 --- a/PDP18B/pdp18b_mt.c +++ b/PDP18B/pdp18b_mt.c @@ -216,10 +216,11 @@ if (pulse == 004) { /* MTGO */ (((f == FN_SPACER) || (f == FN_REWIND)) & (uptr->USTAT & STA_BOT)) || (((f == FN_WRITE) || (f == FN_WREOF)) && (uptr->flags & UNIT_WPRT)) || ((uptr->flags & UNIT_ATT) == 0) || (f == FN_NOP)) - mt_sta = mt_sta | STA_ILL; /* illegal op flag */ - else { if (f == FN_REWIND) uptr->USTAT = STA_REW; /* rewind? */ - else mt_sta = uptr->USTAT = 0; /* no, clear status */ - sim_activate (uptr, mt_time); } } /* start io */ + mt_sta = mt_sta | STA_ILL; /* illegal op flag */ + else { + if (f == FN_REWIND) uptr->USTAT = STA_REW; /* rewind? */ + else mt_sta = uptr->USTAT = 0; /* no, clear status */ + sim_activate (uptr, mt_time); } } /* start io */ mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ return AC; } @@ -257,8 +258,8 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ if ((f == FN_WRITE) || (f == FN_WREOF)) { /* write? */ if (uptr->flags & UNIT_WPRT) { /* write locked? */ - mt_updcsta (uptr, STA_ILL); /* illegal operation */ - return SCPE_OK; } + mt_updcsta (uptr, STA_ILL); /* illegal operation */ + return SCPE_OK; } mt_cu = mt_cu & ~CU_ERASE; } /* clear erase flag */ switch (f) { /* case on function */ @@ -268,39 +269,40 @@ switch (f) { /* case on function */ case FN_READ: /* read */ case FN_CMPARE: /* read/compare */ if (mt_rdlntf (uptr, &tbc, &err)) { /* read rec lnt, err? */ - mt_updcsta (uptr, STA_RLE); /* set RLE flag */ - break; } + mt_updcsta (uptr, STA_RLE); /* set RLE flag */ + break; } if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */ wc = DBSIZE - (M[MT_WC] & DBMASK); /* get word count */ cbc = PACKED (mt_cu)? wc * 3: wc * 2; /* expected bc */ if (tbc != cbc) mt_sta = mt_sta | STA_RLE; /* wrong size? */ if (tbc < cbc) { /* record small? */ - cbc = tbc; /* use smaller */ - wc = PACKED (mt_cu)? ((tbc + 2) / 3): ((tbc + 1) / 2); } + cbc = tbc; /* use smaller */ + wc = PACKED (mt_cu)? ((tbc + 2) / 3): ((tbc + 1) / 2); } abc = fxread (dbuf, sizeof (int8), cbc, uptr->fileref); if (err = ferror (uptr->fileref)) { /* error */ - MT_SET_PNU (uptr); /* pos not upd */ - break; } + MT_SET_PNU (uptr); /* pos not upd */ + break; } for ( ; abc < cbc; abc++) dbuf[abc] = 0; /* fill with 0's */ for (i = p = 0; i < wc; i++) { /* copy buffer */ - M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */ - M[MT_CA] = (M[MT_CA] + 1) & 0777777; - xma = M[MT_CA] & ADDRMASK; - if (PACKED (mt_cu)) { /* packed? */ - c1 = dbuf[p++] & 077; - c2 = dbuf[p++] & 077; - c3 = dbuf[p++] & 077; - c = (c1 << 12) | (c2 << 6) | c3; } - else { c1 = dbuf[p++]; - c2 = dbuf[p++]; - c = (c1 << 8) | c2; } - if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c; - else if ((f == FN_CMPARE) && (c != (M[xma] & - (PACKED (mt_cu)? 0777777: 0177777)))) { - mt_updcsta (uptr, STA_CPE); - break; } } + M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */ + M[MT_CA] = (M[MT_CA] + 1) & 0777777; + xma = M[MT_CA] & ADDRMASK; + if (PACKED (mt_cu)) { /* packed? */ + c1 = dbuf[p++] & 077; + c2 = dbuf[p++] & 077; + c3 = dbuf[p++] & 077; + c = (c1 << 12) | (c2 << 6) | c3; } + else { + c1 = dbuf[p++]; + c2 = dbuf[p++]; + c = (c1 << 8) | c2; } + if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c; + else if ((f == FN_CMPARE) && (c != (M[xma] & + (PACKED (mt_cu)? 0777777: 0177777)))) { + mt_updcsta (uptr, STA_CPE); + break; } } uptr->pos = uptr->pos + ((tbc + 1) & ~1) + - (2 * sizeof (t_mtrlnt)); + (2 * sizeof (t_mtrlnt)); break; case FN_WRITE: /* write */ @@ -309,15 +311,16 @@ case FN_WRITE: /* write */ tbc = PACKED (mt_cu)? wc * 3: wc * 2; fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref); for (i = p = 0; i < wc; i++) { /* copy buf to tape */ - M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */ - M[MT_CA] = (M[MT_CA] + 1) & 0777777; - xma = M[MT_CA] & ADDRMASK; - if (PACKED (mt_cu)) { /* packed? */ - dbuf[p++] = (M[xma] >> 12) & 077; - dbuf[p++] = (M[xma] >> 6) & 077; - dbuf[p++] = M[xma] & 077; } - else { dbuf[p++] = (M[xma] >> 8) & 0377; - dbuf[p++] = M[xma] & 0377; } } + M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */ + M[MT_CA] = (M[MT_CA] + 1) & 0777777; + xma = M[MT_CA] & ADDRMASK; + if (PACKED (mt_cu)) { /* packed? */ + dbuf[p++] = (M[xma] >> 12) & 077; + dbuf[p++] = (M[xma] >> 6) & 077; + dbuf[p++] = M[xma] & 077; } + else { + dbuf[p++] = (M[xma] >> 8) & 0377; + dbuf[p++] = M[xma] & 0377; } } fxwrite (dbuf, sizeof (char), (tbc + 1) & ~1, uptr->fileref); fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref); if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */ @@ -336,17 +339,20 @@ case FN_WREOF: break; case FN_SPACEF: /* space forward */ - do { if (mt_rdlntf (uptr, &tbc, &err)) break;/* read rec lnt, err? */ - uptr->pos = uptr->pos + ((tbc + 1) & ~1) + - (2 * sizeof (t_mtrlnt)); } + do { + if (mt_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */ + uptr->pos = uptr->pos + ((tbc + 1) & ~1) + + (2 * sizeof (t_mtrlnt)); } while ((M[MT_WC] = (M[MT_WC] + 1) & 0777777) != 0); break; case FN_SPACER: /* space reverse */ - do { if (pnu) pnu = 0; /* pos not upd? */ - else { if (mt_rdlntf (uptr, &tbc, &err)) break; - uptr->pos = uptr->pos - ((tbc + 1) & ~1) - - (2 * sizeof (t_mtrlnt)); } } + do { + if (pnu) pnu = 0; /* pos not upd? */ + else { + if (mt_rdlntf (uptr, &tbc, &err)) break; + uptr->pos = uptr->pos - ((tbc + 1) & ~1) - + (2 * sizeof (t_mtrlnt)); } } while ((M[MT_WC] = (M[MT_WC] + 1) & 0777777) != 0); break; } /* end case */ diff --git a/PDP18B/pdp18b_rf.c b/PDP18B/pdp18b_rf.c index beef0729..2d180954 100644 --- a/PDP18B/pdp18b_rf.c +++ b/PDP18B/pdp18b_rf.c @@ -182,9 +182,9 @@ if (pulse == 064) { /* DLAH */ if ((pulse & 064) == 044) { /* DSCN */ if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */ else if (GET_FNC (rf_sta) != FN_NOP) { - t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new */ - if (t < 0) t = t + RF_NUMWD; /* wrap around? */ - sim_activate (&rf_unit, t * rf_time); } } /* schedule op */ + t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new */ + if (t < 0) t = t + RF_NUMWD; /* wrap around? */ + sim_activate (&rf_unit, t * rf_time); } } /* schedule op */ rf_updsta (0); /* update status */ return AC; } @@ -220,25 +220,25 @@ f = GET_FNC (rf_sta); /* get function */ do { M[RF_WC] = (M[RF_WC] + 1) & 0777777; /* incr word count */ pa = M[RF_CA] = (M[RF_CA] + 1) & ADDRMASK; /* incr mem addr */ if ((f == FN_READ) && MEM_ADDR_OK (pa)) /* read? */ - M[pa] = *(((int32 *) uptr->filebuf) + rf_da); + M[pa] = *(((int32 *) uptr->filebuf) + rf_da); if ((f == FN_WCHK) && /* write check? */ (M[pa] != *(((int32 *) uptr->filebuf) + rf_da))) { - rf_updsta (RFS_WCE); /* flag error */ - break; } + rf_updsta (RFS_WCE); /* flag error */ + break; } if (f == FN_WRITE) { /* write? */ - d = (rf_da >> 18) & 07; /* disk */ - t = (rf_da >> 14) & 017; /* track groups */ - if ((rf_wlk[d] >> t) & 1) { /* write locked? */ - rf_updsta (RFS_WLO); - break; } - else { *(((int32 *) uptr->filebuf) + rf_da) = M[pa]; - if (((t_addr) rf_da) >= uptr->hwmark) - uptr->hwmark = rf_da + 1; } } + d = (rf_da >> 18) & 07; /* disk */ + t = (rf_da >> 14) & 017; /* track groups */ + if ((rf_wlk[d] >> t) & 1) { /* write locked? */ + rf_updsta (RFS_WLO); + break; } + else { + *(((int32 *) uptr->filebuf) + rf_da) = M[pa]; + if (((t_addr) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1; } } rf_da = rf_da + 1; /* incr disk addr */ if (rf_da > RF_SIZE) { /* disk overflow? */ - rf_da = 0; - rf_updsta (RFS_NED); /* nx disk error */ - break; } } + rf_da = 0; + rf_updsta (RFS_NED); /* nx disk error */ + break; } } while ((M[RF_WC] != 0) && (rf_burst != 0)); /* brk if wc, no brst */ if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0)) /* more to do? */ diff --git a/PDP18B/pdp18b_rp.c b/PDP18B/pdp18b_rp.c index 721d9b64..d00fc07a 100644 --- a/PDP18B/pdp18b_rp.c +++ b/PDP18B/pdp18b_rp.c @@ -226,7 +226,7 @@ if (pulse == 004) { /* DPLA */ if (pulse == 024) { /* DPCS */ rp_sta = rp_sta & ~(STA_HNF | STA_DON); rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE | - STB_TME | STB_PGE | STB_EOP); + STB_TME | STB_PGE | STB_EOP); rp_updsta (0, 0); } if (pulse == 044) rp_ma = AC; /* DPCA */ if (pulse == 064) rp_wc = AC; /* DPWC */ @@ -261,13 +261,14 @@ if (rp_sta & STA_GO) { rp_busy = 1; /* set ctrl busy */ rp_sta = rp_sta & ~(STA_HNF | STA_DON); /* clear flags */ rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE | - STB_TME | STB_PGE | STB_EOP | (1 << (STB_V_ATT0 - u))); + STB_TME | STB_PGE | STB_EOP | (1 << (STB_V_ATT0 - u))); if (((uptr->flags & UNIT_ATT) == 0) || (f == FN_IDLE) || (f == FN_SEEK) || (f == FN_RECAL)) - sim_activate (uptr, RP_MIN); /* short delay */ - else { c = GET_CYL (rp_da); - c = abs (c - uptr->CYL) * rp_swait; /* seek time */ - sim_activate (uptr, MAX (RP_MIN, c + rp_rwait)); } } + sim_activate (uptr, RP_MIN); /* short delay */ + else { + c = GET_CYL (rp_da); + c = abs (c - uptr->CYL) * rp_swait; /* seek time */ + sim_activate (uptr, MAX (RP_MIN, c + rp_rwait)); } } rp_updsta (0, 0); return AC; } @@ -346,14 +347,14 @@ if ((f == FN_WRITE) && (err == 0)) { /* write? */ fxwrite (&M[pa], sizeof (int32), wc, uptr->fileref); err = ferror (uptr->fileref); if ((err == 0) && (i = (wc & (RP_NUMWD - 1)))) { - fxwrite (fill, sizeof (int), i, uptr->fileref); - err = ferror (uptr->fileref); } } + fxwrite (fill, sizeof (int), i, uptr->fileref); + err = ferror (uptr->fileref); } } if ((f == FN_WRCHK) && (err == 0)) { /* write check? */ for (i = 0; (err == 0) && (i < wc); i++) { - awc = fxread (&comp, sizeof (int32), 1, uptr->fileref); - if (awc == 0) comp = 0; - if (comp != M[pa + i]) rp_updsta (0, STB_WCE); } + awc = fxread (&comp, sizeof (int32), 1, uptr->fileref); + if (awc == 0) comp = 0; + if (comp != M[pa + i]) rp_updsta (0, STB_WCE); } err = ferror (uptr->fileref); } rp_wc = (rp_wc + wc) & 0777777; /* final word count */ @@ -389,7 +390,7 @@ if ((uptr->flags & UNIT_ATT) == 0) rp_stb = rp_stb | STB_SUFU | STB_SUNR; else if (sim_is_active (uptr)) { f = (uptr->FUNC) & STA_M_FUNC; if ((f == FN_SEEK) || (f == FN_RECAL)) - rp_stb = rp_stb | STB_SUSU | STB_SUNR; } + rp_stb = rp_stb | STB_SUSU | STB_SUNR; } else if (uptr->CYL >= RP_NUMCY) rp_sta = rp_sta | STA_SUSI; if ((rp_sta & STA_EFLGS) || (rp_stb & STB_EFLGS)) rp_sta = rp_sta | STA_ERR; if (((rp_sta & (STA_ERR | STA_DON)) && (rp_sta & STA_IED)) || diff --git a/PDP18B/pdp18b_stddev.c b/PDP18B/pdp18b_stddev.c index 30364897..0522181f 100644 --- a/PDP18B/pdp18b_stddev.c +++ b/PDP18B/pdp18b_stddev.c @@ -29,6 +29,7 @@ tto teleprinter clk clock + 22-Dec-02 RMS Added break support 01-Nov-02 RMS Added 7B/8B support to terminal 05-Oct-02 RMS Added DIBs, device number support, IORS call 14-Jul-02 RMS Added ASCII reader/punch support (from Hans Pufal) @@ -350,11 +351,11 @@ if (pulse & 001) { /* CLSF */ if (TST_INT (CLK)) AC = AC | IOT_SKP; } if (pulse & 004) { /* CLON/CLOF */ if (pulse & 040) { /* CLON */ - CLR_INT (CLK); /* clear flag */ - clk_state = 1; /* clock on */ - if (!sim_is_active (&clk_unit)) /* already on? */ - sim_activate (&clk_unit, /* start, calibr */ - sim_rtc_init (clk_unit.wait)); } + CLR_INT (CLK); /* clear flag */ + clk_state = 1; /* clock on */ + if (!sim_is_active (&clk_unit)) /* already on? */ + sim_activate (&clk_unit, /* start, calibr */ + sim_rtc_init (clk_unit.wait)); } else clk_reset (&clk_dev); } /* CLOF */ return AC; } @@ -427,8 +428,8 @@ if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ ptr_err = 1; #endif if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } + if (ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; } else perror ("PTR I/O error"); clearerr (ptr_unit.fileref); return SCPE_IOERR; } @@ -671,7 +672,7 @@ if (pulse & 002) CLR_INT (PTP); /* PCF */ if (pulse & 004) { /* PSA, PSB, PLS */ CLR_INT (PTP); /* clear flag */ ptp_unit.buf = (pulse & 040)? /* load punch buf */ - (AC & 077) | 0200: AC & 0377; /* bin or alpha */ + (AC & 077) | 0200: AC & 0377; /* bin or alpha */ sim_activate (&ptp_unit, ptp_unit.wait); } /* activate unit */ return AC; } @@ -687,7 +688,7 @@ if ((ptp_unit.flags & UNIT_ATT) == 0) { /* not attached? */ if (ptp_unit.flags & UNIT_PASCII) { /* ASCII mode? */ ptp_unit.buf = ptp_unit.buf & 0177; /* force 7b */ if ((ptp_unit.buf == 0) || (ptp_unit.buf == 0177)) - return SCPE_OK; } /* skip null, del */ + return SCPE_OK; } /* skip null, del */ if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* I/O error? */ ptp_err = 1; /* set error */ perror ("PTP I/O error"); @@ -771,9 +772,10 @@ else { if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; if (c == 0) return SCPE_OK; /* untranslatable? */ if (((c & TTI_FIGURES) == (tti_state & TTI_FIGURES)) || (c & TTI_BOTH)) tti_unit.buf = c & TTI_MASK; - else { tti_unit.buf = (c & TTI_FIGURES)? - BAUDOT_FIGURES: BAUDOT_LETTERS; - tti_state = c | TTI_2ND; } } /* set 2nd waiting */ + else { + tti_unit.buf = (c & TTI_FIGURES)? + BAUDOT_FIGURES: BAUDOT_LETTERS; + tti_state = c | TTI_2ND; } } /* set 2nd waiting */ #else /* ASCII... */ int32 c, out; @@ -781,11 +783,12 @@ int32 c, out; sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ out = c & 0177; /* mask echo to 7b */ -if (tti_unit.flags & UNIT_KSR) { /* KSR? */ +if (c & SCPE_BREAK) c = 0; /* break? */ +else if (tti_unit.flags & UNIT_KSR) { /* KSR? */ if (islower (out)) out = toupper (out); /* convert to UC */ c = out | 0200; } /* set TTY bit */ else c = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); /* no, 7b/8b */ -if ((tti_unit.flags & UNIT_HDX) && /* half duplex and */ +if ((tti_unit.flags & UNIT_HDX) && out && /* half duplex and */ (!(tto_unit.flags & UNIT_KSR) || /* 7b/8b or */ ((out >= 007) && (out <= 0137)))) { /* in range? */ sim_putchar (out); /* echo */ diff --git a/PDP18B/pdp18b_sys.c b/PDP18B/pdp18b_sys.c index 2f386b72..d88eba15 100644 --- a/PDP18B/pdp18b_sys.c +++ b/PDP18B/pdp18b_sys.c @@ -136,9 +136,9 @@ int32 word, bits, st, ch; word = st = bits = 0; do { if ((ch = getc (fileref)) == EOF) return -1; if (ch & 0200) { - word = (word << 6) | (ch & 077); - bits = (bits << 1) | ((ch >> 6) & 1); - st++; } } + word = (word << 6) | (ch & 077); + bits = (bits << 1) | ((ch >> 6) & 1); + st++; } } while (st < 3); if (hi != NULL) *hi = bits; return word; @@ -165,12 +165,12 @@ if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; for (;;) { if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; if ((val & 0760000) == 0040000) { /* DAC? */ - origin = val & 017777; - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; - if (MEM_ADDR_OK (origin)) M[origin++] = val; } + origin = val & 017777; + if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; + if (MEM_ADDR_OK (origin)) M[origin++] = val; } else if ((val & 0760000) == OP_JMP) { /* JMP? */ - saved_PC = ((origin - 1) & 060000) | (val & 017777); - return SCPE_OK; } + saved_PC = ((origin - 1) & 060000) | (val & 017777); + return SCPE_OK; } else if (val == OP_HLT) return SCPE_OK; /* HLT? */ else return SCPE_FMT; } /* error */ return SCPE_FMT; /* error */ @@ -211,20 +211,20 @@ extern t_bool match_ext (char *fnm, char *ext); if ((sim_switches & SWMASK ('R')) || /* RIM format? */ (match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B')))) { if (*cptr != 0) { /* more input? */ - cptr = get_glyph (cptr, gbuf, 0); /* get origin */ - origin = get_uint (gbuf, 8, ADDRMASK, &r); - if (r != SCPE_OK) return r; - if (*cptr != 0) return SCPE_ARG; } /* no more */ + cptr = get_glyph (cptr, gbuf, 0); /* get origin */ + origin = get_uint (gbuf, 8, ADDRMASK, &r); + if (r != SCPE_OK) return r; + if (*cptr != 0) return SCPE_ARG; } /* no more */ else origin = 0200; /* default 200 */ for (;;) { /* word loop */ - if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT; - if (bits & 1) { /* end of tape? */ - if ((val & 0760000) == OP_JMP) saved_PC = - ((origin - 1) & 060000) | (val & 017777); - else if (val != OP_HLT) return SCPE_FMT; - break; } - else if (MEM_ADDR_OK (origin)) M[origin++] = val; } + if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT; + if (bits & 1) { /* end of tape? */ + if ((val & 0760000) == OP_JMP) saved_PC = + ((origin - 1) & 060000) | (val & 017777); + else if (val != OP_HLT) return SCPE_FMT; + break; } + else if (MEM_ADDR_OK (origin)) M[origin++] = val; } return SCPE_OK; } /* Binary loader */ @@ -236,8 +236,8 @@ if (val == EOF) rewind (fileref); /* no RIM? rewind */ for (;;) { /* block loop */ if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; if (val & SIGN) { - if (val != DMASK) saved_PC = val & 077777; - break; } + if (val != DMASK) saved_PC = val & 077777; + break; } cksum = origin = val; /* save origin */ if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; cksum = cksum + val; /* add to cksum */ @@ -245,9 +245,9 @@ for (;;) { /* block loop */ if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; cksum = cksum + val; /* add to cksum */ for (i = 0; i < count; i++) { - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; - cksum = cksum + val; - if (MEM_ADDR_OK (origin)) M[origin++] = val; } + if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; + cksum = cksum + val; + if (MEM_ADDR_OK (origin)) M[origin++] = val; } if ((cksum & DMASK) != 0) return SCPE_CSUM; } return SCPE_OK; } @@ -607,9 +607,9 @@ int32 i, j; for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ if ((j == class) && (opc_val[i] & inst)) { /* same class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } + inst = inst & ~opc_val[i]; /* mask bit set? */ + fprintf (of, (sp? " %s": "%s"), opcode[i]); + sp = 1; } } return sp; } @@ -665,58 +665,57 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ switch (j) { /* case on class */ case I_V_NPN: /* no operands */ case I_V_XR: /* index no opers */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; + fprintf (of, "%s", opcode[i]); /* opcode */ + break; case I_V_NPI: /* IOT no operand */ - fprintf (of, "%s", opcode[i]); /* opcode */ - if (inst & 010) fprintf (of, " +10"); - break; + fprintf (of, "%s", opcode[i]); /* opcode */ + if (inst & 010) fprintf (of, " +10"); + break; case I_V_IOT: /* IOT or EAE */ - fprintf (of, "%s %-o", opcode[i], inst & 037777); - break; + fprintf (of, "%s %-o", opcode[i], inst & 037777); + break; case I_V_MRF: /* mem ref */ #if defined (PDP15) - if (memm) { - disp = inst & 017777; - ma = (addr & 0760000) | disp; } - else { disp = inst & 007777; - ma = (addr & 0770000) | disp; } - fprintf (of, "%s %-o", opcode[i], - (cflag? ma & ADDRMASK: disp)); - if (!memm && (inst & 0010000)) fprintf (of, ",X"); + if (memm) { + disp = inst & 017777; + ma = (addr & 0760000) | disp; } + else { + disp = inst & 007777; + ma = (addr & 0770000) | disp; } + fprintf (of, "%s %-o", opcode[i], (cflag? ma & ADDRMASK: disp)); + if (!memm && (inst & 0010000)) fprintf (of, ",X"); #else - disp = inst & 017777; - ma = (addr & 0760000) | disp; - fprintf (of, "%s %-o", opcode[i], - (cflag? ma & ADDRMASK: disp)); + disp = inst & 017777; + ma = (addr & 0760000) | disp; + fprintf (of, "%s %-o", opcode[i], (cflag? ma & ADDRMASK: disp)); #endif break; case I_V_OPR: /* operate */ - if (sp = (inst & 03730)) fprintf (of, "%s", opcode[i]); - fprint_opr (of, inst & 014047, I_V_OPR, sp); - break; + if (sp = (inst & 03730)) fprintf (of, "%s", opcode[i]); + fprint_opr (of, inst & 014047, I_V_OPR, sp); + break; case I_V_LAW: /* LAW */ - fprintf (of, "%s %-o", opcode[i], inst & 017777); - break; + fprintf (of, "%s %-o", opcode[i], inst & 017777); + break; case I_V_XR9: /* index with lit */ - disp = inst & 0777; - if (disp & 0400) fprintf (of, "%s -%-o", opcode[i], 01000 - disp); - else fprintf (of, "%s %-o", opcode[i], disp); - break; + disp = inst & 0777; + if (disp & 0400) fprintf (of, "%s -%-o", opcode[i], 01000 - disp); + else fprintf (of, "%s %-o", opcode[i], disp); + break; case I_V_EST: /* EAE setup */ - fprint_opr (of, inst & 037007, I_V_EST, 0); - break; + fprint_opr (of, inst & 037007, I_V_EST, 0); + break; case I_V_ESH: /* EAE shift */ - sp = fprint_opr (of, inst & 017000, I_V_EST, 0); - fprintf (of, (sp? " %s %-o": "%s %-o"), opcode[i], inst & 077); - break; + sp = fprint_opr (of, inst & 017000, I_V_EST, 0); + fprintf (of, (sp? " %s %-o": "%s %-o"), opcode[i], inst & 077); + break; case I_V_EMD: /* EAE mul-div */ - disp = inst & 077; /* get actual val */ - k = (opc_val[i] >> I_V_DC) & 077; /* get default val */ - if (disp == k) fprintf (of, "%s", opcode[i]); - else if (disp < k) fprintf (of, "%s -%-o", opcode[i], k - disp); - else fprintf (of, "%s +%-o", opcode[i], disp - k); - break; } /* end case */ + disp = inst & 077; /* get actual val */ + k = (opc_val[i] >> I_V_DC) & 077; /* get default val */ + if (disp == k) fprintf (of, "%s", opcode[i]); + else if (disp < k) fprintf (of, "%s -%-o", opcode[i], k - disp); + else fprintf (of, "%s +%-o", opcode[i], disp - k); + break; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; @@ -804,7 +803,7 @@ case I_V_XR9: /* index literal */ d = get_sint (gbuf, &sign, &r); if (r != SCPE_OK) return SCPE_ARG; if (((sign >= 0) && (d > 0377)) || ((sign < 0) && (d > 0400))) - return SCPE_ARG; + return SCPE_ARG; val[0] = val[0] | ((sign >= 0)? d: (01000 - d)); break; case I_V_LAW: /* law */ @@ -824,22 +823,22 @@ case I_V_MRF: /* mem ref */ #endif #if defined (PDP4) || defined (PDP7) if (strcmp (gbuf, "I") == 0) { /* indirect? */ - val[0] = val[0] | 020000; - cptr = get_glyph (cptr, gbuf, 0); } + val[0] = val[0] | 020000; + cptr = get_glyph (cptr, gbuf, 0); } #endif epcmask = ADDRMASK & ~dmask; /* get ePC */ d = get_uint (gbuf, 8, ADDRMASK, &r); /* get addr */ if (r != SCPE_OK) return SCPE_ARG; if (d <= dmask) val[0] = val[0] | d; /* fit in 12/13b? */ else if (cflag && (((addr ^ d) & epcmask) == 0)) - val[0] = val[0] | (d & dmask); /* hi bits = ePC? */ + val[0] = val[0] | (d & dmask); /* hi bits = ePC? */ else return SCPE_ARG; #if defined (PDP15) if (!memm) { - cptr = get_glyph (cptr, gbuf, 0); - if (gbuf[0] != 0) { - if (strcmp (gbuf, "X") != 0) return SCPE_ARG; - val[0] = val[0] | 010000; } } + cptr = get_glyph (cptr, gbuf, 0); + if (gbuf[0] != 0) { + if (strcmp (gbuf, "X") != 0) return SCPE_ARG; + val[0] = val[0] | 010000; } } #endif break; case I_V_EMD: /* or'able */ @@ -848,17 +847,18 @@ case I_V_EST: case I_V_ESH: case I_V_NPN: case I_V_NPI: case I_V_IOT: case I_V_OPR: for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && + for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; - if (opcode[i] != NULL) { - k = opc_val[i] & DMASK; - if (((k ^ val[0]) & 0740000) != 0) return SCPE_ARG; - val[0] = val[0] | k; } - else { d = get_sint (gbuf, & sign, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (sign > 0) val[0] = val[0] + d; - else if (sign < 0) val[0] = val[0] - d; - else val[0] = val[0] | d; } } + if (opcode[i] != NULL) { + k = opc_val[i] & DMASK; + if (((k ^ val[0]) & 0740000) != 0) return SCPE_ARG; + val[0] = val[0] | k; } + else { + d = get_sint (gbuf, & sign, &r); + if (r != SCPE_OK) return SCPE_ARG; + if (sign > 0) val[0] = val[0] + d; + else if (sign < 0) val[0] = val[0] - d; + else val[0] = val[0] | d; } } break; } /* end case */ if (*cptr != 0) return SCPE_ARG; /* junk at end? */ return SCPE_OK; diff --git a/PDP18B/pdp18b_tt1.c b/PDP18B/pdp18b_tt1.c index 7544d558..49e33321 100644 --- a/PDP18B/pdp18b_tt1.c +++ b/PDP18B/pdp18b_tt1.c @@ -26,6 +26,7 @@ tti1 keyboard tto1 teleprinter + 22-Dec-02 RMS Added break support 02-Nov-02 RMS Added 7B/8B support 05-Oct-02 RMS Added DIB, device number support 22-Aug-02 RMS Updated for changes to sim_tmxr @@ -167,11 +168,12 @@ int32 c, newln; if (tt1_ldsc.conn) { /* connected? */ tmxr_poll_rx (&tt_desc); /* poll for input */ if (c = tmxr_getc_ln (&tt1_ldsc)) { /* get char */ - if (uptr->flags & UNIT_KSR) { /* KSR? */ + if (c & SCPE_BREAK) uptr->buf = 0; /* break? */ + else if (uptr->flags & UNIT_KSR) { /* KSR? */ c = c & 0177; if (islower (c)) c = toupper (c); uptr->buf = c | 0200; } /* got char */ - else c = c & ((tti1_unit.flags & UNIT_8B)? 0377: 0177); + else uptr->buf = c & ((tti1_unit.flags & UNIT_8B)? 0377: 0177); SET_INT (TTI1); } /* set flag */ sim_activate (uptr, uptr->wait); } /* continue poll */ if (uptr->flags & UNIT_ATT) { /* attached? */ @@ -306,4 +308,4 @@ t_stat tt1_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) tti1_unit.flags = (tti1_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; tto1_unit.flags = (tto1_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; return SCPE_OK; -} \ No newline at end of file +} diff --git a/PDP1o/pdp1_cpu.c b/PDP1o/pdp1_cpu.c deleted file mode 100644 index aadb48a2..00000000 --- a/PDP1o/pdp1_cpu.c +++ /dev/null @@ -1,795 +0,0 @@ -/* pdp1_cpu.c: PDP-1 CPU simulator - - Copyright (c) 1993-2002, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - cpu PDP-1 central processor - - 06-Oct-02 RMS Revised for V2.10 - 20-Aug-02 RMS Added DECtape support - 30-Dec-01 RMS Added old PC queue - 07-Dec-01 RMS Revised to use breakpoint package - 30-Nov-01 RMS Added extended SET/SHOW support - 16-Dec-00 RMS Fixed bug in XCT address calculation - 14-Apr-99 RMS Changed t_addr to unsigned - - The PDP-1 was Digital's first computer. Although Digital built four - other 18b computers, the later systems (the PDP-4, PDP-7, PDP-9, and - PDP-15) were similar to each other and quite different from the PDP-1. - Accordingly, the PDP-1 requires a distinct simulator. - - The register state for the PDP-1 is: - - AC<0:17> accumulator - IO<0:17> IO register - OV overflow flag - PC<0:15> program counter - IOSTA I/O status register - SBS<0:2> sequence break flip flops - IOH I/O halt flip flop - IOC I/O completion flip flop - EXTM extend mode - PF<1:6> program flags - SS<1:6> sense switches - TW<0:17> test word (switch register) - - Questions: - - cks: which bits are line printer print done and space done? - cks: is there a bit for sequence break enabled (yes, according - to the 1963 Handbook) - sbs: do sequence breaks accumulate while the system is disabled - (yes, according to the Maintenance Manual) -*/ - -/* The PDP-1 has six instruction formats: memory reference, skips, - shifts, load immediate, I/O transfer, and operate. The memory - reference format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op |in| address | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:4> <5> mnemonic action - - 00 - 02 AND AC = AC & M[MA] - 04 IOR AC = AC | M[MA] - 06 XOR AC = AC ^ M[MA] - 10 XCT M[MA] is executed as an instruction - 12 - 14 - 16 0 CAL M[100] = AC, AC = PC, PC = 101 - 16 1 JDA M[MA] = AC, AC = PC, PC = MA + 1 - 20 LAC AC = M[MA] - 22 LIO IO = M[MA] - 24 DAC M[MA] = AC - 26 DAP M[MA]<6:17> = AC<6:17> - 30 DIP M[MA]<0:5> = AC<0:5> - 32 DIO M[MA] = IO - 34 DZM M[MA] = 0 - 36 - 40 ADD AC = AC + M[MA] - 42 SUB AC = AC - M[MA] - 44 IDX AC = M[MA] = M[MA] + 1 - 46 ISP AC = M[MA] = M[MA] + 1, skip if AC >= 0 - 50 SAD skip if AC != M[MA] - 52 SAS skip if AC == M[MA] - 54 MUL AC'IO = AC * M[MA] - 56 DIV AC, IO = AC'IO / M[MA] - 60 JMP PC = MA - 62 JSP AC = PC, PC = MA - - Memory reference instructions can access an address space of 64K words. - The address space is divided into sixteen 4K word fields. An - instruction can directly address, via its 12b address, the entire - current field. If extend mode is off, indirect addresses access - the current field, and indirect addressing is multi-level; if off, - they can access all 64K, and indirect addressing is single level. -*/ - -/* The skip format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 0 1 0| | | | | | | | | | | | | | skip - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | \______/ \______/ - | | | | | | | | - | | | | | | | +---- program flags - | | | | | | +------------- sense switches - | | | | | +------------------- AC == 0 - | | | | +---------------------- AC >= 0 - | | | +------------------------- AC < 0 - | | +---------------------------- OV == 0 - | +------------------------------- IO >= 0 - +------------------------------------- invert skip - - The shift format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 0 1 1| subopcode | encoded count | shift - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The load immediate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 0 0| S| immediate | LAW - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:4> mnemonic action - - 70 LAW if S = 0, AC = IR<6:17> - else AC = ~IR<6:17> -*/ - -/* The I/O transfer format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 0 1| W| C| subopcode | device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The IO transfer instruction sends the the specified subopcode to - specified I/O device. The I/O device may take data from the IO or - return data to the IO, initiate or cancel operations, etc. The - W bit specifies whether the CPU waits for completion, the C bit - whether a completion pulse will be returned from the device. - - The operate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 1 1 1| | | | | | | | | | | | | | operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | \______/ - | | | | | | | | - | | | | | | | +---- PF select - | | | | | | +---------- clear/set PF - | | | | | +------------------- or PC - | | | | +---------------------- clear AC - | | | +------------------------- halt - | | +---------------------------- CMA - | +------------------------------- or TW - +---------------------------------- clear IO - - The operate instruction can be microprogrammed. -*/ - -/* This routine is the instruction decode routine for the PDP-1. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - breakpoint encountered - unimplemented instruction and STOP_INST flag set - XCT loop - indirect address loop - infinite wait state - I/O error in I/O simulator - - 2. Interrupts. With a single channel sequence break system, the - PDP-1 has a single break request (flop b2, here sbs). - If sequence breaks are enabled (flop sbm, here sbs), - and one is not already in progress (flop b4, here sbs), - a sequence break occurs. - - 3. Arithmetic. The PDP-1 is a 1's complement system. In 1's - complement arithmetic, a negative number is represented by the - complement (XOR 0777777) of its absolute value. Addition of 1's - complement numbers requires propagating the carry out of the high - order bit back to the low order bit. - - 4. Adding I/O devices. Three modules must be modified: - - pdp1_defs.h add interrupt request definition - pdp1_cpu.c add IOT dispatch code - pdp1_sys.c add sim_devices table entry -*/ - -#include "pdp1_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC -#define UNIT_V_MDV (UNIT_V_UF + 0) /* mul/div */ -#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */ -#define UNIT_MDV (1 << UNIT_V_MDV) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -int32 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 AC = 0; /* AC */ -int32 IO = 0; /* IO */ -int32 PC = 0; /* PC */ -int32 OV = 0; /* overflow */ -int32 SS = 0; /* sense switches */ -int32 PF = 0; /* program flags */ -int32 TW = 0; /* test word */ -int32 iosta = 0; /* status reg */ -int32 sbs = 0; /* sequence break */ -int32 sbs_init = 0; /* seq break startup */ -int32 ioh = 0; /* I/O halt */ -int32 ioc = 0; /* I/O completion */ -int32 extm = 0; /* ext mem mode */ -int32 extm_init = 0; /* ext mem startup */ -int32 stop_inst = 0; /* stop on rsrv inst */ -int32 xct_max = 16; /* nested XCT limit */ -int32 ind_max = 16; /* nested ind limit */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ - -extern UNIT *sim_clock_queue; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -extern int32 ptr (int32 inst, int32 dev, int32 IO); -extern int32 ptp (int32 inst, int32 dev, int32 IO); -extern int32 tti (int32 inst, int32 dev, int32 IO); -extern int32 tto (int32 inst, int32 dev, int32 IO); -extern int32 lpt (int32 inst, int32 dev, int32 IO); -extern int32 dt (int32 inst, int32 dev, int32 IO); - -int32 sc_map[512] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, /* 00000xxxx */ - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 00001xxxx */ - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 00010xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 00011xxxx */ - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 00100xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 00101xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 00110xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 00111xxxx */ - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 01000xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 01001xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 01010xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 01011xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 01100xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 01101xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 01110xxxx */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, /* 01111xxxx */ - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 10000xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 10001xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 10010xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 10011xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 10100xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 10101xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 10110xxxx */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, /* 11011xxxx */ - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 11000xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 11001xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 11010xxxx */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, /* 11011xxxx */ - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 11100xxxx */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, /* 11101xxxx */ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, /* 11110xxxx */ - 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9 /* 11111xxxx */ -}; - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, PC, ASIZE) }, - { ORDATA (AC, AC, 18) }, - { ORDATA (IO, IO, 18) }, - { FLDATA (OV, OV, 0) }, - { ORDATA (PF, PF, 6) }, - { ORDATA (SS, SS, 6) }, - { ORDATA (TW, TW, 18) }, - { FLDATA (EXTM, extm, 0) }, - { ORDATA (IOSTA, iosta, 18), REG_RO }, - { FLDATA (SBON, sbs, SB_V_ON) }, - { FLDATA (SBRQ, sbs, SB_V_RQ) }, - { FLDATA (SBIP, sbs, SB_V_IP) }, - { FLDATA (IOH, ioh, 0) }, - { FLDATA (IOC, ioc, 0) }, - { BRDATA (PCQ, pcq, 8, ASIZE, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { FLDATA (SBS_INIT, sbs_init, SB_V_ON) }, - { FLDATA (EXTM_INIT, extm_init, 0) }, - { DRDATA (XCT_MAX, xct_max, 8), PV_LEFT + REG_NZ }, - { DRDATA (IND_MAX, ind_max, 8), PV_LEFT + REG_NZ }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_MDV, UNIT_MDV, "multiply/divide", "MDV", NULL }, - { UNIT_MDV, 0, "no multiply/divide", "NOMDV", NULL }, - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size }, - { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, ASIZE, 1, 8, 18, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - NULL, 0 }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -int32 IR, MA, op, i, t, xct_count; -int32 sign, signd, v; -int32 dev, io_data, sc, skip; -t_stat reason; -static int32 fs_test[8] = { - 0, 040, 020, 010, 04, 02, 01, 077 }; - -#define EPC_WORD ((OV << 17) | (extm << 16) | PC) -#define INCR_ADDR(x) (((x) & EPCMASK) | (((x) + 1) & DAMASK)) -#define DECR_ADDR(x) (((x) & EPCMASK) | (((x) - 1) & DAMASK)) -#define ABS(x) ((x) ^ (((x) & 0400000)? 0777777: 0)) - -/* Main instruction fetch/decode loop: check events and interrupts */ - -reason = 0; -while (reason == 0) { /* loop until halted */ - -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (sbs == (SB_ON | SB_RQ)) { /* interrupt? */ - sbs = SB_ON | SB_IP; /* set in prog flag */ - PCQ_ENTRY; /* save old PC */ - M[0] = AC; /* save state */ - M[1] = EPC_WORD; - M[2] = IO; - PC = 3; /* fetch next from 3 */ - extm = 0; /* extend off */ - OV = 0; } /* clear overflow */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -/* Fetch, decode instruction */ - -MA = PC; /* PC to MA */ -IR = M[MA]; /* fetch instruction */ -PC = INCR_ADDR (PC); /* increment PC */ -xct_count = 0; /* track nested XCT's */ -sim_interval = sim_interval - 1; - -xct_instr: /* label for XCT */ -if ((IR == 0610001) && ((MA & EPCMASK) == 0) && (sbs & SB_ON)) { - sbs = sbs & ~SB_IP; /* seq debreak */ - PCQ_ENTRY; /* save old PC */ - OV = (M[1] >> 17) & 1; /* restore OV */ - extm = (M[1] >> 16) & 1; /* restore ext mode */ - PC = M[1] & AMASK; /* JMP I 1 */ - continue; } - -op = ((IR >> 13) & 037); /* get opcode */ -if ((op < 032) && (op != 007)) { /* mem ref instr */ - MA = (MA & EPCMASK) | (IR & DAMASK); /* direct address */ - if (IR & IA) { /* indirect addr? */ - if (extm) MA = M[MA] & AMASK; /* if ext, one level */ - else { for (i = 0; i < ind_max; i++) { /* count indirects */ - t = M[MA]; /* get indirect word */ - MA = (MA & EPCMASK) | (t & DAMASK); - if ((t & IA) == 0) break; } - if (i >= ind_max) { /* indirect loop? */ - reason = STOP_IND; - break; } } } } - -switch (op) { /* decode IR<0:4> */ - -/* Logical, load, store instructions */ - -case 001: /* AND */ - AC = AC & M[MA]; - break; -case 002: /* IOR */ - AC = AC | M[MA]; - break; -case 003: /* XOR */ - AC = AC ^ M[MA]; - break; -case 004: /* XCT */ - if (xct_count >= xct_max) { /* too many XCT's? */ - reason = STOP_XCT; - break; } - xct_count = xct_count + 1; /* count XCT's */ - IR = M[MA]; /* get instruction */ - goto xct_instr; /* go execute */ -case 007: /* CAL, JDA */ - MA = (PC & EPCMASK) | ((IR & IA)? (IR & DAMASK): 0100); - PCQ_ENTRY; - M[MA] = AC; - AC = EPC_WORD; - PC = INCR_ADDR (MA); - break; -case 010: /* LAC */ - AC = M[MA]; - break; -case 011: /* LIO */ - IO = M[MA]; - break; -case 012: /* DAC */ - if (MEM_ADDR_OK (MA)) M[MA] = AC; - break; -case 013: /* DAP */ - if (MEM_ADDR_OK (MA)) M[MA] = (AC & DAMASK) | (M[MA] & ~DAMASK); - break; -case 014: /* DIP */ - if (MEM_ADDR_OK (MA)) M[MA] = (AC & ~DAMASK) | (M[MA] & DAMASK); - break; -case 015: /* DIO */ - if (MEM_ADDR_OK (MA)) M[MA] = IO; - break; -case 016: /* DZM */ - if (MEM_ADDR_OK (MA)) M[MA] = 0; - break; - -/* Add, subtract, control - - Add is performed in sequential steps, as follows: - 1. add - 2. end around carry propagate - 3. overflow check - 4. -0 cleanup - - Subtract is performed in sequential steps, as follows: - 1. complement AC - 2. add - 3. end around carry propagate - 4. overflow check - 5. complement AC - Because no -0 check is done, (-0) - (+0) yields a result of -0 -*/ - -case 020: /* ADD */ - t = AC; - AC = AC + M[MA]; - if (AC > 0777777) AC = (AC + 1) & 0777777; /* end around carry */ - if (((~t ^ M[MA]) & (t ^ AC)) & 0400000) OV = 1; - if (AC == 0777777) AC = 0; /* minus 0 cleanup */ - break; -case 021: /* SUB */ - t = AC ^ 0777777; /* complement AC */ - AC = t + M[MA]; /* -AC + MB */ - if (AC > 0777777) AC = (AC + 1) & 0777777; /* end around carry */ - if (((~t ^ M[MA]) & (t ^ AC)) & 0400000) OV = 1; - AC = AC ^ 0777777; /* recomplement AC */ - break; -case 022: /* IDX */ - AC = M[MA] + 1; - if (AC >= 0777777) AC = (AC + 1) & 0777777; - if (MEM_ADDR_OK (MA)) M[MA] = AC; - break; -case 023: /* ISP */ - AC = M[MA] + 1; - if (AC >= 0777777) AC = (AC + 1) & 0777777; - if (MEM_ADDR_OK (MA)) M[MA] = AC; - if (AC < 0400000) PC = INCR_ADDR (PC); - break; -case 024: /* SAD */ - if (AC != M[MA]) PC = INCR_ADDR (PC); - break; -case 025: /* SAS */ - if (AC == M[MA]) PC = INCR_ADDR (PC); - break; -case 030: /* JMP */ - PCQ_ENTRY; - PC = MA; - break; -case 031: /* JSP */ - AC = EPC_WORD; - PCQ_ENTRY; - PC = MA; - break; -case 034: /* LAW */ - AC = (IR & 07777) ^ ((IR & IA)? 0777777: 0); - break; - -/* Multiply and divide - - Multiply and divide step and hardware multiply are exact implementations. - Hardware divide is a 2's complement analog to the actual hardware. -*/ - -case 026: /* MUL */ - if (cpu_unit.flags & UNIT_MDV) { /* hardware? */ - sign = AC ^ M[MA]; /* result sign */ - IO = ABS (AC); /* IO = |AC| */ - v = ABS (M[MA]); /* v = |mpy| */ - for (i = AC = 0; i < 17; i++) { - if (IO & 1) AC = AC + v; - IO = (IO >> 1) | ((AC & 1) << 17); - AC = AC >> 1; } - if ((sign & 0400000) && (AC | IO)) { /* negative, > 0? */ - AC = AC ^ 0777777; - IO = IO ^ 0777777; } } - else { if (IO & 1) AC = AC + M[MA]; /* multiply step */ - if (AC > 0777777) AC = (AC + 1) & 0777777; - if (AC == 0777777) AC = 0; - IO = (IO >> 1) | ((AC & 1) << 17); - AC = AC >> 1; } - break; - -case 027: /* DIV */ - if (cpu_unit.flags & UNIT_MDV) { /* hardware */ - sign = AC ^ M[MA]; /* result sign */ - signd = AC; /* remainder sign */ - if (AC & 0400000) { - AC = AC ^ 0777777; /* AC'IO = |AC'IO| */ - IO = IO ^ 0777777; } - v = ABS (M[MA]); /* v = |divr| */ - if (AC >= v) break; /* overflow? */ - for (i = t = 0; i < 18; i++) { - if (t) AC = (AC + v) & 0777777; - else AC = (AC - v) & 0777777; - t = AC >> 17; - if (i != 17) AC = ((AC << 1) | (IO >> 17)) & 0777777; - IO = ((IO << 1) | (t ^ 1)) & 0777777; } - if (t) AC = (AC + v) & 0777777; /* correct remainder */ - t = ((signd & 0400000) && AC)? AC ^ 0777777: AC; - AC = ((sign & 0400000) && IO)? IO ^ 0777777: IO; - IO = t; - PC = INCR_ADDR (PC); } /* skip */ - else { t = AC >> 17; /* divide step */ - AC = ((AC << 1) | (IO >> 17)) & 0777777; - IO = ((IO << 1) | (t ^ 1)) & 0777777; - if (IO & 1) AC = AC + (M[MA] ^ 0777777); - else AC = AC + M[MA] + 1; - if (AC > 0777777) AC = (AC + 1) & 0777777; - if (AC == 0777777) AC = 0; } - break; - -/* Skip and operate - - Operates execute in the order shown; there are no timing conflicts -*/ - -case 032: /* skip */ - v = (IR >> 3) & 07; /* sense switches */ - t = IR & 07; /* program flags */ - skip = (((IR & 02000) && (IO < 0400000)) || /* SPI */ - ((IR & 01000) && (OV == 0)) || /* SZO */ - ((IR & 00400) && (AC >= 0400000)) || /* SMA */ - ((IR & 00200) && (AC < 0400000)) || /* SPA */ - ((IR & 00100) && (AC == 0)) || /* SZA */ - (v && ((SS & fs_test[v]) == 0)) || /* SZSn */ - (t && ((PF & fs_test[t]) == 0))); /* SZFn */ - if (IR & IA) skip = skip ^ 1; /* invert skip? */ - if (skip) PC = INCR_ADDR (PC); - if (IR & 01000) OV = 0; /* SOV clears OV */ - break; - -case 037: /* operate */ - if (IR & 04000) IO = 0; /* CLI */ - if (IR & 00200) AC = 0; /* CLA */ - if (IR & 02000) AC = AC | TW; /* LAT */ - if (IR & 00100) AC = AC | EPC_WORD; /* LAP */ - if (IR & 01000) AC = AC ^ 0777777; /* CMA */ - if (IR & 00400) reason = STOP_HALT; /* HALT */ - t = IR & 07; /* flag select */ - if (IR & 010) PF = PF | fs_test[t]; /* STFn */ - else PF = PF & ~fs_test[t]; /* CLFn */ - break; - -/* Shifts */ - -case 033: - sc = sc_map[IR & 0777]; /* map shift count */ - switch ((IR >> 9) & 017) { /* case on IR<5:8> */ - case 001: /* RAL */ - AC = ((AC << sc) | (AC >> (18 - sc))) & 0777777; - break; - case 002: /* RIL */ - IO = ((IO << sc) | (IO >> (18 - sc))) & 0777777; - break; - case 003: /* RCL */ - t = AC; - AC = ((AC << sc) | (IO >> (18 - sc))) & 0777777; - IO = ((IO << sc) | (t >> (18 - sc))) & 0777777; - break; - case 005: /* SAL */ - t = (AC & 0400000)? 0777777: 0; - AC = (AC & 0400000) | ((AC << sc) & 0377777) | - (t >> (18 - sc)); - break; - case 006: /* SIL */ - t = (IO & 0400000)? 0777777: 0; - IO = (IO & 0400000) | ((IO << sc) & 0377777) | - (t >> (18 - sc)); - break; - case 007: /* SCL */ - t = (AC & 0400000)? 0777777: 0; - AC = (AC & 0400000) | ((AC << sc) & 0377777) | - (IO >> (18 - sc)); - IO = ((IO << sc) | (t >> (18 - sc))) & 0777777; - break; - case 011: /* RAR */ - AC = ((AC >> sc) | (AC << (18 - sc))) & 0777777; - break; - case 012: /* RIR */ - IO = ((IO >> sc) | (IO << (18 - sc))) & 0777777; - break; - case 013: /* RCR */ - t = IO; - IO = ((IO >> sc) | (AC << (18 - sc))) & 0777777; - AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; - break; - case 015: /* SAR */ - t = (AC & 0400000)? 0777777: 0; - AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; - break; - case 016: /* SIR */ - t = (IO & 0400000)? 0777777: 0; - IO = ((IO >> sc) | (t << (18 - sc))) & 0777777; - break; - case 017: /* SCR */ - t = (AC & 0400000)? 0777777: 0; - IO = ((IO >> sc) | (AC << (18 - sc))) & 0777777; - AC = ((AC >> sc) | (t << (18 - sc))) & 0777777; - break; - default: /* undefined */ - reason = stop_inst; - break; } /* end switch shifts */ - break; - -/* IOT */ - -case 035: - if (IR & IO_WAIT) { /* wait? */ - if (ioh) { /* I/O halt? */ - if (ioc) ioh = 0; /* comp pulse? done */ - else { sim_interval = 0; /* force event */ - PC = DECR_ADDR (PC); } /* re-execute */ - break; } /* skip iot */ - ioh = 1; /* turn on halt */ - PC = DECR_ADDR (PC); } /* re-execute */ - dev = IR & 077; /* get dev addr */ - io_data = IO; /* default data */ - switch (dev) { /* case on dev */ - case 000: /* I/O wait */ - break; - case 001: - if (IR & 003700) io_data = dt (IR, dev, IO); /* DECtape */ - else io_data = ptr (IR, dev, IO); /* paper tape rdr */ - break; - case 002: case 030: /* paper tape rdr */ - io_data = ptr (IR, dev, IO); - break; - case 003: /* typewriter */ - io_data = tto (IR, dev, IO); - break; - case 004: /* keyboard */ - io_data = tti (IR, dev, IO); - break; - case 005: case 006: /* paper tape punch */ - io_data = ptp (IR, dev, IO); - break; - case 033: /* check status */ - io_data = iosta | ((sbs & SB_ON)? IOS_SQB: 0); - break; - case 045: /* line printer */ - io_data = lpt (IR, dev, IO); - break; - case 054: /* seq brk off */ - sbs = sbs & ~SB_ON; - break; - case 055: /* seq brk on */ - sbs = sbs | SB_ON; - break; - case 056: /* clear seq brk */ - sbs = sbs & ~SB_IP; - break; - case 074: /* extend mode */ - extm = (IR >> 11) & 1; /* set from IR<6> */ - break; - default: /* undefined */ - reason = stop_inst; - break; } /* end switch dev */ - IO = io_data & 0777777; - if (io_data >= IOT_REASON) reason = io_data >> IOT_V_REASON; - break; -default: /* undefined */ - reason = STOP_RSRV; /* halt */ - break; } /* end switch opcode */ -} /* end while */ -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -sbs = sbs_init; -extm = extm_init; -ioh = ioc = 0; -OV = 0; -PF = 0; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & 0777777; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & 0777777; -return SCPE_OK; -} - -/* Change memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -t_addr i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; -for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; -if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; -MEMSIZE = val; -for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; -return SCPE_OK; -} diff --git a/PDP1o/pdp1_defs.h b/PDP1o/pdp1_defs.h deleted file mode 100644 index 5890abce..00000000 --- a/PDP1o/pdp1_defs.h +++ /dev/null @@ -1,104 +0,0 @@ -/* pdp1_defs.h: 18b PDP simulator definitions - - Copyright (c) 1993-2002, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 14-Apr-99 RMS Changed t_addr to unsigned - - The PDP-1 was Digital's first computer. The system design evolved during - its life, and as a result, specifications are sketchy or contradictory. - This simulator is based on the 1962 maintenance manual. - - This simulator implements the following options: - - Automatic multiply/divide Type 10 - Memory extension control Type 15 - Line printer control Type 62 -*/ - -#include "sim_defs.h" - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_XCT 4 /* nested XCT's */ -#define STOP_IND 5 /* nested indirects */ -#define STOP_WAIT 6 /* wait state */ - -/* Memory */ - -#define ASIZE 16 /* address bits */ -#define MAXMEMSIZE (1u << ASIZE) /* max mem size */ -#define AMASK (MAXMEMSIZE - 1) /* address mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE) - -/* Architectural constants */ - -#define DMASK 0777777 /* data mask */ -#define DAMASK 007777 /* direct addr */ -#define EPCMASK (AMASK & ~DAMASK) /* extended addr */ -#define IA 010000 /* indirect flag */ -#define IO_WAIT 010000 /* I/O sync wait */ -#define IO_CPLS 004000 /* completion pulse */ -#define GEN_CPLS(x) (((x) ^ ((x) << 1)) & IO_WAIT) /* completion pulse? */ - -/* IOT subroutine return codes */ - -#define IOT_V_REASON 18 /* reason */ -#define IOT_REASON (1 << IOT_V_REASON) -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* I/O status flags */ - -#define IOS_V_LPN 17 /* light pen */ -#define IOS_V_PTR 16 /* paper tape reader */ -#define IOS_V_TTO 15 /* typewriter out */ -#define IOS_V_TTI 14 /* typewriter in */ -#define IOS_V_PTP 13 /* paper tape punch */ -#define IOS_V_DRM 12 /* drum */ -#define IOS_V_SQB 11 /* sequence break */ -#define IOS_V_PNT 2 /* print done */ -#define IOS_V_SPC 1 /* space done */ - -#define IOS_LPN (1 << IOS_V_LPN) -#define IOS_PTR (1 << IOS_V_PTR) -#define IOS_TTO (1 << IOS_V_TTO) -#define IOS_TTI (1 << IOS_V_TTI) -#define IOS_PTP (1 << IOS_V_PTP) -#define IOS_DRM (1 << IOS_V_DRM) -#define IOS_SQB (1 << IOS_V_SQB) -#define IOS_PNT (1 << IOS_V_PNT) -#define IOS_SPC (1 << IOS_V_SPC) - -/* Sequence break flags */ - -#define SB_V_IP 0 /* in progress */ -#define SB_V_RQ 1 /* request */ -#define SB_V_ON 2 /* enabled */ - -#define SB_IP (1 << SB_V_IP) -#define SB_RQ (1 << SB_V_RQ) -#define SB_ON (1 << SB_V_ON) diff --git a/PDP1o/pdp1_doc.txt b/PDP1o/pdp1_doc.txt deleted file mode 100644 index f28c0eb2..00000000 --- a/PDP1o/pdp1_doc.txt +++ /dev/null @@ -1,476 +0,0 @@ -To: Users -From: Bob Supnik -Subj: PDP-1 Simulator Usage -Date: 15-Nov-2002 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - Original code published in 1993-2002, written by Robert M Supnik - Copyright (c) 1993-2002, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - -This memorandum documents the PDP-1 simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tmxr.c - -sim/pdp1/ pdp1_defs.h - pdp1_cpu.c - pdp1_dt.c - pdp1_lp.c - pdp1_stddev.c - pdp1_sys.c - -2. PDP-1 Features - -The PDP-1 is configured as follows: - -device simulates -name(s) - -CPU PDP-1 CPU with up to 64KW of memory -PTR,PTP integral paper tape reader/punch -TTI,TTO Flexowriter typewriter input/output -LPT Type 62 line printer -DT Type 550 Microtape (DECtape) - -The PDP-1 simulator implements the following unique stop conditions: - - - an unimplemented instruction is decoded, and register - STOP_INST is set - - more than INDMAX indirect addresses are detected during - memory reference address decoding - - more than XCTMAX nested executes are detected during - instruction execution - - wait state entered, and no I/O operations outstanding - (ie, no interrupt can ever occur) - -The PDP-1 loader supports RIM format tapes. The DUMP command is not -implemented. - -2.1 CPU - -The only CPU options are the presence of hardware multiply/divide and the -size of main memory. - - SET CPU MDV enable multiply/divide - SET CPU NOMDV disable multiply/divide - SET CPU 4K set memory size = 4K - SET CPU 8K set memory size = 8K - SET CPU 12K set memory size = 12K - SET CPU 16K set memory size = 16K - SET CPU 20K set memory size = 20K - SET CPU 24K set memory size = 24K - SET CPU 28K set memory size = 28K - SET CPU 32K set memory size = 32K - SET CPU 48K set memory size = 48K - SET CPU 64K set memory size = 64K - -If memory size is being reduced, and the memory being truncated contains -non-zero data, the simulator asks for confirmation. Data in the truncated -portion of memory is lost. Initial memory size is 64K. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 16 program counter - AC 18 accumulator - IO 18 IO register - OV 1 overflow flag - PF 6 program flags<1:6> - SS 6 sense switches<1:6> - TW 18 test word (front panel switches) - EXTM 1 extend mode - IOSTA 18 IO status register - SBON 1 sequence break enable - SBRQ 1 sequence break request - SBIP 1 sequence break in progress - IOH 1 I/O halt in progress - IOC 1 I/O continue - PCQ[0:63] 16 PC prior to last jump or interrupt; - most recent PC change first - STOP_INST 1 stop on undefined instruction - SBS_INIT 1 initial state of sequence break enable - EXTM_INIT 1 initial state of extend mode - WRU 8 interrupt character - -2.2 Programmed I/O Devices - -2.2.1 Paper Tape Reader (PTR) - -The paper tape reader (PTR) reads data from or a disk file. The POS -register specifies the number of the next data item to be read. Thus, -by changing POS, the user can backspace or advance the reader. - -The paper tape reader supports the BOOT command. BOOT PTR copies the -RIM loader into memory and starts it running. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - DONE 1 device done flag - RPLS 1 return restart pulse flag - POS 32 position in the input file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - end of file 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.2.2 Paper Tape Punch (PTP) - -The paper tape punch (PTP) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by changing POS, the user can backspace or advance the punch. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - DONE 1 device done flag - RPLS 1 return restart pulse flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape - - OS I/O error x report error and stop - -2.2.3 Terminal Input (TTI) - -The terminal input (TTI) polls the console keyboard for input. It -implements these registers: - - name size comments - - BUF 8 last data item processed - DONE 1 device done flag - POS 32 number of characters input - TIME 24 keyboard polling interval - -2.2.4 Terminal Output (TTO) - -The terminal output (TTO) writes to the simulator console window. -It implements these registers: - - name size comments - - BUF 8 last data item processed - DONE 1 device done flag - RPLS 1 return restart pulse flag - POS 32 number of characters output - TIME 24 time from I/O initiation to interrupt - -2.2.5 Type 62 Line Printer (LPT) - -The paper line printer (LPT) writes data to a disk file. The POS -register specifies the number of the next data item to be written. -Thus, by changing POS, the user can backspace or advance the printer. - -The line printer can be disabled and enabled with the SET LPT DISABLED -and SET LPT ENABLED commands, respectively. - -The line printer implements these registers: - - name size comments - - BUF 8 last data item processed - PNT 1 printing done flag - SPC 1 spacing done flag - RPLS 1 return restart pulse flag - BPTR 6 print buffer pointer - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - STOP_IOE 1 stop on I/O error - LBUF[0:119] 8 line buffer - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.3 Type 550/555 Microtape (DECtape) (DT) - -The PDP-1 used the Type 550 Microtape (later renamed DECtape), a programmed -I/O controller. PDP-1 DECtape format had 4 18b words in its block headers -and trailers. - -DECtapes drives are numbered 1-8; in the simulator, drive 8 is unit 0. -DECtape options include the ability to make units write enabled or write -locked. - - SET DTn WRITEENABLED set unit n write enabled - SET DTn LOCKED set unit n write locked - -Units can also be set ONLINE or OFFLINE. - -The DECtape controller can be disabled and enabled with the SET DT DISABLED -and SET DT ENABLED commands, respectively. - -The Type 550 supports PDP-8 format, PDP-11 format, and 18b format DECtape -images. ATTACH tries to determine the tape format from the DECtape image; -the user can force a particular format with switches: - - -r PDP-8 format - -s PDP-11 format - -t 18b format - -The DECtape controller is a data-only simulator; the timing and mark -track, and block header and trailer, are not stored. Thus, the WRITE -TIMING AND MARK TRACK function is not supported; the READ ALL function -always returns the hardware standard block header and trailer; and the -WRITE ALL function dumps non-data words into the bit bucket. - -The DECtape controller implements these registers: - - name size comments - - DTSA 12 status register A - DTSB 12 status register B - DTDB 18 data buffer - DTF 1 DECtape flag - BEF 1 block end flag - ERF 1 error flag - LTIME 31 time between lines - ACTIME 31 time to accelerate to full speed - DCTIME 31 time to decelerate to a full stop - SUBSTATE 2 read/write command substate - POS[0:7] 32 position, in lines, units 0-7 - STATT[0:7] 18 unit state, units 0-7 - -It is critically important to maintain certain timing relationships -among the DECtape parameters, or the DECtape simulator will fail to -operate correctly. - - - LTIME must be at least 6 - - ACTIME must be less than DCTIME, and both need to be at - least 100 times LTIME - -2.4 Symbolic Display and Input - -The PDP-1 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as FIODEC character string - -m display instruction mnemonics - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c three character FIODEC string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses modified PDP-1 assembler syntax. There are six -instruction classes: memory reference, shift, skip, operate, IOT, and -LAW. - -Memory reference instructions have the format - - memref {I} address - -where I signifies indirect reference. The address is an octal number in -the range 0 - 0177777. - -Shift instructions have the format - - shift shift_count - -The shift count is an octal number in the range 0-9. - -Skip instructions consist of single mnemonics, eg, SZA, SZS4. Skip -instructions may be or'd together - - skip skip skip... - -The sense of a skip can be inverted by including the mnemonic I. - -Operate instructions consist of single mnemonics, eg, CLA, CLI. Operate -instructions may be or'd together - - opr opr opr... - -IOT instructions consist of single mnemonics, eg, TYI, TYO. IOT -instructions may include an octal numeric modifier or the modifier I: - - iot modifier - -The simulator does not check the legality of skip, operate, or IOT -combinations. - -Finally, the LAW instruction has the format - - LAW {I} immediate - -where immediate is in the range 0 to 07777. - -2.5 Character Sets - -The PDP-1's console was a Frieden Flexowriter; its character encoding -was known as FIODEC. The PDP-1's line printer used a modified Hollerith -character set. The following table provides equivalences between ASCII -characters and the PDP-1's I/O devices. In the console table, UC stands -for upper case. - - PDP-1 PDP-1 -ASCII console line printer - -000 - 007 none none -bs 075 none -tab 036 none -012 - 014 none none -cr 077 none -016 - 037 none none -space 000 000 -! {OR} UC+005 none -" UC+001 none -# {IMPLIES} UC+004 none -$ none none -% none none -& {AND} UC+006 none -' UC+002 none -( 057 057 -) 055 055 -* {TIMES} UC+073 072 -+ UC+054 074 -, 033 033 -- 054 054 -. 073 073 -/ 021 021 -0 020 020 -1 001 001 -2 002 002 -3 003 003 -4 004 004 -5 005 005 -6 006 006 -7 007 007 -8 010 010 -9 011 011 -: none none -; none none -< UC+007 034 -= UC+033 053 -> UC+010 034 -? UC+021 037 -@ {MID DOT} 040 {MID DOT} 040 -A UC+061 061 -B UC+062 062 -C UC+063 063 -D UC+064 064 -E UC+065 065 -F UC+066 066 -G UC+067 067 -H UC+070 070 -I UC+071 071 -J UC+041 041 -K UC+042 042 -L UC+043 043 -M UC+044 044 -N UC+045 045 -O UC+046 046 -P UC+047 047 -Q UC+050 050 -R UC+051 051 -S UC+022 022 -T UC+023 023 -U UC+024 024 -V UC+025 025 -W UC+026 026 -X UC+027 027 -Y UC+030 030 -Z UC+031 031 -[ UC+057 none -\ {OVERLINE} 056 {OVERLINE} 056 -] UC+055 none -^ {UP ARROW} UC+011 {UP ARROW} 035 -_ UC+040 UC+040 -` {RT ARROW} UC+020 036 -a 061 none -b 062 none -c 063 none -d 064 none -e 065 none -f 066 none -g 067 none -h 070 none -i 071 none -j 041 none -k 042 none -l 043 none -m 044 none -n 045 none -o 046 none -p 047 none -q 050 none -r 051 none -s 022 none -t 023 none -u 024 none -v 025 none -w 026 none -x 027 none -y 030 none -z 031 none -{ none none -| UC+056 076 -} none none -~ UC+003 013 -del 075 none diff --git a/PDP1o/pdp1_dt.c b/PDP1o/pdp1_dt.c deleted file mode 100644 index b7eb872d..00000000 --- a/PDP1o/pdp1_dt.c +++ /dev/null @@ -1,976 +0,0 @@ -/* pdp1_dt.c: 18b DECtape simulator - - Copyright (c) 1993-2002, Robert M Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - dt Type 550/555 DECtape - - 17-Oct-02 RMS Fixed bug in end of reel logic - 06-Oct-02 RMS Added device disable support - 13-Aug-02 RMS Cloned from pdp18b_dt.c - - 18b DECtapes are represented in memory by fixed length buffer of 32b words. - Three file formats are supported: - - 18b/36b 256 words per block [256 x 18b] - 16b 256 words per block [256 x 16b] - 12b 129 words per block [129 x 12b] - - When a 16b or 12b DECtape file is read in, it is converted to 18b/36b format. - - DECtape motion is measured in 3b lines. Time between lines is 33.33us. - Tape density is nominally 300 lines per inch. The format of a DECtape is - - reverse end zone 36000 lines ~ 10 feet - block 0 - : - block n - forward end zone 36000 lines ~ 10 feet - - A block consists of five 18b header words, a tape-specific number of data - words, and five 18b trailer words. All systems except the PDP-8 use a - standard block length of 256 words; the PDP-8 uses a standard block length - of 86 words (x 18b = 129 words x 12b). [A PDP-1/4/7 DECtape has only four 18b - header words; for consistency, the PDP-1/4/7 uses the same format as the PDP-9/15 - but skips the missing header words.] - - Because a DECtape file only contains data, the simulator cannot support - write timing and mark track and can only do a limited implementation - of read all and write all. Read all assumes that the tape has been - conventionally written forward: - - header word 0 0 - header word 1 block number (for forward reads) - header words 2,3 0 - header word 4 0 - : - trailer word 4 checksum - trailer words 3,2 0 - trailer word 1 block number (for reverse reads) - trailer word 0 0 - - Write all writes only the data words and dumps the interblock words in the - bit bucket. - - The Type 550 controller has a 4b unit select field, for units 1-8; the TC02 - has a 3b unit select field, with unit 8 being represented as 0. The code - assumes that the GETUNIT macro returns a unit number in the range of 0-7, - with 8 represented as 0, and an invalid unit as -1. -*/ - -#include "pdp1_defs.h" - -#define DT_NUMDR 8 /* #drives */ -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_8FMT (UNIT_V_UF + 1) /* 12b format */ -#define UNIT_V_11FMT (UNIT_V_UF + 2) /* 16b format */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_8FMT (1 << UNIT_V_8FMT) -#define UNIT_11FMT (1 << UNIT_V_11FMT) -#define STATE u3 /* unit state */ -#define LASTT u4 /* last time update */ -#define DT_WC 030 /* word count */ -#define DT_CA 031 /* current addr */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* System independent DECtape constants */ - -#define DT_EZLIN 36000 /* end zone length */ -#define DT_HTLIN 30 /* header/trailer lines */ -#define DT_BLKLN 6 /* blk no line in h/t */ -#define DT_CSMLN 24 /* checksum line in h/t */ -#define DT_HTWRD (DT_HTLIN / DT_WSIZE) /* header/trailer words */ -#define DT_BLKWD (DT_BLKLN / DT_WSIZE) /* blk no word in h/t */ -#define DT_CSMWD (DT_CSMLN / DT_WSIZE) /* checksum word in h/t */ - -/* 16b, 18b, 36b DECtape constants */ - -#define D18_WSIZE 6 /* word size in lines */ -#define D18_BSIZE 256 /* block size in 18b */ -#define D18_TSIZE 578 /* tape size */ -#define D18_LPERB (DT_HTLIN + (D18_BSIZE * DT_WSIZE) + DT_HTLIN) -#define D18_FWDEZ (DT_EZLIN + (D18_LPERB * D18_TSIZE)) -#define D18_CAPAC (D18_TSIZE * D18_BSIZE) /* tape capacity */ -#define D11_FILSIZ (D18_CAPAC * sizeof (int16)) - -/* 12b DECtape constants */ - -#define D8_WSIZE 4 /* word size in lines */ -#define D8_BSIZE 86 /* block size in 18b */ -#define D8_TSIZE 1474 /* tape size */ -#define D8_LPERB (DT_HTLIN + (D8_BSIZE * DT_WSIZE) + DT_HTLIN) -#define D8_FWDEZ (DT_EZLIN + (D8_LPERB * D8_TSIZE)) -#define D8_CAPAC (D8_TSIZE * D8_BSIZE) /* tape capacity */ - -#define D8_NBSIZE ((D8_BSIZE * D18_WSIZE) / D8_WSIZE) -#define D8_FILSIZ (D8_NBSIZE * D8_TSIZE * sizeof (int16)) - -/* This controller */ - -#define DT_CAPAC D18_CAPAC /* default */ -#define DT_WSIZE D18_WSIZE - -/* Calculated constants, per unit */ - -#define DTU_BSIZE(u) (((u)->flags & UNIT_8FMT)? D8_BSIZE: D18_BSIZE) -#define DTU_TSIZE(u) (((u)->flags & UNIT_8FMT)? D8_TSIZE: D18_TSIZE) -#define DTU_LPERB(u) (((u)->flags & UNIT_8FMT)? D8_LPERB: D18_LPERB) -#define DTU_FWDEZ(u) (((u)->flags & UNIT_8FMT)? D8_FWDEZ: D18_FWDEZ) -#define DTU_CAPAC(u) (((u)->flags & UNIT_8FMT)? D8_CAPAC: D18_CAPAC) - -#define DT_LIN2BL(p,u) (((p) - DT_EZLIN) / DTU_LPERB (u)) -#define DT_LIN2OF(p,u) (((p) - DT_EZLIN) % DTU_LPERB (u)) -#define DT_LIN2WD(p,u) ((DT_LIN2OF (p,u) - DT_HTLIN) / DT_WSIZE) -#define DT_BLK2LN(p,u) (((p) * DTU_LPERB (u)) + DT_EZLIN) -#define DT_QREZ(u) (((u)->pos) < DT_EZLIN) -#define DT_QFEZ(u) (((u)->pos) >= ((uint32) DTU_FWDEZ (u))) -#define DT_QEZ(u) (DT_QREZ (u) || DT_QFEZ (u)) - -/* Status register A */ - -#define DTA_V_UNIT 12 /* unit select */ -#define DTA_M_UNIT 017 -#define DTA_UNIT (DTA_M_UNIT << DTA_V_UNIT) -#define DTA_V_MOT 4 /* motion */ -#define DTA_M_MOT 03 -#define DTA_V_FNC 0 /* function */ -#define DTA_M_FNC 07 -#define FNC_MOVE 00 /* move */ -#define FNC_SRCH 01 /* search */ -#define FNC_READ 02 /* read */ -#define FNC_WRIT 03 /* write */ -#define FNC_RALL 05 /* read all */ -#define FNC_WALL 06 /* write all */ -#define FNC_WMRK 07 /* write timing */ -#define DTA_STSTP (1u << (DTA_V_MOT + 1)) -#define DTA_FWDRV (1u << DTA_V_MOT) -#define DTA_MODE 0 /* not implemented */ -#define DTA_RW 077 -#define DTA_GETUNIT(x) map_unit[(((x) >> DTA_V_UNIT) & DTA_M_UNIT)] -#define DT_UPDINT if (dtsb & (DTB_DTF | DTB_BEF | DTB_ERF)) \ - sbs = sbs | SB_RQ; - -#define DTA_GETMOT(x) (((x) >> DTA_V_MOT) & DTA_M_MOT) -#define DTA_GETFNC(x) (((x) >> DTA_V_FNC) & DTA_M_FNC) - -/* Status register B */ - -#define DTB_V_DTF 17 /* data flag */ -#define DTB_V_BEF 16 /* block end flag */ -#define DTB_V_ERF 15 /* error flag */ -#define DTB_V_END 14 /* end of tape */ -#define DTB_V_TIM 13 /* timing err */ -#define DTB_V_REV 12 /* reverse */ -#define DTB_V_GO 11 /* go */ -#define DTB_V_MRK 10 /* mark trk err */ -#define DTB_V_SEL 9 /* select err */ -#define DTB_DTF (1u << DTB_V_DTF) -#define DTB_BEF (1u << DTB_V_BEF) -#define DTB_ERF (1u << DTB_V_ERF) -#define DTB_END (1u << DTB_V_END) -#define DTB_TIM (1u << DTB_V_TIM) -#define DTB_REV (1u << DTB_V_REV) -#define DTB_GO (1u << DTB_V_GO) -#define DTB_MRK (1u << DTB_V_MRK) -#define DTB_SEL (1u << DTB_V_SEL) -#define DTB_ALLERR (DTB_END | DTB_TIM | DTB_MRK | DTB_SEL) - -/* DECtape state */ - -#define DTS_V_MOT 3 /* motion */ -#define DTS_M_MOT 07 -#define DTS_STOP 0 /* stopped */ -#define DTS_DECF 2 /* decel, fwd */ -#define DTS_DECR 3 /* decel, rev */ -#define DTS_ACCF 4 /* accel, fwd */ -#define DTS_ACCR 5 /* accel, rev */ -#define DTS_ATSF 6 /* @speed, fwd */ -#define DTS_ATSR 7 /* @speed, rev */ -#define DTS_DIR 01 /* dir mask */ -#define DTS_V_FNC 0 /* function */ -#define DTS_M_FNC 07 -#define DTS_OFR 7 /* "off reel" */ -#define DTS_GETMOT(x) (((x) >> DTS_V_MOT) & DTS_M_MOT) -#define DTS_GETFNC(x) (((x) >> DTS_V_FNC) & DTS_M_FNC) -#define DTS_V_2ND 6 /* next state */ -#define DTS_V_3RD (DTS_V_2ND + DTS_V_2ND) /* next next */ -#define DTS_STA(y,z) (((y) << DTS_V_MOT) | ((z) << DTS_V_FNC)) -#define DTS_SETSTA(y,z) uptr->STATE = DTS_STA (y, z) -#define DTS_SET2ND(y,z) uptr->STATE = (uptr->STATE & 077) | \ - ((DTS_STA (y, z)) << DTS_V_2ND) -#define DTS_SET3RD(y,z) uptr->STATE = (uptr->STATE & 07777) | \ - ((DTS_STA (y, z)) << DTS_V_3RD) -#define DTS_NXTSTA(x) (x >> DTS_V_2ND) - -/* Operation substates */ - -#define DTO_WCO 1 /* wc overflow */ -#define DTO_SOB 2 /* start of block */ - -/* Logging */ - -#define LOG_MS 001 /* move, search */ -#define LOG_RW 002 /* read, write */ -#define LOG_RA 004 /* read all */ -#define LOG_BL 010 /* block # lblk */ - -#define ABS(x) (((x) < 0)? (-(x)): (x)) - -extern int32 M[]; -extern int32 sbs; -extern int32 stop_inst; -extern UNIT cpu_unit; -extern int32 sim_switches; -extern int32 sim_is_running; - -int32 dtsa = 0; /* status A */ -int32 dtsb = 0; /* status B */ -int32 dtdb = 0; /* data buffer */ -int32 dt_ltime = 12; /* interline time */ -int32 dt_actime = 54000; /* accel time */ -int32 dt_dctime = 72000; /* decel time */ -int32 dt_substate = 0; -int32 dt_log = 0; -int32 dt_logblk = 0; -static const int32 map_unit[16] = { /* Type 550 unit map */ - -1, 1, 2, 3, 4, 5, 6, 7, - 0, -1, -1, -1, -1, -1, -1, -1 }; - -t_stat dt_svc (UNIT *uptr); -t_stat dt_reset (DEVICE *dptr); -t_stat dt_attach (UNIT *uptr, char *cptr); -t_stat dt_detach (UNIT *uptr); -void dt_deselect (int32 oldf); -void dt_newsa (int32 newf); -void dt_newfnc (UNIT *uptr, int32 newsta); -t_bool dt_setpos (UNIT *uptr); -void dt_schedez (UNIT *uptr, int32 dir); -void dt_seterr (UNIT *uptr, int32 e); -int32 dt_comobv (int32 val); -int32 dt_csum (UNIT *uptr, int32 blk); -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos); - -/* DT data structures - - dt_dev DT device descriptor - dt_unit DT unit list - dt_reg DT register list - dt_mod DT modifier list -*/ - -UNIT dt_unit[] = { - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DT_CAPAC) } }; - -REG dt_reg[] = { - { ORDATA (DTSA, dtsa, 18) }, - { ORDATA (DTSB, dtsb, 18) }, - { ORDATA (DTDB, dtdb, 18) }, - { FLDATA (DTF, dtsb, DTB_V_DTF) }, - { FLDATA (BEF, dtsb, DTB_V_BEF) }, - { FLDATA (ERF, dtsb, DTB_V_ERF) }, - { DRDATA (LTIME, dt_ltime, 31), REG_NZ }, - { DRDATA (ACTIME, dt_actime, 31), REG_NZ }, - { DRDATA (DCTIME, dt_dctime, 31), REG_NZ }, - { ORDATA (SUBSTATE, dt_substate, 2) }, - { ORDATA (LOG, dt_log, 4), REG_HIDDEN }, - { DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN }, - { URDATA (POS, dt_unit[0].pos, 10, 32, 0, - DT_NUMDR, PV_LEFT | REG_RO) }, - { URDATA (STATT, dt_unit[0].STATE, 8, 18, 0, - DT_NUMDR, REG_RO) }, - { URDATA (LASTT, dt_unit[0].LASTT, 10, 32, 0, - DT_NUMDR, REG_HRO) }, - { NULL } }; - -MTAB dt_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_8FMT + UNIT_11FMT, 0, "18b", NULL, NULL }, - { UNIT_8FMT + UNIT_11FMT, UNIT_8FMT, "12b", NULL, NULL }, - { UNIT_8FMT + UNIT_11FMT, UNIT_11FMT, "16b", NULL, NULL }, - { 0 } }; - -DEVICE dt_dev = { - "DT", dt_unit, dt_reg, dt_mod, - DT_NUMDR, 8, 24, 1, 8, 18, - NULL, NULL, &dt_reset, - NULL, &dt_attach, &dt_detach, - NULL, DEV_DISABLE }; - -int32 dt (int32 IR, int32 dev, int32 IO) -{ -int32 pulse = (IR >> 6) & 037; -int32 fnc, mot, unum; -UNIT *uptr = NULL; - -if (dt_dev.flags & DEV_DIS) /* disabled? */ - return (stop_inst << IOT_V_REASON) | IO; /* stop if requested */ -unum = DTA_GETUNIT (dtsa); /* get unit no */ -if (unum >= 0) uptr = dt_dev.units + unum; /* get unit */ - -if (pulse == 003) { /* MSE */ - if ((dtsa ^ IO) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ - dtsa = (dtsa & ~DTA_UNIT) | (IO & DTA_UNIT); - dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); } -if (pulse == 004) { /* MLC */ - dtsa = (dtsa & ~DTA_RW) | (IO & DTA_RW); /* load dtsa */ - dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); - fnc = DTA_GETFNC (dtsa); /* get fnc */ - if ((uptr == NULL) || /* invalid? */ - ((uptr->flags) & UNIT_DIS) || /* disabled? */ - (fnc >= FNC_WMRK) || /* write mark? */ - ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WLK)) || - ((fnc == FNC_WALL) && (uptr->flags & UNIT_WLK))) - dt_seterr (uptr, DTB_SEL); /* select err */ - else dt_newsa (dtsa); } -if (pulse == 005) { /* MRD */ - IO = (IO & ~DMASK) | dtdb; - dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } -if (pulse == 006) { /* MWR */ - dtdb = IO & DMASK; - dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } -if (pulse == 007) { /* MRS */ - dtsb = dtsb & ~(DTB_REV | DTB_GO); /* clr rev, go */ - if (uptr) { /* valid unit? */ - mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if (mot & DTS_DIR) dtsb = dtsb | DTB_REV; /* rev? set */ - if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700)) - dtsb = dtsb | DTB_GO; } /* accel? go */ - IO = (IO & ~DMASK) | dtsb; } -DT_UPDINT; -return IO; -} - -/* Unit deselect */ - -void dt_deselect (int32 oldf) -{ -int32 old_unit, old_mot; -UNIT *uptr; - -old_unit = DTA_GETUNIT (oldf); /* get unit no */ -if (old_unit < 0) return; /* invalid? */ -uptr = dt_dev.units + old_unit; /* get unit */ -old_mot = DTS_GETMOT (uptr->STATE); -if (old_mot >= DTS_ATSF) /* at speed? */ - dt_newfnc (uptr, DTS_STA (old_mot, DTS_OFR)); -else if (old_mot >= DTS_ACCF) /* accelerating? */ - DTS_SET2ND (DTS_ATSF | (old_mot & DTS_DIR), DTS_OFR); -return; -} - -/* Command register change - - 1. If change in motion, stop to start - - schedule acceleration - - set function as next state - 2. If change in motion, start to stop - - if not already decelerating (could be reversing), - schedule deceleration - 3. If change in direction, - - if not decelerating, schedule deceleration - - set accelerating (other dir) as next state - - set function as next next state - 4. If not accelerating or at speed, - - schedule acceleration - - set function as next state - 5. If not yet at speed, - - set function as next state - 6. If at speed, - - set function as current state, schedule function -*/ - -void dt_newsa (int32 newf) -{ -int32 new_unit, prev_mot, new_fnc; -int32 prev_mving, new_mving, prev_dir, new_dir; -UNIT *uptr; - -new_unit = DTA_GETUNIT (newf); /* new unit */ -if (new_unit < 0) return; /* invalid? */ -uptr = dt_dev.units + new_unit; -if ((uptr->flags & UNIT_ATT) == 0) { /* new unit attached? */ - dt_seterr (uptr, DTB_SEL); /* no, error */ - return; } -prev_mot = DTS_GETMOT (uptr->STATE); /* previous motion */ -prev_mving = prev_mot != DTS_STOP; /* previous moving? */ -prev_dir = prev_mot & DTS_DIR; /* previous dir? */ -new_mving = (newf & DTA_STSTP) != 0; /* new moving? */ -new_dir = (newf & DTA_FWDRV) != 0; /* new dir? */ -new_fnc = DTA_GETFNC (newf); /* new function? */ - -if ((prev_mving | new_mving) == 0) return; /* stop to stop */ - -if (new_mving & ~prev_mving) { /* start? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_actime); /* schedule accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -if (prev_mving & ~new_mving) { /* stop? */ - if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ - DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ - return; } - -if (prev_dir ^ new_dir) { /* dir chg? */ - if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ - DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ - DTS_SET2ND (DTS_ACCF | new_dir, 0); /* next = accel */ - DTS_SET3RD (DTS_ATSF | new_dir, new_fnc); /* next next = fnc */ - return; } - -if (prev_mot < DTS_ACCF) { /* not accel/at speed? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* cancel cur */ - sim_activate (uptr, dt_actime); /* schedule accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -if (prev_mot < DTS_ATSF) { /* not at speed? */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } - -dt_newfnc (uptr, DTS_STA (DTS_ATSF | new_dir, new_fnc));/* state = fnc */ -return; -} - -/* Schedule new DECtape function - - This routine is only called if - - the selected unit is attached - - the selected unit is at speed (forward or backward) - - This routine - - updates the selected unit's position - - updates the selected unit's state - - schedules the new operation -*/ - -void dt_newfnc (UNIT *uptr, int32 newsta) -{ -int32 fnc, dir, blk, unum, newpos; -uint32 oldpos; - -oldpos = uptr->pos; /* save old pos */ -if (dt_setpos (uptr)) return; /* update pos */ -uptr->STATE = newsta; /* update state */ -fnc = DTS_GETFNC (uptr->STATE); /* set variables */ -dir = DTS_GETMOT (uptr->STATE) & DTS_DIR; -unum = uptr - dt_dev.units; -if (oldpos == uptr->pos) /* bump pos */ - uptr->pos = uptr->pos + (dir? -1: 1); -blk = DT_LIN2BL (uptr->pos, uptr); - -if (dir? DT_QREZ (uptr): DT_QFEZ (uptr)) { /* wrong ez? */ - dt_seterr (uptr, DTB_END); /* set ez flag, stop */ - return; } -sim_cancel (uptr); /* cancel cur op */ -dt_substate = DTO_SOB; /* substate = block start */ -switch (fnc) { /* case function */ -case DTS_OFR: /* off reel */ - if (dir) newpos = -1000; /* rev? < start */ - else newpos = DTU_FWDEZ (uptr) + DT_EZLIN + 1000; /* fwd? > end */ - break; -case FNC_MOVE: /* move */ - dt_schedez (uptr, dir); /* sched end zone */ - if (dt_log & LOG_MS) printf ("[DT%d: moving %s]\n", unum, (dir? - "backward": "forward")); - return; /* done */ -case FNC_SRCH: /* search */ - if (dir) newpos = DT_BLK2LN ((DT_QFEZ (uptr)? - DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; - else newpos = DT_BLK2LN ((DT_QREZ (uptr)? - 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); - if (dt_log & LOG_MS) printf ("[DT%d: searching %s]\n", unum, - (dir? "backward": "forward")); - break; -case FNC_WRIT: /* write */ -case FNC_READ: /* read */ -case FNC_RALL: /* read all */ -case FNC_WALL: /* write all */ - if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE; - else newpos = DT_EZLIN + (DT_WSIZE - 1); } - else { newpos = ((uptr->pos) / DT_WSIZE) * DT_WSIZE; - if (!dir) newpos = newpos + (DT_WSIZE - 1); } - if ((dt_log & LOG_RA) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: read all block %d %s%s\n", - unum, blk, (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - break; -default: - dt_seterr (uptr, DTB_SEL); /* bad state */ - return; } -if ((fnc == FNC_WRIT) || (fnc == FNC_WALL)) { /* write function? */ - dtsb = dtsb | DTB_DTF; /* set data flag */ - DT_UPDINT; } -sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); -return; -} - -/* Update DECtape position - - DECtape motion is modeled as a constant velocity, with linear - acceleration and deceleration. The motion equations are as follows: - - t = time since operation started - tmax = time for operation (accel, decel only) - v = at speed velocity in lines (= 1/dt_ltime) - - Then: - at speed dist = t * v - accel dist = (t^2 * v) / (2 * tmax) - decel dist = (((2 * t * tmax) - t^2) * v) / (2 * tmax) - - This routine uses the relative (integer) time, rather than the absolute - (floating point) time, to allow save and restore of the start times. -*/ - -t_bool dt_setpos (UNIT *uptr) -{ -uint32 new_time, ut, ulin, udelt; -int32 mot = DTS_GETMOT (uptr->STATE); -int32 unum, delta; - -new_time = sim_grtime (); /* current time */ -ut = new_time - uptr->LASTT; /* elapsed time */ -if (ut == 0) return FALSE; /* no time gone? exit */ -uptr->LASTT = new_time; /* update last time */ -switch (mot & ~DTS_DIR) { /* case on motion */ -case DTS_STOP: /* stop */ - delta = 0; - break; -case DTS_DECF: /* slowing */ - ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime; - delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt); - break; -case DTS_ACCF: /* accelerating */ - ulin = ut / (uint32) dt_ltime; udelt = dt_actime / dt_ltime; - delta = (ulin * ulin) / (2 * udelt); - break; -case DTS_ATSF: /* at speed */ - delta = ut / (uint32) dt_ltime; - break; } -if (mot & DTS_DIR) uptr->pos = uptr->pos - delta; /* update pos */ -else uptr->pos = uptr->pos + delta; -if (((int32) uptr->pos < 0) || - ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { - detach_unit (uptr); /* off reel? */ - uptr->STATE = uptr->pos = 0; - unum = uptr - dt_dev.units; - if (unum == DTA_GETUNIT (dtsa)) /* if selected, */ - dt_seterr (uptr, DTB_SEL); /* error */ - return TRUE; } -return FALSE; -} - -/* Unit service - - Unit must be attached, detach cancels operation -*/ - -t_stat dt_svc (UNIT *uptr) -{ -int32 mot = DTS_GETMOT (uptr->STATE); -int32 dir = mot & DTS_DIR; -int32 fnc = DTS_GETFNC (uptr->STATE); -int32 *bptr = uptr->filebuf; -int32 unum = uptr - dt_dev.units; -int32 blk, wrd, ma, relpos; -t_addr ba; - -/* Motion cases - - Decelerating - if next state != stopped, must be accel reverse - Accelerating - next state must be @speed, schedule function - At speed - do functional processing -*/ - -switch (mot) { -case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ - if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ - return SCPE_OK; -case DTS_ACCF: case DTS_ACCR: /* accelerating */ - dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ - return SCPE_OK; -case DTS_ATSF: case DTS_ATSR: /* at speed */ - break; /* check function */ -default: /* other */ - dt_seterr (uptr, DTB_SEL); /* state error */ - return SCPE_OK; } - -/* Functional cases - - Move - must be at end zone - Search - transfer block number, schedule next block - Off reel - detach unit (it must be deselected) -*/ - -if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ -if (DT_QEZ (uptr)) { /* in end zone? */ - dt_seterr (uptr, DTB_END); /* end zone error */ - return SCPE_OK; } -blk = DT_LIN2BL (uptr->pos, uptr); /* get block # */ -switch (fnc) { /* at speed, check fnc */ -case FNC_MOVE: /* move */ - dt_seterr (uptr, DTB_END); /* end zone error */ - return SCPE_OK; -case DTS_OFR: /* off reel */ - detach_unit (uptr); /* must be deselected */ - uptr->STATE = uptr->pos = 0; /* no visible action */ - break; - -/* Search */ - -case FNC_SRCH: /* search */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ - dtdb = blk; /* store block # */ - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; - -/* Read and read all */ - -case FNC_READ: case FNC_RALL: - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DT_WSIZE * dt_ltime); /* sched next word */ - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - dtdb = bptr[ba]; /* get tape word */ - dtsb = dtsb | DTB_DTF; } /* set flag */ - else { ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1; - wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ - if ((wrd == 0) || /* skip 1st, last */ - (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; - if ((fnc == FNC_READ) && /* read, skip if not */ - (wrd != DT_CSMWD) && /* fwd, rev cksum */ - (wrd != ma)) break; - dtdb = dt_gethdr (uptr, blk, relpos); - if (wrd == (dir? DT_CSMWD: ma)) /* at end csum? */ - dtsb = dtsb | DTB_BEF; /* end block */ - else dtsb = dtsb | DTB_DTF; } /* else next word */ - if (dir) dtdb = dt_comobv (dtdb); - break; - -/* Write and write all */ - -case FNC_WRIT: case FNC_WALL: - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - sim_activate (uptr, DT_WSIZE * dt_ltime); /* sched next word */ - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - if (dir) bptr[ba] = dt_comobv (dtdb); /* get data word */ - else bptr[ba] = dtdb; - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1)) - dtsb = dtsb | DTB_BEF; /* end block */ - else dtsb = dtsb | DTB_DTF; } /* else next word */ - else { wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */ - if ((wrd == 0) || /* skip 1st, last */ - (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break; - if ((fnc == FNC_WRIT) && /* wr, skip if !csm */ - (wrd != ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1))) - break; - dtsb = dtsb | DTB_DTF; } /* set flag */ - break; - -default: - dt_seterr (uptr, DTB_SEL); /* impossible state */ - break; } -DT_UPDINT; /* update interrupts */ -return SCPE_OK; -} - -/* Utility routines */ - -/* Set error flag */ - -void dt_seterr (UNIT *uptr, int32 e) -{ -int32 mot = DTS_GETMOT (uptr->STATE); - -dtsa = dtsa & ~DTA_STSTP; /* clear go */ -dtsb = dtsb | DTB_ERF | e; /* set error flag */ -if (mot >= DTS_ACCF) { /* ~stopped or stopping? */ - sim_cancel (uptr); /* cancel activity */ - if (dt_setpos (uptr)) return; /* update position */ - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (mot & DTS_DIR), 0); } /* state = decel */ -DT_UPDINT; -return; -} - -/* Schedule end zone */ - -void dt_schedez (UNIT *uptr, int32 dir) -{ -int32 newpos; - -if (dir) newpos = DT_EZLIN - DT_WSIZE; /* rev? rev ez */ -else newpos = DTU_FWDEZ (uptr) + DT_WSIZE; /* fwd? fwd ez */ -sim_activate (uptr, ABS (newpos - ((int32) uptr->pos)) * dt_ltime); -return; -} - -/* Complement obverse routine */ - -int32 dt_comobv (int32 dat) -{ -dat = dat ^ 0777777; /* compl obverse */ -dat = ((dat >> 15) & 07) | ((dat >> 9) & 070) | - ((dat >> 3) & 0700) | ((dat & 0700) << 3) | - ((dat & 070) << 9) | ((dat & 07) << 15); -return dat; -} - -/* Checksum routine */ - -int32 dt_csum (UNIT *uptr, int32 blk) -{ -int32 *bptr = uptr->filebuf; -int32 ba = blk * DTU_BSIZE (uptr); -int32 i, csum, wrd; - -csum = 0777777; -for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i]; /* get word */ - csum = csum + wrd; /* 1's comp add */ - if (csum > 0777777) csum = (csum + 1) & 0777777; } -return (csum ^ 0777777); /* 1's comp res */ -} - -/* Get header word */ - -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos) -{ -int32 wrd = relpos / DT_WSIZE; - -if (wrd == DT_BLKWD) return blk; /* fwd blknum */ -if (wrd == DT_CSMWD) return 0777777; /* rev csum */ -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ - return (dt_csum (uptr, blk)); -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */ - return dt_comobv (blk); -return 0; /* all others */ -} - -/* Reset routine */ - -t_stat dt_reset (DEVICE *dptr) -{ -int32 i, prev_mot; -UNIT *uptr; - -for (i = 0; i < DT_NUMDR; i++) { /* stop all drives */ - uptr = dt_dev.units + i; - if (sim_is_running) { /* CAF? */ - prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ - if (dt_setpos (uptr)) continue; /* update pos */ - sim_cancel (uptr); - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); - } } - else { sim_cancel (uptr); /* sim reset */ - uptr->STATE = 0; - uptr->LASTT = sim_grtime (); } } -dtsa = dtsb = 0; /* clear status */ -DT_UPDINT; /* reset interrupt */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 dt_iors (void) -{ -#if defined IOS_DTA -return ((dtsb & (DTB_ERF | DTB_DTF))? IOS_DTA: 0); -#else -return 0; -#endif -} - -/* Attach routine - - Determine 12b, 16b, or 18b/36b format - Allocate buffer - If 12b, read 12b format and convert to 18b in buffer - If 16b, read 16b format and convert to 18b in buffer - If 18b/36b, read data into buffer -*/ - -t_stat dt_attach (UNIT *uptr, char *cptr) -{ -uint16 pdp8b[D8_NBSIZE]; -uint16 pdp11b[D18_BSIZE]; -uint32 k, p, *bptr; -t_stat r; -t_addr ba; - -r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error? */ -uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default 18b */ -if (sim_switches & SWMASK ('R')) /* att 12b? */ - uptr->flags = uptr->flags | UNIT_8FMT; -else if (sim_switches & SWMASK ('S')) /* att 16b? */ - uptr->flags = uptr->flags | UNIT_11FMT; -else if (!(sim_switches & SWMASK ('T')) && /* autosize? */ - (fseek (uptr->fileref, 0, SEEK_END) == 0) && - ((p = ftell (uptr->fileref)) != 0)) { - if (p == D8_FILSIZ) uptr->flags = uptr->flags | UNIT_8FMT; - if (p == D11_FILSIZ) uptr->flags = uptr->flags | UNIT_11FMT; } -uptr->capac = DTU_CAPAC (uptr); /* set capacity */ -uptr->filebuf = calloc (uptr->capac, sizeof (int32)); -if (uptr->filebuf == NULL) { /* can't alloc? */ - detach_unit (uptr); - return SCPE_MEM; } -bptr = uptr->filebuf; /* file buffer */ -if (uptr->flags & UNIT_8FMT) printf ("DT: 12b format"); -else if (uptr->flags & UNIT_11FMT) printf ("DT: 16b format"); -else printf ("DT: 18b/36b format"); -printf (", buffering file in memory\n"); -rewind (uptr->fileref); /* start of file */ -if (uptr->flags & UNIT_8FMT) { /* 12b? */ - for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ - k = fxread (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0; - for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */ - bptr[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | - ((uint32) (pdp8b[k + 1] >> 6) & 077); - bptr[ba + 1] = ((uint32) (pdp8b[k + 1] & 077) << 12) | - (pdp8b[k + 2] & 07777); - ba = ba + 2; } /* end blk loop */ - } /* end file loop */ - uptr->hwmark = ba; } /* end if */ -else if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ - k = fxread (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0; - for (k = 0; k < D18_BSIZE; k++) - bptr[ba++] = pdp11b[k]; } - uptr->hwmark = ba; } /* end elif */ -else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32), - uptr->capac, uptr->fileref); -uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */ -uptr->pos = DT_EZLIN; /* beyond leader */ -uptr->LASTT = sim_grtime (); /* last pos update */ -return SCPE_OK; -} - -/* Detach routine - - Cancel in progress operation - If 12b, convert 18b buffer to 12b and write to file - If 16b, convert 18b buffer to 16b and write to file - If 18b/36b, write buffer to file - Deallocate buffer -*/ - -t_stat dt_detach (UNIT* uptr) -{ -uint16 pdp8b[D8_NBSIZE]; -uint16 pdp11b[D18_BSIZE]; -uint32 k, *bptr; -int32 unum = uptr - dt_dev.units; -t_addr ba; - -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if (sim_is_active (uptr)) { - sim_cancel (uptr); - if ((unum == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) { - dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF; - DT_UPDINT; } - uptr->STATE = uptr->pos = 0; } -bptr = uptr->filebuf; /* file buffer */ -if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ - printf ("DT: writing buffer to file\n"); - rewind (uptr->fileref); /* start of file */ - if (uptr->flags & UNIT_8FMT) { /* 12b? */ - for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ - for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */ - pdp8b[k] = (bptr[ba] >> 6) & 07777; - pdp8b[k + 1] = ((bptr[ba] & 077) << 6) | - ((bptr[ba + 1] >> 12) & 077); - pdp8b[k + 2] = bptr[ba + 1] & 07777; - ba = ba + 2; } /* end loop blk */ - fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; } /* end loop file */ - } /* end if 12b */ - else if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ - for (k = 0; k < D18_BSIZE; k++) /* loop blk */ - pdp11b[k] = bptr[ba++] & 0177777; - fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); - if (ferror (uptr->fileref)) break; } /* end loop file */ - } /* end if 16b */ - else fxwrite (uptr->filebuf, sizeof (int32), /* write file */ - uptr->hwmark, uptr->fileref); - if (ferror (uptr->fileref)) perror ("I/O error"); } /* end if hwmark */ -free (uptr->filebuf); /* release buf */ -uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ -uptr->filebuf = NULL; /* clear buf ptr */ -uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default fmt */ -uptr->capac = DT_CAPAC; /* default size */ -return detach_unit (uptr); -} diff --git a/PDP1o/pdp1_lp.c b/PDP1o/pdp1_lp.c deleted file mode 100644 index d4e43a84..00000000 --- a/PDP1o/pdp1_lp.c +++ /dev/null @@ -1,172 +0,0 @@ -/* pdp1_lp.c: PDP-1 line printer simulator - - Copyright (c) 1993-2002, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - lpt Type 62 line printer for the PDP-1 - - 30-May-02 RMS Widened POS to 32b - 13-Apr-01 RMS Revised for register arrays -*/ - -#include "pdp1_defs.h" - -#define BPTR_MAX 40 /* pointer max */ -#define LPT_BSIZE (BPTR_MAX * 3) /* line size */ -#define BPTR_MASK 077 /* buf ptr mask */ - -extern int32 ioc, sbs, iosta; -extern int32 stop_inst; - -int32 lpt_rpls = 0, lpt_iot = 0, lpt_stopioe = 0, bptr = 0; -char lpt_buf[LPT_BSIZE + 1] = { 0 }; -static const unsigned char lpt_trans[64] = { - ' ','1','2','3','4','5','6','7','8','9','\'','~','#','V','^','<', - '0','/','S','T','U','V','W','X','Y','Z','"',',','>','^','-','?', - '@','J','K','L','M','N','O','P','Q','R','$','=','-',')','-','(', - '_','A','B','C','D','E','F','G','H','I','*','.','+',']','|','[' }; - -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lpt_reg[] = { - { ORDATA (BUF, lpt_unit.buf, 8) }, - { FLDATA (PNT, iosta, IOS_V_PNT) }, - { FLDATA (SPC, iosta, IOS_V_SPC) }, - { FLDATA (RPLS, lpt_rpls, 0) }, - { DRDATA (BPTR, bptr, 6) }, - { ORDATA (LPT_STATE, lpt_iot, 6), REG_HRO }, - { DRDATA (POS, lpt_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { BRDATA (LBUF, lpt_buf, 8, 8, LPT_BSIZE) }, - { NULL } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, NULL, NULL, - NULL, DEV_DISABLE }; - -/* Line printer IOT routine */ - -int32 lpt (int32 inst, int32 dev, int32 data) -{ -int32 i; - -if (lpt_dev.flags & DEV_DIS) /* disabled? */ - return (stop_inst << IOT_V_REASON) | data; /* stop if requested */ -if ((inst & 0700) == 0100) { /* fill buf */ - if (bptr < BPTR_MAX) { /* limit test ptr */ - i = bptr * 3; /* cvt to chr ptr */ - lpt_buf[i] = lpt_trans[(data >> 12) & 077]; - lpt_buf[i + 1] = lpt_trans[(data >> 6) & 077]; - lpt_buf[i + 2] = lpt_trans[data & 077]; } - bptr = (bptr + 1) & BPTR_MASK; - return data; } -lpt_rpls = 0; -if ((inst & 0700) == 0200) { /* space */ - iosta = iosta & ~IOS_SPC; /* space, clear flag */ - lpt_iot = (inst >> 6) & 077; } /* state = space n */ -else { iosta = iosta & ~IOS_PNT; /* clear flag */ - lpt_iot = 0; } /* state = print */ -if (GEN_CPLS (inst)) { /* comp pulse? */ - ioc = 0; /* clear flop */ - lpt_rpls = 1; } /* request completion */ -sim_activate (&lpt_unit, lpt_unit.wait); /* activate */ -return data; -} - -/* Unit service, printer is in one of three states - - lpt_iot = 000 write buffer to file, set state to - lpt_iot = 010 write cr, then write buffer to file - lpt_iot = 02x space command x, then set state to 0 -*/ - -t_stat lpt_svc (UNIT *uptr) -{ -int32 i; -static const char *lpt_cc[] = { - "\n", - "\n\n", - "\n\n\n", - "\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\f" }; - -sbs = sbs | SB_RQ; /* req seq break */ -ioc = ioc | lpt_rpls; /* restart */ -if (lpt_iot & 020) { /* space? */ - iosta = iosta | IOS_SPC; /* set flag */ - if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); - fputs (lpt_cc[lpt_iot & 07], lpt_unit.fileref); /* print cctl */ - if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } - lpt_iot = 0; } /* clear state */ -else { iosta = iosta | IOS_PNT; /* print */ - if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); - if (lpt_iot & 010) fputc ('\r', lpt_unit.fileref); - fputs (lpt_buf, lpt_unit.fileref); /* print buffer */ - if (ferror (lpt_unit.fileref)) { /* test error */ - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } - bptr = 0; - for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ - lpt_iot = 010; } /* set state */ -lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -int32 i; - -iosta = iosta & ~(IOS_PNT | IOS_SPC); /* clear flags */ -bptr = 0; /* clear buffer ptr */ -for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ -lpt_iot = 0; /* clear state */ -lpt_rpls = 0; -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/PDP1o/pdp1_stddev.c b/PDP1o/pdp1_stddev.c deleted file mode 100644 index aa8c5c71..00000000 --- a/PDP1o/pdp1_stddev.c +++ /dev/null @@ -1,427 +0,0 @@ -/* pdp1_stddev.c: PDP-1 standard devices - - Copyright (c) 1993-2002, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - ptr paper tape reader - ptp paper tape punch - tti keyboard - tto teleprinter - - 06-Oct-02 RMS Revised for V2.10 - 30-May-02 RMS Widened POS to 32b - 29-Nov-01 RMS Added read only unit support - 07-Sep-01 RMS Moved function prototypes - 10-Jun-01 RMS Fixed comment - 30-Oct-00 RMS Standardized device naming -*/ - -#include "pdp1_defs.h" - -#define FIODEC_UC 074 -#define FIODEC_LC 072 -#define UC 0100 /* upper case */ -#define BOTH 0200 /* both cases */ -#define CW 0400 /* char waiting */ -#define TT_WIDTH 077 - -extern int32 sbs, ioc, iosta, PF, IO, PC; -extern int32 M[]; - -int32 ptr_rpls = 0, ptr_stopioe = 0, ptr_state = 0; -int32 ptp_rpls = 0, ptp_stopioe = 0; -int32 tti_state = 0; -int32 tto_rpls = 0, tto_state = 0; - -t_stat ptr_svc (UNIT *uptr); -t_stat ptp_svc (UNIT *uptr); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptp_reset (DEVICE *dptr); -t_stat tti_reset (DEVICE *dptr); -t_stat tto_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); - -/* Character translation tables */ - -int32 fiodec_to_ascii[128] = { - ' ', '1', '2', '3', '4', '5', '6', '7', /* lower case */ - '8', '9', 0, 0, 0, 0, 0, 0, - '0', '/', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', 0, ',', 0, 0, '\t', 0, - '@', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 0, 0, '-', ')', '\\', '(', - 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', '{', '.', '}', '\b', 0, '\r', - ' ', '"', '\'', '~', '#', '!', '&', '<', /* upper case */ - '>', '^', 0, 0, 0, 0, 0, 0, - '`', '?', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 0, '=', 0, 0, '\t', 0, - '_', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 0, 0, '+', ']', '|', '[', - 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '{', '*', '}', '\b', 0, '\r' }; - -int32 ascii_to_fiodec[128] = { - 0, 0, 0, 0, 0, 0, 0, 0, - BOTH+075, BOTH+036, 0, 0, 0, BOTH+077, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - BOTH+0, UC+005, UC+001, UC+004, 0, 0, UC+006, UC+002, - 057, 055, UC+073, UC+054, 033, 054, 073, 021, - 020, 001, 002, 003, 004, 005, 006, 007, - 010, 011, 0, 0, UC+007, UC+033, UC+010, UC+021, - 040, UC+061, UC+062, UC+063, UC+064, UC+065, UC+066, UC+067, - UC+070, UC+071, UC+041, UC+042, UC+043, UC+044, UC+045, UC+046, - UC+047, UC+050, UC+051, UC+022, UC+023, UC+024, UC+025, UC+026, - UC+027, UC+030, UC+031, UC+057, 056, UC+055, UC+011, UC+040, - UC+020, 061, 062, 063, 064, 065, 066, 067, - 070, 071, 041, 042, 043, 044, 045, 046, - 047, 050, 051, 022, 023, 024, 025, 026, - 027, 030, 031, 0, UC+056, 0, UC+003, BOTH+075 }; - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit - ptr_reg PTR register list -*/ - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { ORDATA (BUF, ptr_unit.buf, 18) }, - { FLDATA (DONE, iosta, IOS_V_PTR) }, - { FLDATA (RPLS, ptr_rpls, 0) }, - { ORDATA (STATE, ptr_state, 5), REG_HRO }, - { DRDATA (POS, ptr_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL, - NULL, 0 }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit - ptp_reg PTP register list -*/ - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (DONE, iosta, IOS_V_PTP) }, - { FLDATA (RPLS, ptp_rpls, 0) }, - { DRDATA (POS, ptp_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit - tti_reg TTI register list -*/ - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 6) }, - { FLDATA (DONE, iosta, IOS_V_TTI) }, - { ORDATA (STATE, tti_state, 10), REG_HRO }, - { DRDATA (POS, tti_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit - tto_reg TTO register list -*/ - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 6) }, - { FLDATA (DONE, iosta, IOS_V_TTO) }, - { FLDATA (RPLS, tto_rpls, 0) }, - { ORDATA (STATE, tto_state, 10), REG_HRO }, - { DRDATA (POS, tto_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* Paper tape reader: IOT routine */ - -int32 ptr (int32 inst, int32 dev, int32 data) -{ -iosta = iosta & ~IOS_PTR; /* clear flag */ -if (dev == 0030) return ptr_unit.buf; /* RRB */ -ptr_state = (dev == 0002)? 18: 0; /* mode = bin/alp */ -ptr_rpls = 0; -ptr_unit.buf = 0; /* clear buffer */ -sim_activate (&ptr_unit, ptr_unit.wait); -if (GEN_CPLS (inst)) { /* comp pulse? */ - ioc = 0; - ptr_rpls = 1; } -return data; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptr_stopioe, SCPE_UNATT); -if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ - if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -ptr_unit.pos = ptr_unit.pos + 1; -if (ptr_state == 0) ptr_unit.buf = temp & 0377; /* alpha */ -else if (temp & 0200) { /* binary */ - ptr_state = ptr_state - 6; - ptr_unit.buf = ptr_unit.buf | ((temp & 077) << ptr_state); } -if (ptr_state == 0) { /* done? */ - if (ptr_rpls) IO = ptr_unit.buf; /* restart? fill IO */ - iosta = iosta | IOS_PTR; /* set flag */ - sbs = sbs | SB_RQ; /* req seq break */ - ioc = ioc | ptr_rpls; } /* restart */ -else sim_activate (&ptr_unit, ptr_unit.wait); /* get next char */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_state = 0; /* clear state */ -ptr_unit.buf = 0; -ptr_rpls = 0; -iosta = iosta & ~IOS_PTR; /* clear flag */ -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 07772 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 0730002, /* r, rpb + wait */ - 0327776, /* dio x */ - 0107776, /* xct x */ - 0730002, /* rpb + wait */ - 0760400, /* x, halt */ - 0607772 /* jmp r */ -}; - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -PC = BOOT_START; -return SCPE_OK; -} - -/* Paper tape punch: IOT routine */ - -int32 ptp (int32 inst, int32 dev, int32 data) -{ -iosta = iosta & ~IOS_PTP; /* clear flag */ -ptp_rpls = 0; -ptp_unit.buf = (dev == 0006)? ((data >> 12) | 0200): (data & 0377); -sim_activate (&ptp_unit, ptp_unit.wait); /* start unit */ -if (GEN_CPLS (inst)) { /* comp pulse? */ - ioc = 0; - ptp_rpls = 1; } -return data; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -iosta = iosta | IOS_PTP; /* set flag */ -sbs = sbs | SB_RQ; /* req seq break */ -ioc = ioc | ptp_rpls; /* process restart */ -if ((ptp_unit.flags & UNIT_ATT) == 0) /* not attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* I/O error? */ - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ptp_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -ptp_unit.buf = 0; /* clear state */ -ptp_rpls = 0; -iosta = iosta & ~IOS_PTP; /* clear flag */ -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Terminal input: IOT routine */ - -int32 tti (int32 inst, int32 dev, int32 data) -{ -iosta = iosta & ~IOS_TTI; /* clear flag */ -if (inst & (IO_WAIT | IO_CPLS)) /* wait or sync? */ - return (STOP_RSRV << IOT_V_REASON) | (tti_unit.buf & 077); -return tti_unit.buf & 077; -} - -/* Unit service */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 in, temp; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if (tti_state & CW) { /* char waiting? */ - tti_unit.buf = tti_state & TT_WIDTH; /* return char */ - tti_state = tti_state & ~CW; } /* not waiting */ -else { if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; - temp = temp & 0177; - if (temp == 0177) temp = '\b'; /* rubout? bs */ - sim_putchar (temp); /* echo */ - if (temp == '\r') sim_putchar ('\n'); /* cr? add nl */ - in = ascii_to_fiodec[temp]; /* translate char */ - if (in == 0) return SCPE_OK; /* no xlation? */ - if ((in & BOTH) || ((in & UC) == (tti_state & UC))) - tti_unit.buf = in & TT_WIDTH; - else { tti_unit.buf = (in & UC)? FIODEC_UC: FIODEC_LC; - tti_state = in | CW; } } /* set 2nd waiting */ -iosta = iosta | IOS_TTI; /* set flag */ -sbs = sbs | SB_RQ; /* req seq break */ -PF = PF | 040; /* set prog flag 1 */ -tti_unit.pos = tti_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; /* clear buffer */ -tti_state = 0; /* clear state */ -iosta = iosta & ~IOS_TTI; /* clear flag */ -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto (int32 inst, int32 dev, int32 data) -{ -iosta = iosta & ~IOS_TTO; /* clear flag */ -tto_rpls = 0; -tto_unit.buf = data & TT_WIDTH; /* load buffer */ -sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ -if (GEN_CPLS (inst)) { /* comp pulse? */ - ioc = 0; - tto_rpls = 1; } -return data; -} - -/* Unit service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 out; - -iosta = iosta | IOS_TTO; /* set flag */ -sbs = sbs | SB_RQ; /* req seq break */ -ioc = ioc | tto_rpls; /* process restart */ -if (tto_unit.buf == FIODEC_UC) { /* upper case? */ - tto_state = UC; - return SCPE_OK; } -if (tto_unit.buf == FIODEC_LC) { /* lower case? */ - tto_state = 0; - return SCPE_OK; } -out = fiodec_to_ascii[tto_unit.buf | tto_state]; /* translate */ -if (out == 0) return SCPE_OK; /* no translation? */ -sim_putchar (out); -tto_unit.pos = tto_unit.pos + 1; -if (out == '\r') { /* cr? add lf */ - sim_putchar ('\n'); - tto_unit.pos = tto_unit.pos + 1; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; /* clear buffer */ -tto_state = 0; /* clear state */ -tto_rpls = 0; -iosta = iosta & ~IOS_TTO; /* clear flag */ -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/PDP1o/pdp1_sys.c b/PDP1o/pdp1_sys.c deleted file mode 100644 index 0a61f15b..00000000 --- a/PDP1o/pdp1_sys.c +++ /dev/null @@ -1,458 +0,0 @@ -/* pdp1_sys.c: PDP-1 simulator interface - - Copyright (c) 1993-2002, Robert M. Supnik - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of Robert M Supnik shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. - - 20-Aug-02 RMS Added DECtape support - 17-Sep-01 RMS Removed multiconsole support - 13-Jul-01 RMS Fixed RIM loader format - 27-May-01 RMS Added multiconsole support - 14-Mar-01 RMS Revised load/dump interface (again) - 30-Oct-00 RMS Added support for examine to file - 27-Oct-98 RMS V2.4 load interface - 20-Oct-97 RMS Fixed endian-dependence in RIM loader - (found by Michael Somos) -*/ - -#include "pdp1_defs.h" -#include - -extern DEVICE cpu_dev; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tti_dev, tto_dev; -extern DEVICE lpt_dev, dt_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern int32 M[]; -extern int32 PC; -extern int32 ascii_to_fiodec[], fiodec_to_ascii[]; -extern int32 sc_map[]; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "PDP-1"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 1; - -DEVICE *sim_devices[] = { - &cpu_dev, - &ptr_dev, - &ptp_dev, - &tti_dev, - &tto_dev, - &lpt_dev, - &dt_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Undefined instruction", - "HALT instruction", - "Breakpoint", - "Nested XCT's", - "Nested indirect addresses", - "Infinite wait state" }; - -/* Binary loader - - At the moment, implements RIM loader format -*/ - -int32 getword (FILE *fileref) -{ -int32 i, tmp, word; - -word = 0; -for (i = 0; i < 3;) { - if ((tmp = getc (fileref)) == EOF) return -1; - if (tmp & 0200) { - word = (word << 6) | (tmp & 077); - i++; } } -return word; -} - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 origin, val; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -for (;;) { - if ((val = getword (fileref)) < 0) return SCPE_FMT; - if (((val & 0770000) == 0320000) || /* DIO? */ - ((val & 0770000) == 0240000)) { /* DAC? - incorrect */ - origin = val & 07777; - if ((val = getword (fileref)) < 0) return SCPE_FMT; - if (MEM_ADDR_OK (origin)) M[origin++] = val; } - else if ((val & 0770000) == 0600000) { /* JMP? */ - PC = val & 007777; - break; } - } -return SCPE_OK; /* done */ -} - -/* Symbol tables */ - -#define I_V_FL 18 /* inst class */ -#define I_M_FL 07 /* class mask */ -#define I_V_NPN 0 /* no operand */ -#define I_V_IOT 1 /* IOT */ -#define I_V_LAW 2 /* LAW */ -#define I_V_MRF 3 /* memory reference */ -#define I_V_MRI 4 /* mem ref no ind */ -#define I_V_OPR 5 /* OPR */ -#define I_V_SKP 6 /* skip */ -#define I_V_SHF 7 /* shift */ -#define I_NPN (I_V_NPN << I_V_FL) /* no operand */ -#define I_IOT (I_V_IOT << I_V_FL) /* IOT */ -#define I_LAW (I_V_LAW << I_V_FL) /* LAW */ -#define I_MRF (I_V_MRF << I_V_FL) /* memory reference */ -#define I_MRI (I_V_MRI << I_V_FL) /* mem ref no ind */ -#define I_OPR (I_V_OPR << I_V_FL) /* OPR */ -#define I_SKP (I_V_SKP << I_V_FL) /* skip */ -#define I_SHF (I_V_SHF << I_V_FL) /* shift */ - -static const int32 masks[] = { - 0777777, 0763777, 0760000, 0760000, - 0770000, 0760017, 0760077, 0777000 }; - -static const char *opcode[] = { - "AND", "IOR", "XOR", "XCT", /* mem refs */ - "LAC", "LIO", "DAC", "DAP", - "DIP", "DIO", "DZM", "ADD", - "SUB", "IDX", "ISP", "SAD", - "SAS", "MUL", "DIV", "JMP", "JSP", - - "CAL", "JDA", /* mem ref no ind */ - - "IOH", "RPA", "RPB", "RRB", /* I/O instructions */ - "PPA", "PPB", "TYO", "TYI", - "LSM", "ESM", "CBS", - "LEM", "EEM", "CKS", - "MSE", "MLC", "MRD", "MWR", "MRS", - - "SKP", "SKP I", "CLO", - "SFT", "LAW", "OPR", - - "RAL", "RIL", "RCL", /* shifts */ - "SAL", "SIL", "SCL", - "RAR", "RIR", "RCR", - "SAR", "SIR", "SCR", - - "SZF1", "SZF2", "SZF3", /* skips */ - "SZF4", "SZF5", "SZF6", "SZF7", - "SZS1", "SZS1 SZF1", "SZS1 SZF2", "SZS1 SZ3", - "SZS1 SZF4", "SZS1 SZF5", "SZS1 SZF6", "SZS1 SZF7", - "SZS2", "SZS2 SZF1", "SZS2 SZF2", "SZS2 SZ3", - "SZS2 SZF4", "SZS2 SZF5", "SZS2 SZF6", "SZS2 SZF7", - "SZS3", "SZS3 SZF1", "SZS3 SZF2", "SZS3 SZ3", - "SZS3 SZF4", "SZS3 SZF5", "SZS3 SZF6", "SZS3 SZF7", - "SZS4", "SZS4 SZF1", "SZS4 SZF2", "SZS4 SZ3", - "SZS4 SZF4", "SZS4 SZF5", "SZS4 SZF6", "SZS4 SZF7", - "SZS5", "SZS5 SZF1", "SZS5 SZF2", "SZS5 SZ3", - "SZS5 SZF4", "SZS5 SZF5", "SZS5 SZF6", "SZS5 SZF7", - "SZS6", "SZS6 SZF1", "SZS6 SZF2", "SZS6 SZ3", - "SZS6 SZF4", "SZS6 SZF5", "SZS6 SZF6", "SZS6 SZF7", - "SZS7", "SZS7 SZF1", "SZS7 SZF2", "SZS7 SZ3", - "SZS7 SZF4", "SZS7 SZF5", "SZS7 SZF6", "SZS7 SZF7", - - "CLF1", "CLF2", "CLF3", /* operates */ - "CLF4", "CLF5", "CLF6", "CLF7", - "STF1", "STF2", "STF3", - "STF4", "STF5", "STF6", "STF7", - - "SZA", "SPA", "SMA", /* encode only */ - "SZO", "SPI", "I", - "LAP", "CLA", "HLT", - "CMA", "LAT", "CLI", - NULL, NULL, /* decode only */ - NULL }; - -static const int32 opc_val[] = { - 0020000+I_MRF, 0040000+I_MRF, 0060000+I_MRF, 0100000+I_MRF, - 0200000+I_MRF, 0220000+I_MRF, 0240000+I_MRF, 0260000+I_MRF, - 0300000+I_MRF, 0320000+I_MRF, 0340000+I_MRF, 0400000+I_MRF, - 0420000+I_MRF, 0440000+I_MRF, 0460000+I_MRF, 0500000+I_MRF, - 0520000+I_MRF, 0540000+I_MRF, 0560000+I_MRF, 0600000+I_MRF, 0620000+I_MRF, - - 0160000+I_MRI, 0170000+I_MRI, - - 0730000+I_NPN, 0720001+I_IOT, 0720002+I_IOT, 0720030+I_IOT, - 0720005+I_IOT, 0720006+I_IOT, 0720003+I_IOT, 0720004+I_IOT, - 0720054+I_NPN, 0720055+I_NPN, 0720056+I_NPN, - 0720074+I_NPN, 0724074+I_NPN, 0720033+I_NPN, - 0720301+I_NPN, 0720401+I_NPN, 0720501+I_NPN, 0720601+I_NPN, 0720701+I_NPN, - - 0640000+I_NPN, 0650000+I_NPN, 0651600+I_NPN, - 0660000+I_NPN, 0700000+I_LAW, 0760000+I_NPN, - - 0661000+I_SHF, 0662000+I_SHF, 0663000+I_SHF, - 0665000+I_SHF, 0666000+I_SHF, 0667000+I_SHF, - 0671000+I_SHF, 0672000+I_SHF, 0673000+I_SHF, - 0675000+I_SHF, 0676000+I_SHF, 0677000+I_SHF, - - 0640001+I_SKP, 0640002+I_SKP, 0640003+I_SKP, - 0640004+I_SKP, 0640005+I_SKP, 0640006+I_SKP, 0640007+I_SKP, - 0640010+I_SKP, 0640011+I_SKP, 0640012+I_SKP, 0640013+I_SKP, - 0640014+I_SKP, 0640015+I_SKP, 0640016+I_SKP, 0640017+I_SKP, - 0640020+I_SKP, 0640021+I_SKP, 0640022+I_SKP, 0640023+I_SKP, - 0640024+I_SKP, 0640025+I_SKP, 0640026+I_SKP, 0640027+I_SKP, - 0640030+I_SKP, 0640031+I_SKP, 0640032+I_SKP, 0640033+I_SKP, - 0640034+I_SKP, 0640035+I_SKP, 0640036+I_SKP, 0640037+I_SKP, - 0640040+I_SKP, 0640041+I_SKP, 0640042+I_SKP, 0640043+I_SKP, - 0640044+I_SKP, 0640045+I_SKP, 0640046+I_SKP, 0640047+I_SKP, - 0640050+I_SKP, 0640051+I_SKP, 0640052+I_SKP, 0640053+I_SKP, - 0640054+I_SKP, 0640055+I_SKP, 0640056+I_SKP, 0640057+I_SKP, - 0640060+I_SKP, 0640061+I_SKP, 0640062+I_SKP, 0640063+I_SKP, - 0640064+I_SKP, 0640065+I_SKP, 0640066+I_SKP, 0640067+I_SKP, - 0640070+I_SKP, 0640071+I_SKP, 0640072+I_SKP, 0640073+I_SKP, - 0640074+I_SKP, 0640075+I_SKP, 0640076+I_SKP, 0640077+I_SKP, - - 0760001+I_OPR, 0760002+I_OPR, 0760003+I_OPR, - 0760004+I_OPR, 0760005+I_OPR, 0760006+I_OPR, 0760007+I_OPR, - 0760011+I_OPR, 0760012+I_OPR, 0760013+I_OPR, - 0760014+I_OPR, 0760015+I_OPR, 0760016+I_OPR, 0760017+I_OPR, - - 0640100+I_SKP, 0640200+I_SKP, 0640400+I_SKP, /* encode only */ - 0641000+I_SKP, 0642000+I_SKP, 0010000+I_SKP, - 0760100+I_OPR, 0760200+I_OPR, 0760400+I_OPR, - 0761000+I_OPR, 0762000+I_OPR, 0764000+I_OPR, - - 0640000+I_SKP, 0760000+I_OPR, /* decode only */ - -1 }; - -/* Operate or skip decode - - Inputs: - *of = output stream - inst = mask bits - class = instruction class code - sp = space needed? - Outputs: - status = space needed? -*/ - -int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp) -{ -int32 i, j; - -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((j == class) && (opc_val[i] & inst)) { /* same class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } -return sp; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) -#define SIXTOASC(x) fiodec_to_ascii[x] -#define ASCTOSIX(x) (ascii_to_fiodec[x] & 077) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, sp, inst, disp, ma; - -inst = val[0]; -cflag = (uptr == NULL) || (uptr == &cpu_unit); -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* character? */ - fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077)); - fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077)); - fprintf (of, "%c", SIXTOASC (inst & 077)); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -disp = inst & 007777; -ma = (addr & EPCMASK) | disp; -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - if ((opc_val[i] & 0777777) == (inst & masks[j])) { /* match? */ - - switch (j) { /* case on class */ - case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; - case I_V_IOT: /* IOT */ - disp = (inst - opc_val[i]) & 017777; - if (disp == IA) fprintf (of, "%s I", opcode[i]); - else if (disp) fprintf (of, "%s %-o", opcode[i], disp); - else fprintf (of, "%s", opcode[i]); - break; - case I_V_LAW: /* LAW */ - cflag = 0; /* fall thru to MRF */ - case I_V_MRF: /* mem ref */ - fprintf (of, "%s%s%-o", opcode[i], - ((inst & IA)? " I ": " "), (cflag? ma: disp)); - break; - case I_V_MRI: /* mem ref no ind */ - fprintf (of, "%s %-o", opcode[i], (cflag? ma: disp)); - break; - case I_V_OPR: /* operates */ - sp = fprint_opr (of, inst & 007700, j, 0); - if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); - break; - case I_V_SKP: /* skips */ - sp = fprint_opr (of, inst & 007700, j, 0); - if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]); - if (inst & IA) fprintf (of, sp? " I": "I"); - break; - case I_V_SHF: /* shifts */ - fprintf (of, "%s %-d", opcode[i], sc_map[inst & 0777]); - break; } /* end case */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Get 18b signed number - - Inputs: - *cptr = pointer to input string - *sign = pointer to sign - *status = pointer to error status - Outputs: - val = output value -*/ - -t_value get_sint (char *cptr, int32 *sign, t_stat *status) -{ -*sign = 1; -if (*cptr == '+') { - *sign = 0; - cptr++; } -else if (*cptr == '-') { - *sign = -1; - cptr++; } -return get_uint (cptr, 8, 0777777, status); -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, d, i, j, k, sign; -t_stat r; -static int32 sc_enc[10] = { 0, 01, 03, 07, 017, 037, 077, 0177, 0377, 0777 }; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; -for (i = 1; (i < 3) && (cptr[i] != 0); i++) - if (cptr[i] == 0) for (j = i + 1; j <= 3; j++) cptr[j] = 0; -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) cptr[0]; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (ASCTOSIX (cptr[0] & 077) << 12) | - (ASCTOSIX (cptr[1] & 077) << 6) | - ASCTOSIX (cptr[2] & 077); - return SCPE_OK; } - -/* Symbolic input, continued */ - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & 0777777; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - -switch (j) { /* case on class */ -case I_V_LAW: /* LAW */ - cflag = 0; /* fall through */ -case I_V_MRF: case I_V_MRI: /* mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if ((j != I_V_MRI) && strcmp (gbuf, "I") == 0) { /* indirect? */ - val[0] = val[0] | IA; - cptr = get_glyph (cptr, gbuf, 0); } - d = get_uint (gbuf, 8, AMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (d <= DAMASK) val[0] = val[0] | d; - else if (cflag && (((addr ^ d) & EPCMASK) == 0)) - val[0] = val[0] | (d & DAMASK); - else return SCPE_ARG; - break; -case I_V_SHF: /* shift */ - cptr = get_glyph (cptr, gbuf, 0); - d = get_uint (gbuf, 10, 9, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | sc_enc[d]; - break; -case I_V_NPN: case I_V_IOT: case I_V_OPR: case I_V_SKP: - for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && - (strcmp (opcode[i], gbuf) != 0) ; i++) ; - if (opcode[i] != NULL) { - k = opc_val[i] & 0777777; - if ((k != IA) && (((k ^ val[0]) & 0760000) != 0)) - return SCPE_ARG; - val[0] = val[0] | k; } - else { d = get_sint (gbuf, &sign, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (sign == 0) val[0] = val[0] + d; - else if (sign < 0) val[0] = val[0] - d; - else val[0] = val[0] | d; } } - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return SCPE_OK; -} diff --git a/PDP8/pdp8_clk.c b/PDP8/pdp8_clk.c index 7030c739..27b24f20 100644 --- a/PDP8/pdp8_clk.c +++ b/PDP8/pdp8_clk.c @@ -94,9 +94,9 @@ case 2: /* CLDI */ return AC; case 3: /* CLSC */ if (dev_done & INT_CLK) { /* flag set? */ - dev_done = dev_done & ~INT_CLK; /* clear flag */ - int_req = int_req & ~INT_CLK; /* clear int req */ - return IOT_SKP + AC; } + dev_done = dev_done & ~INT_CLK; /* clear flag */ + int_req = int_req & ~INT_CLK; /* clear int req */ + return IOT_SKP + AC; } return AC; case 5: /* CLLE */ if (AC & 1) int_enable = int_enable | INT_CLK; /* test AC<11> */ diff --git a/PDP8/pdp8_cpu.c b/PDP8/pdp8_cpu.c index 2c0e147f..6f33d562 100644 --- a/PDP8/pdp8_cpu.c +++ b/PDP8/pdp8_cpu.c @@ -524,142 +524,143 @@ case 027: /* JMP, indir, curr */ case 034:case 035: /* OPR, group 1 */ switch ((IR >> 4) & 017) { /* decode IR<4:7> */ case 0: /* nop */ - break; + break; case 1: /* CML */ - LAC = LAC ^ 010000; - break; + LAC = LAC ^ 010000; + break; case 2: /* CMA */ - LAC = LAC ^ 07777; - break; + LAC = LAC ^ 07777; + break; case 3: /* CMA CML */ - LAC = LAC ^ 017777; - break; + LAC = LAC ^ 017777; + break; case 4: /* CLL */ - LAC = LAC & 07777; - break; + LAC = LAC & 07777; + break; case 5: /* CLL CML = STL */ - LAC = LAC | 010000; - break; + LAC = LAC | 010000; + break; case 6: /* CLL CMA */ - LAC = (LAC ^ 07777) & 07777; - break; + LAC = (LAC ^ 07777) & 07777; + break; case 7: /* CLL CMA CML */ - LAC = (LAC ^ 07777) | 010000; - break; + LAC = (LAC ^ 07777) | 010000; + break; case 010: /* CLA */ - LAC = LAC & 010000; - break; + LAC = LAC & 010000; + break; case 011: /* CLA CML */ - LAC = (LAC & 010000) ^ 010000; - break; + LAC = (LAC & 010000) ^ 010000; + break; case 012: /* CLA CMA = STA */ - LAC = LAC | 07777; - break; + LAC = LAC | 07777; + break; case 013: /* CLA CMA CML */ - LAC = (LAC | 07777) ^ 010000; - break; + LAC = (LAC | 07777) ^ 010000; + break; case 014: /* CLA CLL */ - LAC = 0; - break; + LAC = 0; + break; case 015: /* CLA CLL CML */ - LAC = 010000; - break; + LAC = 010000; + break; case 016: /* CLA CLL CMA */ - LAC = 07777; - break; + LAC = 07777; + break; case 017: /* CLA CLL CMA CML */ - LAC = 017777; - break; } /* end switch opers */ + LAC = 017777; + break; } /* end switch opers */ /* OPR group 1, continued */ if (IR & 01) LAC = (LAC + 1) & 017777; /* IAC */ switch ((IR >> 1) & 07) { /* decode IR<8:10> */ case 0: /* nop */ - break; + break; case 1: /* BSW */ - LAC = (LAC & 010000) | ((LAC >> 6) & 077) | ((LAC & 077) << 6); - break; + LAC = (LAC & 010000) | ((LAC >> 6) & 077) | ((LAC & 077) << 6); + break; case 2: /* RAL */ - LAC = ((LAC << 1) | (LAC >> 12)) & 017777; - break; + LAC = ((LAC << 1) | (LAC >> 12)) & 017777; + break; case 3: /* RTL */ - LAC = ((LAC << 2) | (LAC >> 11)) & 017777; - break; + LAC = ((LAC << 2) | (LAC >> 11)) & 017777; + break; case 4: /* RAR */ - LAC = ((LAC >> 1) | (LAC << 12)) & 017777; - break; + LAC = ((LAC >> 1) | (LAC << 12)) & 017777; + break; case 5: /* RTR */ - LAC = ((LAC >> 2) | (LAC << 11)) & 017777; - break; + LAC = ((LAC >> 2) | (LAC << 11)) & 017777; + break; case 6: /* RAL RAR - undef */ - LAC = LAC & (IR | 010000); /* uses AND path */ - break; + LAC = LAC & (IR | 010000); /* uses AND path */ + break; case 7: /* RTL RTR - undef */ - LAC = (LAC & 010000) | (MA & 07600) | (IR & 0177); - break; } /* uses address path */ + LAC = (LAC & 010000) | (MA & 07600) | (IR & 0177); + break; } /* uses address path */ break; /* end group 1 */ /* OPR group 2 */ case 036:case 037: /* OPR, groups 2, 3 */ if ((IR & 01) == 0) { /* group 2 */ - switch ((IR >> 3) & 017) { /* decode IR<6:8> */ - case 0: /* nop */ - break; - case 1: /* SKP */ + switch ((IR >> 3) & 017) { /* decode IR<6:8> */ + case 0: /* nop */ + break; + case 1: /* SKP */ + PC = (PC + 1) & 07777; + break; + case 2: /* SNL */ + if (LAC >= 010000) PC = (PC + 1) & 07777; + break; + case 3: /* SZL */ + if (LAC < 010000) PC = (PC + 1) & 07777; + break; + case 4: /* SZA */ + if ((LAC & 07777) == 0) PC = (PC + 1) & 07777; + break; + case 5: /* SNA */ + if ((LAC & 07777) != 0) PC = (PC + 1) & 07777; + break; + case 6: /* SZA | SNL */ + if ((LAC == 0) || (LAC >= 010000)) + PC = (PC + 1) & 07777; + break; + case 7: /* SNA & SZL */ + if ((LAC != 0) && (LAC < 010000)) PC = (PC + 1) & 07777; + break; + case 010: /* SMA */ + if ((LAC & 04000) != 0) PC = (PC + 1) & 07777; + break; + case 011: /* SPA */ + if ((LAC & 04000) == 0) PC = (PC + 1) & 07777; + break; + case 012: /* SMA | SNL */ + if (LAC >= 04000) PC = (PC + 1) & 07777; + break; + case 013: /* SPA & SZL */ + if (LAC < 04000) PC = (PC + 1) & 07777; + break; + case 014: /* SMA | SZA */ + if (((LAC & 04000) != 0) || ((LAC & 07777) == 0)) + PC = (PC + 1) & 07777; + break; + case 015: /* SPA & SNA */ + if (((LAC & 04000) == 0) && ((LAC & 07777) != 0)) PC = (PC + 1) & 07777; - break; - case 2: /* SNL */ - if (LAC >= 010000) PC = (PC + 1) & 07777; - break; - case 3: /* SZL */ - if (LAC < 010000) PC = (PC + 1) & 07777; - break; - case 4: /* SZA */ - if ((LAC & 07777) == 0) PC = (PC + 1) & 07777; - break; - case 5: /* SNA */ - if ((LAC & 07777) != 0) PC = (PC + 1) & 07777; - break; - case 6: /* SZA | SNL */ - if ((LAC == 0) || (LAC >= 010000)) - PC = (PC + 1) & 07777; - break; - case 7: /* SNA & SZL */ - if ((LAC != 0) && (LAC < 010000)) PC = (PC + 1) & 07777; - break; - case 010: /* SMA */ - if ((LAC & 04000) != 0) PC = (PC + 1) & 07777; - break; - case 011: /* SPA */ - if ((LAC & 04000) == 0) PC = (PC + 1) & 07777; - break; - case 012: /* SMA | SNL */ - if (LAC >= 04000) PC = (PC + 1) & 07777; - break; - case 013: /* SPA & SZL */ - if (LAC < 04000) PC = (PC + 1) & 07777; - break; - case 014: /* SMA | SZA */ - if (((LAC & 04000) != 0) || ((LAC & 07777) == 0)) - PC = (PC + 1) & 07777; - break; - case 015: /* SPA & SNA */ - if (((LAC & 04000) == 0) && ((LAC & 07777) != 0)) - PC = (PC + 1) & 07777; - break; - case 016: /* SMA | SZA | SNL */ - if ((LAC >= 04000) || (LAC == 0)) PC = (PC + 1) & 07777; - break; - case 017: /* SPA & SNA & SZL */ - if ((LAC < 04000) && (LAC != 0)) PC = (PC + 1) & 07777; - break; } /* end switch skips */ - if (IR & 0200) LAC = LAC & 010000; /* CLA */ - if ((IR & 06) && UF) int_req = int_req | INT_UF; - else { if (IR & 04) LAC = LAC | OSR; /* OSR */ - if (IR & 02) reason = STOP_HALT; } /* HLT */ - break; } /* end group 2 */ + break; + case 016: /* SMA | SZA | SNL */ + if ((LAC >= 04000) || (LAC == 0)) PC = (PC + 1) & 07777; + break; + case 017: /* SPA & SNA & SZL */ + if ((LAC < 04000) && (LAC != 0)) PC = (PC + 1) & 07777; + break; } /* end switch skips */ + if (IR & 0200) LAC = LAC & 010000; /* CLA */ + if ((IR & 06) && UF) int_req = int_req | INT_UF; + else { + if (IR & 04) LAC = LAC | OSR; /* OSR */ + if (IR & 02) reason = STOP_HALT; } /* HLT */ + break; } /* end group 2 */ /* OPR group 3 standard @@ -673,12 +674,12 @@ case 036:case 037: /* OPR, groups 2, 3 */ temp = MQ; /* group 3 */ if (IR & 0200) LAC = LAC & 010000; /* CLA */ if (IR & 0020) { /* MQL */ - MQ = LAC & 07777; - LAC = LAC & 010000; } + MQ = LAC & 07777; + LAC = LAC & 010000; } if (IR & 0100) LAC = LAC | temp; /* MQA */ if ((IR & 0056) && (cpu_unit.flags & UNIT_NOEAE)) { - reason = stop_inst; /* EAE not present */ - break; } + reason = stop_inst; /* EAE not present */ + break; } /* OPR group 3 EAE @@ -697,11 +698,11 @@ case 036:case 037: /* OPR, groups 2, 3 */ */ if (IR == 07431) { /* SWAB */ - emode = 1; /* set mode flag */ - break; } + emode = 1; /* set mode flag */ + break; } if (IR == 07447) { /* SWBA */ - emode = gtf = 0; /* clear mode, gtf */ - break; } + emode = gtf = 0; /* clear mode, gtf */ + break; } /* If not switching modes, the EAE operation is determined by the mode and IR<6,8:10>: @@ -736,271 +737,273 @@ case 036:case 037: /* OPR, groups 2, 3 */ if (emode == 0) gtf = 0; /* mode A? clr gtf */ switch ((IR >> 1) & 027) { /* decode IR<6,8:10> */ case 020: /* mode A, B: SCA */ - LAC = LAC | SC; - break; + LAC = LAC | SC; + break; case 0: /* mode A, B: NOP */ - break; + break; case 021: /* mode B: DAD */ - if (emode) { - MA = IF | PC; - INDIRECT; /* defer state */ - MQ = MQ + M[MA]; - MA = DF | ((MA + 1) & 07777); - LAC = (LAC & 07777) + M[MA] + (MQ >> 12); - MQ = MQ & 07777; - PC = (PC + 1) & 07777; - break; } - LAC = LAC | SC; /* mode A: SCA then */ - case 1: /* mode B: ACS */ - if (emode) { - SC = LAC & 037; - LAC = LAC & 010000; - break; } - SC = (~M[IF | PC]) & 037; /* mode A: SCL */ - PC = (PC + 1) & 07777; - break; - case 022: /* mode B: DST */ - if (emode) { - MA = IF | PC; - INDIRECT; /* defer state */ - if (MEM_ADDR_OK (MA)) M[MA] = MQ & 07777; - MA = DF | ((MA + 1) & 07777); - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; - PC = (PC + 1) & 07777; - break; } - LAC = LAC | SC; /* mode A: SCA then */ - case 2: /* MUY */ + if (emode) { MA = IF | PC; - if (emode) { INDIRECT; } /* mode B: defer */ - temp = (MQ * M[MA]) + (LAC & 07777); - LAC = (temp >> 12) & 07777; - MQ = temp & 07777; + INDIRECT; /* defer state */ + MQ = MQ + M[MA]; + MA = DF | ((MA + 1) & 07777); + LAC = (LAC & 07777) + M[MA] + (MQ >> 12); + MQ = MQ & 07777; PC = (PC + 1) & 07777; - SC = 014; /* 12 shifts */ - break; + break; } + LAC = LAC | SC; /* mode A: SCA then */ + case 1: /* mode B: ACS */ + if (emode) { + SC = LAC & 037; + LAC = LAC & 010000; + break; } + SC = (~M[IF | PC]) & 037; /* mode A: SCL */ + PC = (PC + 1) & 07777; + break; + case 022: /* mode B: DST */ + if (emode) { + MA = IF | PC; + INDIRECT; /* defer state */ + if (MEM_ADDR_OK (MA)) M[MA] = MQ & 07777; + MA = DF | ((MA + 1) & 07777); + if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; + PC = (PC + 1) & 07777; + break; } + LAC = LAC | SC; /* mode A: SCA then */ + case 2: /* MUY */ + MA = IF | PC; + if (emode) { INDIRECT; } /* mode B: defer */ + temp = (MQ * M[MA]) + (LAC & 07777); + LAC = (temp >> 12) & 07777; + MQ = temp & 07777; + PC = (PC + 1) & 07777; + SC = 014; /* 12 shifts */ + break; /* EAE continued */ case 023: /* mode B: SWBA */ - if (emode) break; - LAC = LAC | SC; /* mode A: SCA then */ + if (emode) break; + LAC = LAC | SC; /* mode A: SCA then */ case 3: /* DVI */ - MA = IF | PC; - if (emode) { INDIRECT; } /* mode B: defer */ - if ((LAC & 07777) >= M[MA]) { /* overflow? */ - LAC = LAC | 010000; /* set link */ - MQ = ((MQ << 1) + 1) & 07777; /* rotate MQ */ - SC = 01; } /* 1 shift */ - else { temp = ((LAC & 07777) << 12) | MQ; - MQ = temp / M[MA]; - LAC = temp % M[MA]; - SC = 015; } /* 13 shifts */ - PC = (PC + 1) & 07777; - break; + MA = IF | PC; + if (emode) { INDIRECT; } /* mode B: defer */ + if ((LAC & 07777) >= M[MA]) { /* overflow? */ + LAC = LAC | 010000; /* set link */ + MQ = ((MQ << 1) + 1) & 07777; /* rotate MQ */ + SC = 01; } /* 1 shift */ + else { + temp = ((LAC & 07777) << 12) | MQ; + MQ = temp / M[MA]; + LAC = temp % M[MA]; + SC = 015; } /* 13 shifts */ + PC = (PC + 1) & 07777; + break; case 024: /* mode B: DPSZ */ - if (emode) { - if (((LAC | MQ) & 07777) == 0) PC = (PC + 1) & 07777; - break; } - LAC = LAC | SC; /* mode A: SCA then */ + if (emode) { + if (((LAC | MQ) & 07777) == 0) PC = (PC + 1) & 07777; + break; } + LAC = LAC | SC; /* mode A: SCA then */ case 4: /* NMI */ - temp = (LAC << 12) | MQ; /* preserve link */ - for (SC = 0; ((temp & 017777777) != 0) && - (temp & 040000000) == ((temp << 1) & 040000000); SC++) - temp = temp << 1; - LAC = (temp >> 12) & 017777; - MQ = temp & 07777; - if (emode && ((LAC & 07777) == 04000) && (MQ == 0)) - LAC = LAC & 010000; /* clr if 4000'0000 */ - break; + temp = (LAC << 12) | MQ; /* preserve link */ + for (SC = 0; ((temp & 017777777) != 0) && + (temp & 040000000) == ((temp << 1) & 040000000); SC++) + temp = temp << 1; + LAC = (temp >> 12) & 017777; + MQ = temp & 07777; + if (emode && ((LAC & 07777) == 04000) && (MQ == 0)) + LAC = LAC & 010000; /* clr if 4000'0000 */ + break; case 025: /* mode B: DPIC */ - if (emode) { - temp = (LAC + 1) & 07777; /* SWP already done! */ - LAC = MQ + (temp == 0); - MQ = temp; - break; } - LAC = LAC | SC; /* mode A: SCA then */ + if (emode) { + temp = (LAC + 1) & 07777; /* SWP already done! */ + LAC = MQ + (temp == 0); + MQ = temp; + break; } + LAC = LAC | SC; /* mode A: SCA then */ case 5: /* SHL */ - SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ - if (SC > 25) temp = 0; /* >25? result = 0 */ - else temp = ((LAC << 12) | MQ) << SC; /* <=25? shift LAC:MQ */ - LAC = (temp >> 12) & 017777; - MQ = temp & 07777; - PC = (PC + 1) & 07777; - SC = emode? 037: 0; /* SC = 0 if mode A */ - break; + SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ + if (SC > 25) temp = 0; /* >25? result = 0 */ + else temp = ((LAC << 12) | MQ) << SC; /* <=25? shift LAC:MQ */ + LAC = (temp >> 12) & 017777; + MQ = temp & 07777; + PC = (PC + 1) & 07777; + SC = emode? 037: 0; /* SC = 0 if mode A */ + break; /* EAE continued */ case 026: /* mode B: DCM */ - if (emode) { - temp = (-LAC) & 07777; /* SWP already done! */ - LAC = (MQ ^ 07777) + (temp == 0); - MQ = temp; - break; } - LAC = LAC | SC; /* mode A: SCA then */ + if (emode) { + temp = (-LAC) & 07777; /* SWP already done! */ + LAC = (MQ ^ 07777) + (temp == 0); + MQ = temp; + break; } + LAC = LAC | SC; /* mode A: SCA then */ case 6: /* ASR */ - SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ - temp = ((LAC & 07777) << 12) | MQ; /* sext from AC0 */ - if (LAC & 04000) temp = temp | ~037777777; - if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1; - if (SC > 25) temp = (LAC & 04000)? -1: 0; - else temp = temp >> SC; - LAC = (temp >> 12) & 017777; - MQ = temp & 07777; - PC = (PC + 1) & 07777; - SC = emode? 037: 0; /* SC = 0 if mode A */ - break; + SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ + temp = ((LAC & 07777) << 12) | MQ; /* sext from AC0 */ + if (LAC & 04000) temp = temp | ~037777777; + if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1; + if (SC > 25) temp = (LAC & 04000)? -1: 0; + else temp = temp >> SC; + LAC = (temp >> 12) & 017777; + MQ = temp & 07777; + PC = (PC + 1) & 07777; + SC = emode? 037: 0; /* SC = 0 if mode A */ + break; case 027: /* mode B: SAM */ - if (emode) { - temp = LAC & 07777; - LAC = MQ + (temp ^ 07777) + 1; /* L'AC = MQ - AC */ - gtf = (temp <= MQ) ^ ((temp ^ MQ) >> 11); - break; } - LAC = LAC | SC; /* mode A: SCA then */ + if (emode) { + temp = LAC & 07777; + LAC = MQ + (temp ^ 07777) + 1; /* L'AC = MQ - AC */ + gtf = (temp <= MQ) ^ ((temp ^ MQ) >> 11); + break; } + LAC = LAC | SC; /* mode A: SCA then */ case 7: /* LSR */ - SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ - temp = ((LAC & 07777) << 12) | MQ; /* clear link */ - if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1; - if (SC > 24) temp = 0; /* >24? result = 0 */ - else temp = temp >> SC; /* <=24? shift AC:MQ */ - LAC = (temp >> 12) & 07777; - MQ = temp & 07777; - PC = (PC + 1) & 07777; - SC = emode? 037: 0; /* SC = 0 if mode A */ - break; } /* end switch */ + SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */ + temp = ((LAC & 07777) << 12) | MQ; /* clear link */ + if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1; + if (SC > 24) temp = 0; /* >24? result = 0 */ + else temp = temp >> SC; /* <=24? shift AC:MQ */ + LAC = (temp >> 12) & 07777; + MQ = temp & 07777; + PC = (PC + 1) & 07777; + SC = emode? 037: 0; /* SC = 0 if mode A */ + break; } /* end switch */ break; /* end case 7 */ /* Opcode 6, IOT */ case 030:case 031:case 032:case 033: /* IOT */ if (UF) { /* privileged? */ - int_req = int_req | INT_UF; - break; } + int_req = int_req | INT_UF; + break; } device = (IR >> 3) & 077; /* device = IR<3:8> */ pulse = IR & 07; /* pulse = IR<9:11> */ iot_data = LAC & 07777; /* AC unchanged */ switch (device) { /* decode IR<3:8> */ case 0: /* CPU control */ - switch (pulse) { /* decode IR<9:11> */ - case 0: /* SKON */ - if (int_req & INT_ION) PC = (PC + 1) & 07777; - int_req = int_req & ~INT_ION; - break; - case 1: /* ION */ - int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING; - break; - case 2: /* IOF */ - int_req = int_req & ~INT_ION; - break; - case 3: /* SRQ */ - if (int_req & INT_ALL) PC = (PC + 1) & 07777; - break; - case 4: /* GTF */ - LAC = (LAC & 010000) | - ((LAC & 010000) >> 1) | (gtf << 10) | - (((int_req & INT_ALL) != 0) << 9) | - (((int_req & INT_ION) != 0) << 7) | SF; - break; - case 5: /* RTF */ - gtf = ((LAC & 02000) >> 10); - UB = (LAC & 0100) >> 6; - IB = (LAC & 0070) << 9; - DF = (LAC & 0007) << 12; - LAC = ((LAC & 04000) << 1) | iot_data; - int_req = (int_req | INT_ION) & ~INT_NO_CIF_PENDING; - break; - case 6: /* SGT */ - if (gtf) PC = (PC + 1) & 07777; - break; - case 7: /* CAF */ - gtf = 0; - emode = 0; - int_req = int_req & INT_NO_CIF_PENDING; - dev_done = 0; - int_enable = INT_INIT_ENABLE; - LAC = 0; - break; } /* end switch pulse */ - break; /* end case 0 */ + switch (pulse) { /* decode IR<9:11> */ + case 0: /* SKON */ + if (int_req & INT_ION) PC = (PC + 1) & 07777; + int_req = int_req & ~INT_ION; + break; + case 1: /* ION */ + int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING; + break; + case 2: /* IOF */ + int_req = int_req & ~INT_ION; + break; + case 3: /* SRQ */ + if (int_req & INT_ALL) PC = (PC + 1) & 07777; + break; + case 4: /* GTF */ + LAC = (LAC & 010000) | + ((LAC & 010000) >> 1) | (gtf << 10) | + (((int_req & INT_ALL) != 0) << 9) | + (((int_req & INT_ION) != 0) << 7) | SF; + break; + case 5: /* RTF */ + gtf = ((LAC & 02000) >> 10); + UB = (LAC & 0100) >> 6; + IB = (LAC & 0070) << 9; + DF = (LAC & 0007) << 12; + LAC = ((LAC & 04000) << 1) | iot_data; + int_req = (int_req | INT_ION) & ~INT_NO_CIF_PENDING; + break; + case 6: /* SGT */ + if (gtf) PC = (PC + 1) & 07777; + break; + case 7: /* CAF */ + gtf = 0; + emode = 0; + int_req = int_req & INT_NO_CIF_PENDING; + dev_done = 0; + int_enable = INT_INIT_ENABLE; + LAC = 0; + break; } /* end switch pulse */ + break; /* end case 0 */ /* IOT, continued: memory extension */ case 020:case 021:case 022:case 023: case 024:case 025:case 026:case 027: /* memory extension */ - switch (pulse) { /* decode IR<9:11> */ - case 1: /* CDF */ - DF = (IR & 0070) << 9; - break; - case 2: /* CIF */ - IB = (IR & 0070) << 9; - int_req = int_req & ~INT_NO_CIF_PENDING; - break; - case 3: /* CDF CIF */ - DF = IB = (IR & 0070) << 9; - int_req = int_req & ~INT_NO_CIF_PENDING; - break; - case 4: - switch (device & 07) { /* decode IR<6:8> */ - case 0: /* CINT */ - int_req = int_req & ~INT_UF; - break; - case 1: /* RDF */ - LAC = LAC | (DF >> 9); - break; - case 2: /* RIF */ - LAC = LAC | (IF >> 9); - break; - case 3: /* RIB */ - LAC = LAC | SF; - break; - case 4: /* RMF */ - UB = (SF & 0100) >> 6; - IB = (SF & 0070) << 9; - DF = (SF & 0007) << 12; - int_req = int_req & ~INT_NO_CIF_PENDING; - break; - case 5: /* SINT */ - if (int_req & INT_UF) PC = (PC + 1) & 07777; - break; - case 6: /* CUF */ - UB = 0; - int_req = int_req & ~INT_NO_CIF_PENDING; - break; - case 7: /* SUF */ - UB = 1; - int_req = int_req & ~INT_NO_CIF_PENDING; - break; } /* end switch device */ - break; - default: - reason = stop_inst; - break; } /* end switch pulse */ - break; /* end case 20-27 */ + switch (pulse) { /* decode IR<9:11> */ + case 1: /* CDF */ + DF = (IR & 0070) << 9; + break; + case 2: /* CIF */ + IB = (IR & 0070) << 9; + int_req = int_req & ~INT_NO_CIF_PENDING; + break; + case 3: /* CDF CIF */ + DF = IB = (IR & 0070) << 9; + int_req = int_req & ~INT_NO_CIF_PENDING; + break; + case 4: + switch (device & 07) { /* decode IR<6:8> */ + case 0: /* CINT */ + int_req = int_req & ~INT_UF; + break; + case 1: /* RDF */ + LAC = LAC | (DF >> 9); + break; + case 2: /* RIF */ + LAC = LAC | (IF >> 9); + break; + case 3: /* RIB */ + LAC = LAC | SF; + break; + case 4: /* RMF */ + UB = (SF & 0100) >> 6; + IB = (SF & 0070) << 9; + DF = (SF & 0007) << 12; + int_req = int_req & ~INT_NO_CIF_PENDING; + break; + case 5: /* SINT */ + if (int_req & INT_UF) PC = (PC + 1) & 07777; + break; + case 6: /* CUF */ + UB = 0; + int_req = int_req & ~INT_NO_CIF_PENDING; + break; + case 7: /* SUF */ + UB = 1; + int_req = int_req & ~INT_NO_CIF_PENDING; + break; } /* end switch device */ + break; + default: + reason = stop_inst; + break; } /* end switch pulse */ + break; /* end case 20-27 */ /* IOT, continued: other special cases */ case 010: /* power fail */ - switch (pulse) { /* decode IR<9:11> */ - case 1: /* SBE */ - break; - case 2: /* SPL */ - if (int_req & INT_PWR) PC = (PC + 1) & 07777; - break; - case 3: /* CAL */ - int_req = int_req & ~INT_PWR; - break; - default: - reason = stop_inst; - break; } /* end switch pulse */ - break; /* end case 10 */ + switch (pulse) { /* decode IR<9:11> */ + case 1: /* SBE */ + break; + case 2: /* SPL */ + if (int_req & INT_PWR) PC = (PC + 1) & 07777; + break; + case 3: /* CAL */ + int_req = int_req & ~INT_PWR; + break; + default: + reason = stop_inst; + break; } /* end switch pulse */ + break; /* end case 10 */ default: /* I/O device */ - if (dev_tab[device]) { /* dev present? */ - iot_data = dev_tab[device] (IR, iot_data); - LAC = (LAC & 010000) | (iot_data & 07777); - if (iot_data & IOT_SKP) PC = (PC + 1) & 07777; - if (iot_data >= IOT_REASON) - reason = iot_data >> IOT_V_REASON; } - else reason = stop_inst; /* stop on flag */ - break; } /* end switch device */ - break; } /* end switch opcode */ + if (dev_tab[device]) { /* dev present? */ + iot_data = dev_tab[device] (IR, iot_data); + LAC = (LAC & 010000) | (iot_data & 07777); + if (iot_data & IOT_SKP) PC = (PC + 1) & 07777; + if (iot_data >= IOT_REASON) + reason = iot_data >> IOT_V_REASON; } + else reason = stop_inst; /* stop on flag */ + break; } /* end switch device */ + break; /* end case IOT */ + } /* end switch opcode */ } /* end while */ /* Simulation halted */ diff --git a/PDP8/pdp8_df.c b/PDP8/pdp8_df.c index 4def4ed9..3165a717 100644 --- a/PDP8/pdp8_df.c +++ b/PDP8/pdp8_df.c @@ -223,14 +223,15 @@ da = GET_DEX (df_sta) | df_da; /* form disk addr */ do { M[DF_WC] = (M[DF_WC] + 1) & 07777; /* incr word count */ M[DF_MA] = (M[DF_MA] + 1) & 07777; /* incr mem addr */ pa = mex | M[DF_MA]; /* add extension */ - if (uptr->FUNC == DF_READ) { - if (MEM_ADDR_OK (pa)) /* read, check nxm */ - M[pa] = *(((int16 *) uptr->filebuf) + da); } - else { t = (da >> 14) & 07; - if ((df_wlk >> t) & 1) df_sta = df_sta | DFS_WLS; - else { *(((int16 *) uptr->filebuf) + da) = M[pa]; - if (da >= uptr->hwmark) - uptr->hwmark = da + 1; } } + if (uptr->FUNC == DF_READ) { /* read? */ + if (MEM_ADDR_OK (pa)) /* check nxm */ + M[pa] = *(((int16 *) uptr->filebuf) + da); } + else { /* write */ + t = (da >> 14) & 07; /* check wr lock */ + if ((df_wlk >> t) & 1) df_sta = df_sta | DFS_WLS; + else { /* not locked */ + *(((int16 *) uptr->filebuf) + da) = M[pa]; + if (da >= uptr->hwmark) uptr->hwmark = da + 1; } } da = (da + 1) & 0377777; } /* incr disk addr */ while ((M[DF_WC] != 0) && (df_burst != 0)); /* brk if wc, no brst */ @@ -287,10 +288,10 @@ extern int32 sim_switches, saved_PC; if (sim_switches & SWMASK ('D')) { for (i = 0; i < DM4_LEN; i = i + 2) - M[dm4_rom[i]] = dm4_rom[i + 1]; + M[dm4_rom[i]] = dm4_rom[i + 1]; saved_PC = DM4_START; } else { for (i = 0; i < OS8_LEN; i++) - M[OS8_START + i] = os8_rom[i]; + M[OS8_START + i] = os8_rom[i]; saved_PC = OS8_START; } return SCPE_OK; } diff --git a/PDP8/pdp8_dt.c b/PDP8/pdp8_dt.c index ad499e97..0bb1f2fe 100644 --- a/PDP8/pdp8_dt.c +++ b/PDP8/pdp8_dt.c @@ -361,10 +361,10 @@ if (pulse & 01) AC = AC | dtsa; /* DTRA */ if (pulse & 06) { /* select */ if (pulse & 02) dtsa = 0; /* DTCA */ if (pulse & 04) { /* DTXA */ - if ((AC & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; - if ((AC & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; - dtsa = dtsa ^ (AC & DTA_RW); - AC = 0; } /* clr AC */ + if ((AC & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; + if ((AC & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; + dtsa = dtsa ^ (AC & DTA_RW); + AC = 0; } /* clr AC */ if ((old_dtsa ^ dtsa) & DTA_UNIT) dt_deselect (old_dtsa); uptr = dt_dev.units + DTA_GETUNIT (dtsa); /* get unit */ fnc = DTA_GETFNC (dtsa); /* get fnc */ @@ -372,7 +372,7 @@ if (pulse & 06) { /* select */ (fnc >= FNC_WMRK) || /* write mark? */ ((fnc == FNC_WALL) && (uptr->flags & UNIT_WPRT)) || ((fnc == FNC_WRIT) && (uptr->flags & UNIT_WPRT))) - dt_seterr (uptr, DTB_SEL); /* select err */ + dt_seterr (uptr, DTB_SEL); /* select err */ else dt_newsa (dtsa); DT_UPDINT; } return AC; @@ -456,17 +456,17 @@ if (new_mving & ~prev_mving) { /* start? */ if (prev_mving & ~new_mving) { /* stop? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, dt_dctime); } /* schedule decel */ DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ return; } if (prev_dir ^ new_dir) { /* dir chg? */ if ((prev_mot & ~DTS_DIR) != DTS_DECF) { /* !already stopping? */ - if (dt_setpos (uptr)) return; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, dt_dctime); } /* schedule decel */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, dt_dctime); } /* schedule decel */ DTS_SETSTA (DTS_DECF | prev_dir, 0); /* state = decel */ DTS_SET2ND (DTS_ACCF | new_dir, 0); /* next = accel */ DTS_SET3RD (DTS_ATSF | new_dir, new_fnc); /* next next = fnc */ @@ -528,33 +528,33 @@ case DTS_OFR: /* off reel */ case FNC_MOVE: /* move */ dt_schedez (uptr, dir); /* sched end zone */ if (dt_log & LOG_MS) printf ("[DT%d: moving %s]\n", unum, (dir? - "backward": "forward")); + "backward": "forward")); return; /* done */ case FNC_SRCH: /* search */ if (dir) newpos = DT_BLK2LN ((DT_QFEZ (uptr)? - DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; + DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE; else newpos = DT_BLK2LN ((DT_QREZ (uptr)? - 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); + 0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1); if (dt_log & LOG_MS) printf ("[DT%d: searching %s]\n", unum, - (dir? "backward": "forward")); + (dir? "backward": "forward")); break; case FNC_WRIT: /* write */ case FNC_READ: /* read */ case FNC_RALL: /* read all */ case FNC_WALL: /* write all */ if (DT_QEZ (uptr)) { /* in "ok" end zone? */ - if (dir) newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); - break; } + if (dir) newpos = DTU_FWDEZ (uptr) - DT_HTLIN - DT_WSIZE; + else newpos = DT_EZLIN + DT_HTLIN + (DT_WSIZE - 1); + break; } relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - dt_seterr (uptr, DTB_SEL); - return; } + dt_seterr (uptr, DTB_SEL); + return; } if (dir) newpos = DT_BLK2LN (((relpos >= (DTU_LPERB (uptr) - DT_HTLIN))? - blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; + blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; else newpos = DT_BLK2LN (((relpos < DT_HTLIN)? - blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); + blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); break; default: dt_seterr (uptr, DTB_SEL); /* bad state */ @@ -614,7 +614,7 @@ if (((int32) uptr->pos < 0) || uptr->STATE = uptr->pos = 0; unum = uptr - dt_dev.units; if (unum == DTA_GETUNIT (dtsa)) /* if selected, */ - dt_seterr (uptr, DTB_SEL); /* error */ + dt_seterr (uptr, DTB_SEL); /* error */ return TRUE; } return FALSE; } @@ -646,7 +646,7 @@ case DTS_DECF: case DTS_DECR: /* decelerating */ if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ + sim_activate (uptr, dt_actime); /* must be reversing */ return SCPE_OK; case DTS_ACCF: case DTS_ACCR: /* accelerating */ dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ @@ -675,14 +675,14 @@ case FNC_MOVE: /* move */ return SCPE_OK; case FNC_SRCH: /* search */ if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr word cnt */ ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ if (MEM_ADDR_OK (ma)) M[ma] = blk & 07777; /* store block # */ if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ + dtsb = dtsb | DTB_DTF; /* set DTF */ break; case DTS_OFR: /* off reel */ detach_unit (uptr); /* must be deselected */ @@ -706,36 +706,37 @@ case FNC_READ: /* read */ wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ switch (dt_substate) { /* case on substate */ case DTO_SOB: /* start of block */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: reading block %d %s%s\n", - unum, blk, (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - dt_substate = 0; /* fall through */ + if (dtsb & DTB_DTF) { /* DTF set? */ + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } + if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) + printf ("[DT%d: reading block %d %s%s\n", + unum, blk, (dir? "backward": "forward"), + ((dtsa & DTA_MODE)? " continuous]": "]")); + dt_substate = 0; /* fall through */ case 0: /* normal read */ - M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & 07777; - ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - dat = bptr[ba]; /* get tape word */ - if (dir) dat = dt_comobv (dat); /* rev? comp obv */ - if (MEM_ADDR_OK (ma)) M[ma] = dat; /* mem addr legal? */ - if (M[DT_WC] == 0) dt_substate = DTO_WCO; /* wc ovf? */ + M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ + M[DT_CA] = (M[DT_CA] + 1) & 07777; + ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ + ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ + dat = bptr[ba]; /* get tape word */ + if (dir) dat = dt_comobv (dat); /* rev? comp obv */ + if (MEM_ADDR_OK (ma)) M[ma] = dat; /* mem addr legal? */ + if (M[DT_WC] == 0) dt_substate = DTO_WCO; /* wc ovf? */ case DTO_WCO: /* wc ovf, not sob */ - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else { dt_substate = dt_substate | DTO_SOB; - sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; } /* set DTF */ - break; + if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ + sim_activate (uptr, DT_WSIZE * dt_ltime); + else { + dt_substate = dt_substate | DTO_SOB; + sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); + if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) + dtsb = dtsb | DTB_DTF; } /* set DTF */ + break; case DTO_WCO | DTO_SOB: /* next block */ - if (wrd == (dir? 0: DTU_BSIZE (uptr))) /* end of block? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - else sim_activate (uptr, DT_WSIZE * dt_ltime); - break; } + if (wrd == (dir? 0: DTU_BSIZE (uptr))) /* end of block? */ + dt_seterr (uptr, DTB_TIM); /* timing error */ + else sim_activate (uptr, DT_WSIZE * dt_ltime); + break; } break; /* Write has four subcases @@ -754,31 +755,32 @@ case FNC_WRIT: /* write */ wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ switch (dt_substate) { /* case on substate */ case DTO_SOB: /* start block */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) - printf ("[DT%d: writing block %d %s%s\n", unum, blk, - (dir? "backward": "forward"), - ((dtsa & DTA_MODE)? " continuous]": "]")); - dt_substate = 0; /* fall through */ + if (dtsb & DTB_DTF) { /* DTF set? */ + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } + if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk))) + printf ("[DT%d: writing block %d %s%s\n", unum, blk, + (dir? "backward": "forward"), + ((dtsa & DTA_MODE)? " continuous]": "]")); + dt_substate = 0; /* fall through */ case 0: /* normal write */ - M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & 07777; + M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ + M[DT_CA] = (M[DT_CA] + 1) & 07777; case DTO_WCO: /* wc ovflo */ - ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - dat = dt_substate? 0: M[ma]; /* get word */ - if (dir) dat = dt_comobv (dat); /* rev? comp obv */ - bptr[ba] = dat; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else { dt_substate = dt_substate | DTO_SOB; - sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; } /* set DTF */ + ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ + ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ + dat = dt_substate? 0: M[ma]; /* get word */ + if (dir) dat = dt_comobv (dat); /* rev? comp obv */ + bptr[ba] = dat; /* write word */ + if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; + if (M[DT_WC] == 0) dt_substate = DTO_WCO; + if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not last? */ + sim_activate (uptr, DT_WSIZE * dt_ltime); + else { + dt_substate = dt_substate | DTO_SOB; + sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); + if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) + dtsb = dtsb | DTB_DTF; } /* set DTF */ break; case DTO_WCO | DTO_SOB: /* all done */ dt_schedez (uptr, dir); /* sched end zone */ @@ -794,29 +796,29 @@ case FNC_WRIT: /* write */ case FNC_RALL: switch (dt_substate) { /* case on substate */ case 0: case DTO_SOB: /* read in progress */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & 07777; - ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - dat = bptr[ba]; /* get tape word */ - if (dir) dat = dt_comobv (dat); } /* rev? comp obv */ - else dat = dt_gethdr (uptr, blk, relpos, dir); /* get hdr */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - if (MEM_ADDR_OK (ma)) M[ma] = dat; /* mem addr legal? */ - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; + if (dtsb & DTB_DTF) { /* DTF set? */ + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } + relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ + M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ + M[DT_CA] = (M[DT_CA] + 1) & 07777; + ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ + if ((relpos >= DT_HTLIN) && /* in data zone? */ + (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { + wrd = DT_LIN2WD (uptr->pos, uptr); + ba = (blk * DTU_BSIZE (uptr)) + wrd; + dat = bptr[ba]; /* get tape word */ + if (dir) dat = dt_comobv (dat); } /* rev? comp obv */ + else dat = dt_gethdr (uptr, blk, relpos, dir); /* get hdr */ + sim_activate (uptr, DT_WSIZE * dt_ltime); + if (MEM_ADDR_OK (ma)) M[ma] = dat; /* mem addr legal? */ + if (M[DT_WC] == 0) dt_substate = DTO_WCO; + if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) + dtsb = dtsb | DTB_DTF; /* set DTF */ + break; case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ + dt_schedez (uptr, dir); /* sched end zone */ + break; } /* end case substate */ break; /* Write all has two subcases @@ -828,30 +830,30 @@ case FNC_RALL: case FNC_WALL: switch (dt_substate) { /* case on substate */ case 0: case DTO_SOB: /* read in progress */ - if (dtsb & DTB_DTF) { /* DTF set? */ - dt_seterr (uptr, DTB_TIM); /* timing error */ - return SCPE_OK; } - relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ - M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ - M[DT_CA] = (M[DT_CA] + 1) & 07777; - ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ - if ((relpos >= DT_HTLIN) && /* in data zone? */ - (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { - dat = M[ma]; /* get mem word */ - if (dir) dat = dt_comobv (dat); - wrd = DT_LIN2WD (uptr->pos, uptr); - ba = (blk * DTU_BSIZE (uptr)) + wrd; - bptr[ba] = dat; /* write word */ - if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } + if (dtsb & DTB_DTF) { /* DTF set? */ + dt_seterr (uptr, DTB_TIM); /* timing error */ + return SCPE_OK; } + relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ + M[DT_WC] = (M[DT_WC] + 1) & 07777; /* incr WC, CA */ + M[DT_CA] = (M[DT_CA] + 1) & 07777; + ma = DTB_GETMEX (dtsb) | M[DT_CA]; /* get mem addr */ + if ((relpos >= DT_HTLIN) && /* in data zone? */ + (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { + dat = M[ma]; /* get mem word */ + if (dir) dat = dt_comobv (dat); + wrd = DT_LIN2WD (uptr->pos, uptr); + ba = (blk * DTU_BSIZE (uptr)) + wrd; + bptr[ba] = dat; /* write word */ + if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } /* /* ignore hdr */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - if (M[DT_WC] == 0) dt_substate = DTO_WCO; - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ + sim_activate (uptr, DT_WSIZE * dt_ltime); + if (M[DT_WC] == 0) dt_substate = DTO_WCO; + if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) + dtsb = dtsb | DTB_DTF; /* set DTF */ break; case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ + dt_schedez (uptr, dir); /* sched end zone */ + break; } /* end case substate */ break; default: dt_seterr (uptr, DTB_SEL); /* impossible state */ @@ -891,31 +893,31 @@ if (relpos >= DT_HTLIN) relpos = relpos - (DT_WSIZE * DTU_BSIZE (uptr)); if (dir) { /* reverse */ switch (relpos / DT_WSIZE) { case 6: /* fwd csum */ - return (dt_comobv (dt_csum (uptr, blk))); + return (dt_comobv (dt_csum (uptr, blk))); case 2: /* lo fwd blk */ - return dt_comobv ((blk & 077) << 6); + return dt_comobv ((blk & 077) << 6); case 1: /* hi fwd blk */ - return dt_comobv (blk >> 6); + return dt_comobv (blk >> 6); case 12: /* hi rev blk */ - return (blk >> 6) & 07777; + return (blk >> 6) & 07777; case 11: /* lo rev blk */ - return ((blk & 077) << 6); + return ((blk & 077) << 6); default: /* others */ - return 077; } } + return 077; } } else { /* forward */ switch (relpos / DT_WSIZE) { case 8: /* rev csum */ - return (dt_csum (uptr, blk) << 6); + return (dt_csum (uptr, blk) << 6); case 12: /* lo rev blk */ - return dt_comobv ((blk & 077) << 6); + return dt_comobv ((blk & 077) << 6); case 13: /* hi rev blk */ - return dt_comobv (blk >> 6); + return dt_comobv (blk >> 6); case 2: /* hi fwd blk */ - return ((blk >> 6) & 07777); + return ((blk >> 6) & 07777); case 3: /* lo fwd blk */ - return ((blk & 077) << 6); + return ((blk & 077) << 6); default: /* others */ - break; } } + break; } } return 0; } @@ -985,16 +987,17 @@ UNIT *uptr; for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ uptr = dt_dev.units + i; if (sim_is_running) { /* CAF? */ - prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ - if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ - if (dt_setpos (uptr)) continue; /* update pos */ - sim_cancel (uptr); - sim_activate (uptr, dt_dctime); /* sched decel */ - DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); - } } - else { sim_cancel (uptr); /* sim reset */ - uptr->STATE = 0; - uptr->LASTT = sim_grtime (); } } + prev_mot = DTS_GETMOT (uptr->STATE); /* get motion */ + if ((prev_mot & ~DTS_DIR) > DTS_DECF) { /* accel or spd? */ + if (dt_setpos (uptr)) continue; /* update pos */ + sim_cancel (uptr); + sim_activate (uptr, dt_dctime); /* sched decel */ + DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0); + } } + else { + sim_cancel (uptr); /* sim reset */ + uptr->STATE = 0; + uptr->LASTT = sim_grtime (); } } dtsa = dtsb = 0; /* clear status */ DT_UPDINT; /* reset interrupt */ return SCPE_OK; diff --git a/PDP8/pdp8_lp.c b/PDP8/pdp8_lp.c index 604d7104..b88d4b7a 100644 --- a/PDP8/pdp8_lp.c +++ b/PDP8/pdp8_lp.c @@ -99,8 +99,8 @@ case 4: /* PSTB */ lpt_unit.buf = AC & 0177; /* load buffer */ if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) || (lpt_unit.buf == 012)) { - sim_activate (&lpt_unit, lpt_unit.wait); - return AC; } + sim_activate (&lpt_unit, lpt_unit.wait); + return AC; } return (lpt_svc (&lpt_unit) << IOT_V_REASON) + AC; case 5: /* PSIE */ int_enable = int_enable | INT_LPT; /* set enable */ diff --git a/PDP8/pdp8_mt.c b/PDP8/pdp8_mt.c index 8b9dfb5a..c8988a0f 100644 --- a/PDP8/pdp8_mt.c +++ b/PDP8/pdp8_mt.c @@ -243,24 +243,24 @@ case 6: /* LFGR */ if (mt_busy ()) mt_sta = mt_sta | STA_ILL; /* busy? illegal op */ mt_fn = AC; /* load function */ if ((mt_fn & FN_GO) == 0) { /* go set? */ - mt_updcsta (uptr); /* update status */ - return 0; } + mt_updcsta (uptr); /* update status */ + return 0; } f = GET_FNC (mt_fn); /* get function */ if (((uptr->flags & UNIT_ATT) == 0) || !TUR (uptr) || (((f == FN_WRITE) || (f == FN_WREOF)) && (uptr->flags & UNIT_WPRT)) || (((f == FN_SPACER) || (f == FN_REWIND)) && (uptr->USTAT & STA_BOT))) { - mt_sta = mt_sta | STA_ILL; /* illegal op error */ - mt_set_done (); /* set done */ - mt_updcsta (uptr); /* update status */ - return 0; } + mt_sta = mt_sta | STA_ILL; /* illegal op error */ + mt_set_done (); /* set done */ + mt_updcsta (uptr); /* update status */ + return 0; } uptr->USTAT = uptr->USTAT & STA_WLK; /* clear status */ if (f == FN_UNLOAD) { /* unload? */ - detach_unit (uptr); /* set offline */ - uptr->USTAT = STA_REW | STA_REM; /* rewinding, off */ - mt_set_done (); } /* set done */ + detach_unit (uptr); /* set offline */ + uptr->USTAT = STA_REW | STA_REM; /* rewinding, off */ + mt_set_done (); } /* set done */ else if (f == FN_REWIND) { /* rewind */ - uptr->USTAT = uptr->USTAT | STA_REW; /* rewinding */ - mt_set_done (); } /* set done */ + uptr->USTAT = uptr->USTAT | STA_REW; /* rewinding */ + mt_set_done (); } /* set done */ else mt_done = 0; /* clear done */ mt_updcsta (uptr); /* update status */ sim_activate (uptr, mt_time); /* start io */ @@ -317,9 +317,10 @@ case 4: /* SKTR */ return (TUR (uptr))? IOT_SKP + AC: AC; case 5: /* CLF */ if (TUR (uptr)) mt_reset (&mt_dev); /* if TUR, zap */ - else { mt_sta = 0; /* clear status */ - mt_done = 0; /* clear done */ - mt_updcsta (uptr); } /* update status */ + else { /* just ctrl zap */ + mt_sta = 0; /* clear status */ + mt_done = 0; /* clear done */ + mt_updcsta (uptr); } /* update status */ return AC; } /* end switch */ return (stop_inst << IOT_V_REASON) + AC; /* ill inst */ } @@ -347,11 +348,11 @@ MT_CLR_PNU (uptr); /* and clear */ if (uptr->USTAT & STA_REW) { /* rewind? */ uptr->pos = 0; /* update position */ if (uptr->flags & UNIT_ATT) /* still on line? */ - uptr->USTAT = (uptr->USTAT & STA_WLK) | STA_BOT; + uptr->USTAT = (uptr->USTAT & STA_WLK) | STA_BOT; else uptr->USTAT = STA_REM; if (u == GET_UNIT (mt_cu)) { /* selected? */ - mt_set_done (); /* set done */ - mt_updcsta (uptr); } /* update status */ + mt_set_done (); /* set done */ + mt_updcsta (uptr); } /* update status */ return SCPE_OK; } if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ @@ -376,33 +377,34 @@ switch (f) { /* case on function */ case FN_READ: /* read */ case FN_CMPARE: /* read/compare */ if (mt_rdlntf (uptr, &tbc, &err)) { /* read rec lnt */ - mt_sta = mt_sta | STA_RLE; /* err, eof/eom, tmk */ - break; } + mt_sta = mt_sta | STA_RLE; /* err, eof/eom, tmk */ + break; } if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */ cbc = (mt_cu & CU_UNPAK)? wc: wc * 2; /* expected bc */ if (tbc != cbc) mt_sta = mt_sta | STA_RLE; /* wrong size? */ if (tbc < cbc) { /* record small? */ - cbc = tbc; /* use smaller */ - wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2; } + cbc = tbc; /* use smaller */ + wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2; } abc = fxread (dbuf, sizeof (uint8), cbc, uptr->fileref); if (err = ferror (uptr->fileref)) { /* error? */ - mt_sta = mt_sta | STA_RLE; /* set flag */ - MT_SET_PNU (uptr); /* pos not upd */ - break; } + mt_sta = mt_sta | STA_RLE; /* set flag */ + MT_SET_PNU (uptr); /* pos not upd */ + break; } for ( ; abc < cbc; abc++) dbuf[abc] = 0; /* fill with 0's */ for (i = p = 0; i < wc; i++) { /* copy buffer */ - xma = mt_ixma (xma); /* increment xma */ - if (mt_cu & CU_UNPAK) c = dbuf[p++]; - else { c1 = dbuf[p++] & 077; - c2 = dbuf[p++] & 077; - c = (c1 << 6) | c2; } - if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c; - else if ((f == FN_CMPARE) && (M[xma] != c)) { - mt_sta = mt_sta | STA_CPE; - break; } } + xma = mt_ixma (xma); /* increment xma */ + if (mt_cu & CU_UNPAK) c = dbuf[p++]; + else { + c1 = dbuf[p++] & 077; + c2 = dbuf[p++] & 077; + c = (c1 << 6) | c2; } + if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c; + else if ((f == FN_CMPARE) && (M[xma] != c)) { + mt_sta = mt_sta | STA_CPE; + break; } } mt_wc = (mt_wc + wc) & 07777; /* update wc */ uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* update tape pos */ - (2 * sizeof (t_mtrlnt)); + (2 * sizeof (t_mtrlnt)); break; case FN_WRITE: /* write */ @@ -410,15 +412,17 @@ case FN_WRITE: /* write */ tbc = (mt_cu & CU_UNPAK)? wc: wc * 2; fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref); for (i = p = 0; i < wc; i++) { /* copy buf to tape */ - xma = mt_ixma (xma); /* incr mem addr */ - if (mt_cu & CU_UNPAK) dbuf[p++] = M[xma] & 0377; - else { dbuf[p++] = (M[xma] >> 6) & 077; - dbuf[p++] = M[xma] & 077; } } + xma = mt_ixma (xma); /* incr mem addr */ + if (mt_cu & CU_UNPAK) dbuf[p++] = M[xma] & 0377; + else { + dbuf[p++] = (M[xma] >> 6) & 077; + dbuf[p++] = M[xma] & 077; } } fxwrite (dbuf, sizeof (int8), (tbc + 1) & ~1, uptr->fileref); fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref); if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */ - else { mt_wc = 0; - uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* upd tape pos */ + else { + mt_wc = 0; + uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* upd tape pos */ (2 * sizeof (t_mtrlnt)); } break; @@ -432,19 +436,22 @@ case FN_WREOF: break; case FN_SPACEF: /* space forward */ - do { mt_wc = (mt_wc + 1) & 07777; /* incr wc */ - if (mt_rdlntf (uptr, &tbc, &err)) break;/* read rec lnt, err? */ - uptr->pos = uptr->pos + ((tbc + 1) & ~1) + - (2 * sizeof (t_mtrlnt)); } + do { + mt_wc = (mt_wc + 1) & 07777; /* incr wc */ + if (mt_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */ + uptr->pos = uptr->pos + ((tbc + 1) & ~1) + + (2 * sizeof (t_mtrlnt)); } while (mt_wc != 0); break; case FN_SPACER: /* space reverse */ - do { mt_wc = (mt_wc + 1) & 07777; /* incr wc */ - if (pnu) pnu = 0; /* pos not upd? */ - else { if (mt_rdlntr (uptr, &tbc, &err)) break; - uptr->pos = uptr->pos - ((tbc + 1) & ~1) - - (2 * sizeof (t_mtrlnt)); } } + do { + mt_wc = (mt_wc + 1) & 07777; /* incr wc */ + if (pnu) pnu = 0; /* pos not upd? */ + else { + if (mt_rdlntr (uptr, &tbc, &err)) break; + uptr->pos = uptr->pos - ((tbc + 1) & ~1) - + (2 * sizeof (t_mtrlnt)); } } while (mt_wc != 0); break; } /* end case */ @@ -482,7 +489,7 @@ UNIT *uptr; for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ uptr = mt_dev.units + u; if (sim_is_active (uptr) && ((uptr->USTAT & STA_REW) == 0)) - return uptr; } + return uptr; } return NULL; } @@ -568,8 +575,8 @@ for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ sim_cancel (uptr); /* cancel activity */ MT_CLR_PNU (uptr); /* clear pos flag */ if (uptr->flags & UNIT_ATT) uptr->USTAT = - ((uptr->pos)? 0: STA_BOT) | - ((uptr->flags & UNIT_WPRT)? STA_WLK: 0); + ((uptr->pos)? 0: STA_BOT) | + ((uptr->flags & UNIT_WPRT)? STA_WLK: 0); else uptr->USTAT = STA_REM; } return SCPE_OK; } diff --git a/PDP8/pdp8_pt.c b/PDP8/pdp8_pt.c index 018e6183..9e6b0c0a 100644 --- a/PDP8/pdp8_pt.c +++ b/PDP8/pdp8_pt.c @@ -148,8 +148,8 @@ if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ptr_stopioe, SCPE_UNATT); if ((temp = getc (ptr_unit.fileref)) == EOF) { if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } + if (ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; } else perror ("PTR I/O error"); clearerr (ptr_unit.fileref); return SCPE_IOERR; } diff --git a/PDP8/pdp8_rf.c b/PDP8/pdp8_rf.c index f14a3b07..f38badfb 100644 --- a/PDP8/pdp8_rf.c +++ b/PDP8/pdp8_rf.c @@ -191,8 +191,8 @@ case 2: /* DSAC */ case 5: /* DIML */ rf_sta = (rf_sta & 07007) | (AC & 0770); /* STA<3:8> <- AC */ if (rf_sta & RFS_PIE) /* photocell int? */ - sim_activate (&pcell_unit, (RF_NUMWD - GET_POS (rf_time)) * - rf_time); + sim_activate (&pcell_unit, (RF_NUMWD - GET_POS (rf_time)) * + rf_time); else sim_cancel (&pcell_unit); RF_INT_UPDATE; /* update int req */ return 0; /* clear AC */ @@ -256,14 +256,15 @@ mex = GET_MEX (rf_sta); do { M[RF_WC] = (M[RF_WC] + 1) & 07777; /* incr word count */ M[RF_MA] = (M[RF_MA] + 1) & 07777; /* incr mem addr */ pa = mex | M[RF_MA]; /* add extension */ - if (uptr->FUNC == RF_READ) { - if (MEM_ADDR_OK (pa)) /* read, check nxm */ - M[pa] = *(((int16 *) uptr->filebuf) + rf_da); } - else { t = ((rf_da >> 15) & 030) | ((rf_da >> 14) & 07); - if ((rf_wlk >> t) & 1) rf_sta = rf_sta | RFS_WLS; - else { *(((int16 *) uptr->filebuf) + rf_da) = M[pa]; - if (((t_addr) rf_da) >= uptr->hwmark) - uptr->hwmark = rf_da + 1; } } + if (uptr->FUNC == RF_READ) { /* read? */ + if (MEM_ADDR_OK (pa)) /* check nxm */ + M[pa] = *(((int16 *) uptr->filebuf) + rf_da); } + else { /* write */ + t = ((rf_da >> 15) & 030) | ((rf_da >> 14) & 07); + if ((rf_wlk >> t) & 1) rf_sta = rf_sta | RFS_WLS; + else { + *(((int16 *) uptr->filebuf) + rf_da) = M[pa]; + if (((t_addr) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1; } } rf_da = (rf_da + 1) & 03777777; } /* incr disk addr */ while ((M[RF_WC] != 0) && (rf_burst != 0)); /* brk if wc, no brst */ @@ -330,10 +331,10 @@ extern int32 sim_switches, saved_PC; if (rf_dib.dev != DEV_RF) return STOP_NOTSTD; /* only std devno */ if (sim_switches & SWMASK ('D')) { for (i = 0; i < DM4_LEN; i = i + 2) - M[dm4_rom[i]] = dm4_rom[i + 1]; + M[dm4_rom[i]] = dm4_rom[i + 1]; saved_PC = DM4_START; } else { for (i = 0; i < OS8_LEN; i++) - M[OS8_START + i] = os8_rom[i]; + M[OS8_START + i] = os8_rom[i]; saved_PC = OS8_START; } return SCPE_OK; } diff --git a/PDP8/pdp8_rk.c b/PDP8/pdp8_rk.c index 3ca8816f..ef172bc5 100644 --- a/PDP8/pdp8_rk.c +++ b/PDP8/pdp8_rk.c @@ -205,23 +205,24 @@ case 2: /* DCLR */ rk_sta = 0; /* clear status */ switch (AC & 03) { /* decode AC<10:11> */ case RKX_CLS: /* clear status */ - if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; + if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; case RKX_CLSA: /* clear status alt */ - break; + break; case RKX_CLC: /* clear control */ - rk_cmd = rk_busy = 0; /* clear registers */ - rk_ma = rk_da = 0; - for (i = 0; i < RK_NUMDR; i++) sim_cancel (&rk_unit[i]); - break; + rk_cmd = rk_busy = 0; /* clear registers */ + rk_ma = rk_da = 0; + for (i = 0; i < RK_NUMDR; i++) sim_cancel (&rk_unit[i]); + break; case RKX_CLD: /* reset drive */ - if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; - else rk_go (RKC_SEEK, 0); /* seek to 0 */ - break; } /* end switch AC */ + if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; + else rk_go (RKC_SEEK, 0); /* seek to 0 */ + break; } /* end switch AC */ break; case 3: /* DLAG */ if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; - else { rk_da = AC; /* load disk addr */ - rk_go (GET_FUNC (rk_cmd), GET_CYL (rk_cmd, rk_da)); } + else { + rk_da = AC; /* load disk addr */ + rk_go (GET_FUNC (rk_cmd), GET_CYL (rk_cmd, rk_da)); } break; case 4: /* DLCA */ if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; @@ -235,8 +236,9 @@ case 5: /* DRST */ return rk_sta; case 6: /* DLDC */ if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; - else { rk_cmd = AC; /* load command */ - rk_sta = 0; } /* clear status */ + else { + rk_cmd = AC; /* load command */ + rk_sta = 0; } /* clear status */ break; case 7: /* DMAN */ break; } /* end case pulse */ @@ -305,8 +307,8 @@ UNIT *seluptr; if (uptr->FUNC == RKC_SEEK) { /* seek? */ seluptr = rk_dev.units + GET_DRIVE (rk_cmd); /* see if selected */ if ((uptr == seluptr) && ((rk_cmd & RKC_SKDN) != 0)) { - rk_sta = rk_sta | RKS_DONE; - RK_INT_UPDATE; } + rk_sta = rk_sta | RKS_DONE; + RK_INT_UPDATE; } return SCPE_OK; } if ((uptr->flags & UNIT_ATT) == 0) { /* not att? abort */ @@ -332,21 +334,21 @@ if ((uptr->FUNC == RKC_READ) && (err == 0) && MEM_ADDR_OK (pa)) { /* read? */ for ( ; awc < wc; awc++) M[pa + awc] = 0; /* fill if eof */ err = ferror (uptr->fileref); if ((wc1 > 0) && (err == 0)) { /* field wraparound? */ - pa = pa & 070000; /* wrap phys addr */ - awc = fxread (&M[pa], sizeof (int16), wc1, uptr->fileref); - for ( ; awc < wc1; awc++) M[pa + awc] = 0; /* fill if eof */ - err = ferror (uptr->fileref); } } + pa = pa & 070000; /* wrap phys addr */ + awc = fxread (&M[pa], sizeof (int16), wc1, uptr->fileref); + for ( ; awc < wc1; awc++) M[pa + awc] = 0; /* fill if eof */ + err = ferror (uptr->fileref); } } if ((uptr->FUNC == RKC_WRITE) && (err == 0)) { /* write? */ fxwrite (&M[pa], sizeof (int16), wc, uptr->fileref); err = ferror (uptr->fileref); if ((wc1 > 0) && (err == 0)) { /* field wraparound? */ - pa = pa & 070000; /* wrap phys addr */ - fxwrite (&M[pa], sizeof (int16), wc1, uptr->fileref); - err = ferror (uptr->fileref); } + pa = pa & 070000; /* wrap phys addr */ + fxwrite (&M[pa], sizeof (int16), wc1, uptr->fileref); + err = ferror (uptr->fileref); } if ((rk_cmd & RKC_HALF) && (err == 0)) { /* fill half sector */ - fxwrite (fill, sizeof (int16), RK_NUMWD/2, uptr->fileref); - err = ferror (uptr->fileref); } } + fxwrite (fill, sizeof (int16), RK_NUMWD/2, uptr->fileref); + err = ferror (uptr->fileref); } } rk_ma = (rk_ma + swc) & 07777; /* incr mem addr reg */ rk_sta = rk_sta | RKS_DONE; /* set done */ diff --git a/PDP8/pdp8_rl.c b/PDP8/pdp8_rl.c index f0aa16fd..9e2a2a1b 100644 --- a/PDP8/pdp8_rl.c +++ b/PDP8/pdp8_rl.c @@ -278,26 +278,27 @@ case 4: /* RLCB */ uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */ switch (GET_FUNC (rlcsb)) { /* case on func */ case RLCSB_CLRD: /* clear drive */ - uptr->STAT = uptr->STAT & ~RLDS_ERR; /* clear errors */ + uptr->STAT = uptr->STAT & ~RLDS_ERR; /* clear errors */ case RLCSB_MNT: /* mnt */ - rl_set_done (0); - break; + rl_set_done (0); + break; case RLCSB_SEEK: /* seek */ - curr = GET_CYL (uptr->TRK); /* current cylinder */ - offs = GET_CYL (rlcsa); /* offset */ - if (rlcsa & RLCSA_DIR) { /* in or out? */ - newc = curr + offs; /* out */ - maxc = (uptr->flags & UNIT_RL02)? - RL_NUMCY * 2: RL_NUMCY; - if (newc >= maxc) newc = maxc - 1; } - else { newc = curr - offs; /* in */ - if (newc < 0) newc = 0; } - uptr->TRK = newc | (rlcsa & RLCSA_HD); - sim_activate (uptr, rl_swait * abs (newc - curr)); - break; + curr = GET_CYL (uptr->TRK); /* current cylinder */ + offs = GET_CYL (rlcsa); /* offset */ + if (rlcsa & RLCSA_DIR) { /* in or out? */ + newc = curr + offs; /* out */ + maxc = (uptr->flags & UNIT_RL02)? + RL_NUMCY * 2: RL_NUMCY; + if (newc >= maxc) newc = maxc - 1; } + else { + newc = curr - offs; /* in */ + if (newc < 0) newc = 0; } + uptr->TRK = newc | (rlcsa & RLCSA_HD); + sim_activate (uptr, rl_swait * abs (newc - curr)); + break; default: /* data transfer */ - sim_activate (uptr, rl_swait); /* activate unit */ - break; } /* end switch func */ + sim_activate (uptr, rl_swait); /* activate unit */ + break; } /* end switch func */ break; case 5: /* RLSA */ rlsa = GET_SECT (AC); @@ -322,7 +323,7 @@ case 0: /* RRER */ uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */ if (!sim_is_active (uptr) && /* update drdy */ (uptr->flags & UNIT_ATT)) - rler = rler | RLER_DRDY; + rler = rler | RLER_DRDY; else rler = rler & ~RLER_DRDY; dat = rler & RLER_MASK; break; @@ -340,9 +341,9 @@ case 4: /* RRSA */ break; case 5: /* RRSI */ if (rl_lft) { /* silo left? */ - dat = (rlsi >> 8) & 0377; /* get left 8b */ - rlsi = rlsi1; /* ripple */ - rlsi1 = rlsi2; } + dat = (rlsi >> 8) & 0377; /* get left 8b */ + rlsi = rlsi1; /* ripple */ + rlsi1 = rlsi2; } else dat = rlsi & 0377; /* get right 8b */ rl_lft = rl_lft ^ 1; /* change side */ break; @@ -374,8 +375,8 @@ t_addr ma; func = GET_FUNC (rlcsb); /* get function */ if (func == RLCSB_GSTA) { /* get status? */ rlsi = uptr->STAT | - ((uptr->TRK & RLCSA_HD)? RLDS_HD: 0) | - ((uptr->flags & UNIT_ATT)? RLDS_ATT: RLDS_UNATT); + ((uptr->TRK & RLCSA_HD)? RLDS_HD: 0) | + ((uptr->flags & UNIT_ATT)? RLDS_ATT: RLDS_UNATT); if (uptr->flags & UNIT_RL02) rlsi = rlsi | RLDS_RL02; if (uptr->flags & UNIT_WPRT) rlsi = rlsi | RLDS_WLK; rlsi2 = rlsi1 = rlsi; @@ -416,8 +417,8 @@ if (rlcsb & RLCSB_8B) { /* 8b mode? */ if (bc > maxc) wc = bc = maxc; } /* trk ovrun? limit */ else { bc = ((wc * 3) + 1) / 2; /* 12b mode */ if (bc > RL_NUMBY) { /* > 1 sector */ - bc = RL_NUMBY; /* cap xfer */ - wc = (RL_NUMBY * 2) / 3; } } + bc = RL_NUMBY; /* cap xfer */ + wc = (RL_NUMBY * 2) / 3; } } err = fseek (uptr->fileref, da, SEEK_SET); diff --git a/PDP8/pdp8_rx.c b/PDP8/pdp8_rx.c index 239815ff..65b25046 100644 --- a/PDP8/pdp8_rx.c +++ b/PDP8/pdp8_rx.c @@ -223,44 +223,45 @@ case 1: /* LCD */ rx_tr = rx_err = 0; /* clear flags */ bptr = 0; /* clear buf pointer */ if (rx_28 && (AC & RXCS_MODE)) { /* RX28 8b mode? */ - rx_dbr = rx_csr = AC & 0377; /* save 8b */ - rx_tr = 1; /* xfer is ready */ - rx_state = CMD8; } /* wait for part 2 */ - else { rx_dbr = rx_csr = AC; /* save new command */ - rx_cmd (); } /* issue command */ + rx_dbr = rx_csr = AC & 0377; /* save 8b */ + rx_tr = 1; /* xfer is ready */ + rx_state = CMD8; } /* wait for part 2 */ + else { + rx_dbr = rx_csr = AC; /* save new command */ + rx_cmd (); } /* issue command */ return 0; /* clear AC */ case 2: /* XDR */ switch (rx_state & 017) { /* case on state */ case EMPTY: /* emptying buffer */ - sim_activate (&rx_unit[drv], rx_xwait); /* sched xfer */ - return READ_RXDBR; /* return data reg */ + sim_activate (&rx_unit[drv], rx_xwait); /* sched xfer */ + return READ_RXDBR; /* return data reg */ case CMD8: /* waiting for cmd */ - rx_dbr = AC & 0377; - rx_csr = (rx_csr & 0377) | ((AC & 017) << 8); - rx_cmd (); - break; + rx_dbr = AC & 0377; + rx_csr = (rx_csr & 0377) | ((AC & 017) << 8); + rx_cmd (); + break; case RWDS:case RWDT:case FILL:case SDCNF: /* waiting for data */ - rx_dbr = AC; /* save data */ - sim_activate (&rx_unit[drv], rx_xwait); /* schedule */ - break; + rx_dbr = AC; /* save data */ + sim_activate (&rx_unit[drv], rx_xwait); /* schedule */ + break; default: /* default */ - return READ_RXDBR; } /* return data reg */ + return READ_RXDBR; } /* return data reg */ break; case 3: /* STR */ if (rx_tr != 0) { - rx_tr = 0; - return IOT_SKP + AC; } + rx_tr = 0; + return IOT_SKP + AC; } break; case 4: /* SER */ if (rx_err != 0) { - rx_err = 0; - return IOT_SKP + AC; } + rx_err = 0; + return IOT_SKP + AC; } break; case 5: /* SDN */ if ((dev_done & INT_RX) != 0) { - dev_done = dev_done & ~INT_RX; - int_req = int_req & ~INT_RX; - return IOT_SKP + AC; } + dev_done = dev_done & ~INT_RX; + int_req = int_req & ~INT_RX; + return IOT_SKP + AC; } break; case 6: /* INTR */ if (AC & 1) int_enable = int_enable | INT_RX; @@ -293,9 +294,9 @@ case RXCS_READ: case RXCS_WRITE: case RXCS_WRDEL: break; case RXCS_SDEN: if (rx_28) { /* RX28? */ - rx_state = SDCNF; /* state = get conf */ - rx_tr = 1; /* xfer is ready */ - break; } /* else fall thru */ + rx_state = SDCNF; /* state = get conf */ + rx_tr = 1; /* xfer is ready */ + break; } /* else fall thru */ default: rx_state = CMD_COMPLETE; /* state = cmd compl */ sim_activate (&rx_unit[drv], rx_cwait); /* sched done */ diff --git a/PDP8/pdp8_sys.c b/PDP8/pdp8_sys.c index d9efba82..6325b5e2 100644 --- a/PDP8/pdp8_sys.c +++ b/PDP8/pdp8_sys.c @@ -114,59 +114,60 @@ rubout = state = field = newf = origin = csum = 0; if ((sim_switches & SWMASK ('R')) || /* RIM format? */ (match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B')))) { while ((i = getc (fileref)) != EOF) { - switch (state) { - case 0: /* leader */ - if ((i != 0) && (i < 0200)) state = 1; - high = i; - break; - case 1: /* low byte */ - word = (high << 6) | i; /* form word */ - if (word > 07777) origin = word & 07777; - else M[origin] = word; - state = 2; - break; - case 2: /* high byte */ - if (i >= 0200) return SCPE_OK; /* end of tape? */ - high = i; /* save high */ - state = 1; - break; } /* end switch */ - } /* end while */ + switch (state) { + case 0: /* leader */ + if ((i != 0) && (i < 0200)) state = 1; + high = i; + break; + case 1: /* low byte */ + word = (high << 6) | i; /* form word */ + if (word > 07777) origin = word & 07777; + else M[origin] = word; + state = 2; + break; + case 2: /* high byte */ + if (i >= 0200) return SCPE_OK; /* end of tape? */ + high = i; /* save high */ + state = 1; + break; } /* end switch */ + } /* end while */ } /* end if */ else { while ((i = getc (fileref)) != EOF) { /* BIN format */ - if (rubout) { - rubout = 0; - continue; } - if (i == 0377) { - rubout = 1; - continue; } - if (i > 0200) { - newf = (i & 070) << 9; - continue; } - switch (state) { - case 0: /* leader */ - if ((i != 0) && (i != 0200)) state = 1; - high = i; /* save as high */ - break; - case 1: /* low byte */ - low = i; - state = 2; - break; - case 2: /* high with test */ - word = (high << 6) | low; - if (i == 0200) { /* end of tape? */ - if ((csum - word) & 07777) return SCPE_CSUM; - return SCPE_OK; } - csum = csum + low + high; - if (word >= 010000) origin = word & 07777; - else { if ((field | origin) >= MEMSIZE) - return SCPE_NXM; - M[field | origin] = word & 07777; - origin = (origin + 1) & 07777; } - field = newf; - high = i; - state = 1; - break; } /* end switch */ - } /* end while */ + if (rubout) { + rubout = 0; + continue; } + if (i == 0377) { + rubout = 1; + continue; } + if (i > 0200) { + newf = (i & 070) << 9; + continue; } + switch (state) { + case 0: /* leader */ + if ((i != 0) && (i != 0200)) state = 1; + high = i; /* save as high */ + break; + case 1: /* low byte */ + low = i; + state = 2; + break; + case 2: /* high with test */ + word = (high << 6) | low; + if (i == 0200) { /* end of tape? */ + if ((csum - word) & 07777) return SCPE_CSUM; + return SCPE_OK; } + csum = csum + low + high; + if (word >= 010000) origin = word & 07777; + else { + if ((field | origin) >= MEMSIZE) + return SCPE_NXM; + M[field | origin] = word & 07777; + origin = (origin + 1) & 07777; } + field = newf; + high = i; + state = 1; + break; } /* end switch */ + } /* end while */ } /* end else */ return SCPE_FMT; /* eof? error */ } @@ -330,9 +331,9 @@ int32 i, j; for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ if ((j == class) && (opc_val[i] & inst)) { /* same class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } + inst = inst & ~opc_val[i]; /* mask bit set? */ + fprintf (of, (sp? " %s": "%s"), opcode[i]); + sp = 1; } } return sp; } @@ -383,34 +384,34 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ switch (j) { /* case on class */ case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; + fprintf (of, "%s", opcode[i]); /* opcode */ + break; case I_V_FLD: /* field change */ - fprintf (of, "%s %-o", opcode[i], (inst >> 3) & 07); - break; + fprintf (of, "%s %-o", opcode[i], (inst >> 3) & 07); + break; case I_V_MRF: /* mem ref */ - disp = inst & 0177; /* displacement */ - fprintf (of, "%s%s", opcode[i], ((inst & 00400)? " I ": " ")); - if (inst & 0200) { /* current page? */ - if (cflag) fprintf (of, "%-o", (addr & 07600) | disp); - else fprintf (of, "C %-o", disp); } - else fprintf (of, "%-o", disp); /* page zero */ - break; + disp = inst & 0177; /* displacement */ + fprintf (of, "%s%s", opcode[i], ((inst & 00400)? " I ": " ")); + if (inst & 0200) { /* current page? */ + if (cflag) fprintf (of, "%-o", (addr & 07600) | disp); + else fprintf (of, "C %-o", disp); } + else fprintf (of, "%-o", disp); /* page zero */ + break; case I_V_IOT: /* IOT */ - fprintf (of, "%s %-o", opcode[i], inst & 0777); - break; + fprintf (of, "%s %-o", opcode[i], inst & 0777); + break; case I_V_OP1: /* operate group 1 */ - sp = fprint_opr (of, inst & 0361, j, 0); - if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); - break; + sp = fprint_opr (of, inst & 0361, j, 0); + if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); + break; case I_V_OP2: /* operate group 2 */ - if (opcode[i]) fprintf (of, "%s", opcode[i]); /* skips */ - fprint_opr (of, inst & 0206, j, opcode[i] != NULL); - break; + if (opcode[i]) fprintf (of, "%s", opcode[i]); /* skips */ + fprint_opr (of, inst & 0206, j, opcode[i] != NULL); + break; case I_V_OP3: /* operate group 3 */ - sp = fprint_opr (of, inst & 0320, j, 0); - if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); - break; } /* end case */ + sp = fprint_opr (of, inst & 0320, j, 0); + if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]); + break; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; @@ -468,44 +469,46 @@ case I_V_IOT: /* IOT */ break; case I_V_FLD: /* field */ for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && + cptr = get_glyph (cptr, gbuf, 0)) { + for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; - if (opcode[i] != NULL) { - k = (opc_val[i] >> I_V_FL) & I_M_FL; - if (k != j) return SCPE_ARG; - val[0] = val[0] | (opc_val[i] & 07777); } - else { d = get_uint (gbuf, 8, 07, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << 3); - break; } } - break; + if (opcode[i] != NULL) { + k = (opc_val[i] >> I_V_FL) & I_M_FL; + if (k != j) return SCPE_ARG; + val[0] = val[0] | (opc_val[i] & 07777); } + else { + d = get_uint (gbuf, 8, 07, &r); + if (r != SCPE_OK) return SCPE_ARG; + val[0] = val[0] | (d << 3); + break; } } + break; case I_V_MRF: /* mem ref */ cptr = get_glyph (cptr, gbuf, 0); /* get next field */ if (strcmp (gbuf, "I") == 0) { /* indirect? */ - val[0] = val[0] | 0400; - cptr = get_glyph (cptr, gbuf, 0); } + val[0] = val[0] | 0400; + cptr = get_glyph (cptr, gbuf, 0); } if ((k = (strcmp (gbuf, "C") == 0)) || (strcmp (gbuf, "Z") == 0)) { - cptr = get_glyph (cptr, gbuf, 0); - d = get_uint (gbuf, 8, 0177, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d | (k? 0200: 0); } - else { d = get_uint (gbuf, 8, 07777, &r); - if (r != SCPE_OK) return SCPE_ARG; - if (d <= 0177) val[0] = val[0] | d; - else if (cflag && (((addr ^ d) & 07600) == 0)) - val[0] = val[0] | (d & 0177) | 0200; - else return SCPE_ARG; } + cptr = get_glyph (cptr, gbuf, 0); + d = get_uint (gbuf, 8, 0177, &r); + if (r != SCPE_OK) return SCPE_ARG; + val[0] = val[0] | d | (k? 0200: 0); } + else { + d = get_uint (gbuf, 8, 07777, &r); + if (r != SCPE_OK) return SCPE_ARG; + if (d <= 0177) val[0] = val[0] | d; + else if (cflag && (((addr ^ d) & 07600) == 0)) + val[0] = val[0] | (d & 0177) | 0200; + else return SCPE_ARG; } break; case I_V_NPN: case I_V_OP1: case I_V_OP2: case I_V_OP3: /* operates */ for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, 0)) { - for (i = 0; (opcode[i] != NULL) && + cptr = get_glyph (cptr, gbuf, 0)) { + for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; - k = opc_val[i] & 07777; - if ((opcode[i] == NULL) || (((k ^ val[0]) & 07000) != 0)) - return SCPE_ARG; - val[0] = val[0] | k; } + k = opc_val[i] & 07777; + if ((opcode[i] == NULL) || (((k ^ val[0]) & 07000) != 0)) + return SCPE_ARG; + val[0] = val[0] | k; } break; } /* end case */ if (*cptr != 0) return SCPE_ARG; /* junk at end? */ return SCPE_OK; diff --git a/PDP8/pdp8_tt.c b/PDP8/pdp8_tt.c index 5c204110..4af32ac6 100644 --- a/PDP8/pdp8_tt.c +++ b/PDP8/pdp8_tt.c @@ -25,6 +25,7 @@ tti,tto KL8E terminal input/output + 22-Dec-02 RMS Added break support 01-Nov-02 RMS Added 7B/8B support 04-Oct-02 RMS Added DIBs, device number support 30-May-02 RMS Widened POS to 32b @@ -157,7 +158,8 @@ int32 c; sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (tti_unit.flags & UNIT_KSR) { /* UC only? */ +if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */ +else if (tti_unit.flags & UNIT_KSR) { /* UC only? */ c = c & 0177; if (islower (c)) c = toupper (c); tti_unit.buf = c | 0200; } /* add TTY bit */ diff --git a/PDP8/pdp8_ttx.c b/PDP8/pdp8_ttx.c index 55f82c54..4e54dac8 100644 --- a/PDP8/pdp8_ttx.c +++ b/PDP8/pdp8_ttx.c @@ -25,6 +25,7 @@ ttix,ttox PT08/KL8JA terminal input/output + 22-Dec-02 RMS Added break support 02-Nov-02 RMS Added 7B/8B support 04-Oct-02 RMS Added DIB, device number support 22-Aug-02 RMS Updated for changes to sim_tmxr.c @@ -202,15 +203,16 @@ if (ln >= 0) { /* got one? */ ttx_ldsc[ln].rcve = 1; } /* rcv enabled */ tmxr_poll_rx (&ttx_desc); /* poll for input */ for (ln = 0; ln < TTX_LINES; ln++) { /* loop thru lines */ - if (ttx_ldsc[ln].conn) { /* connected? */ - if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */ - if (ttox_unit[ln].flags & UNIT_UC) { /* UC mode? */ - c = temp & 0177; - if (islower (c)) c = toupper (c); } - else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); - ttix_buf[ln] = c; - dev_done = dev_done | (INT_TTI1 << ln); - int_req = INT_UPDATE; } } } + if (ttx_ldsc[ln].conn) { /* connected? */ + if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */ + if (temp & SCPE_BREAK) c = 0; /* break? */ + else if (ttox_unit[ln].flags & UNIT_UC) { /* UC? */ + c = temp & 0177; + if (islower (c)) c = toupper (c); } + else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); + ttix_buf[ln] = c; + dev_done = dev_done | (INT_TTI1 << ln); + int_req = INT_UPDATE; } } } return SCPE_OK; } @@ -358,10 +360,10 @@ int32 i; for (i = 0; (i < TTX_LINES) && (ttx_ldsc[i].conn == 0); i++) ; if (i < TTX_LINES) { - for (i = 0; i < TTX_LINES; i++) { - if (ttx_ldsc[i].conn) - if (val) tmxr_fconns (st, &ttx_ldsc[i], i); - else tmxr_fstats (st, &ttx_ldsc[i], i); } } + for (i = 0; i < TTX_LINES; i++) { + if (ttx_ldsc[i].conn) + if (val) tmxr_fconns (st, &ttx_ldsc[i], i); + else tmxr_fstats (st, &ttx_ldsc[i], i); } } else fprintf (st, "all disconnected\n"); return SCPE_OK; } diff --git a/S3/s3_defs.h b/S3/s3_defs.h index bd7a5610..b24adad5 100644 --- a/S3/s3_defs.h +++ b/S3/s3_defs.h @@ -92,4 +92,3 @@ struct opdef { 2 - 2-address (0x<0,1,2,4,5,6,8,9,A>x) 3 - 1-address B (0x<3,7,B>x) */ }; - \ No newline at end of file diff --git a/SDS/sds_cpu.c b/SDS/sds_cpu.c new file mode 100644 index 00000000..0db8b16c --- /dev/null +++ b/SDS/sds_cpu.c @@ -0,0 +1,1247 @@ +/* sds_cpu.c: SDS 940 CPU simulator + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + The system state for the SDS 940 is: + + A<0:23> A register + B<0:23> B register + X<0:23> X (index) register + OV overflow indicator + P<0:13> program counter + nml_mode compatible (1) vs 940 (0) mode + usr_mode user (1) vs monitor (0) mode + RL1<0:23> user map low + RL2<0:23> user map high + RL4<12:23> monitor map high + EM2<0:2> memory extension, block 2 + EM3<0:2> memory extension, block 3 + bpt breakpoint switches + + cpu central processor + rtc real time clock +*/ + +/* The SDS 940 has three instruction format -- memory reference, register change, + and I/O. The memory reference format is: + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 23 23 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | U| X| P| opcode |IN| address | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + U force user mode addressing (monitor mode only) + X indexed + P opcode is a programmed operator + opcode opcode + IN indirect addressing + address virtual address + + Virtual addresses are 14b. Depending on the operating mode (normal, user, + or monitor), virtual addresses are translated to 15b or 16b physical addresses. + + normal virtual [000000:017777] are unmapped + EM2 and EM3 extend virtual [020000:037777] to 15b + user RL1 and RL2 map virtual [000000:037777] to 16b + monitor virtual [000000:017777] are unmapped + EM2 extends virtual [020000:027777] to 15b + RL4 maps virtual [030000:037777] to 16b + + The register change format is: + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 23 23 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 0| m| 0| opcode | microcoded register change instruction | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + The I/O format is: + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 23 23 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 0|CH| 0| opcode |mode | I/O function | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +*/ + +/* This routine is the instruction decode routine for the SDS 940. + It is called from the simulator control program to execute + instructions in simulated memory, starting at the simulated PC. + It runs until 'reason' is set non-zero. + + General notes: + + 1. Reasons to stop. The simulator can be stopped by: + + HALT instruction + breakpoint encountered + invalid instruction and stop_invins flag set + invalid I/O device and stop_invdev flag set + invalid I/O operation and stop_inviop flag set + I/O error in I/O simulator + indirect loop exceeding limit + EXU loop exceeding limit + mapping exception in interrupt or trap instruction + + 2. Interrupts. The interrupt structure consists of the following: + + int_req interrupt requests (low bit reserved) + api_lvl active interrupt levels + int_reqhi highest interrupt request + api_lvlhi highest interrupt service (0 if none) + ion interrupt enable + ion_defer interrupt defer (one instruction) + + 3. Channels. The SDS 940 has a channel-based I/O structure. Each + channel is represented by a set of registers. Channels test the + I/O transfer requests from devices, which are kept in xfr_req. + + 4. Non-existent memory. On the SDS 940, reads to non-existent memory + return zero, and writes are ignored. In the simulator, the + largest possible memory is instantiated and initialized to zero. + Thus, only writes need be checked against actual memory size. + + 5. Adding I/O devices. These modules must be modified: + + sds_defs.h add interrupt, transfer, and alert definitions + sds_io.c add alert dispatches aldisp + sds_sys.c add pointer to data structures to sim_devices +*/ + +#include "sds_defs.h" + +#define PCQ_SIZE 64 /* must be 2**n */ +#define PCQ_MASK (PCQ_SIZE - 1) +#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = pc +#define UNIT_V_MSIZE (UNIT_V_GENIE + 1) /* dummy mask */ +#define UNIT_MSIZE (1 << UNIT_V_MSIZE) + +uint32 M[MAXMEMSIZE] = { 0 }; /* memory */ +uint32 A, B, X; /* registers */ +uint32 P; /* program counter */ +uint32 OV; /* overflow */ +uint32 xfr_req = 0; /* xfr req */ +uint32 ion = 0; /* int enable */ +uint32 ion_defer = 0; /* int defer */ +uint32 int_req = 0; /* int requests */ +uint32 int_reqhi = 0; /* highest int request */ +uint32 api_lvl = 0; /* api active */ +uint32 api_lvlhi = 0; /* highest api active */ +t_bool chan_req; /* chan request */ +uint32 nml_mode = 1; /* normal mode */ +uint32 usr_mode = 0; /* user mode */ +uint32 mon_usr_trap = 0; /* mon-user trap */ +uint32 EM2 = 2, EM3 = 3; /* extension registers */ +uint32 RL1, RL2, RL4; /* relocation maps */ +uint32 bpt; /* breakpoint switches */ +uint32 alert; /* alert dispatch */ +uint32 em2_dyn, em3_dyn; /* extensions, dynamic */ +uint32 usr_map[8]; /* user map, dynamic */ +uint32 mon_map[8]; /* mon map, dynamic */ +int32 ind_lim = 32; /* indirect limit */ +int32 exu_lim = 32; /* EXU limit */ +int32 cpu_genie = 0; /* Genie flag */ +int32 cpu_astop = 0; /* address stop */ +int32 stop_invins = 1; /* stop inv inst */ +int32 stop_invdev = 1; /* stop inv dev */ +int32 stop_inviop = 1; /* stop inv io op */ +uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ +int32 pcq_p = 0; /* PC queue ptr */ +REG *pcq_r = NULL; /* PC queue reg ptr */ +int32 rtc_pie = 0; /* rtc pulse ie */ +int32 rtc_tps = 60; /* rtc ticks/sec */ + +extern int32 sim_int_char; +extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +extern UNIT mux_unit; + +t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); +t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); +t_stat cpu_reset (DEVICE *dptr); +t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_set_type (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat Ea (uint32 wd, uint32 *va); +t_stat EaSh (uint32 wd, uint32 *va); +t_stat Read (uint32 va, uint32 *dat); +t_stat Write (uint32 va, uint32 dat); +void set_dyn_map (void); +uint32 api_findreq (void); +void api_dismiss (void); +uint32 Add24 (uint32 s1, uint32 s2, uint32 cin); +uint32 AddM24 (uint32 s1, uint32 s2); +void Mul48 (uint32 mplc, uint32 mplr); +void Div48 (uint32 dvdh, uint32 dvdl, uint32 dvr); +void RotR48 (uint32 sc); +void ShfR48 (uint32 sc, uint32 sgn); +t_stat one_inst (uint32 inst, uint32 pc, uint32 mode); +t_stat rtc_inst (uint32 inst); +t_stat rtc_svc (UNIT *uptr); +t_stat rtc_reset (DEVICE *dptr); +extern t_bool io_init (void); +extern t_stat op_wyim (uint32 inst, uint32 *dat); +extern t_stat op_miwy (uint32 inst, uint32 dat); +extern t_stat op_pin (uint32 *dat); +extern t_stat op_pot (uint32 dat); +extern t_stat op_eomd (uint32 inst); +extern t_stat op_sks (uint32 inst, uint32 *skp); + +/* CPU data structures + + cpu_dev CPU device descriptor + cpu_unit CPU unit descriptor + cpu_reg CPU register list + cpu_mod CPU modifiers list +*/ + +UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) }; + +REG cpu_reg[] = { + { ORDATA (P, P, 14) }, + { ORDATA (A, A, 24) }, + { ORDATA (B, B, 24) }, + { ORDATA (X, X, 24) }, + { FLDATA (OV, OV, 0) }, + { ORDATA (EM2, EM2, 3) }, + { ORDATA (EM3, EM3, 3) }, + { ORDATA (RL1, RL1, 24) }, + { ORDATA (RL2, RL2, 24) }, + { ORDATA (RL4, RL4, 12) }, + { FLDATA (NML, nml_mode, 0) }, + { FLDATA (USR, usr_mode, 0) }, + { FLDATA (MONUSR, mon_usr_trap, 0) }, + { FLDATA (ION, ion, 0) }, + { FLDATA (INTDEF, ion_defer, 0) }, + { ORDATA (INTREQ, int_req, 32) }, + { ORDATA (APILVL, api_lvl, 32) }, + { DRDATA (INTRHI, int_reqhi, 5) }, + { DRDATA (APILHI, api_lvlhi, 5), REG_RO }, + { ORDATA (XFRREQ, xfr_req, 32) }, + { FLDATA (BPT1, bpt, 3) }, + { FLDATA (BPT2, bpt, 2) }, + { FLDATA (BPT3, bpt, 1) }, + { FLDATA (BPT4, bpt, 0) }, + { ORDATA (ALERT, alert, 6) }, + { FLDATA (STOP_INVINS, stop_invins, 0) }, + { FLDATA (STOP_INVDEV, stop_invdev, 0) }, + { FLDATA (STOP_INVIOP, stop_inviop, 0) }, + { DRDATA (INDLIM, ind_lim, 8), REG_NZ+PV_LEFT }, + { DRDATA (EXULIM, exu_lim, 8), REG_NZ+PV_LEFT }, + { BRDATA (PCQ, pcq, 8, 14, PCQ_SIZE), REG_RO+REG_CIRC }, + { ORDATA (PCQP, pcq_p, 6), REG_HRO }, + { ORDATA (WRU, sim_int_char, 8) }, + { NULL } }; + +MTAB cpu_mod[] = { + { UNIT_GENIE, 0, "standard peripherals", "SDS", &cpu_set_type }, + { UNIT_GENIE, UNIT_GENIE, "Genie peripherals", "GENIE", &cpu_set_type }, + { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, + { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, + { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size }, + { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, + { 0 } }; + +DEVICE cpu_dev = { + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 8, 16, 1, 8, 24, + &cpu_ex, &cpu_dep, &cpu_reset, + NULL, NULL, NULL, + NULL, 0 }; + +/* Clock data structures + + rtc_dev RTC device descriptor + rtc_unit RTC unit + rtc_reg RTC register list +*/ + +UNIT rtc_unit = { UDATA (&rtc_svc, 0, 0), 16000 }; + +REG rtc_reg[] = { + { FLDATA (PIE, rtc_pie, 0) }, + { DRDATA (TIME, rtc_unit.wait, 24), REG_NZ + PV_LEFT }, + { DRDATA (TPS, rtc_tps, 8), REG_NZ + PV_LEFT }, + { NULL } }; + +DEVICE rtc_dev = { + "RTC", &rtc_unit, rtc_reg, NULL, + 1, 8, 8, 1, 8, 8, + NULL, NULL, &rtc_reset, + NULL, NULL, NULL }; + +/* Interrupt tables */ + +static const uint32 api_mask[32] = { + 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, 0xFFFFFFF0, + 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, 0xFFFFFF00, + 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800, 0xFFFFF000, + 0xFFFFE000, 0xFFFFC000, 0xFFFF8000, 0xFFFF0000, + 0xFFFE0000, 0xFFFC0000, 0xFFF80000, 0xFFF00000, + 0xFFE00000, 0xFFC00000, 0xFF800000, 0xFF000000, + 0xFE000000, 0xFC000000, 0xF8000000, 0xF0000000, + 0xE0000000, 0xC0000000, 0x80000000, 0x00000000 }; + +static const uint32 int_vec[32] = { + 0, 0, 0, 0, + VEC_FORK, VEC_DRM, VEC_MUXCF,VEC_MUXCO, + VEC_MUXT, VEC_MUXR, VEC_HEOR, VEC_HZWC, + VEC_GEOR, VEC_GZWC, VEC_FEOR, VEC_FZWC, + VEC_EEOR, VEC_EZWC, VEC_DEOR, VEC_DZWC, + VEC_CEOR, VEC_CZWC, VEC_WEOR, VEC_YEOR, + VEC_WZWC, VEC_YZWC, VEC_RTCP, VEC_RTCS, + VEC_IPAR, VEC_CPAR, VEC_PWRF, VEC_PWRO }; + +t_stat sim_instr (void) +{ +extern int32 sim_interval; +uint32 inst, tinst, pa, save_P, save_mode; +t_stat reason, tr; + +/* Restore register state */ + +if (io_init ()) return SCPE_STOP; /* init IO; conflict? */ +reason = 0; +xfr_req = xfr_req & ~1; /* <0> reserved */ +int_req = int_req & ~1; /* <0> reserved */ +api_lvl = api_lvl & ~1; /* <0> reserved */ +set_dyn_map (); /* set up mapping */ +int_reqhi = api_findreq (); /* recalc int req */ +chan_req = chan_testact (); /* recalc chan act */ +sim_rtcn_init (rtc_unit.wait, TMR_RTC); /* init calibration */ +sim_rtcn_init (mux_unit.wait, TMR_MUX); /* init calibration */ + +/* Main instruction fetch/decode loop */ + +while (reason == 0) { /* loop until halted */ + +if (cpu_astop) { /* debug stop? */ + cpu_astop = 0; + return SCPE_STOP; } + +if (sim_interval <= 0) { /* event queue? */ + if (reason = sim_process_event ()) break; /* process */ + int_reqhi = api_findreq (); /* recalc int req */ + chan_req = chan_testact (); /* recalc chan act */ + } + +if (chan_req) { /* channel request? */ + if (reason = chan_process ()) break; /* process */ + int_reqhi = api_findreq (); /* recalc int req */ + chan_req = chan_testact (); /* recalc chan act */ + } + +sim_interval = sim_interval - 1; /* count down */ +if (ion && !ion_defer && int_reqhi) { /* int request? */ + pa = int_vec[int_reqhi]; /* get vector */ + if (pa == 0) { /* bad value? */ + reason = STOP_ILLVEC; + break; } + tinst = ReadP (pa); /* get inst */ + save_mode = usr_mode; /* save mode */ + usr_mode = 0; /* switch to mon */ + if (pa != VEC_RTCP) { /* normal intr? */ + tr = one_inst (tinst, P, save_mode); /* exec intr inst */ + if (tr) { /* stop code? */ + usr_mode = save_mode; /* restore mode */ + reason = (tr > 0)? tr: STOP_MMINT; + break; } + api_lvl = api_lvl | (1u << int_reqhi); /* set level active */ + api_lvlhi = int_reqhi; } /* elevate api */ + else { /* clock intr */ + tr = rtc_inst (tinst); /* exec RTC inst */ + usr_mode = save_mode; /* restore mode */ + if (tr) { /* stop code? */ + reason = (tr > 0)? tr: STOP_MMINT; + break; } + int_req = int_req & ~INT_RTCP; } /* clr clkp intr */ + int_reqhi = api_findreq (); /* recalc int req */ + } +else { /* normal instr */ + if (sim_brk_summ && sim_brk_test (P, SWMASK ('E'))) { /* breakpoint? */ + reason = STOP_IBKPT; /* stop simulation */ + break; } + reason = Read (save_P = P, &inst); /* get instr */ + P = (P + 1) & VA_MASK; /* incr PC */ + if (reason == SCPE_OK) { /* fetch ok? */ + ion_defer = 0; /* clear ion */ + reason = one_inst (inst, save_P, usr_mode); /* exec inst */ + if (reason > 0) { /* stop code? */ + if (reason != STOP_HALT) P = save_P; + if (reason == STOP_IONRDY) reason = 0; } + } /* end if r == 0 */ + if (reason < 0) { /* mm (fet or ex)? */ + pa = -reason; /* get vector */ + reason = 0; /* defang */ + tinst = ReadP (pa); /* get inst */ + if (I_GETOP (tinst) != BRM) { /* not BRM? */ + reason = STOP_TRPINS; /* fatal err */ + break; } + save_mode = usr_mode; /* save mode */ + usr_mode = 0; /* switch to mon */ + mon_usr_trap = 0; + tr = one_inst (tinst, save_P, save_mode); /* trap inst */ + if (tr) { /* stop code? */ + usr_mode = save_mode; /* restore mode */ + P = save_P; /* restore PC */ + reason = (tr > 0)? tr: STOP_MMTRP; + break; } + } /* end if reason */ + } /* end else int */ +} /* end while */ + +/* Simulation halted */ + +pcq_r->qptr = pcq_p; /* update pc q ptr */ +return reason; +} + +/* Simulate one instruction */ + +t_stat one_inst (uint32 inst, uint32 pc, uint32 mode) +{ +uint32 op, shf_op, va, dat; +uint32 old_A, old_B, old_X; +int32 i, exu_cnt, sc; +t_stat r; + +exu_cnt = 0; /* init EXU count */ +EXU_LOOP: +op = I_GETOP (inst); /* get opcode */ +if (inst & I_POP) { /* POP? */ + dat = (EM3 << 18) | (EM2 << 15) | I_IND | pc; /* data to save */ + if (nml_mode) { /* normal mode? */ + dat = (OV << 23) | dat; /* ov in <0> */ + WriteP (0, dat); } + else if (usr_mode) { /* user mode? */ + if (inst & I_USR) { /* SYSPOP? */ + dat = I_USR | (OV << 21) | dat; /* ov in <2> */ + WriteP (0, dat); + usr_mode = 0; } /* set mon mode */ + else { /* normal POP */ + dat = (OV << 23) | dat; /* ov in <0> */ + if (r = Write (0, dat)) return r; } } + else { /* mon mode */ + dat = (OV << 21) | dat; /* ov in <2> */ + WriteP (0, dat); } /* store return */ + PCQ_ENTRY; /* save PC */ + P = 0100 | op; /* new PC */ + OV = 0; /* clear ovflo */ + return SCPE_OK; } /* end POP */ +switch (op) { /* case on opcode */ + +/* Loads and stores */ + +case LDA: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &A)) return r; /* get operand */ + break; +case LDB: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &B)) return r; /* get operand */ + break; +case LDX: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &X)) return r; /* get operand */ + break; +case STA: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Write (va, A)) return r; /* write operand */ + break; +case STB: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Write (va, B)) return r; /* write operand */ + break; +case STX: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Write (va, X)) return r; /* write operand */ + break; +case EAX: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (nml_mode || usr_mode) /* normal or user? */ + X = (X & ~VA_MASK) | (va & VA_MASK); /* only 14b */ + else X = (X & ~XVA_MASK) | (va & XVA_MASK); /* mon, 15b */ + break; +case XMA: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + if (r = Write (va, A)) return r; /* write A */ + A = dat; /* load A */ + break; + +/* Arithmetic and logical */ + +case ADD: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + A = Add24 (A, dat, 0); /* add */ + break; +case ADC: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + OV = 0; /* clear overflow */ + A = Add24 (A, dat, X >> 23); /* add with carry */ + break; +case SUB: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + A = Add24 (A, dat ^ DMASK, 1); /* subtract */ + break; +case SUC: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + OV = 0; /* clear overflow */ + A = Add24 (A, dat ^ DMASK, X >> 23); /* sub with carry */ + break; +case ADM: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + dat = AddM24 (dat, A); /* mem + A */ + if (r = Write (va, dat)) return r; /* rewrite */ + break; +case MIN: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + dat = AddM24 (dat, 1); /* mem + 1 */ + if (r = Write (va, dat)) return r; /* rewrite */ + break; +case MUL: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + Mul48 (A, dat); /* multiply */ + break; +case DIV: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + Div48 (A, B, dat); /* divide */ + break; +case ETR: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + A = A & dat; /* and */ + break; +case MRG: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + A = A | dat; /* or */ + break; +case EOR: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + A = A ^ dat; /* xor */ + break; + +/* Skips */ + +case SKE: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + if (A == dat) P = (P + 1) & VA_MASK; /* if A = op, skip */ + break; +case SKG: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + if (SXT (A) > SXT (dat)) P = (P + 1) & VA_MASK; /* if A > op, skip */ + break; +case SKM: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + if (((A ^ dat) & B) == 0) P = (P + 1) & VA_MASK; /* if A = op masked */ + break; +case SKA: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + if ((A & dat) == 0) P = (P + 1) & VA_MASK; /* if !(A & op), skip */ + break; +case SKB: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + if ((B & dat) == 0) P = (P + 1) & VA_MASK; /* if !(B & op), skip */ + break; +case SKN: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + if (dat & SIGN) P = (P + 1) & VA_MASK; /* if op < 0, skip */ + break; +case SKR: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + dat = AddM24 (dat, DMASK); /* decr operand */ + if (r = Write (va, dat)) return r; /* rewrite operand */ + if (dat & SIGN) P = (P + 1) & VA_MASK; /* if op < 0, skip */ + break; +case SKD: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + if (SXT_EXP (B) < SXT_EXP (dat)) { /* B < dat? */ + X = (dat - B) & DMASK; /* X = dat - B */ + P = (P + 1) & VA_MASK; } /* skip */ + else X = (B - dat) & DMASK; /* X = B - dat */ + break; + +/* Control */ + +case NOP: + break; +case HLT: + if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ + return STOP_HALT; /* halt CPU */ +case EXU: + exu_cnt = exu_cnt + 1; /* count chained EXU */ + if (exu_cnt > exu_lim) return STOP_EXULIM; /* too many? */ + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + inst = dat; + goto EXU_LOOP; +case BRU: + if (nml_mode && (inst & I_IND)) api_dismiss (); /* normal BRU*, dism */ + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* test dest access */ + PCQ_ENTRY; + P = va & VA_MASK; /* branch */ + break; +case BRX: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + X = (X + 1) & DMASK; /* incr X */ + if (X & I_IND) { /* bit 9 set? */ + if (r = Read (va, &dat)) return r; /* test dest access */ + PCQ_ENTRY; + P = va & VA_MASK; } /* branch */ + break; +case BRM: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + dat = (EM3 << 18) | (EM2 << 15) | pc; /* form return word */ + if (!nml_mode && !usr_mode) /* monitor mode? */ + dat = dat | (mode << 23) | (OV << 21); + else dat = dat | (OV << 23); /* normal or user */ + if (r = Write (va, dat)) return r; /* write ret word */ + PCQ_ENTRY; + P = (va + 1) & VA_MASK; /* branch */ + break; +case BRR: + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + PCQ_ENTRY; + P = (dat + 1) & VA_MASK; /* branch */ + if (!nml_mode && !usr_mode) { /* monitor mode? */ + OV = OV | ((dat >> 21) & 1); /* restore OV */ + if ((va & VA_USR) | (dat & I_USR)) { /* mode change? */ + usr_mode = 1; + if (mon_usr_trap) return MM_MONUSR; } } + else OV = OV | ((dat >> 23) & 1); /* restore OV */ + break; +case BRI: + if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + api_dismiss (); /* dismiss hi api */ + PCQ_ENTRY; + P = dat & VA_MASK; /* branch */ + if (!nml_mode) { /* monitor mode? */ + OV = (dat >> 21) & 1; /* restore OV */ + if ((va & VA_USR) | (dat & I_USR)) { /* mode change? */ + usr_mode = 1; + if (mon_usr_trap) return MM_MONUSR; } } + else OV = (dat >> 23) & 1; /* restore OV */ + break; + +/* Register change (microprogrammed) */ + +case RCH: + old_A = A; /* save orig reg */ + old_B = B; + old_X = X; + if (inst & 000001211) { /* A change? */ + if (inst & 01000) dat = (~old_A + 1) & DMASK; /* CNA */ + else dat = 0; + if (inst & 00200) dat = dat | old_X; + if (inst & 00010) dat = dat | old_B; + if (inst & 00100) A = (A & ~EXPMASK) | (dat & EXPMASK); + else A = dat; } + if (inst & 000000046) { /* B change? */ + if (inst & 00040) dat = old_X; + else dat = 0; + if (inst & 00004) dat = dat | old_A; + if (inst & 00100) B = (B & ~EXPMASK) | (dat & EXPMASK); + else B = dat; } + if (inst & 020000420) { /* X change? */ + if (inst & 00400) dat = old_A; + else dat = 0; + if (inst & 00020) dat = dat | old_B; + if (inst & 00100) X = SXT_EXP (dat) & DMASK; + else X = dat; } + break; + +/* Overflow instruction */ + +case OVF: + if ((inst & 0100) & OV) P = (P + 1) & VA_MASK; + if (inst & 0001) OV = 0; + if ((inst & 0010) && (((X >> 1) ^ X) & EXPS)) OV = 1; + break; + +/* Shifts */ + +case RSH: + if (r = EaSh (inst, &va)) return r; /* decode eff addr */ + shf_op = I_GETSHFOP (va); /* get eff op */ + sc = va & I_SHFMSK; /* get eff count */ + switch (shf_op) { /* case on sub-op */ + case 00: /* right arithmetic */ + if (sc) ShfR48 (sc, (A & SIGN)? DMASK: 0); + break; + case 04: /* right cycle */ + sc = sc % 48; /* mod 48 */ + if (sc) RotR48 (sc); + break; + case 05: /* right logical */ + if (sc) ShfR48 (sc, 0); + break; + default: + CRETINS; /* invalid inst */ + break; } /* end case shf op */ + break; + +case LSH: + if (r = EaSh (inst, &va)) return r; /* decode eff addr */ + shf_op = I_GETSHFOP (va); /* get eff op */ + sc = va & I_SHFMSK; /* get eff count */ + switch (shf_op) { /* case on sub-op */ + case 00: /* left arithmetic */ + dat = A; /* save sign */ + if (sc > 48) sc = 48; + for (i = 0; i < sc; i++) { /* loop */ + A = ((A << 1) | (B >> 23)) & DMASK; + B = (B << 1) & DMASK; + if ((A ^ dat) & SIGN) OV = 1; } + break; + case 02: /* normalize */ + if (sc > 48) sc = 48; + for (i = 0; i < sc; i++) { /* until max count */ + if ((A ^ (A << 1)) & SIGN) break; + A = ((A << 1) | (B >> 23)) & DMASK; + B = (B << 1) & DMASK; } + X = (X - i) & DMASK; + break; + case 04: /* left cycle */ + sc = sc % 48; /* mod 48 */ + if (sc) RotR48 (48 - sc); /* rotate */ + break; + case 06: /* cycle normalize */ + if (sc > 48) sc = 48; + for (i = 0; i < sc; i++) { /* until max count */ + if ((A ^ (A << 1)) & SIGN) break; + old_A = A; /* cyclic shift */ + A = ((A << 1) | (B >> 23)) & DMASK; + B = ((B << 1) | (old_A >> 23)) & DMASK; } + X = (X - i) & DMASK; + break; + default: + CRETINS; /* invalid inst */ + break; } /* end case shf op */ + break; + +/* I/O instructions */ + +case MIW: case MIY: + if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + if (r = op_miwy (inst, dat)) return r; /* process inst */ + int_reqhi = api_findreq (); /* recalc int req */ + chan_req = chan_testact (); /* recalc chan act */ + break; +case WIM: case YIM: + if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = op_wyim (inst, &dat)) return r; /* process inst */ + if (r = Write (va, dat)) return r; /* write result */ + int_reqhi = api_findreq (); /* recalc int req */ + chan_req = chan_testact (); /* recalc chan act */ + break; +case EOM: case EOD: + if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ + if (r = op_eomd (inst)) return r; /* process inst */ + int_reqhi = api_findreq (); /* recalc int req */ + chan_req = chan_testact (); /* recalc chan act */ + ion_defer = 1; + break; +case POT: + if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = Read (va, &dat)) return r; /* get operand */ + if (r = op_pot (dat)) return r; /* process inst */ + int_reqhi = api_findreq (); /* recalc int req */ + chan_req = chan_testact (); /* recalc chan act */ + break; +case PIN: + if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ + if (r = Ea (inst, &va)) return r; /* decode eff addr */ + if (r = op_pin (&dat)) return r; /* process inst */ + if (r = Write (va, dat)) return r; /* write result */ + int_reqhi = api_findreq (); /* recalc int req */ + chan_req = chan_testact (); /* recalc chan act */ + break; +case SKS: + if (!nml_mode && usr_mode) return MM_PRVINS; /* priv inst */ + if (r = op_sks (inst, &dat)) return r; /* process inst */ + if (dat) P = (P + 1) & VA_MASK; + break; + +default: + if (!nml_mode && usr_mode) return MM_PRVINS; /* usr? priv viol */ + CRETINS; /* invalid inst */ + break; } +return SCPE_OK; +} + +/* Effective address calculation */ + +t_stat Ea (uint32 inst, uint32 *addr) +{ +int32 i; +uint32 wd = inst; /* homeable */ +uint32 va = wd & XVA_MASK; /* initial va */ +t_stat r; + +for (i = 0; i < ind_lim; i++) { /* count indirects */ + if (wd & I_IDX) va = (va & VA_USR) | ((va + X) & VA_MASK); + *addr = va; + if ((wd & I_IND) == 0) return SCPE_OK; /* indirect? */ + if (r = Read (va, &wd)) return r; /* read ind; fails? */ + va = (va & VA_USR) | (wd & XVA_MASK); + } +return STOP_INDLIM; /* too many indirects */ +} + +/* Effective address calculation for shifts - direct indexing is 9b */ + +t_stat EaSh (uint32 inst, uint32 *addr) +{ +int32 i; +uint32 wd = inst; /* homeable */ +uint32 va = wd & XVA_MASK; /* initial va */ +t_stat r; + +for (i = 0; i < ind_lim; i++) { /* count indirects */ + if ((wd & I_IND) == 0) { /* end of ind chain? */ + if (wd & I_IDX) *addr = (va & (VA_MASK & ~I_SHFMSK)) | + ((va + X) & I_SHFMSK); /* 9b indexing */ + else *addr = va & VA_MASK; + return SCPE_OK; } + if (wd & I_IDX) va = (va & VA_USR) | ((va + X) & VA_MASK); + if (r = Read (va, &wd)) return r; /* read ind; fails? */ + va = (va & VA_USR) | (wd & XVA_MASK); + } +return STOP_INDLIM; /* too many indirects */ +} + +/* Read word from virtual address */ + +t_stat Read (uint32 va, uint32 *dat) +{ +uint32 pgn, map, pa; + +if (nml_mode) { /* normal? */ + va = va & VA_MASK; /* ignore user */ + if (va < 020000) pa = va; /* first 8K: 1 for 1 */ + else if (va < 030000) pa = va + em2_dyn; /* next 4K: ext EM2 */ + else pa = va + em3_dyn; } /* next 4K: ext EM3 */ +else if (usr_mode || (va & VA_USR)) { /* user mapping? */ + pgn = VA_GETPN (va); /* get page no */ + map = usr_map[pgn]; /* get map entry */ + if (map == MAP_PROT) return MM_NOACC; /* prot? no access */ + pa = (map & ~MAP_PROT) | (va & VA_POFF); } /* map address */ +else { pgn = VA_GETPN (va); /* mon, get page no */ + map = mon_map[pgn]; /* get map entry */ + if (map & MAP_PROT) return MM_NOACC; /* prot? no access */ + pa = map | (va & VA_POFF); } /* map address */ +*dat = M[pa]; /* return word */ +return SCPE_OK; +} + +/* Write word to virtual address */ + +t_stat Write (uint32 va, uint32 dat) +{ +uint32 pgn, map, pa; + +if (nml_mode) { /* normal? */ + va = va & VA_MASK; /* ignore user */ + if (va < 020000) pa = va; /* first 8K: 1 for 1 */ + else if (va < 030000) pa = va + em2_dyn; /* next 4K: ext EM2 */ + else pa = va + em3_dyn; } /* next 4K: ext EM3 */ +else if (usr_mode || (va & VA_USR)) { /* user mapping? */ + pgn = VA_GETPN (va); /* get page no */ + map = usr_map[pgn]; /* get map entry */ + if (map & MAP_PROT) { /* protected page? */ + if (map == MAP_PROT) return MM_NOACC; /* zero? no access */ + else return MM_WRITE; } /* else, write prot */ + pa = map | (va & VA_POFF); } /* map address */ +else { pgn = VA_GETPN (va); /* mon, get page no */ + map = mon_map[pgn]; /* get map entry */ + if (map & MAP_PROT) return MM_NOACC; /* prot? no access */ + pa = map | (va & VA_POFF); } /* map address */ +if (MEM_ADDR_OK (pa)) M[pa] = dat; +return SCPE_OK; +} + +/* Relocate addr for console access */ + +t_addr RelocC (int32 va, int32 sw) +{ +uint32 nml = nml_mode, usr = usr_mode; +uint32 pgn, map; +t_addr pa; + +if (sw & SWMASK ('N')) nml = 1; /* -n: normal */ +else if (sw & SWMASK ('X')) nml = usr = 0; /* -x: mon */ +else if (sw & SWMASK ('U')) nml = 0, usr = 1; /* -u: user */ +else if (!(sw & SWMASK ('V'))) return va; /* -v: curr */ +set_dyn_map (); +if (nml) { /* normal? */ + if (va < 020000) pa = va; /* first 8K: 1 for 1 */ + else if (va < 030000) pa = va + em2_dyn; /* next 4K: ext EM2 */ + else pa = va + em3_dyn; } /* next 4K: ext EM3 */ +else { pgn = VA_GETPN (va); /* get page no */ + map = usr? usr_map[pgn]: mon_map[pgn]; /* get map entry */ + if (map == MAP_PROT) return MAXMEMSIZE + 1; /* no access page? */ + pa = (map & ~MAP_PROT) | (va & VA_POFF); } /* map address */ +return pa; +} + +/* Arithmetic routines */ + +uint32 Add24 (uint32 s1, uint32 s2, uint32 cin) +{ +uint32 t = s1 + s2 + cin; /* add with carry in */ +if (t > DMASK) X = X | SIGN; /* carry to X<0> */ +else X = X & ~SIGN; +if (((s1 ^ ~s2) & (s1 ^ t)) & SIGN) OV = 1; /* overflow */ +return t & DMASK; +} + +uint32 AddM24 (uint32 s1, uint32 s2) +{ +uint32 t = s1 + s2; /* add */ +if (((s1 ^ ~s2) & (s1 ^ t)) & SIGN) OV = 1; /* overflow */ +return t & DMASK; +} + +void Mul48 (uint32 s1, uint32 s2) +{ +uint32 a = ABS (s1); +uint32 b = ABS (s2); +uint32 hi, md, lo, t, u; + +if ((a == 0) || (b == 0)) { /* ops zero? */ + A = B = 0; + return; } +t = a >> 12; /* split op1 */ +a = a & 07777; +u = b >> 12; /* split op2 */ +b = b & 07777; +md = (a * u) + (b * t); /* cross product */ +lo = (a * b) + ((md & 07777) << 12); /* low result */ +hi = (t * u) + (md >> 12) + (lo >> 24); /* hi result */ +A = ((hi << 1) & DMASK) | ((lo & DMASK) >> 23); +B = (lo << 1) & DMASK; +if ((s1 ^ s2) & SIGN) { + B = ((B ^ DMASK) + 1) & DMASK; + A = ((A ^ DMASK) + (B == 0)) & DMASK; } +else if (A & SIGN) OV = 1; +return; +} + +/* Divide - the SDS 940 uses a non-restoring divide. The algorithm + runs even for overflow cases. Hence it must be emulated precisely + to give the right answers for diagnostics. If the dividend is + negative, AB are 2's complemented starting at B<22>, and B<23> + is unchanged. */ + +void Div48 (uint32 ar, uint32 br, uint32 m) +{ +int32 i; +uint32 quo = 0; /* quotient */ +uint32 dvdh = ar, dvdl = br; /* dividend */ +uint32 dvr = ABS (m); /* make dvr pos */ + +if (TSTS (dvdh)) { /* dvd < 0? */ + dvdl = (((dvdl ^ DMASK) + 2) & (DMASK & ~1)) | /* 23b negate */ + (dvdl & 1); /* low bit unch */ + dvdh = ((dvdh ^ DMASK) + (dvdl <= 1)) & DMASK; } +if ((dvdh > dvr) || /* divide fail? */ + ((dvdh == dvr) && dvdl) || + ((dvdh == dvr) && !TSTS (ar ^ m))) OV = 1; +dvdh = (dvdh - dvr) & DMASK; /* initial sub */ +for (i = 0; i < 23; i++) { /* 23 iterations */ + quo = (quo << 1) | ((dvdh >> 23) ^ 1); /* quo bit = ~sign */ + dvdh = ((dvdh << 1) | (dvdl >> 23)) & DMASK; /* shift divd */ + dvdl = (dvdl << 1) & DMASK; + if (quo & 1) /* test ~sign */ + dvdh = (dvdh - dvr) & DMASK; /* sign was +, sub */ + else dvdh = (dvdh + dvr) & DMASK; } /* sign was -, add */ +quo = quo << 1; /* shift quo */ +if (dvdh & SIGN) dvdh = (dvdh + dvr) & DMASK; /* last op -? restore */ +else quo = quo | 1; /* +, set quo bit */ +if (TSTS (ar ^ m)) A = NEG (quo); /* sign of quo */ +else A = quo; /* A = quo */ +if (TSTS (ar)) B = NEG (dvdh); /* sign of rem */ +else B = dvdh; /* B = rem */ +return; +} + +void RotR48 (uint32 sc) +{ +uint32 t = A; + +if (sc >= 24) { + sc = sc - 24; + A = ((B >> sc) | (A << (24 - sc))) & DMASK; + B = ((t >> sc) | (B << (24 - sc))) & DMASK; } +else { A = ((A >> sc) | (B << (24 - sc))) & DMASK; + B = ((B >> sc) | (t << (24 - sc))) & DMASK; } +return; +} + +void ShfR48 (uint32 sc, uint32 sgn) +{ +if (sc >= 48) A = B = sgn; +if (sc >= 24) { + sc = sc - 24; + B = ((A >> sc) | (sgn << (24 - sc))) & DMASK; + A = sgn; } +else { B = ((B >> sc) | (A << (24 - sc)) & DMASK); + A = ((A >> sc) | (sgn << (24 - sc))) & DMASK; } +return; +} + +/* POT routines for RL1, RL2, RL4 */ + +t_stat pot_RL1 (uint32 num, uint32 *dat) +{ +RL1 = *dat; +set_dyn_map (); +return SCPE_OK; +} + +t_stat pot_RL2 (uint32 num, uint32 *dat) +{ +RL2 = *dat; +set_dyn_map (); +return SCPE_OK; +} + +t_stat pot_RL4 (uint32 num, uint32 *dat) +{ +RL4 = (*dat) & 03737; +set_dyn_map (); +return SCPE_OK; +} + +/* Map EM2, EM3, RL1, RL2, RL4 to dynamic forms + + EM2, EM3 - left shifted 12, base virtual address subtracted + RL1, RL2 - page left shifted 11 + RL3 - filled in as 1 to 1 map + RL4 - EM2 or page left shifted 11, PROT bit inserted +*/ + +void set_dyn_map (void) +{ +em2_dyn = ((EM2 & 07) << 12) - 020000; +em3_dyn = ((EM3 & 07) << 12) - 030000; +usr_map[0] = (RL1 >> 7) & (MAP_PROT | MAP_PAGE); +usr_map[1] = (RL1 >> 1) & (MAP_PROT | MAP_PAGE); +usr_map[2] = (RL1 << 5) & (MAP_PROT | MAP_PAGE); +usr_map[3] = (RL1 << 11) & (MAP_PROT | MAP_PAGE); +usr_map[4] = (RL2 >> 7) & (MAP_PROT | MAP_PAGE); +usr_map[5] = (RL2 >> 1) & (MAP_PROT | MAP_PAGE); +usr_map[6] = (RL2 << 5) & (MAP_PROT | MAP_PAGE); +usr_map[7] = (RL2 << 11) & (MAP_PROT | MAP_PAGE); +mon_map[0] = (0 << VA_V_PN); +mon_map[1] = (1 << VA_V_PN); +mon_map[2] = (2 << VA_V_PN); +mon_map[3] = (3 << VA_V_PN); +mon_map[4] = ((EM2 & 07) << 12); +mon_map[5] = ((EM2 & 07) << 12) + (1 << VA_V_PN); +mon_map[6] = (RL4 << 5) & MAP_PAGE; +mon_map[7] = (RL4 << 11) & MAP_PAGE; +if (mon_map[6] == 0) mon_map[6] = MAP_PROT; +if (mon_map[7] == 0) mon_map[7] = MAP_PROT; +return; +} + +/* Recalculate api requests */ + +uint32 api_findreq (void) +{ +uint32 i, t; + +t = (int_req & ~1) & api_mask[api_lvlhi]; /* unmasked int */ +for (i = 31; t && (i > 0); i--) { /* find highest */ + if ((t >> i) & 1) return i; } +return 0; /* none */ +} + +/* Dismiss highest priority interrupt */ + +void api_dismiss (void) +{ +uint32 i, t; + +t = 1u << api_lvlhi; /* highest active */ +int_req = int_req & ~t; /* clear int req */ +api_lvl = api_lvl & ~t; /* clear api level */ +api_lvlhi = 0; /* assume all clear */ +for (i = 31; api_lvl && (i > 0); i--) { /* find highest api */ + if ((api_lvl >> i) & 1) { /* bit set? */ + api_lvlhi = i; /* record level */ + break; } } /* done */ +int_reqhi = api_findreq (); /* recalc intreq */ +return; +} + +/* Reset routine */ + +t_stat cpu_reset (DEVICE *dptr) +{ +OV = 0; +EM2 = 2; +EM3 = 3; +RL1 = RL2 = RL4 = 0; +ion = ion_defer = 0; +nml_mode = 1; +usr_mode = 0; +mon_usr_trap = 0; +int_req = 0; +int_reqhi = 0; +api_lvl = 0; +api_lvlhi = 0; +alert = 0; +pcq_r = find_reg ("PCQ", NULL, dptr); +if (pcq_r) pcq_r->qptr = 0; +else return SCPE_IERR; +sim_brk_types = sim_brk_dflt = SWMASK ('E'); +return SCPE_OK; +} + +/* Memory examine */ + +t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) +{ +t_addr pa; + +pa = RelocC (addr, sw); +if (pa > MAXMEMSIZE) return SCPE_REL; +if (pa >= MEMSIZE) return SCPE_NXM; +if (vptr != NULL) *vptr = M[pa] & DMASK; +return SCPE_OK; +} + +/* Memory deposit */ + +t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) +{ +t_addr pa; + +pa = RelocC (addr, sw); +if (pa > MAXMEMSIZE) return SCPE_REL; +if (pa >= MEMSIZE) return SCPE_NXM; +M[pa] = val & DMASK; +return SCPE_OK; +} + +/* Set memory size */ + +t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 mc = 0; +t_addr i; + +if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 037777) != 0)) + return SCPE_ARG; +for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; +if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) + return SCPE_OK; +MEMSIZE = val; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; +return SCPE_OK; +} + +/* Set system type (1 = Genie, 0 = standard) */ + +t_stat cpu_set_type (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +extern t_stat drm_reset (DEVICE *dptr); +extern DEVICE drm_dev, mux_dev, muxl_dev; +extern UNIT drm_unit, mux_unit; +extern DIB mux_dib; + +if ((cpu_unit.flags & UNIT_GENIE) == val) return SCPE_OK; +if ((drm_unit.flags & UNIT_ATT) || /* attached? */ + (mux_unit.flags & UNIT_ATT)) return SCPE_NOFNC; /* can't do it */ +if (val) { /* Genie? */ + drm_dev.flags = drm_dev.flags & ~DEV_DIS; /* enb drum */ + mux_dev.flags = mux_dev.flags & ~DEV_DIS; /* enb mux */ + muxl_dev.flags = muxl_dev.flags & ~DEV_DIS; + mux_dib.dev = DEV3_GMUX; } /* Genie mux */ +else { drm_dev.flags = drm_dev.flags | DEV_DIS; /* dsb drum */ + mux_dib.dev = DEV3_SMUX; /* std mux */ + return drm_reset (&drm_dev); } +return SCPE_OK; +} + +/* The real time clock runs continuously; therefore, it only has + a unit service routine and a reset routine. The service routine + sets an interrupt that invokes the clock counter. The clock counter + is a "one instruction interrupt", and only MIN/SKR are valid. +*/ + +t_stat rtc_svc (UNIT *uptr) +{ +if (rtc_pie) int_req = int_req | INT_RTCP; /* set pulse intr */ +sim_activate (&rtc_unit, sim_rtcn_calb (rtc_tps, TMR_RTC)); /* reactivate unit */ +return SCPE_OK; +} + +t_stat rtc_inst (uint32 inst) +{ +uint32 op, dat, val, va; +t_stat r; + +op = I_GETOP (inst); /* get opcode */ +if (op == MIN) val = 1; /* incr */ +else if (op == SKR) val = DMASK; /* decr */ +else return STOP_RTCINS; /* can't do it */ +if (r = Ea (inst, &va)) return r; /* decode eff addr */ +if (r = Read (va, &dat)) return r; /* get operand */ +dat = AddM24 (dat, val); /* mem +/- 1 */ +if (r = Write (va, dat)) return r; /* rewrite */ +if (dat == 0) int_req = int_req | INT_RTCS; /* set clk sync int */ +return SCPE_OK; +} + +t_stat rtc_reset (DEVICE *dptr) +{ +rtc_pie = 0; /* disable pulse */ +sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */ +return SCPE_OK; +} diff --git a/SDS/sds_defs.h b/SDS/sds_defs.h new file mode 100644 index 00000000..6b974d86 --- /dev/null +++ b/SDS/sds_defs.h @@ -0,0 +1,401 @@ +/* sds_defs.h: SDS 940 simulator definitions + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. +*/ + +#include "sim_defs.h" /* simulator defns */ + +/* Simulator stop codes */ + +#define STOP_IONRDY 1 /* I/O dev not ready */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_INVDEV 4 /* invalid dev */ +#define STOP_INVINS 5 /* invalid instr */ +#define STOP_INVIOP 6 /* invalid I/O op */ +#define STOP_INDLIM 7 /* indirect limit */ +#define STOP_EXULIM 8 /* EXU limit */ +#define STOP_MMINT 9 /* mm in intr */ +#define STOP_MMTRP 10 /* mm in trap */ +#define STOP_TRPINS 11 /* trap inst not BRM */ +#define STOP_RTCINS 12 /* rtc inst not MIN/SKR */ +#define STOP_ILLVEC 13 /* zero vector */ +#define STOP_CCT 14 /* runaway CCT */ + +/* Trap codes */ + +#define MM_PRVINS -040 /* privileged */ +#define MM_NOACC -041 /* no access */ +#define MM_WRITE -043 /* write protect */ +#define MM_MONUSR -044 /* mon to user */ + +/* Conditional error returns */ + +#define CRETINS return ((stop_invins)? STOP_INVINS: SCPE_OK) +#define CRETDEV return ((stop_invdev)? STOP_INVDEV: SCPE_OK) +#define CRETIOP return ((stop_inviop)? STOP_INVIOP: SCPE_OK) +#define CRETIOE(f,c) return ((f)? c: SCPE_OK) + +/* Architectural constants */ + +#define SIGN 040000000 /* sign */ +#define DMASK 077777777 /* data mask */ +#define EXPS 0400 /* exp sign */ +#define EXPMASK 0777 /* exp mask */ +#define SXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): \ + ((x) & DMASK))) +#define SXT_EXP(x) ((int32) (((x) & EXPS)? ((x) | ~EXPMASK): \ + ((x) & EXPMASK))) + +/* Memory */ + +#define MAXMEMSIZE (1 << 16) /* max memory size */ +#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */ +#define MEMSIZE (cpu_unit.capac) /* actual memory size */ +#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE) +#define ReadP(x) M[x] +#define WriteP(x,y) if (MEM_ADDR_OK (x)) M[x] = y + +/* Virtual addressing */ + +#define VA_SIZE (1 << 14) /* virtual addr size */ +#define VA_MASK (VA_SIZE - 1) /* virtual addr mask */ +#define VA_V_PN 11 /* page number */ +#define VA_M_PN 07 +#define VA_GETPN(x) (((x) >> VA_V_PN) & VA_M_PN) +#define VA_POFF ((1 << VA_V_PN) - 1) /* offset */ +#define VA_USR (I_USR) /* user flag in addr */ +#define XVA_MASK (VA_USR | VA_MASK) + +/* Arithmetic */ + +#define TSTS(x) ((x) & SIGN) +#define NEG(x) (-((int32) (x)) & DMASK) +#define ABS(x) (TSTS (x)? NEG(x): (x)) + +/* Memory map */ + +#define MAP_PROT (040 << VA_V_PN) /* protected */ +#define MAP_PAGE (037 << VA_V_PN) /* phys page number */ + +/* Instruction format */ + +#define I_USR (1 << 23) /* user */ +#define I_IDX (1 << 22) /* indexed */ +#define I_POP (1 << 21) /* programmed op */ +#define I_V_TAG 21 /* tag */ +#define I_V_OP 15 /* opcode */ +#define I_M_OP 077 +#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP) +#define I_IND (1 << 14) /* indirect */ +#define I_V_SHFOP 11 /* shift op */ +#define I_M_SHFOP 07 +#define I_GETSHFOP(x) (((x) >> I_V_SHFOP) & I_M_SHFOP) +#define I_SHFMSK 0777 /* shift count */ +#define I_V_IOMD 12 /* IO inst mode */ +#define I_M_IOMD 03 +#define I_GETIOMD(x) (((x) >> I_V_IOMD) & I_M_IOMD) +#define I_V_SKCND 7 /* SKS skip cond */ +#define I_M_SKCND 037 +#define I_GETSKCND(x) (((x) >> I_V_SKCND) & I_M_SKCND) +#define I_EOB2 000400000 /* chan# bit 2 */ +#define I_SKB2 000040000 /* skschan# bit 2 */ +#define I_EOB1 020000000 /* chan# bit 1 */ +#define I_EOB0 000000100 /* chan# bit 0 */ +#define I_GETEOCH(x) ((((x) & I_EOB2)? 4: 0) | \ + (((x) & I_EOB1)? 2: 0) | \ + (((x) & I_EOB0)? 1: 0)) +#define I_SETEOCH(x) ((((x) & 4)? I_EOB2: 0) | \ + (((x) & 2)? I_EOB1: 0) | \ + (((x) & 1)? I_EOB0: 0)) +#define I_GETSKCH(x) ((((x) & I_SKB2)? 4: 0) | \ + (((x) & I_EOB1)? 2: 0) | \ + (((x) & I_EOB0)? 1: 0)) +#define I_SETSKCH(x) ((((x) & 4)? I_SKB2: 0) | \ + (((x) & 2)? I_EOB1: 0) | \ + (((x) & 1)? I_EOB0: 0)) + +/* Globally visible flags */ + +#define UNIT_V_GENIE (UNIT_V_UF + 0) +#define UNIT_GENIE (1 << UNIT_V_GENIE) + +/* Timers */ + +#define TMR_RTC 0 /* clock */ +#define TMR_MUX 1 /* mux */ + +/* I/O routine functions */ + +#define IO_CONN 0 /* connect */ +#define IO_EOM1 1 /* EOM mode 1 */ +#define IO_DISC 2 /* disconnect */ +#define IO_READ 3 /* read */ +#define IO_WRITE 4 /* write */ +#define IO_WREOR 5 /* write eor */ +#define IO_SKS 6 /* skip signal */ + +/* Dispatch template */ + +struct sdsdspt { + uint32 num; /* # entries */ + uint32 off; /* offset from base */ + }; + +typedef struct sdsdspt DSPT; + +/* Device information block */ + +struct sdsdib { + int32 chan; /* channel */ + int32 dev; /* base dev no */ + int32 xfr; /* xfer flag */ + DSPT *tplt; /* dispatch templates */ + t_stat (*iop) (uint32 fnc, uint32 dev, uint32 *dat); + }; + +typedef struct sdsdib DIB; + +/* Channels */ + +#define NUM_CHAN 8 /* max num chan */ +#define CHAN_W 0 /* TMCC */ +#define CHAN_Y 1 +#define CHAN_C 2 +#define CHAN_D 3 +#define CHAN_E 4 /* DACC */ +#define CHAN_F 5 +#define CHAN_G 6 +#define CHAN_H 7 + +/* I/O control EOM */ + +#define CHC_REV 04000 /* reverse */ +#define CHC_NLDR 02000 /* no leader */ +#define CHC_BIN 01000 /* binary */ +#define CHC_V_CPW 7 /* char/word */ +#define CHC_M_CPW 03 +#define CHC_GETCPW(x) (((x) >> CHC_V_CPW) & CHC_M_CPW) + +/* Buffer control (extended) EOM */ + +#define CHM_CE 04000 /* compat/ext */ +#define CHM_ER 02000 /* end rec int */ +#define CHM_ZC 01000 /* zero wc int */ +#define CHM_V_FNC 7 /* term func */ +#define CHM_M_FNC 03 +#define CHM_GETFNC(x) (((x) & CHM_CE)? (((x) >> CHM_V_FNC) & CHM_M_FNC): CHM_COMP) +#define CHM_IORD 0 /* record, disc */ +#define CHM_IOSD 1 /* signal, disc */ +#define CHM_IORP 2 /* record, proc */ +#define CHM_IOSP 3 /* signal, proc */ +#define CHM_COMP 5 /* compatible */ +#define CHM_SGNL 1 /* signal bit */ +#define CHM_PROC 2 /* proceed bit */ +#define CHM_V_HMA 5 /* hi mem addr */ +#define CHM_M_HMA 03 +#define CHM_GETHMA(x) (((x) >> CHM_V_HMA) & CHM_M_HMA) +#define CHM_V_HWC 0 /* hi word count */ +#define CHM_M_HWC 037 +#define CHM_GETHWC(x) (((x) >> CHM_V_HWC) & CHM_M_HWC) + +/* Channel flags word */ + +#define CHF_ERR 00001 /* error */ +#define CHF_IREC 00002 /* interrecord */ +#define CHF_ILCE 00004 /* interlace */ +#define CHF_DCHN 00010 /* data chain */ +#define CHF_EOR 00020 /* end of record */ +#define CHF_12B 00040 /* 12 bit mode */ +#define CHF_24B 00100 /* 24 bit mode */ +#define CHF_OWAK 00200 /* output wake */ +#define CHF_SCAN 00400 /* scan */ +#define CHF_TOP 01000 /* TOP pending */ +#define CHF_N_FLG 9 /* <= 16 */ + +/* Interrupts and vectors (0 is reserved), highest bit is highest priority */ + +#define INT_V_PWRO 31 /* power on */ +#define INT_V_PWRF 30 /* power off */ +#define INT_V_CPAR 29 /* CPU parity err */ +#define INT_V_IPAR 28 /* IO parity err */ +#define INT_V_RTCS 27 /* clock sync */ +#define INT_V_RTCP 26 /* clock pulse */ +#define INT_V_YZWC 25 /* chan Y zero wc */ +#define INT_V_WZWC 24 /* chan W zero wc */ +#define INT_V_YEOR 23 /* chan Y end rec */ +#define INT_V_WEOR 22 /* chan W end rec */ +#define INT_V_CZWC 21 /* chan C */ +#define INT_V_CEOR 20 +#define INT_V_DZWC 19 /* chan D */ +#define INT_V_DEOR 18 +#define INT_V_EZWC 17 /* chan E */ +#define INT_V_EEOR 16 +#define INT_V_FZWC 15 /* chan F */ +#define INT_V_FEOR 14 +#define INT_V_GZWC 13 /* chan G */ +#define INT_V_GEOR 12 +#define INT_V_HZWC 11 /* chan H */ +#define INT_V_HEOR 10 +#define INT_V_MUXR 9 /* mux receive */ +#define INT_V_MUXT 8 /* mux transmit */ +#define INT_V_MUXCO 7 /* SDS carrier on */ +#define INT_V_MUXCF 6 /* SDS carrier off */ +#define INT_V_DRM 5 /* Genie drum */ +#define INT_V_FORK 4 /* fork */ + +#define INT_PWRO (1 << INT_V_PWRO) +#define INT_PWRF (1 << INT_V_PWRF) +#define INT_CPAR (1 << INT_V_CPAR) +#define INT_IPAR (1 << INT_V_IPAR) +#define INT_RTCS (1 << INT_V_RTCS) +#define INT_RTCP (1 << INT_V_RTCP) +#define INT_YZWC (1 << INT_V_YZWC) +#define INT_WZWC (1 << INT_V_WZWC) +#define INT_YEOR (1 << INT_V_YEOR) +#define INT_WEOR (1 << INT_V_WEOR) +#define INT_CZWC (1 << INT_V_CZWC) +#define INT_CEOR (1 << INT_V_CEOR) +#define INT_DZWC (1 << INT_V_DZWC) +#define INT_DEOR (1 << INT_V_DEOR) +#define INT_EZWC (1 << INT_V_EZWC) +#define INT_EEOR (1 << INT_V_EEOR) +#define INT_FZWC (1 << INT_V_FZWC) +#define INT_FEOR (1 << INT_V_FEOR) +#define INT_GZWC (1 << INT_V_GZWC) +#define INT_GEOR (1 << INT_V_GEOR) +#define INT_HZWC (1 << INT_V_HZWC) +#define INT_HEOR (1 << INT_V_HEOR) +#define INT_MUXR (1 << INT_V_MUXR) +#define INT_MUXT (1 << INT_V_MUXT) +#define INT_MUXCO (1 << INT_V_MUXCO) +#define INT_MUXCF (1 << INT_V_MUXCF) +#define INT_DRM (1 << INT_V_DRM) +#define INT_FORK (1 << INT_V_FORK) + +#define VEC_PWRO 0036 +#define VEC_PWRF 0037 +#define VEC_CPAR 0056 +#define VEC_IPAR 0057 +#define VEC_RTCS 0074 +#define VEC_RTCP 0075 +#define VEC_YZWC 0030 +#define VEC_WZWC 0031 +#define VEC_YEOR 0032 +#define VEC_WEOR 0033 +#define VEC_CZWC 0060 +#define VEC_CEOR 0061 +#define VEC_DZWC 0062 +#define VEC_DEOR 0063 +#define VEC_EZWC 0064 +#define VEC_EEOR 0065 +#define VEC_FZWC 0066 +#define VEC_FEOR 0067 +#define VEC_GZWC 0070 +#define VEC_GEOR 0071 +#define VEC_HZWC 0072 +#define VEC_HEOR 0073 +#define VEC_MUXR 0200 /* term mux rcv */ +#define VEC_MUXT 0201 /* term mux xmt */ +#define VEC_MUXCO 0202 /* SDS: mux carrier on */ +#define VEC_MUXCF 0203 /* SDS: mux carrier off */ +#define VEC_DRM 0202 /* Genie: drum */ +#define VEC_FORK 0216 /* "fork" */ + +/* Device constants */ + +#define DEV_MASK 077 /* device mask */ +#define DEV_TTI 001 /* teletype */ +#define DEV_PTR 004 /* paper tape rdr */ +#define DEV_MT 010 /* magtape */ +#define DEV_RAD 026 /* fixed head disk */ +#define DEV_DSK 026 /* moving head disk */ +#define DEV_TTO 041 /* teletype */ +#define DEV_PTP 044 /* paper tape punch */ +#define DEV_LPT 060 /* line printer */ +#define DEV_MTS 020 /* MT scan/erase */ +#define DEV_OUT 040 /* output flag */ +#define DEV3_GDRM 004 /* Genie drum */ +#define DEV3_GMUX 001 /* Genie mux */ +#define DEV3_SMUX (DEV_MASK) /* standard mux */ + +#define LPT_WIDTH 132 /* line print width */ +#define CCT_LNT 132 /* car ctrl length */ + +/* Transfer request flags for devices (0 is reserved) */ + +#define XFR_V_TTI 1 /* console */ +#define XFR_V_TTO 2 +#define XFR_V_PTR 3 /* paper tape */ +#define XFR_V_PTP 4 +#define XFR_V_LPT 5 /* line printer */ +#define XFR_V_RAD 6 /* fixed hd disk */ +#define XFR_V_DSK 7 /* mving hd disk */ +#define XFR_V_MT0 8 /* magtape */ + +#define XFR_TTI (1 << XFR_V_TTI) +#define XFR_TTO (1 << XFR_V_TTO) +#define XFR_PTR (1 << XFR_V_PTR) +#define XFR_PTP (1 << XFR_V_PTP) +#define XFR_LPT (1 << XFR_V_LPT) +#define XFR_RAD (1 << XFR_V_RAD) +#define XFR_DSK (1 << XFR_V_DSK) +#define XFR_MT0 (1 << XFR_V_MT0) + +/* PIN/POT ordinals (0 is reserved) */ + +#define POT_ILCY 1 /* interlace */ +#define POT_DCRY (POT_ILCY + NUM_CHAN) /* data chain */ +#define POT_ADRY (POT_DCRY + NUM_CHAN) /* address reg */ +#define POT_RL1 (POT_ADRY + NUM_CHAN) /* RL1 */ +#define POT_RL2 (POT_RL1 + 1) /* RL2 */ +#define POT_RL4 (POT_RL2 + 1) /* RL4 */ +#define POT_RADS (POT_RL4 + 1) /* fhd sector */ +#define POT_RADA (POT_RADS + 1) /* fhd addr */ +#define POT_DSK (POT_RADA + 1) /* mhd sec/addr */ +#define POT_SYSI (POT_DSK + 1) /* sys intr */ +#define POT_MUX (POT_SYSI + 1) /* multiplexor */ + +/* Opcodes */ + +enum opcodes { + HLT, BRU, EOM, EOD = 006, + MIY = 010, BRI, MIW, POT, ETR, MRG = 016, EOR, + NOP, OVF = 022, EXU, + YIM = 030, WIM = 032, PIN, STA = 035, STB, STX, + SKS, BRX, BRM = 043, RCH = 046, + SKE = 050, BRR, SKB, SKN, SUB, ADD, SUC, ADC, + SKR, MIN, XMA, ADM, MUL, DIV, RSH, LSH, + SKM, LDX, SKA, SKG, SKD, LDB, LDA, EAX }; + +/* Channel function prototypes */ + +void chan_set_flag (int32 ch, uint32 fl); +void chan_set_ordy (int32 ch); +void chan_disc (int32 ch); +void chan_set_uar (int32 ch, uint32 dev); +t_stat set_chan (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat show_chan (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat chan_process (void); +t_bool chan_testact (void); diff --git a/SDS/sds_diag.txt b/SDS/sds_diag.txt new file mode 100644 index 00000000..039e81e7 --- /dev/null +++ b/SDS/sds_diag.txt @@ -0,0 +1,114 @@ +SDS Diagnostics, using the SDS 930/940 Master Diagnostic Tape image (D930X4A.TAP) + +Summary + +930 0-16K Memory Test passed +930 16K-32K Memory Test passed +930 Instruction Test passed +930 P&S Register Test passed + +--- +930 0-16K Memory Test + +sim> att mt diag.tap +sim> d a 1 +sim> d bpt4 1 ; stop every 1/2 cycle +sim> boot mt + +HALT instruction, P: 00050 (STA 122,4) +sim> ex a +A: 00000000 ; error count +sim> c + +HALT instruction, P: 37650 (STA 37722,4) + +sim> ex a +A: 00000000 ; error count + +--- +930 16K-32K Memory Test + +sim> att mt diag.tap +sim> d a 2 +sim> d bpt4 2 ; stop every 1/2 cycle +sim> boot mt + + +HALT instruction, P: 00050 (STA 6) +sim> ex a +A: 00000000 ; error count +sim> c + +HALT instruction, P: 37650 (STA 37406) +sim> ex a +A: 00000000 ; error count +sim> c + +--- +930 Instruction Diagnostic + +sim> att mt diag.tap +sim> d a 3 +sim> br 17 ; catch start of diagnostic +sim> boot mt + +Breakpoint, P: 00017 (BRR 12,2) +sim> nobr 17 +sim> br 112 ; catch end of diagnostic +sim> c + +Breakpoint, P: 00112 (BRU 3) + +--- + +930 P&S Register Test + +sim> att mt diag.tap +sim> d a 4 +sim> br 60 ; catch end of pass +sim> boot mt + +Breakpoint, P: 00060 (BRU 22) + +--- +Bugs + +1. IO: Channel WAR not cleared after memory store +2. IO: dev_map should contain _flags, not _v_flags +3. SYS: Errors in system tables +4. SYS: Character conversion table had 0 (space) as illegal, should be -1 +5. IO: Channel CPW calculation wrong for 12b mode +6. RAD, DSK, MT: Instruction masks wrong for RAD, DSK, MT +7. IO: Missing subscripts in dev_disp references +8. RAD: typos referencing DSK +9. IO: SKS 3 call incorrect +10. DRM: Drum track mask width incorrect +11. CPU: Memory management trap left reason in bogus state, stopped simulator +12. CPU: Interrupts require api_lvl as well as api_lvlhi, like PDP-10, PDP-15 +13. CPU: Bug in find interrupt request +14. CPU: Interrupt priority scheme recoded for left to right priority +15. CPU: overflow test coded backwards +16. CPU: Rotates operate mod 48, not with upper limit of 48 (manual incorrect) +17. CPU: RSH not handling >= 48 correctly +18. CPU: CNA is 2's complement not 1's complement +19. CPU: MUL failed to mask cross product correctly +20. CPU: EM2, EM3 test using wrong 'channel' +21. CPU: EM3 test tested EM2 instead +22. CPU: POP must save EM2, EM3 like BRM (manual incorrect) +23. CPU: Shifts need special EA calculation, direct cycles using 9b indexing +24. CPU: Shifts ignore addr<13:14> +25. CPU: Diagnostic uses undefined shift 'normalize cyclic' +26. CPU: Divide 2'c complement of AB leaves B<23> unchanged +27. CPU: Divide overflow test requires special cases for divd.h == divr +28. CPU: Divide uses non-restoring algorithm +29. CPU: Channel terminate output must be deferred until channel buffer clears +30. CPU: Channel terminate output to magtape is convert to scan, must be + handled in channel logic +31. SYS: duplicate entries for shifts +32. SYS: mask for shifts did not include indirect flag +33. MUX: Genie/SDS use inverted meanings for line enable flag +34. MT: missing fseek before write eof +35. MT: displayed characters only 7b wide instead of 8b +36. CPU: EOD 20000 used by diagnostic (EM change is NOP) +37. CPU: SKD sets all 24b of X, not just exponent +38. CPU: reset should not clear A, B, X diff --git a/SDS/sds_doc.txt b/SDS/sds_doc.txt new file mode 100644 index 00000000..e1b448e3 --- /dev/null +++ b/SDS/sds_doc.txt @@ -0,0 +1,527 @@ +To: Users +From: Bob Supnik +Subj: SDS 940 Simulator Usage +Date: 15-Nov-2002 + + COPYRIGHT NOTICE + +The following copyright notice applies to both the SIMH source and binary: + + Original code published in 1993-2002, written by Robert M Supnik + Copyright (c) 1993-2002, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + +This memorandum documents the SDS 940 simulator. + + +1. Simulator Files + +sim/ sim_defs.h + sim_rev.h + sim_sock.h + sim_tmxr.h + scp.c + scp_tty.c + sim_sock.c + sim_tmxr.c + +sim/sds/ sds_defs.h + sds_cpu.c + sds_drm.c + sds_dsk.c + sds_io.c + sds_lp.c + sds_mt.c + sds_mux.c + sds_rad.c + sds_stddev.c + sds_sys.c + +2. SDS 940 Features + +The SDS-940 simulator is configured as follows: + +device simulates +name(s) + +CPU SDS-940 CPU with 16KW to 64KW of memory +CHAN I/O channels +PTR paper tape reader +PTP paper tape punch +TTI console input +TTO console output +LPT line printer +RTC real-time clock +MUX terminal multiplexor +DRM Project Genie drum +RAD fixed head disk +DSK 9164/9165 rapid access (moving head) disk +MT magnetic tape + +Most devices can be disabled or enabled with the SET DISABLED and +SET ENABLED commands, respectively. + +2.1 CPU + +The CPU options set the size of main memory and the configuration of +peripherals. + + SET CPU 16K set memory size = 16KW + SET CPU 32K set memory size = 32KW + SET CPU 48K set memory size = 48KW + SET CPU 64K set memory size = 64KW + SET CPU GENIE enable DRM, set terminal mux + to GENIE mode + SET CPU SDS disable DRM, set terminal mux + to SDS mode + +If memory size is being reduced, and the memory being truncated contains +non-zero data, the simulator asks for confirmation. Data in the truncated +portion of memory is lost. Initial memory size is 64KW. + +CPU registers include the visible state of the processor as well as the +control registers for the interrupt system. + + name size comments + + P 14 program counter + A 24 accumulator A + B 24 accumulator B + X 24 index register + OV 1 overflow indicator + EM2 3 memory extension, quadrant 2 + EM3 3 memory extension, quadrant 3 + RL1 24 user relocation register 1 + RL2 24 user relocation register 2 + RL4 12 kernel relocation register + NML 1 normal mode flag + USR 1 user mode flag + MONUSR 1 monitor-to-user trap enable + ION 1 interrupt enable + INTDEF 1 interrupt defer + INTREQ 32 interrupt request flags + APIACT 5 highest active API level + APIREQ 5 highest requesting API level + XFRREQ 32 device transfer request flags + BPT 4 breakpoint switches + ALERT 6 outstanding alert number + STOP_INVINS 1 stop on invalid instruction + STOP_INVDEV 1 stop on invalid device number + STOP_INVIOP 1 stop on invalid I/O operation + INDLIM 8 maximum indirect nesting depth + EXULIM 8 maximum execute nesting depth + PCQ[0:63] 14 P prior to last branch or interrupt; + most recent P change first + WRU 8 interrupt character + +2.2 Channels (CHAN) + +The SDS 940 has up to eight I/O channels, designated W, Y, C, D, E, F, G, +and H. W, Y, C, and D are time-multiplexed communications channels (TMCC); +E, F, G, and H are direct access communications channels (DACC). Unlike +real SDS 940 channels, the simulated channels handle 6b, 12b, and 24b transfers +simultaneously. The association between a device and a channel is displayed +by the SHOW CHAN command: + + SIM> SHOW LPT CHAN + channel=W + +The user can change the association with the SET CHAN= command, +where is a channel letter: + + SIM> SET LPT CHAN=E + SIM> SHOW LPT CHAN + channel=E + +Each channel has nine registers. The registers are arrays, with entry [0] +for channel W, entry [1] for channel Y, etc. + + name size comments + + UAR[0:7] 6 unit address register + WCR[0:7] 15 word count register + MAR[0:7] 16 memory address register + DCR[0:7] 6 data chaining register + WAR[0:7] 24 word assembly register + CPW[0:7] 2 characters per word + CNT[0:7] 3 character count + MODE[0:7] 12 channel mode (from EOM instruction) + FLAG[0:7] 9 channel flags + +The user can display all the registers in a channel with the command SHOW +CHAN . + +2.3 Console Input (TTI) + +The console input (TTI) polls the console keyboard for input. It +implements these registers: + + name size comments + + BUF 6 data buffer + XFR 1 transfer ready flag + POS 32 number of characters input + TIME 24 polling interval + +By default, the console input is assigned to channel W. + +2.4 Console Output (TTO) + +The console output (TTO) writes to the simulator console window. It +implements these registers: + + name size comments + + BUF 6 data buffer + XFR 1 transfer ready flag + POS 32 number of characters input + TIME 24 time from I/O initiation to interrupt + +By default, the console output is assigned to channel W. + +2.5 Paper Tape Reader (PTR) + +The paper tape reader (PTR) reads data from a disk file. The POS +register specifies the number of the next data item to be read. Thus, +by changing POS, the user can backspace or advance the reader. + +The paper tape reader implements these registers: + + name size comments + + BUF 6 data buffer + XFR 1 transfer ready flag + SOR 1 start of record flag + CHAN 4 active channel + POS 32 number of characters input + TIME 24 time from I/O initiation to interrupt + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 out of tape + + end of file 1 report error and stop + 0 out of tape + + OS I/O error x report error and stop + +By default, the paper tape reader is assigned to channel W. + +2.6 Paper Tape Punch (PTP) + +The paper tape punch (PTP) writes data to a disk file. The POS +register specifies the number of the next data item to be written. +Thus, by by changing POS, the user can backspace or advance the punch. + +The paper tape punch implements these registers: + + name size comments + + BUF 6 data buffer + XFR 1 transfer ready flag + LDR 1 punch leader flag + CHAN 4 active channel + POS 32 number of characters input + TIME 24 time from I/O initiation to interrupt + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 out of tape + + OS I/O error x report error and stop + +By default, the paper tape punch is assigned to channel W. + +2.7 Line Printer (LPT) + +The line printer (LPT) writes data to a disk file. The POS register +specifies the number of the next data item to be written. Thus, +by changing POS, the user can backspace or advance the printer. + +The line printer implements these registers: + + name size comments + + BUF[0:131] 8 data buffer + BPTR 8 buffer pointer + XFR 1 transfer ready flag + ERR 1 error flag + CHAN 4 active channel + CCT[0:131] 8 carriage control tape + CCTP 8 pointer into carriage control tape + CCTL 8 length of carriage control tape + SPCINST 24 spacing instruction + POS 32 number of characters input + CTIME 24 intercharacter time + PTIME 24 print time + STIME 24 space time + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 out of paper + + OS I/O error x report error and stop + +By default, the line printer is assigned to channel W. + +2.8 Real Time Clock (RTC) + +The real time clock (RTC) implements these registers: + + name size comments + + PIE 1 interrupt enable + TIME 24 tick interval + TPS 8 ticks per second + +The real-time clock autocalibrates; the clock interval is adjusted up or +down so that the clock tracks actual elapsed time. + +2.9 Terminal Multiplexor (MUX) + +The terminal multiplexor provides 32 asynchronous interfaces. In Genie +mode, the interfaces are hard-wired; in SDS mode, they implement modem +control. The multiplexor has two controllers: MUX for the scanner, and +MUXL for the individual lines. The terminal multiplexor performs input +and output through Telnet sessions connected to a user-specified port. +The ATTACH command specifies the port to be used: + + ATTACH MUX set up listening port + +where port is a decimal number between 1 and 65535 that is not being used +for other TCP/IP activities. + +Each line (each unit of MUXL) supports one option: UC, when set, causes +lower case input characters to be automatically converted to upper case. + +Once MUX is attached and the simulator is running, the multiplexor listens +for connections on the specified port. It assumes that the incoming +connections are Telnet connections. The connections remain open until +disconnected either by the Telnet client, a SET MUX DISCONNECT command, +or a DETACH MUX command. + +The SHOW MUX CONNECTIONS command displays the current connections to the +extra terminals. The SHOW MUX STATISTICS command displays statistics for +active connections. The SET MUX DISCONNECT=linenumber disconnects the +specified line. + +The controller (MUX) implements these registers: + + name size comments + + STA[0:31] 6 status, lines 0 to 31 + RBUF[0:31] 8 receive buffer, lines 0 to 31 + XBUF[0:31] 8 transmit buffer, lines 0 to 31 + FLAGS[0:127] 1 line flags, 0 to 3 for line 0, + 4 to 7 for line 1, etc + SCAN 7 scanner current flag number + SLCK 1 scanner locked flag + TPS 8 character polls per second + +The lines (MUXL) implements these registers: + + name size comments + + TIME[0:31] 24 transmit time, lines 0 to 31 + +The additional terminals do not support save and restore. All open +connections are lost when the simulator shuts down or MUX is detached. + +2.10 Project Genie Drum (DRM) + +The Project Genie drum (DRM) implements these registers: + + name size comments + + DA 19 drum address + CA 16 core address + WC 14 word count + PAR 12 cumulative sector parity + RW 1 read/write flag + ERR 1 error flag + STA 2 drum state + FTIME 24 channel program fetch time + XTIME 24 interword transfer time + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 drum not ready + +Drum data files are buffered in memory; therefore, end of file and OS +I/O errors cannot occur. Unlike conventional SDS 940 devices, the Project +Genie drum does not use a channel. + +2.11 Rapid Access (fixed head) Disk (RAD) + +The rapid access disk (RAD) implements these registers: + + name size comments + + DA 15 disk address + SA 6 sector word address + BP 1 sector byte pointer + XFR 1 data transfer flag + NOBD 1 inhibit increment across track + ERR 1 error flag + CHAN 4 active channel + PROT 8 write protect switches + TIME 24 interval between halfword transfers + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 disk not ready + + end of file x assume rest of disk is zero + + OS I/O error x report error and stop + +By default, the rapid access disk is assigned to channel E. + +2.12 Moving Head Disk (DSK) + +DSK options include the ability to make the drive write enabled or write +locked: + + SET RAD LOCKED set write locked + SET RAD WRITEENABLED set write enabled + +The moving head disk implements these registers: + + name size comments + + BUF[0:63] 8 transfer buffer + BPTR 9 buffer pointer + BLNT 9 buffer length + DA 21 disk address + INST 24 disk instruction + XFR 1 data transfer flag + ERR 1 error flag + CHAN 4 active channel + WTIME 24 interval between character transfers + STIME 24 seek interval + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 disk not ready + +Rapid access disk data files are buffered in memory; therefore, end of file +and OS I/O errors cannot occur. By default, the rapid access disk is +assigned to channel F. + +2.13 Magnetic Tape (MT) + +MT options include the ability to make units write enabled or write locked. + + SET MTn LOCKED set unit n write locked + SET MTn WRITEENABLED set unit n write enabled + +Units can also be set ONLINE or OFFLINE. + +The magnetic tape implements these registers: + + name size comments + + BUF[0:131071] 8 transfer buffer + BPTR 18 buffer pointer + BLNT 18 buffer length + XFR 1 data transfer flag + CHAN 4 active channel + INST 24 magtape instruction + EOF 1 end-of-file flag + GAP 1 inter-record gap flag + SKIP 1 skip data flag + CTIME 24 interval between character transfers + GTIME 24 gap interval + POS[0:7] 32 position, drives 0:7 + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error processed as + + not attached tape not ready; if STOP_IOE, stop + + end of file end of tape + + OS I/O error end of tape; if STOP_IOE, stop + +By default, the magnetic tape is assigned to channel W. + +2.13 Symbolic Display and Input + +The SDS 940 simulator implements symbolic display and input. Display is +controlled by command line switches: + + -a display as ASCII character + -c display as four character SDS string + -m display instruction mnemonics + +Input parsing is controlled by the first character typed in or by command +line switches: + + ' or -a ASCII character + " or -c four character SDS string + alphabetic instruction mnemonic + numeric octal number + +Instruction input uses (more or less) standard SDS 940 assembler syntax. +There are eight instruction classes: + +class operands examples comments + +no operand none EIR +POP (prog op) op,addr{,tag} POP 66,100 +I/O addr{,tag} EOM 1266 +mem reference addr{,tag} LDA 400,2 + STA* 300 indirect addr +reg change op op op... CLA CLB opcodes OR +shift cnt{,tag} LSH 10 +chan command chan ALC W +chan test chan CAT Y + +All numbers are octal. Channel designators can be alphabetic (W, Y, C, D, E, +F, G, H) or numeric (0-7). Tags must be 0-7, with 2 indicating indexing. diff --git a/SDS/sds_drm.c b/SDS/sds_drm.c new file mode 100644 index 00000000..d49c9378 --- /dev/null +++ b/SDS/sds_drm.c @@ -0,0 +1,270 @@ +/* sds_drm.c: SDS 940 Project Genie drum simulator + + Copyright (c) 2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + drm drum + + The drum is buffered in memory. + + Note: the Project Genie documentation and the actual monitor sources disagree + on the I/O instruction definitions for the drum. The simulator follows the + monitor sources, as follows: + + DCC OP 00230404B RESET DRUM CHANNEL + DSC OP 00230204B START DRUM CHANNEL (NO CHAIN) + DRA OP 00230504B READ DRUM TIMING COUNTER INTO 21B + DSR OP 04030204B SKIP IF DRUM NOT BUSY + DSE OP 04037404B SKIP IF NO DRUM ERROR +*/ + +#include "sds_defs.h" +#include + +/* Constants */ + +#define DRM_N_WD 11 /* word addr width */ +#define DRM_V_WD 0 /* position */ +#define DRM_M_WD ((1 << DRM_N_WD) - 1) /* word mask */ +#define DRM_NUMWD (1 << DRM_N_WD) /* words/sector */ +#define DRM_NUMGP 236 /* gap/sector */ +#define DRM_PHYWD (DRM_NUMWD + DRM_NUMGP) /* phys wds/sector */ +#define DRM_N_SC 3 /* sect addr width */ +#define DRM_V_SC (DRM_N_WD) /* position */ +#define DRM_M_SC ((1 << DRM_N_SC) - 1) /* sector mask */ +#define DRM_NUMSC (1 << DRM_N_SC) /* sectors/track */ +#define DRM_N_TR 7 /* track addr width */ +#define DRM_V_TR (DRM_N_WD+DRM_N_SC) /* position */ +#define DRM_M_TR ((1 << DRM_N_TR) - 1) /* track mask */ +#define DRM_NUMTR 84 /* tracks/drum */ +#define DRM_N_ADDR (DRM_N_WD+DRM_N_SC+DRM_N_TR) /* drum addr width */ +#define DRM_SWMASK ((1 << (DRM_N_WD+DRM_N_SC)) - 1)/* sector+word mask */ +#define DRM_DAMASK ((1 << DRM_N_ADDR) - 1) /* drum addr mask */ +#define DRM_SIZE (DRM_NUMTR*DRM_NUMSC*DRM_NUMWD) /* words/disk */ +#define DRM_WCMASK 037777 /* wc mask */ +#define DRM_GETSC(x) (((x) >> DRM_V_SC) & DRM_M_SC) + +#define DRM_PC 020 +#define DRM_AD 021 +#define DRM_ADAT (1 << (DRM_N_WD + DRM_N_SC)) /* data flag */ + +#define DRM_SFET 0 /* fetch state */ +#define DRM_SFCA 1 /* fetch CA */ +#define DRM_SFDA 2 /* fetch DA */ +#define DRM_SXFR 3 /* xfer */ + +#define DRM_V_OP 21 /* drum op */ +#define DRM_M_OP 07 +#define DRM_V_RW 20 +#define DRM_GETOP(x) (((x) >> DRM_V_OP) & DRM_M_OP) +#define DRM_GETRW(x) (((x) >> DRM_V_RW) & 1) +#define DRM_OXF 0 /* xfer */ +#define DRM_OCX 1 /* cond xfer */ +#define DRM_OBR 2 /* branch */ +#define DRM_ORS 3 /* reset error */ +#define DRM_END 4 /* end prog */ +#define DRM_EIE 5 /* end int if err */ +#define DRM_EIU 7 /* end int uncond */ + +#define GET_TWORD(x) ((int32) fmod (sim_gtime() / ((double) (x)), \ + ((double) (DRM_NUMSC * DRM_PHYWD)))) + +extern uint32 M[]; /* memory */ +extern uint32 alert, int_req; +extern int32 stop_invins, stop_invdev, stop_inviop; +uint32 drm_da = 0; /* disk address */ +uint32 drm_ca = 0; /* core address */ +uint32 drm_wc = 0; /* word count */ +int32 drm_par = 0; /* cumulative par */ +int32 drm_err = 0; /* error */ +int32 drm_rw = 0; /* read/write */ +int32 drm_sta = 0; /* drum state */ +int32 drm_ftime = 3; /* time to fetch */ +int32 drm_xtime = 1; /* time to xfr */ +int32 drm_stopioe = 1; /* stop on error */ + +DEVICE drm_dev; +t_stat drm (uint32 fnc, uint32 inst, uint32 *dat); +t_stat drm_svc (UNIT *uptr); +t_stat drm_reset (DEVICE *dptr); + +/* DRM data structures + + drm_dev device descriptor + drm_unit unit descriptor + drm_reg register list +*/ + +DIB drm_dib = { -1, DEV3_GDRM, 0, NULL, &drm }; + +UNIT drm_unit = + { UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, + DRM_SIZE) }; + +REG drm_reg[] = { + { ORDATA (DA, drm_da, DRM_N_ADDR) }, + { ORDATA (CA, drm_ca, 16) }, + { ORDATA (WC, drm_wc, 14) }, + { ORDATA (PAR, drm_par, 12) }, + { FLDATA (RW, drm_rw, 0) }, + { FLDATA (ERR, drm_err, 0) }, + { ORDATA (STA, drm_sta, 2) }, + { DRDATA (FTIME, drm_ftime, 24), REG_NZ + PV_LEFT }, + { DRDATA (XTIME, drm_xtime, 24), REG_NZ + PV_LEFT }, + { FLDATA (STOP_IOE, drm_stopioe, 0) }, + { NULL } }; + +DEVICE drm_dev = { + "DRM", &drm_unit, drm_reg, NULL, + 1, 8, DRM_N_ADDR, 1, 8, 24, + NULL, NULL, &drm_reset, + NULL, NULL, NULL, + &drm_dib, DEV_DISABLE | DEV_DIS }; + +/* Drum routine - EOM/SKS 3xx04 */ + +t_stat drm (uint32 fnc, uint32 inst, uint32 *dat) +{ +int32 t, op = inst & 07700; + +switch (fnc) { +case IO_CONN: /* connect */ + if (op == 00400) return drm_reset (&drm_dev); /* EOM 404 = reset */ + if (op == 00500) { /* EOM 504 = read DA */ + if (sim_is_active (&drm_unit)) return SCPE_OK; /* must be idle */ + t = GET_TWORD (drm_xtime); /* get position */ + if (t < DRM_NUMGP) M[DRM_AD] = DRM_NUMWD - t; /* in gap? */ + else M[DRM_AD] = (t - DRM_NUMGP) | DRM_ADAT; } /* in data */ + else if (op == 00200) { /* EOM 204 = start */ + if (sim_is_active (&drm_unit)) return SCPE_OK; /* must be idle */ + drm_sta = DRM_SFET; /* state = fetch */ + sim_activate (&drm_unit, drm_ftime); } /* activate */ + else CRETINS; + break; + +case IO_SKS: /* SKS */ + if (((op == 07400) && !drm_err) || /* 37404: no err */ + ((op == 00200) && !sim_is_active (&drm_unit))) /* 30204: idle */ + *dat = 1; + break; + +default: + return SCPE_IERR; } /* can't get here */ +return SCPE_OK; +} + +/* Unit service */ + +t_stat drm_svc (UNIT *uptr) +{ +int32 t, rda; +uint32 dpc, dwd; + +if (drm_sta != DRM_SXFR) { /* fetch drum prog? */ + dpc = M[DRM_PC]; /* get drum PC */ + dwd = M[dpc & PAMASK]; /* get drum inst */ + M[DRM_PC] = (dpc + 1) & PAMASK; /* update drum PC */ + if (drm_sta == DRM_SFCA) { /* fetch core addr? */ + drm_rw = DRM_GETRW (dwd); /* set op */ + drm_ca = dwd & PAMASK; /* set core addr */ + drm_sta = DRM_SFDA; } /* next is disk addr */ + else if (drm_sta == DRM_SFDA) { /* fetch disk addr? */ + drm_da = dwd & DRM_DAMASK; /* set disk addr */ + drm_sta = DRM_SXFR; /* next is xfer */ + drm_par = 0; /* init parity */ + rda = (drm_da & DRM_SWMASK) + (DRM_GETSC (drm_da) * DRM_NUMGP); + t = rda - GET_TWORD (drm_xtime); /* difference */ + if (t <= 0) t = t + (DRM_NUMSC * DRM_PHYWD); /* add trk lnt */ + sim_activate (&drm_unit, t * drm_xtime); } /* activate */ + else { + switch (DRM_GETOP (dwd)) { + case DRM_OCX: /* cond xfr */ + if (drm_err) { /* error? */ + int_req = int_req | INT_DRM; /* req int */ + return SCPE_OK; } /* done */ + case DRM_OXF: /* transfer */ + drm_wc = dwd & DRM_WCMASK; /* save wc */ + drm_sta = DRM_SFCA; /* next state */ + break; + case DRM_OBR: /* branch */ + M[DRM_PC] = dwd & PAMASK; /* new drum PC */ + break; + case DRM_END: /* end */ + return SCPE_OK; + case DRM_EIE: /* end, int if err */ + if (!drm_err) return SCPE_OK; + case DRM_EIU: /* end, int uncond */ + int_req = int_req | INT_DRM; + return SCPE_OK; } /* end switch */ + } /* end else sta */ + sim_activate (uptr, drm_ftime); /* fetch next word */ + } /* end if !xfr */ +else { /* transfer word */ + if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ + drm_err = 1; /* error */ + CRETIOE (drm_stopioe, SCPE_UNATT); } + if (drm_rw) { /* write? */ + dwd = M[drm_ca]; /* get mem word */ + *(((uint32 *) uptr->filebuf) + drm_da) = dwd; /* write to drum */ + if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; } + else { /* read */ + dwd = *(((uint32 *) uptr->filebuf) + drm_da); /* get drum word */ + M[drm_ca] = dwd; } /* write to mem */ + drm_da = drm_da + 1; /* inc drum addr */ + if (drm_da >= DRM_SIZE) drm_da = 0; /* wrap */ + drm_ca = (drm_ca + 1) & PAMASK; /* inc core addr */ + drm_wc = (drm_wc - 1) & DRM_WCMASK; /* dec word cnt */ + drm_par = drm_par ^ (dwd >> 12); /* parity */ + drm_par = ((drm_par << 1) | (drm_par >> 11)) & 07777; + drm_par = drm_par ^ (dwd & 07777); + if (drm_wc) { /* more to do */ + if (drm_da & DRM_M_WD) sim_activate (uptr, drm_xtime); + else sim_activate (uptr, drm_xtime * DRM_NUMGP); } + else { /* end xfr */ +#if defined (DRM_PAR) + if ((drm_da & DRM_M_WD) && drm_rw) { /* wr end mid sector? */ + *(((uint32 *) uptr->filebuf) + drm_da) = drm_par << 12; + if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; } +#endif + drm_sta = DRM_SFET; /* back to fetch */ + sim_activate (uptr, drm_ftime); /* schedule */ + } /* end else end xfr */ + } /* end else xfr */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat drm_reset (DEVICE *dptr) +{ +drm_da = 0; /* clear state */ +drm_ca = 0; +drm_wc = 0; +drm_par = 0; +drm_sta = 0; +drm_err = 0; +drm_rw = 0; +int_req = int_req & ~INT_DRM; /* clear intr */ +sim_cancel (&drm_unit); /* deactivate */ +return SCPE_OK; +} diff --git a/SDS/sds_dsk.c b/SDS/sds_dsk.c new file mode 100644 index 00000000..24af8aa9 --- /dev/null +++ b/SDS/sds_dsk.c @@ -0,0 +1,357 @@ +/* sds_dsk.c: SDS 940 moving head disk simulator + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + dsk moving head disk + + The SDS 9164 disk has a subsector feature, allowing each 64W sector to be + viewed as 16W packets. In addition, it has a chaining feature, allowing + records to be extended beyond a sector boundary. To accomodate this, the + first word of each sector has 3 extra bits: + + <26> = end of chain flag + <25:24> = 4 - number of packets + + These values were chosen so that 000 = continue chain, full sector. +*/ + +#include "sds_defs.h" + +#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_WLK (1 << UNIT_V_WLK) +#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ + +#define DSK_PKTWD 16 /* words/packet */ +#define DSK_NUMPKT 4 /* packets/sector */ +#define DSK_NUMWD (DSK_PKTWD*DSK_NUMPKT) /* words/sector */ +#define DSK_N_SC 5 /* sect addr width */ +#define DSK_V_SC 0 /* position */ +#define DSK_M_SC ((1 << DSK_N_SC) - 1) /* mask */ +#define DSK_NUMSC (1 << DSK_N_SC) /* sectors/track */ +#define DSK_N_TR 8 /* track addr width */ +#define DSK_V_TR (DSK_N_SC) /* position */ +#define DSK_M_TR ((1 << DSK_N_TR) - 1) /* mask */ +#define DSK_NUMTR (1 << DSK_N_TR) /* tracks/surface */ +#define DSK_N_SF 5 /* surf addr width */ +#define DSK_V_SF (DSK_N_SC + DSK_N_TR) /* position */ +#define DSK_M_SF ((1 << DSK_N_SF) - 1) /* mask */ +#define DSK_NUMSF (1 << DSK_N_SF) /* surfaces/drive */ +#define DSK_SCSIZE (DSK_NUMSF*DSK_NUMTR*DSK_NUMSC) /* sectors/drive */ +#define DSK_AMASK (DSK_SCSIZE - 1) /* address mask */ +#define DSK_SIZE (DSK_SCSIZE * DSK_NUMWD) /* words/drive */ +#define DSK_GETTR(x) (((x) >> DSK_V_TR) & DSK_M_TR) +#define cyl u3 /* curr cylinder */ +#define DSK_SIP (1 << (DSK_N_TR + 2)) +#define DSK_V_PKT 24 +#define DSK_M_PKT 03 +#define DSK_V_CHN 26 +#define DSK_GETPKT(x) (4 - (((x) >> DSK_V_PKT) & DSK_M_PKT)) +#define DSK_ENDCHN(x) ((x) & (1 << DSK_V_CHN)) + +extern uint32 xfr_req; +extern uint32 alert; +extern int32 stop_invins, stop_invdev, stop_inviop; +int32 dsk_da = 0; /* disk addr */ +int32 dsk_op = 0; /* operation */ +int32 dsk_err = 0; /* error flag */ +uint32 dsk_buf[DSK_NUMWD]; /* sector buf */ +int32 dsk_bptr = 0; /* byte ptr */ +int32 dsk_blnt = 0; /* byte lnt */ +int32 dsk_time = 5; /* time per char */ +int32 dsk_stime = 200; /* seek time */ +int32 dsk_stopioe = 1; +DSPT dsk_tplt[] = { /* template */ + { 1, 0 }, { 1, DEV_OUT }, { 0, 0 } }; + +DEVICE dsk_dev; +t_stat dsk_svc (UNIT *uptr); +t_stat dsk_reset (DEVICE *dptr); +t_stat dsk_fill (uint32 dev); +t_stat dsk_read_buf (uint32 dev); +t_stat dsk_write_buf (uint32 dev); +void dsk_end_op (uint32 fl); +t_stat dsk (uint32 fnc, uint32 inst, uint32 *dat); + +/* DSK data structures + + dsk_dev device descriptor + dsk_unit unit descriptor + dsk_reg register list +*/ + +DIB dsk_dib = { CHAN_F, DEV_DSK, XFR_DSK, dsk_tplt, &dsk }; + +UNIT dsk_unit = + { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE, DSK_SIZE) }; + +REG dsk_reg[] = { + { BRDATA (BUF, dsk_buf, 8, 24, DSK_NUMWD) }, + { DRDATA (BPTR, dsk_bptr, 9), PV_LEFT }, + { DRDATA (BLNT, dsk_bptr, 9), PV_LEFT }, + { ORDATA (DA, dsk_da, 21) }, + { ORDATA (INST, dsk_op, 24) }, + { FLDATA (XFR, xfr_req, XFR_V_DSK) }, + { FLDATA (ERR, dsk_err, 0) }, + { DRDATA (WTIME, dsk_time, 24), REG_NZ + PV_LEFT }, + { DRDATA (STIME, dsk_stime,24), REG_NZ + PV_LEFT }, + { FLDATA (STOP_IOE, dsk_stopioe, 0) }, + { NULL } }; + +MTAB dsk_mod[] = { + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", + &set_chan, &show_chan, NULL }, + { 0 } }; + +DEVICE dsk_dev = { + "DSK", &dsk_unit, dsk_reg, dsk_mod, + 1, 8, 24, 1, 8, 27, + NULL, NULL, &dsk_reset, + NULL, NULL, NULL, + &dsk_dib, DEV_DISABLE }; + +/* Moving head disk routine + + conn - inst = EOM0, dat = NULL + eom1 - inst = EOM1, dat = NULL + sks - inst = SKS, dat = ptr to result + disc - inst = device number, dat = NULL + wreor - inst = device number, dat = NULL + read - inst = device number, dat = ptr to data + write - inst = device number, dat = ptr to result +*/ + +t_stat dsk (uint32 fnc, uint32 inst, uint32 *dat) +{ +int32 i, t, new_ch, dsk_wptr, dsk_byte; +t_stat r; + +switch (fnc) { /* case on function */ +case IO_CONN: /* connect */ + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */ + dsk_op = inst; /* save instr */ + dsk_bptr = dsk_blnt = 0; /* init ptrs */ + for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */ + xfr_req = xfr_req & ~XFR_DSK; /* clr xfr flg */ + sim_activate (&dsk_unit, dsk_stime); /* activate */ + break; + +case IO_EOM1: /* EOM mode 1 */ + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */ + if (inst & 07600) CRETIOP; /* inv inst? */ + alert = POT_DSK; /* alert */ + break; + +case IO_DISC: /* disconnect */ + dsk_end_op (0); /* normal term */ + if (inst & DEV_OUT) return dsk_fill (inst); /* fill write */ + break; + +case IO_WREOR: /* write eor */ + dsk_end_op (CHF_EOR); /* eor term */ + return dsk_fill (inst); /* fill write */ + +case IO_SKS: /* SKS */ + new_ch = I_GETSKCH (inst); /* sks chan */ + if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */ + t = I_GETSKCND (inst); /* sks cond */ + if (((t == 000) && !sim_is_active (&dsk_unit) && /* 10026: ready */ + (dsk_unit.flags & UNIT_ATT)) || + ((t == 004) && !dsk_err && /* 11026: !err */ + (dsk_unit.flags & UNIT_ATT)) || + ((t == 010) && ((dsk_unit.cyl & DSK_SIP) == 0)) || /* 12026: on trk */ + ((t == 014) && !(dsk_unit.flags & UNIT_WPRT)) ||/* 13026: !wrprot */ + ((t == 001) && (dsk_unit.flags & UNIT_ATT))) /* 10226: online */ + *dat = 1; + break; + +case IO_READ: + xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */ + if (dsk_bptr >= dsk_blnt) { /* no more data? */ + if (r = dsk_read_buf (inst)) return r; } /* read sector */ + dsk_wptr = dsk_bptr >> 2; /* word pointer */ + dsk_byte = dsk_bptr & 03; /* byte in word */ + *dat = (dsk_buf[dsk_wptr] >> ((3 - dsk_byte) * 6)) & 077; + dsk_bptr = dsk_bptr + 1; /* incr buf ptr */ + if ((dsk_bptr >= dsk_blnt) && /* end sector, */ + ((dsk_op & CHC_BIN) || DSK_ENDCHN (dsk_buf[0])))/* sec mode | eoch? */ + dsk_end_op (CHF_EOR); /* eor term */ + break; + +case IO_WRITE: + xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */ + if (dsk_bptr >= (DSK_NUMWD * 4)) { /* full? */ + if (r = dsk_write_buf (inst)) return r; } /* write sector */ + dsk_wptr = dsk_bptr >> 2; /* word pointer */ + dsk_buf[dsk_wptr] = ((dsk_buf[dsk_wptr] << 6) | (*dat & 077)) & DMASK; + dsk_bptr = dsk_bptr + 1; /* incr buf ptr */ + break; + +default: + CRETINS; } +return SCPE_OK; +} + +/* PIN routine - return disk address */ + +t_stat pin_dsk (uint32 num, uint32 *dat) +{ +*dat = dsk_da; /* ret disk addr */ +return SCPE_OK; +} + +/* POT routine - start seek */ + +t_stat pot_dsk (uint32 num, uint32 *dat) +{ +int32 st; + +if (sim_is_active (&dsk_unit)) return STOP_IONRDY; /* busy? wait */ +dsk_da = (*dat) & DSK_AMASK; /* save dsk addr */ +st = abs (DSK_GETTR (dsk_da) - /* calc seek time */ + (dsk_unit.cyl & DSK_M_TR)) * dsk_stime; +if (st == 0) st = dsk_stime; /* min time */ +sim_activate (&dsk_unit, st); /* set timer */ +dsk_unit.cyl = dsk_unit.cyl | DSK_SIP; /* seeking */ +return SCPE_OK; +} + +/* Unit service and read/write */ + +t_stat dsk_svc (UNIT *uptr) +{ +if (uptr->cyl & DSK_SIP) { /* end seek? */ + uptr->cyl = DSK_GETTR (dsk_da); /* on cylinder */ + if (dsk_op) sim_activate (&dsk_unit, dsk_stime); } /* sched r/w */ +else { + xfr_req = xfr_req | XFR_DSK; /* set xfr req */ + sim_activate (&dsk_unit, dsk_time); } /* activate */ +return SCPE_OK; +} + +/* Read sector */ + +t_stat dsk_read_buf (uint32 dev) +{ +int32 da, pkts, awc; + +if ((dsk_unit.flags & UNIT_ATT) == 0) { /* !attached? */ + dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */ + CRETIOE (dsk_stopioe, SCPE_UNATT); } +da = dsk_da * DSK_NUMWD * sizeof (uint32); +fseek (dsk_unit.fileref, da, SEEK_SET); /* locate sector */ +awc = fxread (dsk_buf, sizeof (uint32), DSK_NUMWD, dsk_unit.fileref); +if (ferror (dsk_unit.fileref)) { /* error? */ + dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */ + return SCPE_IOERR; } +for ( ; awc < DSK_NUMWD; awc++) dsk_buf[awc] = 0; +pkts = DSK_GETPKT (dsk_buf[0]); /* get packets */ +dsk_blnt = pkts * DSK_PKTWD * 4; /* new buf size */ +dsk_bptr = 0; /* init bptr */ +dsk_da = (dsk_da + 1) & DSK_AMASK; /* incr disk addr */ +return SCPE_OK; +} + +/* Write sector. If this routine is called directly, then the sector + buffer is full, and there is at least one more character to write; + therefore, there are 4 packets in the sector, and the sector is not + the end of the chain. +*/ + +t_stat dsk_write_buf (uint32 dev) +{ +int32 i, da; + +if ((dsk_unit.flags & UNIT_ATT) == 0) { /* !attached? */ + dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */ + CRETIOE (dsk_stopioe, SCPE_UNATT); } +if (dsk_unit.flags & UNIT_WPRT) { /* write prot? */ + dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */ + return SCPE_OK; } +da = dsk_da * DSK_NUMWD * sizeof (uint32); +fseek (dsk_unit.fileref, da, SEEK_SET); /* locate sector */ +fxwrite (dsk_buf, sizeof (uint32), DSK_NUMWD, dsk_unit.fileref); +if (ferror (dsk_unit.fileref)) { /* error? */ + dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */ + return SCPE_IOERR; } +dsk_bptr = 0; /* init bptr */ +dsk_da = (dsk_da + 1) & DSK_AMASK; /* incr disk addr */ +for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */ +return SCPE_OK; +} + +/* Fill incomplete sector at end of operation. Calculate the number + of packets and set the end of chain flag. +*/ + +t_stat dsk_fill (uint32 dev) +{ +int32 nochn = (dsk_op & CHC_BIN)? 0: 1; /* chain? */ +int32 pktend = (dsk_bptr + ((DSK_PKTWD * 4) - 1)) & /* end pkt */ + ~((DSK_PKTWD * 4) - 1); +int32 pkts = pktend / (DSK_PKTWD * 4); /* # packets */ + +if (dsk_bptr == 0) return SCPE_OK; /* no fill? */ +for ( ; dsk_bptr < pktend; dsk_bptr++) { /* fill packet */ + int32 dsk_wptr = dsk_bptr >> 2; + dsk_buf[dsk_wptr] = (dsk_buf[dsk_wptr] << 6) & DMASK; } +dsk_buf[0] = dsk_buf[0] | (nochn << DSK_V_CHN) | /* insert chain, */ + ((4 - pkts) << DSK_V_PKT); /* num pkts */ +return dsk_write_buf (dev); /* write sec */ +} + +/* Terminate DSK operation */ + +void dsk_end_op (uint32 fl) +{ +if (fl) chan_set_flag (dsk_dib.chan, fl); /* set flags */ +dsk_op = 0; /* clear op */ +xfr_req = xfr_req & ~XFR_DSK; /* clear xfr */ +sim_cancel (&dsk_unit); /* stop */ +if (fl & CHF_ERR) { /* error? */ + chan_disc (dsk_dib.chan); /* disconnect */ + dsk_err = 1; } /* set disk err */ +return; +} + +/* Reset routine */ + +t_stat dsk_reset (DEVICE *dptr) +{ +int32 i; + +chan_disc (dsk_dib.chan); /* disconnect */ +dsk_da = 0; /* clear state */ +dsk_op = 0; +dsk_err = 0; +dsk_bptr = dsk_blnt = 0; +xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */ +sim_cancel (&dsk_unit); /* deactivate */ +dsk_unit.cyl = 0; +for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */ +return SCPE_OK; +} diff --git a/SDS/sds_io.c b/SDS/sds_io.c new file mode 100644 index 00000000..f26b8f6e --- /dev/null +++ b/SDS/sds_io.c @@ -0,0 +1,886 @@ +/* sds_io.c: SDS 940 I/O simulator + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. +*/ + +#include "sds_defs.h" + +/* Data chain word */ + +#define CHD_INT 040 /* int on chain */ +#define CHD_PAGE 037 /* new page # */ + +/* Interlace POT */ + +#define CHI_V_WC 14 /* word count */ +#define CHI_M_WC 01777 +#define CHI_GETWC(x) (((x) >> CHI_V_WC) & CHI_M_WC) +#define CHI_V_MA 0 /* mem address */ +#define CHI_M_MA 037777 +#define CHI_GETMA(x) (((x) >> CHI_V_MA) & CHI_M_MA) + +/* System interrupt POT */ + +#define SYI_V_GRP 18 /* group */ +#define SYI_M_GRP 077 +#define SYI_GETGRP(x) (((x) >> SYI_V_GRP) & SYI_M_GRP) +#define SYI_DIS (1 << 17) /* disarm if 0 */ +#define SYI_ARM (1 << 16) /* arm if 1 */ +#define SYI_M_INT 0177777 /* interrupt */ + +/* Pseudo-device number for EOM/SKS mode 3 */ + +#define I_GETDEV3(x) ((((x) & 020046000) != 020046000)? ((x) & DEV_MASK): DEV_MASK) + +#define TST_XFR(d,c) (xfr_req && dev_map[d][c]) +#define SET_XFR(d,c) xfr_req = xfr_req | dev_map[d][c] +#define CLR_XFR(d,c) xfr_req = xfr_req & ~dev_map[d][c] +#define INV_DEV(d,c) (dev_dsp[d][c] == NULL) +#define VLD_DEV(d,c) (dev_dsp[d][c] != NULL) +#define TST_EOR(c) (chan_flag[c] & CHF_EOR) +#define QAILCE(a) (((a) >= POT_ILCY) && ((a) < (POT_ILCY + NUM_CHAN))) + +uint8 chan_uar[NUM_CHAN]; /* unit addr */ +uint16 chan_wcr[NUM_CHAN]; /* word count */ +uint16 chan_mar[NUM_CHAN]; /* mem addr */ +uint8 chan_dcr[NUM_CHAN]; /* data chain */ +uint32 chan_war[NUM_CHAN]; /* word assembly */ +uint8 chan_cpw[NUM_CHAN]; /* char per word */ +uint8 chan_cnt[NUM_CHAN]; /* char count */ +uint16 chan_mode[NUM_CHAN]; /* mode */ +uint16 chan_flag[NUM_CHAN]; /* flags */ +static const char *chname[NUM_CHAN] = + { "W", "Y", "C", "D", "E", "F", "G", "H" }; + +extern uint32 M[MAXMEMSIZE]; /* memory */ +extern uint32 int_req; /* int req */ +extern uint32 xfr_req; /* xfer req */ +extern uint32 alert; /* pin/pot alert */ +extern uint32 X, EM2, EM3, OV, ion, bpt; +extern uint32 nml_mode, usr_mode, rtc_pie; +extern int32 stop_invins, stop_invdev, stop_inviop; +extern int32 mon_usr_trap; +extern UNIT cpu_unit; +extern FILE *sim_log; +extern DEVICE *sim_devices[]; + +t_stat chan_reset (DEVICE *dptr); +t_stat chan_read (int32 ch); +t_stat chan_write (int32 ch); +void chan_write_mem (int32 ch); +void chan_flush_war (int32 ch); +uint32 chan_mar_inc (int32 ch); +t_stat chan_eor (int32 ch); +t_stat pot_ilc (uint32 num, uint32 *dat); +t_stat pot_dcr (uint32 num, uint32 *dat); +t_stat pin_adr (uint32 num, uint32 *dat); +t_stat pot_fork (uint32 num, uint32 *dat); +t_stat dev_disc (uint32 ch, uint32 dev); +t_stat dev_wreor (uint32 ch, uint32 dev); +extern t_stat pot_RL1 (uint32 num, uint32 *dat); +extern t_stat pot_RL2 (uint32 num, uint32 *dat); +extern t_stat pot_RL4 (uint32 num, uint32 *dat); +extern t_stat pin_rads (uint32 num, uint32 *dat); +extern t_stat pot_rada (uint32 num, uint32 *dat); +extern t_stat pin_dsk (uint32 num, uint32 *dat); +extern t_stat pot_dsk (uint32 num, uint32 *dat); +t_stat pin_mux (uint32 num, uint32 *dat); +t_stat pot_mux (uint32 num, uint32 *dat); +extern void set_dyn_map (void); + +/* SDS I/O model + + A device is modeled by its interactions with a channel. Devices can only be + accessed via channels. Each channel has its own device address space. This + means devices can only be accessed from a specific channel. + + I/O operations start with a channel connect. The EOM instruction is passed + to the device via the conn routine. This routine is also used for non-channel + EOM's to the device. For channel connects, the device must remember the + channel number. + + The device responds (after a delay) by setting its XFR_RDY flag. This causes + the channel to invoke either the read or write routine (for input or output) + to get or put the next character. If the device is an asynchronous output + device, it calls routine chan_set_ordy to see if there is output available. + If there is, XFR_RDY is set; if not, the channel is marked to wake the + attached device when output is available. This prevents invalid rate errors. + + Output may be terminated by a write end of record, a disconnect, or both. + Write end of record occurs when the word count reaches zero on an IORD or IORP + operation. It also occurs if a TOP instruction is issued. The device is + expected to respond by setting the end of record indicator in the channel, + which will in turn trigger an end of record interrupt. + + When the channel operation completes, the channel disconnects and calls the + disconnect processor to perform any device specific cleanup. The differences + between write end of record and disconnect are subtle. On magtape output, + for example, both signal end of record; but write end of record allows the + magtape to continue moving, while disconnect halts its motion. + + Valid devices supply a routine to handle potentially all I/O operations + (connect, disconnect, read, write, write end of record, sks). There are + separate routines for PIN and POT. + + Channels could, optionally, handle 12b or 24b characters. The simulator can + support all widths. +*/ + +t_stat chan_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc); + +struct aldisp { + t_stat (*pin) (uint32 num, uint32 *dat); /* altnum, *dat */ + t_stat (*pot) (uint32 num, uint32 *dat); /* altnum, *dat */ + }; + +/* Channel data structures + + chan_dev channel device descriptor + chan_unit channel unit descriptor + chan_reg channel register list +*/ + +UNIT chan_unit = { UDATA (NULL, 0, 0) }; + +REG chan_reg[] = { + { BRDATA (UAR, chan_uar, 8, 6, NUM_CHAN) }, + { BRDATA (WCR, chan_wcr, 8, 15, NUM_CHAN) }, + { BRDATA (MAR, chan_mar, 8, 16, NUM_CHAN) }, + { BRDATA (DCR, chan_dcr, 8, 6, NUM_CHAN) }, + { BRDATA (WAR, chan_war, 8, 24, NUM_CHAN) }, + { BRDATA (CPW, chan_cpw, 8, 2, NUM_CHAN) }, + { BRDATA (CNT, chan_cnt, 8, 3, NUM_CHAN) }, + { BRDATA (MODE, chan_mode, 8, 12, NUM_CHAN) }, + { BRDATA (FLAG, chan_flag, 8, CHF_N_FLG, NUM_CHAN) }, + { NULL } }; + +MTAB chan_mod[] = { + { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_W, "W", NULL, + NULL, &chan_show_reg, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_Y, "Y", NULL, + NULL, &chan_show_reg, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_C, "C", NULL, + NULL, &chan_show_reg, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_D, "D", NULL, + NULL, &chan_show_reg, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_E, "E", NULL, + NULL, &chan_show_reg, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_F, "F", NULL, + NULL, &chan_show_reg, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_G, "G", NULL, + NULL, &chan_show_reg, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, CHAN_H, "H", NULL, + NULL, &chan_show_reg, NULL } }; + +DEVICE chan_dev = { + "CHAN", &chan_unit, chan_reg, chan_mod, + 1, 8, 8, 1, 8, 8, + NULL, NULL, &chan_reset, + NULL, NULL, NULL }; + +/* Tables */ + +static const uint32 int_zc[8] = { + INT_WZWC, INT_YZWC, INT_CZWC, INT_DZWC, + INT_EZWC, INT_FZWC, INT_GZWC, INT_HZWC }; + +static const uint32 int_er[8] = { + INT_WEOR, INT_YEOR, INT_CEOR, INT_DEOR, + INT_EEOR, INT_FEOR, INT_GEOR, INT_HEOR }; + +/* dev_map maps device and channel numbers to a transfer flag masks */ + +uint32 dev_map[64][NUM_CHAN]; + +/* dev_dsp maps device and channel numbers to dispatch routines */ + +t_stat (*dev_dsp[64][NUM_CHAN])() = { NULL }; + +/* dev_dsp maps system device numbers to dispatch routines */ + +t_stat (*dev3_dsp[64])() = { NULL }; + +/* dev_alt maps alert numbers to dispatch routines */ + +struct aldisp dev_alt[] = { + { NULL, NULL }, + { NULL, &pot_ilc }, { NULL, &pot_ilc }, + { NULL, &pot_ilc }, { NULL, &pot_ilc }, + { NULL, &pot_ilc }, { NULL, &pot_ilc }, + { NULL, &pot_ilc }, { NULL, &pot_ilc }, + { NULL, &pot_dcr }, { NULL, &pot_dcr }, + { NULL, &pot_dcr }, { NULL, &pot_dcr }, + { NULL, &pot_dcr }, { NULL, &pot_dcr }, + { NULL, &pot_dcr }, { NULL, &pot_dcr }, + { &pin_adr, NULL }, { &pin_adr, NULL }, + { &pin_adr, NULL }, { &pin_adr, NULL }, + { &pin_adr, NULL }, { &pin_adr, NULL }, + { &pin_adr, NULL }, { &pin_adr, NULL }, + { NULL, &pot_RL1 }, { NULL, &pot_RL2 }, + { NULL, &pot_RL4 }, + { &pin_rads, NULL }, { NULL, &pot_rada }, + { &pin_dsk, &pot_dsk }, { NULL, &pot_fork }, + { &pin_mux, &pot_mux } }; + +/* Single word I/O instructions */ + +t_stat op_wyim (uint32 inst, uint32 *dat) +{ +int32 ch, dev; + +ch = (inst & 000200000)? CHAN_W: CHAN_Y; /* get chan# */ +dev = chan_uar[ch] & DEV_MASK; /* get dev # */ +if (chan_cnt[ch] <= chan_cpw[ch]) { /* buffer empty? */ + if (dev == 0) return STOP_INVIOP; /* no device? dead */ + return STOP_IONRDY; } /* hang until full */ +*dat = chan_war[ch]; /* get data */ +chan_war[ch] = 0; /* reset war */ +chan_cnt[ch] = 0; /* reset cnt */ +return SCPE_OK; +} + +t_stat op_miwy (uint32 inst, uint32 dat) +{ +int32 ch, dev; + +ch = (inst & 000200000)? CHAN_W: CHAN_Y; /* get chan# */ +dev = chan_uar[ch] & DEV_MASK; /* get dev # */ +if (chan_cnt[ch] != 0) { /* buffer full? */ + if (dev == 0) return STOP_INVIOP; /* no device? dead */ + return STOP_IONRDY; } /* hang until full */ +chan_war[ch] = dat; /* get data */ +chan_cnt[ch] = chan_cpw[ch] + 1; /* buffer full */ +if (chan_flag[ch] & CHF_OWAK) { /* output wake? */ + if (VLD_DEV (dev, ch)) SET_XFR (dev, ch); /* wake channel */ + chan_flag[ch] = chan_flag[ch] & ~CHF_OWAK; } /* clear wake */ +return SCPE_OK; +} + +t_stat op_pin (uint32 *dat) +{ +uint32 al = alert; /* local copy */ + +alert = 0; /* clear alert */ +if ((al == 0) || (dev_alt[al].pin == NULL)) CRETIOP; /* inv alert? */ +return dev_alt[al].pin (al, dat); /* PIN from dev */ +} + +t_stat op_pot (uint32 dat) +{ +uint32 al = alert; /* local copy */ + +alert = 0; /* clear alert */ +if ((al == 0) || (dev_alt[al].pot == NULL)) CRETIOP; /* inv alert? */ +return dev_alt[al].pot (al, &dat); /* POT to dev */ +} + +/* EOM/EOD */ + +t_stat op_eomd (uint32 inst) +{ +uint32 mod = I_GETIOMD (inst); /* get mode */ +uint32 ch = I_GETEOCH (inst); /* get chan # */ +uint32 dev = inst & DEV_MASK; /* get dev # */ +uint32 ch_dev = chan_uar[ch] & DEV_MASK; /* chan curr dev # */ +t_stat r; + +switch (mod) { +case 0: /* IO control */ + if (dev) { /* new dev? */ + if (ch_dev) CRETIOP; /* chan act? err */ + if (INV_DEV (dev, ch)) CRETDEV; /* inv dev? err */ + chan_war[ch] = chan_cnt[ch] = 0; /* init chan */ + chan_flag[ch] = chan_dcr[ch] = 0; + chan_mode[ch] = chan_uar[ch] = 0; + if (ch > CHAN_E) chan_mode[ch] = CHM_CE; + if (r = dev_dsp[dev][ch] (IO_CONN, inst, NULL)) /* connect */ + return r; + if ((inst & I_IND) || (ch >= CHAN_C)) { /* C-H? alert ilc */ + alert = POT_ILCY + ch; + chan_mar[ch] = chan_wcr[ch] = 0; } + if (chan_flag[ch] & CHF_24B) chan_cpw[ch] = 0; /* 24B? 1 ch/wd */ + else if (chan_flag[ch] & CHF_12B) /* 12B? 2 ch/wd */ + chan_cpw[ch] = CHC_GETCPW (inst) & 1; + else chan_cpw[ch] = CHC_GETCPW (inst); /* 6b, 1-4 ch/wd */ + chan_uar[ch] = dev; /* connected */ + if ((dev & DEV_OUT) && ion && !QAILCE (alert)) /* out, prog IO? */ + int_req = int_req | int_zc[ch]; } /* initial intr */ + else return dev_disc (ch, ch_dev); /* disconnect */ + break; +case 1: /* buf control */ + if (QAILCE (alert)) { /* ilce alerted? */ + ch = alert - POT_ILCY; /* derive chan */ + if (ch >= CHAN_E) inst = inst | CHM_CE; /* DACC? ext */ + chan_mode[ch] = inst; /* save mode */ + chan_mar[ch] = (CHM_GETHMA (inst) << 14) | /* get hi mar */ + (chan_mar[ch] & CHI_M_MA); + chan_wcr[ch] = (CHM_GETHWC (inst) << 10) | /* get hi wc */ + (chan_wcr[ch] & CHI_M_WC); } + else if (dev) { /* dev EOM */ + if (INV_DEV (dev, ch)) CRETDEV; /* inv dev? err */ + return dev_dsp[dev][ch] (IO_EOM1, inst, NULL); } + else { /* chan EOM */ + inst = inst & 047677; + if (inst == 040000) { /* alert ilce */ + alert = POT_ILCY + ch; + chan_mar[ch] = chan_wcr[ch] = 0; } + else if (inst == 002000) alert = POT_ADRY + ch; /* alert addr */ + else if (inst == 001000) alert = POT_DCRY + ch; /* alert DCR */ + else if (inst == 004000) { /* term output */ + if (ch_dev & DEV_OUT) { /* to output dev? */ + if (chan_cnt[ch] || (chan_flag[ch] & CHF_ILCE)) /* busy, DMA in prog? */ + chan_flag[ch] = chan_flag[ch] | CHF_TOP; /* TOP pending */ + else return dev_wreor (ch, ch_dev); /* idle, write EOR */ + } /* end else TOP */ + else if (ch_dev & DEV_MT) { /* change to scan? */ + chan_uar[ch] = chan_uar[ch] | DEV_MTS; /* change dev addr */ + chan_flag[ch] = chan_flag[ch] | CHF_SCAN; /* set scan flag */ + } /* end else change scan */ + } /* end else term output */ + } /* end else chan EOM */ + break; +case 2: /* internal */ + if (ch >= CHAN_E) { /* EOD? */ + if (inst & 00300) { /* set EM? */ + if (inst & 00100) EM2 = inst & 07; + if (inst & 00200) EM3 = (inst >> 3) & 07; + set_dyn_map (); } + break; } /* end if EOD */ + if (inst & 00001) OV = 0; /* clr OV */ + if (inst & 00002) ion = 1; /* ion */ + else if (inst & 00004) ion = 0; /* iof */ + if ((inst & 00010) && (((X >> 1) ^ X) & EXPS)) OV = 1; + if (inst & 00020) alert = POT_SYSI; /* alert sys int */ + if (inst & 00100) rtc_pie = 1; /* arm clk pls */ + else if (inst & 00200) rtc_pie = 0; /* disarm pls */ + if ((inst & 01400) == 01400) alert = POT_RL4; /* alert RL4 */ + else if (inst & 00400) alert = POT_RL1; /* alert RL1 */ + else if (inst & 01000) alert = POT_RL2; /* alert RL2 */ + if (inst & 02000) { /* nml to mon */ + nml_mode = usr_mode = 0; + if (inst & 00400) mon_usr_trap = 1; } + break; +case 3: /* special */ + dev = I_GETDEV3 (inst); /* special device */ + if (dev3_dsp[dev]) /* defined? */ + return dev3_dsp[dev] (IO_CONN, inst, NULL); + CRETINS; } /* end case */ +return SCPE_OK; +} + +/* Skip if not signal */ + +t_stat op_sks (uint32 inst, uint32 *dat) +{ +uint32 mod = I_GETIOMD (inst); /* get mode */ +uint32 ch = I_GETSKCH (inst); /* get chan # */ +uint32 dev = inst & DEV_MASK; /* get dev # */ + +*dat = 0; +if ((ch == 4) && !(inst & 037774)) { /* EM test */ + if (((inst & 0001) && (EM2 != 2)) || + ((inst & 0002) && (EM3 != 3))) *dat = 1; + return SCPE_OK; } +switch (mod) { +case 1: /* ch, dev */ + if (dev) { /* device */ + if (INV_DEV (dev, ch)) CRETDEV; /* inv dev? err */ + dev_dsp[dev][ch] (IO_SKS, inst, dat); } /* do test */ + else { /* channel */ + if (((inst & 04000) && (chan_uar[ch] == 0)) || + ((inst & 02000) && (chan_wcr[ch] == 0)) || + ((inst & 01000) && ((chan_flag[ch] & CHF_ERR) == 0)) || + ((inst & 00400) && (chan_flag[ch] & CHF_IREC))) *dat = 1; } + break; +case 2: /* internal test */ + if (inst & 0001) { /* test OV */ + *dat = OV ^ 1; /* skip if off */ + OV = 0; /* and reset */ + break; } + if (((inst & 00002) && !ion) || /* ion, bpt test */ + ((inst & 00004) && ion) || + ((inst & 00010) && ((chan_flag[CHAN_W] & CHF_ERR) == 0)) || + ((inst & 00020) && ((chan_flag[CHAN_Y] & CHF_ERR) == 0)) || + ((inst & 00040) && ((bpt & 001) == 0)) || + ((inst & 00100) && ((bpt & 002) == 0)) || + ((inst & 00200) && ((bpt & 004) == 0)) || + ((inst & 00400) && ((bpt & 010) == 0)) || + ((inst & 01000) && (chan_uar[CHAN_W] == 0)) || + ((inst & 02000) && (chan_uar[CHAN_Y] == 0))) *dat = 1; + break; +case 3: /* special */ + dev = I_GETDEV3 (inst); /* special device */ + if (dev3_dsp[dev]) dev3_dsp[dev] (IO_SKS, inst, dat); + else CRETINS; } /* end case */ +return SCPE_OK; +} + +/* PIN/POT routines */ + +t_stat pot_ilc (uint32 num, uint32 *dat) +{ +uint32 ch = num - POT_ILCY; + +chan_mar[ch] = (chan_mar[ch] & ~CHI_M_MA) | CHI_GETMA (*dat); +chan_wcr[ch] = (chan_wcr[ch] & ~CHI_M_WC) | CHI_GETWC (*dat); +chan_flag[ch] = chan_flag[ch] | CHF_ILCE; +return SCPE_OK; +} + +t_stat pot_dcr (uint32 num, uint32 *dat) +{ +uint32 ch = num - POT_DCRY; + +chan_dcr[ch] = (*dat) & (CHD_INT | CHD_PAGE); +chan_flag[ch] = chan_flag[ch] | CHF_DCHN; +return SCPE_OK; +} + +t_stat pin_adr (uint32 num, uint32 *dat) +{ +uint32 ch = num - POT_ADRY; + +*dat = chan_mar[ch] & PAMASK; +return SCPE_OK; +} + +/* System interrupt POT. + + The SDS 940 timesharing system uses a permanently asserted + system interrupt as a way of forking the teletype input + interrupt handler to a lower priority. The interrupt is + armed to set up the fork, and disarmed in the fork routine */ + +t_stat pot_fork (uint32 num, uint32 *dat) +{ +uint32 igrp = SYI_GETGRP (*dat); /* get group */ +uint32 fbit = (1 << (VEC_FORK & 017)); /* bit in group */ + +if (igrp == (VEC_FORK / 020)) { /* right group? */ + if ((*dat & SYI_ARM) && (*dat & fbit)) /* arm, bit set? */ + int_req = int_req | INT_FORK; + if ((*dat & SYI_DIS) && !(*dat & fbit)) /* disarm, bit clr? */ + int_req = int_req & ~INT_FORK; } +return SCPE_OK; +} + +/* Channel read invokes the I/O device to get the next character and, + if not end of record, assembles it into the word assembly register. + If the interlace is on, the full word is stored in memory. + The key difference points for the various terminal functions are + + end of record comp: EOT interrupt + IORD, IOSD: EOR interrupt, disconnect + IORP, IOSP: EOR interrupt, interrecord + interlace off: comp: EOW interrupt + IORD, IORP: ignore + IOSD, IOSP: overrun error + --wcr == 0: comp: clear interlace + IORD, IORP, IOSP: ZWC interrupt + IOSD: ZWC interrupt, EOR interrupt, disconnect + + Note that the channel can be disconnected if CHN_EOR is set, but must + not be if XFR_REQ is set */ + +t_stat chan_read (int32 ch) +{ +uint32 dat = 0; +uint32 dev = chan_uar[ch] & DEV_MASK; +uint32 tfnc = CHM_GETFNC (chan_mode[ch]); +t_stat r = SCPE_OK; + +if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */ + if (INV_DEV (dev, ch)) CRETIOP; /* can't read? */ + r = dev_dsp[dev][ch] (IO_READ, dev, &dat); /* read data */ + if (r) chan_flag[ch] = chan_flag[ch] | CHF_ERR; /* error? */ + if (chan_flag[ch] & CHF_24B) chan_war[ch] = dat; /* 24B? */ + else if (chan_flag[ch] & CHF_12B) /* 12B? */ + chan_war[ch] = ((chan_war[ch] << 12) | (dat & 07777)) & DMASK; + else chan_war[ch] = ((chan_war[ch] << 6) | (dat & 077)) & DMASK; + if (chan_flag[ch] & CHF_SCAN) /* scanning? */ + chan_cnt[ch] = chan_cpw[ch]; /* never full */ + else chan_cnt[ch] = chan_cnt[ch] + 1; /* insert char */ + if (chan_cnt[ch] > chan_cpw[ch]) { /* full? */ + if (chan_flag[ch] & CHF_ILCE) { /* interlace on? */ + chan_write_mem (ch); /* write to mem */ + if (chan_wcr[ch] == 0) { /* wc zero? */ + chan_flag[ch] = chan_flag[ch] & ~CHF_ILCE; /* clr interlace */ + if ((tfnc != CHM_COMP) && (chan_mode[ch] & CHM_ZC)) + int_req = int_req | int_zc[ch]; /* zwc interrupt */ + if (tfnc == CHM_IOSD) { /* IOSD? also EOR */ + if (chan_mode[ch] & CHM_ER) int_req = int_req | int_er[ch]; + dev_disc (ch, dev); /* disconnect */ + } /* end if IOSD */ + } /* end if wcr == 0 */ + } /* end if ilce on */ + else { /* interlace off */ + if (TST_EOR (ch)) return chan_eor (ch); /* eor? */ + if (tfnc == CHM_COMP) { /* C: EOW, intr */ + if (ion) int_req = int_req | int_zc[ch]; } + else if (tfnc & CHM_SGNL) /* Sx: error */ + chan_flag[ch] = chan_flag[ch] | CHF_ERR; + else chan_cnt[ch] = chan_cpw[ch]; /* Rx: ignore */ + } /* end else ilce */ + } /* end if full */ + } /* end if xfr */ +if (TST_EOR (ch)) { /* end record? */ + if (tfnc == CHM_COMP) chan_flush_war (ch); /* C: fill war */ + else if (chan_cnt[ch]) { /* RX, CX: fill? */ + chan_flush_war (ch); /* fill war */ + if (chan_flag[ch] & CHF_ILCE) /* ilce on? store */ + chan_write_mem (ch); } /* end else if cnt */ + return chan_eor (ch); } /* eot/eor int */ +return r; +} + +void chan_write_mem (int32 ch) +{ +WriteP (chan_mar[ch], chan_war[ch]); /* write to mem */ +chan_mar[ch] = chan_mar_inc (ch); /* incr mar */ +chan_wcr[ch] = (chan_wcr[ch] - 1) & 077777; /* decr wcr */ +chan_war[ch] = 0; /* reset war */ +chan_cnt[ch] = 0; /* reset cnt */ +return; +} + +void chan_flush_war (int32 ch) +{ +int32 i = (chan_cpw[ch] - chan_cnt[ch]) + 1; + +if (i) { + if (chan_flag[ch] & CHF_24B) chan_war[ch] = 0; + else if (chan_flag[ch] & CHF_12B) + chan_war[ch] = (chan_war[ch] << 12) & DMASK; + else chan_war[ch] = (chan_war[ch] << (i * 6)) & DMASK; + chan_cnt[ch] = chan_cpw[ch] + 1; } +return; +} + +/* Channel write gets the next character and sends it to the I/O device. + If this is the last character in an interlace operation, the end of + record operation is invoked. + The key difference points for the various terminal functions are + + end of record: comp: EOT interrupt + IORD, IOSD: EOR interrupt, disconnect + IORP, IOSP: EOR interrupt, interrecord + interlace off: if not end of record, EOW interrupt + --wcr == 0: comp: EOT interrupt, disconnect + IORD, IORP: ignore + IOSD: ZWC interrupt, disconnect + IOSP: ZWC interrupt, interrecord +*/ +t_stat chan_write (int32 ch) +{ +uint32 dat = 0; +uint32 dev = chan_uar[ch] & DEV_MASK; +uint32 tfnc = CHM_GETFNC (chan_mode[ch]); +t_stat r = SCPE_OK; + +if (dev && TST_XFR (dev, ch)) { /* ready to xfr? */ + if (INV_DEV (dev, ch)) CRETIOP; /* invalid dev? */ + if (chan_cnt[ch] == 0) { /* buffer empty? */ + if (chan_flag[ch] & CHF_ILCE) { /* interlace on? */ + chan_war[ch] = ReadP (chan_mar[ch]); + chan_mar[ch] = chan_mar_inc (ch); /* incr mar */ + chan_wcr[ch] = (chan_wcr[ch] - 1) & 077777; /* decr mar */ + chan_cnt[ch] = chan_cpw[ch] + 1; } /* set cnt */ + else { /* ilce off */ + CLR_XFR (dev, ch); /* cant xfr */ + if (TST_EOR (dev)) return chan_eor (ch); /* EOR? */ + chan_flag[ch] = chan_flag[ch] | CHF_ERR; /* rate err */ + return SCPE_OK; } /* end else ilce */ + } /* end if cnt */ + chan_cnt[ch] = chan_cnt[ch] - 1; /* decr cnt */ + if (chan_flag[ch] & CHF_24B) dat = chan_war[ch]; /* 24B? */ + else if (chan_flag[ch] & CHF_12B) { /* 12B? */ + dat = (chan_war[ch] >> 12) & 07777; /* get halfword */ + chan_war[ch] = (chan_war[ch] << 12) & DMASK; } /* remove from war */ + else { /* 6B */ + dat = (chan_war[ch] >> 18) & 077; /* get char */ + chan_war[ch] = (chan_war[ch] << 6) & DMASK; } /* remove from war */ + r = dev_dsp[dev][ch] (IO_WRITE, dev, &dat); /* write */ + if (r) chan_flag[ch] = chan_flag[ch] | CHF_ERR; /* error? */ + if (chan_cnt[ch] == 0) { /* buf empty? */ + if (chan_flag[ch] & CHF_ILCE) { /* ilce on? */ + if (chan_wcr[ch] == 0) { /* wc now 0? */ + chan_flag[ch] = chan_flag[ch] & ~CHF_ILCE; /* ilc off */ + if (tfnc == CHM_COMP) { /* compatible? */ + if (ion) int_req = int_req | int_zc[ch]; + dev_disc (ch, dev); /* disconnnect */ + } /* end if comp */ + else { /* extended */ + if (chan_mode[ch] & CHM_ZC) /* ZWC int */ + int_req = int_req | int_zc[ch]; + if (tfnc == CHM_IOSD) { /* SD */ + if (chan_mode[ch] & CHM_ER) /* EOR int */ + int_req = int_req | int_er[ch]; + dev_disc (ch, dev); /* disconnnect */ + } /* end if SD */ + else if (!(tfnc && CHM_SGNL) || /* IORx or IOSP TOP? */ + (chan_flag[ch] & CHF_TOP)) + dev_wreor (ch, dev); /* R: write EOR */ + chan_flag[ch] = chan_flag[ch] & ~CHF_TOP; + } /* end else comp */ + } /* end if wcr */ + } /* end if ilce */ + else if (chan_flag[ch] & CHF_TOP) { /* off, TOP pending? */ + chan_flag[ch] = chan_flag[ch] & ~CHF_TOP; /* clear TOP */ + dev_wreor (ch, dev); } /* write EOR */ + else if (ion) int_req = int_req | int_zc[ch]; /* no TOP, EOW intr */ + } /* end if cnt */ + } /* end if xfr */ +if (TST_EOR (ch)) return chan_eor (ch); /* eor rcvd? */ +return r; +} + +/* MAR increment */ + +uint32 chan_mar_inc (int32 ch) +{ +uint32 t = (chan_mar[ch] + 1) & PAMASK; /* incr mar */ + +if ((chan_flag[ch] & CHF_DCHN) && ((t & VA_POFF) == 0)) { /* chain? */ + chan_flag[ch] = chan_flag[ch] & ~CHF_DCHN; /* clr flag */ + if (chan_dcr[ch] & CHD_INT) /* if armed, intr */ + int_req = int_req | int_zc[ch]; + t = (chan_dcr[ch] & CHD_PAGE) << VA_V_PN; } /* new mar */ +return t; +} + +/* End of record action */ + +t_stat chan_eor (int32 ch) +{ +uint32 tfnc = CHM_GETFNC (chan_mode[ch]); +uint32 dev = chan_uar[ch] & DEV_MASK; + +chan_flag[ch] = chan_flag[ch] & ~(CHF_EOR | CHF_ILCE); /* clr eor, ilce */ +if (((tfnc == CHM_COMP) && ion) || (chan_mode[ch] & CHM_ER)) + int_req = int_req | int_er[ch]; /* EOT/EOR? */ +if (dev && (tfnc & CHM_PROC)) /* P, still conn? */ + chan_flag[ch] = chan_flag[ch] | CHF_IREC; /* interrecord */ +else return dev_disc (ch, dev); /* disconnect */ +return SCPE_OK; +} + +/* Utility routines */ + +t_stat dev_disc (uint32 ch, uint32 dev) +{ +chan_uar[ch] = 0; /* disconnect */ +if (dev_dsp[dev][ch]) return dev_dsp[dev][ch] (IO_DISC, dev, NULL); +return SCPE_OK; +} + +t_stat dev_wreor (uint32 ch, uint32 dev) +{ +if (dev_dsp[dev][ch]) return dev_dsp[dev][ch] (IO_WREOR, dev, NULL); +chan_flag[ch] = chan_flag[ch] | CHF_EOR; /* set eor */ +return SCPE_OK; +} + +/* Externally visible routines */ +/* Channel driver */ + +t_stat chan_process (void) +{ +int32 i, dev; +t_stat r; + +for (i = 0; i < NUM_CHAN; i++) { /* loop thru */ + dev = chan_uar[i] & DEV_MASK; /* get dev */ + if ((dev && TST_XFR (dev, i)) || TST_EOR (i)) { /* chan active? */ + if (dev & DEV_OUT) r = chan_write (i); /* write */ + else r = chan_read (i); /* read */ + if (r) return r; } } +return SCPE_OK; +} + +/* Test for channel active */ + +t_bool chan_testact (void) +{ +int32 i, dev; + +for (i = 0; i < NUM_CHAN; i++) { + dev = chan_uar[i] & DEV_MASK; + if ((dev && TST_XFR (dev, i)) || TST_EOR (i)) return 1; } +return 0; +} + +/* Async output device ready for more data */ + +void chan_set_ordy (int32 ch) +{ +if ((ch >= 0) && (ch < NUM_CHAN)) { + int32 dev = chan_uar[ch] & DEV_MASK; /* get dev */ + if (chan_cnt[ch] || (chan_flag[ch] & CHF_ILCE)) /* buf or ilce? */ + SET_XFR (dev, ch); /* set xfr flg */ + else chan_flag[ch] = chan_flag[ch] | CHF_OWAK; } /* need wakeup */ +return; +} + +/* Set flag in channel */ + +void chan_set_flag (int32 ch, uint32 fl) +{ +if ((ch >= 0) && (ch < NUM_CHAN)) chan_flag[ch] = chan_flag[ch] | fl; +return; +} + +/* Set UAR in channel */ + +void chan_set_uar (int32 ch, uint32 dev) +{ +if ((ch >= 0) && (ch < NUM_CHAN)) chan_uar[ch] = dev & DEV_MASK; +return; +} + +/* Disconnect channel */ + +void chan_disc (int32 ch) +{ +if ((ch >= 0) && (ch < NUM_CHAN)) chan_uar[ch] = 0; +return; +} + +/* Reset channels */ + +t_stat chan_reset (DEVICE *dptr) +{ +int32 i; + +xfr_req = 0; +for (i = 0; i < NUM_CHAN; i++) { + chan_uar[i] = 0; + chan_wcr[i] = 0; + chan_mar[i] = 0; + chan_dcr[i] = 0; + chan_war[i] = 0; + chan_cpw[i] = 0; + chan_cnt[i] = 0; + chan_mode[i] = 0; + chan_flag[i] = 0; } +return SCPE_OK; +} + +/* Channel assignment routines */ + +t_stat set_chan (UNIT *uptr, int32 val, char *sptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +int32 i; + +if (sptr == NULL) return SCPE_ARG; /* valid args? */ +if (uptr == NULL) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +for (i = 0; i < NUM_CHAN; i++) { /* match input */ + if (strcmp (sptr, chname[i]) == 0) { /* find string */ + if (val && !(val & (1 << i))) return SCPE_ARG; /* legal? */ + dibp->chan = i; /* store new */ + return SCPE_OK; } } +return SCPE_ARG; +} + +t_stat show_chan (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +DEVICE *dptr; +DIB *dibp; + +if (uptr == NULL) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +fprintf (st, "channel=%s", chname[dibp->chan]); +return SCPE_OK; +} + +/* Init device tables */ + +t_bool io_init (void) +{ +DEVICE *dptr; +DIB *dibp; +DSPT *tplp; +int32 ch; +uint32 i, j, dev, doff; + +/* Clear dispatch table, device map */ + +for (i = 0; i < NUM_CHAN; i++) { + for (j = 0; j < (DEV_MASK + 1); j++) { + dev_dsp[j][i] = NULL; + dev_map[j][i] = 0; } } + +/* Test each device for conflict; add to map; init tables */ + +for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */ + dibp = (DIB *) dptr->ctxt; /* get DIB */ + if ((dibp == NULL) || (dptr->flags & DEV_DIS)) continue; /* exist, enabled? */ + ch = dibp->chan; /* get channel */ + dev = dibp->dev; /* get device num */ + if (ch < 0) dev3_dsp[dev] = dibp->iop; /* special device */ + else { + if (dibp->tplt == NULL) return TRUE; /* must have template */ + for (tplp = dibp->tplt; tplp->num; tplp++) { /* loop thru templates */ + for (j = 0; j < tplp->num; j++) { /* repeat as needed */ + doff = dev + tplp->off + j; /* get offset dnum */ + if (dev_map[doff][ch]) { /* slot in use? */ + printf ("Device number conflict, chan = %s, devno = %02o\n", + chname[ch], doff); + if (sim_log) fprintf (sim_log, + "Device number conflict, chan = %s, dev = %02o\n", + chname[ch], doff); + return TRUE; } + dev_map[doff][ch] = dibp->xfr; /* set xfr flag */ + dev_dsp[doff][ch] = dibp->iop; /* set dispatch */ + } /* end for j */ + } /* end for tplt */ + } /* end else */ + } /* end for i */ +return FALSE; +} + +/* Display channel state */ + +t_stat chan_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +if ((val < 0) || (val >= NUM_CHAN)) return SCPE_IERR; +fprintf (st, "UAR: %02o\n", chan_uar[val]); +fprintf (st, "WCR: %05o\n", chan_wcr[val]); +fprintf (st, "MAR: %06o\n", chan_mar[val]); +fprintf (st, "DCR: %02o\n", chan_dcr[val]); +fprintf (st, "WAR: %08o\n", chan_war[val]); +fprintf (st, "CPW: %o\n", chan_cpw[val]); +fprintf (st, "CNT: %o\n", chan_cnt[val]); +fprintf (st, "MODE: %03o\n", chan_mode[val]); +fprintf (st, "FLAG: %04o\n", chan_flag[val]); +return SCPE_OK; +} diff --git a/SDS/sds_lp.c b/SDS/sds_lp.c new file mode 100644 index 00000000..cf33ba85 --- /dev/null +++ b/SDS/sds_lp.c @@ -0,0 +1,283 @@ +/* sds_lp.c: SDS 940 line printer simulator + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + lpt line printer +*/ + +#include "sds_defs.h" + +#define LPT_V_LN 9 +#define LPT_M_LN 07 +#define LPT_GETLN(x) (((x) >> LPT_V_LN) & LPT_M_LN) +#define CHP(ch,val) ((val) & (1 << (ch))) /* CCL chan test */ +#define SET_XFR 1 /* set xfr */ +#define SET_EOR 2 /* print, set eor */ +#define SET_SPC 4 /* space */ + +extern char sds_to_ascii[64]; +extern uint32 xfr_req; +extern int32 stop_invins, stop_invdev, stop_inviop; +int32 lpt_spc = 0; /* space instr */ +int32 lpt_sta = 0; /* timeout state */ +int32 lpt_bptr = 0; /* line buf ptr */ +int32 lpt_err = 0; /* error */ +int32 lpt_ccl = 1, lpt_ccp = 0; /* cctl lnt, ptr */ +int32 lpt_ctime = 10; /* char time */ +int32 lpt_ptime = 1000; /* print time */ +int32 lpt_stime = 10000; /* space time */ +int32 lpt_stopioe = 1; /* stop on err */ +char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */ +uint8 lpt_cct[CCT_LNT] = { 0377 }; /* car ctl tape */ +DSPT lpt_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */ + +DEVICE lpt_dev; +t_stat lpt_svc (UNIT *uptr); +t_stat lpt_reset (DEVICE *dptr); +t_stat lpt_attach (UNIT *uptr, char *cptr); +t_stat lpt_crctl (int32 ch); +t_stat lpt_status (UNIT *uptr); +t_stat lpt_bufout (UNIT *uptr); +void lpt_end_op (int32 fl); +t_stat lpt (uint32 fnc, uint32 inst, uint32 *dat); + +/* LPT data structures + + lpt_dev LPT device descriptor + lpt_unit LPT unit descriptor + lpt_reg LPT register list +*/ + +DIB lpt_dib = { CHAN_W, DEV_LPT, XFR_LPT, lpt_tplt, &lpt }; + +UNIT lpt_unit = { + UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) }; + +REG lpt_reg[] = { + { BRDATA (BUF, lpt_buf, 8, 8, LPT_WIDTH) }, + { DRDATA (BPTR, lpt_bptr, 8), PV_LEFT }, + { FLDATA (XFR, xfr_req, XFR_V_LPT) }, + { FLDATA (ERR, lpt_err, 0) }, + { ORDATA (STA, lpt_sta, 3) }, + { BRDATA (CCT, lpt_cct, 8, 8, CCT_LNT) }, + { DRDATA (CCTP, lpt_ccp, 8), PV_LEFT }, + { DRDATA (CCTL, lpt_ccl, 8), REG_RO + PV_LEFT }, + { ORDATA (SPCINST, lpt_spc, 24) }, + { DRDATA (POS, lpt_unit.pos, 32), PV_LEFT }, + { DRDATA (CTIME, lpt_ctime, 24), REG_NZ + PV_LEFT }, + { DRDATA (PTIME, lpt_ptime, 24), REG_NZ + PV_LEFT }, + { DRDATA (STIME, lpt_stime, 24), REG_NZ + PV_LEFT }, + { FLDATA (STOP_IOE, lpt_stopioe, 0) }, + { NULL } }; + +MTAB lpt_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", + &set_chan, &show_chan, NULL }, + { 0 } }; + +DEVICE lpt_dev = { + "LPT", &lpt_unit, lpt_reg, lpt_mod, + 1, 10, 31, 1, 8, 7, + NULL, NULL, &lpt_reset, + NULL, &lpt_attach, NULL, + &lpt_dib, DEV_DISABLE }; + +/* Line printer routine + + conn - inst = EOM0, dat = NULL + eom1 - inst = EOM1, dat = NULL + sks - inst = SKS, dat = ptr to result + disc - inst = device number, dat = NULL + wreor - inst = device number, dat = NULL + read - inst = device number, dat = ptr to data + write - inst = device number, dat = ptr to result + + The line printer is an asynchronous output device, that is, it + can never set the channel rate error flag. +*/ + +t_stat lpt (uint32 fnc, uint32 inst, uint32 *dat) +{ +int32 i, t, new_ch; +char asc; + +switch (fnc) { /* case function */ +case IO_CONN: /* connect */ + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != lpt_dib.chan) return SCPE_IERR; /* wrong chan? */ + for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = 0; /* clr buffer */ + lpt_bptr = 0; /* clr buf ptr */ + lpt_err = 0; /* err = 0 */ + xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */ + lpt_sta = lpt_sta | SET_XFR; /* need xfr */ + sim_activate (&lpt_unit, lpt_ctime); /* start timer */ + break; + +case IO_EOM1: /* EOM mode 1 */ + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != lpt_dib.chan) CRETIOP; /* wrong chan? */ + if (inst & 0400) { /* space? */ + lpt_spc = inst; /* save instr */ + lpt_sta = lpt_sta | SET_SPC; /* need space */ + sim_cancel (&lpt_unit); /* cancel timer */ + sim_activate (&lpt_unit, lpt_stime); } /* start timer */ + break; + +case IO_DISC: /* disconnect */ + lpt_end_op (0); /* normal term */ + return lpt_bufout (&lpt_unit); /* dump output */ + +case IO_WREOR: /* write eor */ + lpt_sta = (lpt_sta | SET_EOR) & ~SET_XFR; /* need eor */ + sim_activate (&lpt_unit, lpt_ptime); /* start timer */ + break; + +case IO_SKS: /* SKS */ + new_ch = I_GETSKCH (inst); /* sks chan */ + if (new_ch != lpt_dib.chan) return SCPE_IERR; /* wrong chan? */ + t = I_GETSKCND (inst); /* sks cond */ + if (((t == 020) && (!CHP (7, lpt_cct[lpt_ccp]))) || /* 14062: !ch 7 */ + ((t == 010) && (lpt_unit.flags & UNIT_ATT)) || /* 12062: !online */ + (t == 004) && !lpt_err) *dat = 1; /* 11062: !err */ + break; + +case IO_WRITE: /* write */ + asc = sds_to_ascii[(*dat) & 077]; /* convert data */ + xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */ + if (lpt_bptr < LPT_WIDTH) lpt_buf[lpt_bptr++] = asc;/* store data */ + lpt_sta = lpt_sta | SET_XFR; /* need xfr */ + sim_activate (&lpt_unit, lpt_ctime); /* start ch timer */ + break; + +default: + CRETINS; } +return SCPE_OK; +} + +/* Unit service and write */ + +t_stat lpt_svc (UNIT *uptr) +{ +t_stat r = SCPE_OK; +static const char *lpt_stabl[] = { + "\r", "\n", "\n\n", "\n\n\n", + "\n\n\n\n", "\n\n\n\n\n", + "\n\n\n\n\n\n", "\n\n\n\n\n\n\n" }; + +if (lpt_sta & SET_XFR) chan_set_ordy (lpt_dib.chan); /* need lpt xfr? */ +if (lpt_sta & SET_EOR) { /* printing? */ + chan_set_flag (lpt_dib.chan, CHF_EOR); /* set eor flg */ + r = lpt_bufout (uptr); } /* output buf */ +if (lpt_sta & SET_SPC) { /* spacing? */ + if (uptr->flags & UNIT_ATT) { /* attached? */ + int32 ln = LPT_GETLN (lpt_spc); /* get lines, ch */ + if (lpt_spc & 0200) /* n lines? */ + fputs (lpt_stabl[ln], uptr->fileref); /* upspace */ + else lpt_crctl (ln); } /* carriage ctl */ + r = lpt_status (uptr); } /* update status */ +lpt_sta = 0; /* clear state */ +return r; +} + +/* Trim and output buffer */ + +t_stat lpt_bufout (UNIT *uptr) +{ +int32 i; + +if ((uptr->flags & UNIT_ATT) && lpt_bptr) { /* attached? */ + for (i = LPT_WIDTH - 1; (i >= 0) && (lpt_buf[i] == ' '); i--) + lpt_buf[i] = 0; /* trim line */ + fputs (lpt_buf, uptr->fileref); /* write line */ + lpt_bptr = 0; } +return lpt_status (uptr); /* return status */ +} + +/* Status update after I/O */ + +t_stat lpt_status (UNIT *uptr) +{ +if (uptr->flags & UNIT_ATT) { /* attached? */ + uptr->pos = ftell (uptr->fileref); /* update position */ + if (ferror (uptr->fileref)) { /* I/O error? */ + lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */ + perror ("LPT I/O error"); /* print msg */ + clearerr (uptr->fileref); + return SCPE_IOERR; } } /* ret error */ +else { + lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */ + CRETIOE (lpt_stopioe, SCPE_UNATT); } /* ret error */ +return SCPE_OK; +} + +/* Terminate LPT operation */ + +void lpt_end_op (int32 fl) +{ +if (fl) chan_set_flag (lpt_dib.chan, fl); /* set flags */ +xfr_req = xfr_req & ~XFR_LPT; /* clear xfr */ +sim_cancel (&lpt_unit); /* stop */ +if (fl & CHF_ERR) { /* error? */ + chan_disc (lpt_dib.chan); /* disconnect */ + lpt_err = 1; } /* set lpt err */ +return; +} + +/* Carriage control */ + +t_stat lpt_crctl (int32 ch) +{ +int32 i, j; + +if ((ch == 1) && CHP (ch, lpt_cct[0])) { /* top of form? */ + fputs ("\f\n", lpt_unit.fileref); /* ff + nl */ + lpt_ccp = 0; /* top of page */ + return SCPE_OK; } +for (i = 1; i < lpt_ccl + 1; i++) { /* sweep thru cct */ + lpt_ccp = (lpt_ccp + 1) %lpt_ccl; /* adv pointer */ + if (CHP (ch, lpt_cct[lpt_ccp])) { /* chan punched? */ + for (j = 0; j < i; j++) fputc ('\n', lpt_unit.fileref); + return SCPE_OK; } } +return STOP_CCT; /* runaway channel */ +} + +/* Reset routine */ + +t_stat lpt_reset (DEVICE *dptr) +{ +chan_disc (lpt_dib.chan); /* disconnect */ +lpt_spc = 0; /* clr state */ +lpt_sta = 0; +xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */ +sim_cancel (&lpt_unit); /* deactivate */ +return SCPE_OK; +} + +/* Attach routine */ + +t_stat lpt_attach (UNIT *uptr, char *cptr) +{ +lpt_ccp = 0; /* top of form */ +return attach_unit (uptr, cptr); +} diff --git a/SDS/sds_mt.c b/SDS/sds_mt.c new file mode 100644 index 00000000..34620952 --- /dev/null +++ b/SDS/sds_mt.c @@ -0,0 +1,489 @@ +/* sds_mt.c: SDS 940 magnetic tape simulator + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + mt 7 track magnetic tape + + Magnetic tapes are represented as a series of variable 8b records + of the form: + + 32b record length in bytes - exact number + byte 0 + byte 1 + : + byte n-2 + byte n-1 + 32b record length in bytes - exact number + + If the byte count is odd, the record is padded with an extra byte + of junk. File marks are represented by a single record length of 0. + End of tape is two consecutive end of file marks. +*/ + +#include "sds_defs.h" +#define MT_MAXFR (32768 * 4) +#define MT_NUMDR 8 /* number drives */ +#define MT_UNIT 07 +#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_WLK (1 << UNIT_V_WLK) +#define botf u3 /* bot tape flag */ +#define eotf u4 /* eot tape flag */ +#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ + +#define MTR_BOT 0xFFFFFFFE /* BOT pseudo mark */ + +extern uint32 xfr_req; +extern int32 stop_invins, stop_invdev, stop_inviop; +int32 mt_inst = 0; /* saved instr */ +int32 mt_eof = 0; /* end of file */ +int32 mt_gap = 0; /* in gap */ +int32 mt_skip = 0; /* skip rec */ +int32 mt_bptr = 0; /* buf ptr */ +int32 mt_blnt = 0; /* buf length */ +int32 mt_ctime = 10; /* char time */ +int32 mt_gtime = 1000; /* gap time */ +int32 mt_stopioe = 1; /* stop on err */ +uint8 mtxb[MT_MAXFR]; /* record buffer */ +DSPT mt_tplt[] = { /* template */ + { MT_NUMDR, 0 }, { MT_NUMDR, DEV_MTS }, + { MT_NUMDR, DEV_OUT }, { MT_NUMDR, DEV_MTS+DEV_OUT }, + { 0, 0 } }; + +DEVICE mt_dev; +t_stat mt_svc (UNIT *uptr); +t_stat mt_reset (DEVICE *dptr); +t_stat mt_boot (int32 unitno, DEVICE *dptr); +t_stat mt_attach (UNIT *uptr, char *cptr); +t_stat mt_detach (UNIT *uptr); +t_stat mt_readrec (UNIT *uptr); +t_mtrlnt mt_readbc (UNIT *uptr); +void mt_readend (UNIT *uptr); +t_stat mt_wrend (uint32 dev); +void mt_set_err (UNIT *uptr); +t_stat mt (uint32 fnc, uint32 inst, uint32 *dat); + +static const char sds_to_bcd[64] = { + 012, 001, 002, 003, 004, 005, 006, 007, + 010, 011, 012, 013, 014, 015, 016, 017, + 060, 061, 062, 063, 064, 065, 066, 067, + 070, 071, 072, 073, 074, 075, 076, 077, + 040, 041, 042, 043, 044, 045, 046, 047, + 050, 051, 052, 053, 054, 055, 056, 057, + 020, 021, 022, 023, 024, 025, 026, 027, + 030, 031, 032, 033, 034, 035, 036, 037 }; + +static const char bcd_to_sds[64] = { + 000, 001, 002, 003, 004, 005, 006, 007, + 010, 011, 000, 013, 014, 015, 016, 017, + 060, 061, 062, 063, 064, 065, 066, 067, + 070, 071, 072, 073, 074, 075, 076, 077, + 040, 041, 042, 043, 044, 045, 046, 047, + 050, 051, 052, 053, 054, 055, 056, 057, + 020, 021, 022, 023, 024, 025, 026, 027, + 030, 031, 032, 033, 034, 035, 036, 037 }; + +/* MT data structures + + mt_dev MT device descriptor + mt_unit MT unit descriptor + mt_reg MT register list +*/ + +DIB mt_dib = { CHAN_W, DEV_MT, XFR_MT0, mt_tplt, &mt }; + +UNIT mt_unit[] = { + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } }; + +REG mt_reg[] = { + { BRDATA (BUF, mtxb, 8, 8, MT_MAXFR) }, + { DRDATA (BPTR, mt_bptr, 18), PV_LEFT }, + { DRDATA (BLNT, mt_blnt, 18), PV_LEFT }, + { FLDATA (XFR, xfr_req, XFR_V_MT0) }, + { ORDATA (INST, mt_inst, 24) }, + { FLDATA (EOF, mt_eof, 0) }, + { FLDATA (GAP, mt_gap, 0) }, + { FLDATA (SKIP, mt_skip, 0) }, + { DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT }, + { DRDATA (GTIME, mt_gtime, 24), REG_NZ + PV_LEFT }, + { URDATA (POS, mt_unit[0].pos, 10, 32, 0, + MT_NUMDR, PV_LEFT | REG_RO) }, + { URDATA (BOT, mt_unit[0].botf, 10, 1, 0, MT_NUMDR, REG_RO) }, + { URDATA (EOT, mt_unit[0].eotf, 10, 1, 0, MT_NUMDR, REG_RO) }, + { FLDATA (STOP_IOE, mt_stopioe, 0) }, + { NULL } }; + +MTAB mt_mod[] = { + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", + &set_chan, &show_chan, NULL }, + { 0 } }; + +DEVICE mt_dev = { + "MT", mt_unit, mt_reg, mt_mod, + MT_NUMDR, 10, 31, 1, 8, 8, + NULL, NULL, &mt_reset, + &mt_boot, &mt_attach, NULL, + &mt_dib, DEV_DISABLE }; + +/* Mag tape routine + + conn - inst = EOM0, dat = NULL + eom1 - inst = EOM1, dat = NULL + sks - inst = SKS, dat = ptr to result + disc - inst = device number, dat = NULL + wreor - inst = device number, dat = NULL + read - inst = device number, dat = ptr to data + write - inst = device number, dat = ptr to result +*/ + +t_stat mt (uint32 fnc, uint32 inst, uint32 *dat) +{ +int32 u = inst & MT_UNIT; /* get unit */ +UNIT *uptr = mt_dev.units + u; /* get unit ptr */ +int32 t, new_ch; +uint8 chr; +t_stat r; + +switch (fnc) { /* case function */ +case IO_CONN: /* connect */ + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */ + if (mt_gap) { /* in gap? */ + mt_gap = 0; /* clr gap flg */ + sim_cancel (uptr); } /* cancel timer */ + else if (sim_is_active (uptr)) CRETIOP; /* busy? */ + uptr->eotf = 0; /* clr eot flag */ + mt_eof = 0; /* clr eof flag */ + mt_skip = 0; /* clr skp flag */ + mt_bptr = mt_blnt = 0; /* init buffer */ + if ((inst & DEV_MTS)? (CHC_GETCPW (inst) < 2): /* scn & cpw<3? */ + (inst & CHC_REV)) return STOP_INVIOP; /* rw & rev? */ + mt_inst = inst; /* save inst */ + if ((inst & DEV_MTS) && !(inst && DEV_OUT)) /* scanning? */ + chan_set_flag (mt_dib.chan, CHF_SCAN); /* set chan flg */ + xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */ + sim_activate (uptr, mt_gtime); /* start timer */ + break; + +case IO_EOM1: /* EOM mode 1 */ + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != mt_dib.chan) CRETIOP; /* wrong chan? */ + t = inst & 07670; /* get command */ + if ((t == 04010) && !sim_is_active (uptr)) { /* rewind? */ + uptr->pos = uptr->eotf = 0; /* clr pos, eot */ + uptr->botf = 1; } /* set bot */ + else if ((t == 03610) && sim_is_active (uptr) && /* skip rec? */ + ((mt_inst & DEV_OUT) == 0)) mt_skip = 1; /* set flag */ + else CRETINS; + break; + +case IO_DISC: /* disconnect */ + sim_cancel (uptr); /* no more xfr's */ + if (inst & DEV_OUT) { /* write? */ + if (r = mt_wrend (inst)) return r; } /* end record */ + break; + +case IO_WREOR: /* write eor */ + chan_set_flag (mt_dib.chan, CHF_EOR); /* set eor flg */ + if (r = mt_wrend (inst)) return r; /* end record */ + mt_gap = 1; /* in gap */ + sim_activate (uptr, mt_gtime); /* start timer */ + break; + +case IO_SKS: /* SKS */ + new_ch = I_GETSKCH (inst); /* get chan # */ + if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */ + if ((inst & (DEV_OUT | DEV_MTS)) == 0) { /* not sks 1n? */ + t = I_GETSKCND (inst); /* get skip cond */ + switch (t) { /* case sks cond */ + case 001: /* sks 1021n */ + *dat = 1; /* not magpak */ + break; + case 002: /* sks 1041n */ + if (!(uptr->flags & UNIT_ATT) || /* not ready */ + sim_is_active (uptr)) *dat = 1; + break; + case 004: /* sks 1101n */ + if (!uptr->eotf) *dat = 1; /* not EOT */ + break; + case 010: /* sks 1201n */ + if (!uptr->botf) *dat = 1; /* not BOT */ + break; + case 013: /* sks 12610 */ + if (!mt_gap) *dat = 1; /* not in gap */ + break; + case 017: /* sks 13610 */ + if (!mt_eof) *dat = 1; /* not EOF */ + break; + case 020: /* sks 1401n */ + if (!(uptr->flags & UNIT_WPRT)) *dat = 1; /* not wrp */ + break; + case 031: /* sks 1621n */ + case 033: /* sks 1661n */ + *dat = 1; /* not 556bpi */ + case 035: /* sks 1721n */ + break; } /* not 800bpi */ + } /* end if */ + break; + +case IO_READ: /* read */ + xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */ + if (mt_blnt == 0) { /* first read? */ + r = mt_readrec (uptr); /* get data */ + if ((r != SCPE_OK) || (mt_blnt == 0)) return r; } /* err, inv reclnt? */ + uptr->botf = 0; /* off BOT */ + if (mt_inst & CHC_REV) chr = mtxb[--mt_bptr] & 077; /* get next rev */ + else chr = mtxb[mt_bptr++] & 077; /* get next fwd */ + if (!(mt_inst & CHC_BIN)) chr = bcd_to_sds[chr]; /* bcd? */ + *dat = chr & 077; /* give to chan */ + if ((mt_inst & CHC_REV)? (mt_bptr <= 0): /* rev or fwd, */ + (mt_bptr >= mt_blnt)) mt_readend (uptr); /* recd done? */ + break; + +case IO_WRITE: /* write */ + uptr->botf = 0; /* off BOT */ + chr = (*dat) & 077; + xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */ + if (!(mt_inst & CHC_BIN)) chr = sds_to_bcd[chr]; /* bcd? */ + if (mt_bptr < MT_MAXFR) mtxb[mt_bptr++] = chr; /* insert in buf */ + break; + +default: + CRETINS; } + +return SCPE_OK; +} + +/* Unit service */ + +t_stat mt_svc (UNIT *uptr) +{ +if (mt_gap) { /* gap timeout */ + mt_gap = 0; /* clr gap flg */ + chan_disc (mt_dib.chan); } /* disc chan */ +else if (mt_skip) mt_readend (uptr); /* skip record */ +else { /* normal xfr */ + xfr_req = xfr_req | XFR_MT0; /* set xfr req */ + sim_activate (uptr, mt_ctime); } /* reactivate */ +return SCPE_OK; +} + +/* Read start (get new record) */ + +t_stat mt_readrec (UNIT *uptr) +{ +t_mtrlnt abc, tbc; + +if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ + mt_set_err (uptr); /* no, err, disc */ + return SCPE_UNATT; } +tbc = mt_readbc (uptr); /* get bc */ +if (tbc == MTR_EOM) { /* end of med? */ + uptr->eotf = 1; /* end of tape */ + mt_set_err (uptr); /* err, disc */ + return SCPE_OK; } +if (tbc == MTR_BOT) { /* BOT? */ + mt_set_err (uptr); /* err, disc */ + return SCPE_OK; } +if (tbc == MTR_TMK) { /* tape mark? */ + mt_eof = 1; /* set eof flag */ + mtxb[0] = mtxb[1] = 017; /* EOR char */ + mt_blnt = 2; /* store 2 */ + uptr->pos += sizeof (t_mtrlnt); /* update position */ + return SCPE_OK; } +mt_blnt = tbc; /* set buf lnt */ +if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */ +if (mt_inst & CHC_REV) { /* reverse? */ + fseek (uptr->fileref, uptr->pos - ((tbc + 1) & ~1) - sizeof (t_mtrlnt), SEEK_SET); + mt_bptr = mt_blnt; } +abc = fxread (mtxb, sizeof (uint8), tbc, uptr->fileref);/* read record */ +for (; abc < tbc; abc++) mtxb[abc] = 0; /* zero fill */ +if (ferror (uptr->fileref)) { /* I/O error */ + mt_set_err (uptr); /* no, err, disc */ + perror ("MT I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; } +if (mt_inst & CHC_REV) /* update pos */ + uptr->pos -= (((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt))); +else uptr->pos += (((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt))); +return SCPE_OK; +} + +/* Read record byte count */ + +t_mtrlnt mt_readbc (UNIT *uptr) +{ +t_mtrlnt tbc; + +if (mt_inst & CHC_REV) { + if (uptr->pos < sizeof (t_mtrlnt)) { + uptr->botf = 1; + return MTR_BOT; } + fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET); } +else fseek (uptr->fileref, uptr->pos, SEEK_SET); +fxread (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref); +if (ferror (uptr->fileref) || feof (uptr->fileref) || /* err, eof, eom? */ + (tbc == MTR_EOM)) return MTR_EOM; /* return EOM */ +if (MTRF (tbc)) chan_set_flag (mt_dib.chan, CHF_ERR); /* rec err? set flag */ +return MTRL (tbc); +} + +/* Read done (eof, end of record) */ + +void mt_readend (UNIT *uptr) +{ +sim_cancel (uptr); /* stop timer */ +mt_skip = 0; /* clr skp flg */ +chan_set_flag (mt_dib.chan, CHF_EOR); /* end record */ +if (mt_eof) chan_disc (mt_dib.chan); /* EOF? */ +else { + mt_gap = 1; /* no, in gap */ + sim_activate (uptr, mt_gtime); } /* start timer */ +return; +} + +/* Write complete (end of record or disconnect) */ + +t_stat mt_wrend (uint32 dev) +{ +static t_mtrlnt bceom = MTR_EOM; +static t_mtrlnt bceof = MTR_TMK; +UNIT *uptr = mt_dev.units + (dev & MT_UNIT); +t_addr old_pos = uptr->pos; +t_mtrlnt tbc; + +sim_cancel (uptr); /* no more xfr's */ +if (mt_bptr == 0) return SCPE_OK; /* buf empty? */ +if (!(uptr->flags & UNIT_ATT)) { /* attached? */ + mt_set_err (uptr); /* no, err, disc */ + return SCPE_UNATT; } +if (uptr->flags & UNIT_WPRT) { /* write lock? */ + mt_set_err (uptr); /* yes, err, disc */ + return SCPE_OK; } +if (dev & DEV_MTS) { /* erase? */ + if (mt_inst & CHC_REV) { /* reverse? */ + tbc = mt_readbc (uptr); /* get bc */ + if ((tbc == MTR_TMK) || (tbc == MTR_EOM)) /* tmk, eom? */ + fseek (uptr->fileref, uptr->pos -= sizeof (t_mtrlnt), SEEK_SET); + else if (tbc != MTR_BOT) { /* not BOT? */ + tbc = MTRL (tbc); /* clear error */ + fseek (uptr->fileref, uptr->pos -= + (((tbc + 1) & ~1) - sizeof (t_mtrlnt)), SEEK_SET); } } + fxwrite (&bceom, sizeof (t_mtrlnt), 1, uptr->fileref); + } +else { + fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set position */ + if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */ + ((mt_inst & 01670) == 00050)) { + fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref); + uptr->pos += sizeof (t_mtrlnt); } + else { /* normal wr */ + fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref); + fxwrite (mtxb, sizeof (uint8), (mt_bptr + 1) & ~1, uptr->fileref); + fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref); + uptr->pos += ((mt_bptr + 1) & ~1) + (2 * sizeof (t_mtrlnt)); + } + } +mt_bptr = 0; +if (ferror (uptr->fileref)) { /* I/O error */ + uptr->pos = old_pos; /* restore pos */ + mt_set_err (uptr); /* no, err, disc */ + perror ("MT I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; } +return SCPE_OK; +} + +/* Fatal error */ + +void mt_set_err (UNIT *uptr) +{ +chan_set_flag (mt_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */ +chan_disc (mt_dib.chan); /* disconnect */ +xfr_req = xfr_req & ~XFR_MT0; /* clear xfr */ +sim_cancel (uptr); /* stop */ +mt_bptr = 0; /* buf empty */ +return; +} +/* Reset routine */ + +t_stat mt_reset (DEVICE *dptr) +{ +int32 i; + +chan_disc (mt_dib.chan); /* disconnect */ +mt_eof = 0; /* clear state */ +mt_gap = 0; +mt_skip = 0; +mt_inst = 0; +mt_bptr = mt_blnt = 0; +xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */ +for (i = 0; i < MT_NUMDR; i++) { /* deactivate */ + sim_cancel (&mt_unit[i]); + mt_unit[i].eotf = 0; } +return SCPE_OK; +} + +/* Attach and detach routines */ + +t_stat mt_attach (UNIT *uptr, char *cptr) +{ +t_stat r; + +r = attach_unit (uptr, cptr); +if (r != SCPE_OK) return r; +uptr->botf = 1; +uptr->eotf = 0; +return SCPE_OK; +} + +t_stat mt_detach (UNIT *uptr) +{ +uptr->botf = uptr->eotf = 0; +return detach_unit (uptr); +} + +/* Boot routine - simulate FILL console command */ + +t_stat mt_boot (int32 unitno, DEVICE *dptr) +{ +extern uint32 P, M[]; + +if (unitno) return SCPE_ARG; /* only unit 0 */ +M[0] = 077777771; /* -7B */ +M[1] = 007100000; /* LDX 0 */ +M[2] = 000203610; /* EOM 3610B */ +M[3] = 003200002; /* WIM 2 */ +M[4] = 000100002; /* BRU 2 */ +P = 1; /* start at 1 */ +return SCPE_OK; +} diff --git a/SDS/sds_mux.c b/SDS/sds_mux.c new file mode 100644 index 00000000..32253a36 --- /dev/null +++ b/SDS/sds_mux.c @@ -0,0 +1,504 @@ +/* sds_mux.c: SDS 940 terminal multiplexor simulator + + Copyright (c) 2001-2002, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + mux terminal multiplexor + + This module implements up to 32 individual serial interfaces, representing + either the project Genie terminal multiplexor or the SDS 940 CTE option. +*/ + +#include "sds_defs.h" +#include "sim_sock.h" +#include "sim_tmxr.h" +#include + +#define PROJ_GENIE (cpu_unit.flags & UNIT_GENIE) +#define MUX_NUMLIN mux_desc.lines + +#define MUX_LINES 32 /* lines */ +#define MUX_FLAGS 4 /* intr per line */ +#define MUX_FLAGMASK (MUX_FLAGS - 1) +#define MUX_SCANMAX (MUX_LINES * MUX_FLAGS) /* flags to scan */ +#define MUX_SCANMASK (MUX_SCANMAX - 1) +#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */ +#define UNIT_UC (1 << UNIT_V_UC) +#define MUX_INIT_POLL 8000 +#define MUXL_WAIT 500 +#define MUX_SETFLG(l,x) mux_flags[((l) * MUX_FLAGS) + (x)] = 1 +#define MUX_SETINT(x) int_req = int_req | (INT_MUXR >> (x)) +#define MUX_CLRINT(x) int_req = int_req & ~(INT_MUXR >> (x)) + +/* PIN/POT */ + +#define P_V_CHAR 16 /* char */ +#define P_M_CHAR 0377 +#define P_CHAR(x) (((x) >> P_V_CHAR) & P_M_CHAR) +#define PIN_OVR 000100000 /* overrun */ +#define POT_NOX 000100000 /* no xmit */ +#define POT_XMI 000040000 /* xmit int */ +#define POT_GLNE 000020000 /* Genie: enable */ +#define POT_SCDT 000020000 /* 940: clr DTR */ +#define P_V_CHAN 0 /* channel */ +#define P_M_CHAN (MUX_LINES - 1) +#define P_CHAN(x) (((x) >> P_V_CHAN) & P_M_CHAN) + +/* SKS 940 */ + +#define SKS_XBE 000001000 /* xmt buf empty */ +#define SKS_CRO 000000400 /* carrier on */ +#define SKS_DSR 000000200 /* data set ready */ +#define SKS_CHAN(x) P_CHAN(x) + +/* SKS Genie */ + +#define SKG_V_CHAN 7 +#define SKG_M_CHAN (MUX_LINES - 1) +#define SKG_CHAN(x) (((x) >> SKG_V_CHAN) & SKG_M_CHAN) + +/* Flags */ + +#define MUX_FRCV 0 /* receive */ +#define MUX_FXMT 1 /* transmit */ +#define MUX_FCRN 2 /* carrier on */ +#define MUX_FCRF 3 /* carrier off */ + +/* Line status */ + +#define MUX_SCHP 001 /* char pending */ +#define MUX_SOVR 002 /* overrun */ +#define MUX_SLNE 004 /* line enabled */ +#define MUX_SXIE 010 /* xmt int enab */ +#define MUX_SCRO 020 /* carrier on */ +#define MUX_SDSR 040 /* data set ready */ + +/* Data */ +extern uint32 alert, int_req; +extern int32 stop_invins, stop_invdev, stop_inviop; +extern UNIT cpu_unit; + +uint8 mux_rbuf[MUX_LINES]; /* rcv buf */ +uint8 mux_xbuf[MUX_LINES]; /* xmt buf */ +uint8 mux_sta[MUX_LINES]; /* status */ +uint8 mux_flags[MUX_SCANMAX]; /* flags */ +uint32 mux_tps = 100; /* polls/second */ +uint32 mux_scan = 0; /* scanner */ +uint32 mux_slck = 0; /* scanner locked */ + +TMLN mux_ldsc[MUX_LINES] = { 0 }; /* line descriptors */ +TMXR mux_desc = { MUX_LINES, 0, 0, NULL }; /* mux descriptor */ + +t_stat mux (uint32 fnc, uint32 inst, uint32 *dat); +t_stat muxi_svc (UNIT *uptr); +t_stat muxo_svc (UNIT *uptr); +t_stat mux_reset (DEVICE *dptr); +t_stat mux_attach (UNIT *uptr, char *cptr); +t_stat mux_detach (UNIT *uptr); +t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat mux_vlines (UNIT *uptr, int32 val, char *cptr, void *desc); +void mux_reset_ln (int32 ln); +void mux_scan_next (void); + +/* MUX data structures + + mux_dev MUX device descriptor + mux_unit MUX unit descriptor + mux_reg MUX register list + mux_mod MUX modifiers list +*/ + +DIB mux_dib = { -1, DEV3_GMUX, 0, NULL, &mux }; + +REG mux_nlreg = { DRDATA (NLINES, MUX_NUMLIN, 6), PV_LEFT }; + +UNIT mux_unit = { UDATA (&muxi_svc, UNIT_ATTABLE, 0), MUX_INIT_POLL }; + +REG mux_reg[] = { + { BRDATA (STA, mux_sta, 8, 6, MUX_LINES) }, + { BRDATA (RBUF, mux_rbuf, 8, 8, MUX_LINES) }, + { BRDATA (XBUF, mux_xbuf, 8, 8, MUX_LINES) }, + { BRDATA (INT, mux_flags, 8, 1, MUX_SCANMAX) }, + { ORDATA (SCAN, mux_scan, 7) }, + { FLDATA (SLCK, mux_slck, 0) }, + { DRDATA (TPS, mux_tps, 8), REG_NZ + PV_LEFT }, + { NULL } }; + +MTAB mux_mod[] = { + { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", + &mux_vlines, NULL, &mux_nlreg }, + { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &mux_desc }, + { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &mux_summ }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, + NULL, &mux_show, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, + NULL, &mux_show, NULL }, + { 0 } }; + +DEVICE mux_dev = { + "MUX", &mux_unit, mux_reg, mux_mod, + 1, 10, 31, 1, 8, 8, + &tmxr_ex, &tmxr_dep, &mux_reset, + NULL, &mux_attach, &mux_detach, + &mux_dib, DEV_DISABLE }; + +/* MUXL data structures + + muxl_dev MUXL device descriptor + muxl_unit MUXL unit descriptor + muxl_reg MUXL register list + muxl_mod MUXL modifiers list +*/ + +UNIT muxl_unit[] = { + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT } }; + +MTAB muxl_mod[] = { + { UNIT_UC, 0, "lower case", "LC", NULL }, + { UNIT_UC, UNIT_UC, "upper case", "UC", NULL }, + { 0 } }; + +REG muxl_reg[] = { + { URDATA (TIME, muxl_unit[0].wait, 10, 24, 0, + MUX_LINES, REG_NZ + PV_LEFT) }, + { NULL } }; + +DEVICE muxl_dev = { + "MUXL", muxl_unit, muxl_reg, muxl_mod, + MUX_LINES, 10, 31, 1, 8, 8, + NULL, NULL, &mux_reset, + NULL, NULL, NULL, + NULL, 0 }; + +/* MUX: IO routine */ + +/* Mux routine - EOM 30001 or EOM 77777,2 */ + +t_stat mux (uint32 fnc, uint32 inst, uint32 *dat) +{ +uint32 ln; + +switch (fnc) { +case IO_CONN: /* connect */ + if ((PROJ_GENIE && (inst == 000230001)) || /* set alert */ + (!PROJ_GENIE && (inst == 020277777))) alert = POT_MUX; + else CRETINS; + break; +case IO_SKS: /* skip */ + if (PROJ_GENIE && ((inst & 077770077) == 004030001)) { + ln = SKG_CHAN (inst); /* get line */ + if (!sim_is_active (&muxl_unit[ln])) *dat = 1; } + else if (!PROJ_GENIE && ((inst & 077776000) == 024076000)) { + ln = SKS_CHAN (inst); /* get line */ + if (inst & (SKS_XBE|SKS_CRO|SKS_DSR)) *dat = 1; + if (((inst & SKS_XBE) && sim_is_active (&muxl_unit[ln])) || + ((inst & SKS_CRO) && !(mux_sta[ln] & MUX_SCRO)) || + ((inst & SKS_DSR) && !(mux_sta[ln] & MUX_SDSR))) + *dat = 0; } /* no skip if fail */ + else CRETINS; +default: + return SCPE_IERR; } /* end case */ +return SCPE_OK; +} + +/* PIN routine */ + +t_stat pin_mux (uint32 num, uint32 *dat) +{ +uint32 ln = mux_scan >> 2; +uint32 flag = mux_scan & MUX_FLAGMASK; + +mux_scan = mux_scan & MUX_SCANMASK; /* mask scan */ +mux_flags[mux_scan] = 0; /* clear flag */ +if (flag == MUX_FRCV) { /* rcv event? */ + *dat = ln | ((uint32) mux_rbuf[ln] << P_V_CHAR) | /* line + char + */ + ((mux_sta[ln] & MUX_SOVR)? PIN_OVR: 0); /* overrun */ + mux_sta[ln] = mux_sta[ln] & ~(MUX_SCHP | MUX_SOVR); } +else *dat = ln; /* just line */ +mux_slck = 0; /* unlock scanner */ +mux_scan_next (); /* kick scanner */ +return SCPE_OK; +} + +t_stat pot_mux (uint32 num, uint32 *dat) +{ +uint32 ln = P_CHAN (*dat); +uint32 chr = P_CHAR (*dat); + +if (PROJ_GENIE && ((*dat & POT_GLNE) == 0)) { /* Genie disable? */ + mux_sta[ln] = mux_sta[ln] & ~MUX_SLNE; /* clear status */ + mux_ldsc[ln].rcve = 0; } +else if (!PROJ_GENIE && (*dat & POT_SCDT)) { /* SDS disable? */ + if (mux_ldsc[ln].conn) { /* connected? */ + tmxr_msg (mux_ldsc[ln].conn, "\r\nLine hangup\r\n"); + tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */ + mux_reset_ln (ln); /* reset state */ + MUX_SETFLG (ln, MUX_FCRF); /* set carrier off */ + mux_scan_next (); } /* kick scanner */ + mux_sta[ln] = mux_sta[ln] & ~MUX_SLNE; /* clear status */ + mux_ldsc[ln].rcve = 0; } +else { /* enabled */ + if ((*dat & POT_NOX) == 0) { /* output char? */ + mux_xbuf[ln] = chr; /* store char */ + sim_activate (&muxl_unit[ln], muxl_unit[ln].wait); } + if (*dat & POT_XMI) mux_sta[ln] = mux_sta[ln] | MUX_SXIE; + else mux_sta[ln] = mux_sta[ln] & ~MUX_SXIE; + mux_sta[ln] = mux_sta[ln] | MUX_SLNE; /* line is enabled */ + mux_ldsc[ln].rcve = 1; } +return SCPE_OK; +} + +/* Unit service - receive side + + Poll all active lines for input + Poll for new connections +*/ + +t_stat muxi_svc (UNIT *uptr) +{ +int32 ln, c, t; + +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +t = sim_rtcn_calb (mux_tps, TMR_MUX); /* calibrate */ +sim_activate (uptr, t); /* continue poll */ +ln = tmxr_poll_conn (&mux_desc); /* look for connect */ +if (ln >= 0) { /* got one? */ + if (!PROJ_GENIE && (mux_sta[ln] & MUX_SLNE)) { /* modem & DTR? */ + mux_sta[ln] = mux_sta[ln] | (MUX_SCRO|MUX_SDSR);/* carrier on */ + MUX_SETFLG (ln, MUX_FCRN); /* set carr on flag */ + mux_scan_next (); } /* kick scanner */ + mux_ldsc[ln].rcve = 1; } /* set rcv enable */ +tmxr_poll_rx (&mux_desc); /* poll for input */ +for (ln = 0; ln < MUX_NUMLIN; ln++) { /* loop thru lines */ + if (mux_ldsc[ln].conn) { /* connected? */ + if (c = tmxr_getc_ln (&mux_ldsc[ln])) { /* get char */ + if (mux_sta[ln] & MUX_SCHP) /* already got one? */ + mux_sta[ln] = mux_sta[ln] | MUX_SOVR; /* overrun */ + else mux_sta[ln] = mux_sta[ln] | MUX_SCHP; /* char pending */ + c = c & 0177; /* mask to 7b */ + if ((muxl_unit[ln].flags & UNIT_UC) && /* cvt to UC? */ + islower (c & 0x7F)) c = toupper (c); + mux_rbuf[ln] = c; /* save char */ + MUX_SETFLG (ln, MUX_FRCV); /* set rcv flag */ + mux_scan_next (); } } /* kick scanner */ + else mux_sta[ln] = 0; /* disconnected */ + } /* end for */ +return SCPE_OK; +} + +/* Unit service - transmit side */ + +t_stat muxo_svc (UNIT *uptr) +{ +int32 c; +uint32 ln = uptr - muxl_unit; /* line # */ + +if (mux_ldsc[ln].conn) { /* connected? */ + if (mux_ldsc[ln].xmte) { /* xmt enabled? */ + c = mux_xbuf[ln] & 0177; /* get char */ + if ((muxl_unit[ln].flags & UNIT_UC) && islower (c)) + c = toupper (c); /* cvt to UC? */ + tmxr_putc_ln (&mux_ldsc[ln], c); /* output char */ + tmxr_poll_tx (&mux_desc); } /* poll xmt */ + else { /* buf full */ + tmxr_poll_tx (&mux_desc); /* poll xmt */ + sim_activate (uptr, muxl_unit[ln].wait); /* wait */ + return SCPE_OK; } } +if (mux_sta[ln] & MUX_SXIE) { + MUX_SETFLG (ln, MUX_FXMT); /* set flag */ + mux_scan_next (); } /* kick scanner */ +return SCPE_OK; +} + +/* Kick scanner */ + +void mux_scan_next (void) +{ +int32 i; + +if (mux_slck) return; /* locked? */ +for (i = 0; i < MUX_SCANMAX; i++) { /* scan flags */ + mux_scan = (mux_scan + 1) & MUX_SCANMASK; /* next flag */ + if (mux_flags[mux_scan]) { /* flag set? */ + mux_slck = 1; /* lock scanner */ + MUX_SETINT (mux_scan & MUX_FLAGMASK); /* request int */ + return; } + } +return; +} + +/* Reset routine */ + +t_stat mux_reset (DEVICE *dptr) +{ +int32 i, t; + +if (mux_dev.flags & DEV_DIS) /* master disabled? */ + muxl_dev.flags = muxl_dev.flags | DEV_DIS; /* disable lines */ +else muxl_dev.flags = muxl_dev.flags & ~DEV_DIS; +if (mux_unit.flags & UNIT_ATT) { /* master att? */ + if (!sim_is_active (&mux_unit)) { + t = sim_rtcn_init (mux_unit.wait, TMR_MUX); + sim_activate (&mux_unit, t); } } /* activate */ +else sim_cancel (&mux_unit); /* else stop */ +for (i = 0; i < MUX_LINES; i++) { + mux_desc.ldsc[i] = &mux_ldsc[i]; + mux_reset_ln (i); } +for (i = 0; i < MUX_FLAGS; i++) MUX_CLRINT (i); /* clear all ints */ +return SCPE_OK; +} + +/* Attach master unit */ + +t_stat mux_attach (UNIT *uptr, char *cptr) +{ +t_stat r; +int32 t; + +r = tmxr_attach (&mux_desc, uptr, cptr); /* attach */ +if (r != SCPE_OK) return r; /* error */ +t = sim_rtcn_init (mux_unit.wait, TMR_MUX); +sim_activate (uptr, t); /* start poll */ +return SCPE_OK; +} + +/* Detach master unit */ + +t_stat mux_detach (UNIT *uptr) +{ +int32 i; +t_stat r; + +r = tmxr_detach (&mux_desc, uptr); /* detach */ +for (i = 0; i < MUX_LINES; i++) mux_ldsc[i].rcve = 0; /* disable rcv */ +sim_cancel (uptr); /* stop poll */ +return r; +} + +/* Show summary processor */ + +t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +int32 i, t; + +for (i = t = 0; i < MUX_LINES; i++) t = t + (mux_ldsc[i].conn != 0); +if (t == 1) fprintf (st, "1 connection"); +else fprintf (st, "%d connections", t); +return SCPE_OK; +} + +/* SHOW CONN/STAT processor */ + +t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +int32 i; + +for (i = 0; (i < MUX_LINES) && (mux_ldsc[i].conn == 0); i++) ; +if (i < MUX_LINES) { + for (i = 0; i < MUX_LINES; i++) { + if (mux_ldsc[i].conn) + if (val) tmxr_fconns (st, &mux_ldsc[i], i); + else tmxr_fstats (st, &mux_ldsc[i], i); } } +else fprintf (st, "all disconnected\n"); +return SCPE_OK; +} + +/* Change number of lines */ + +t_stat mux_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 newln, i, t; +t_stat r; + +if (cptr == NULL) return SCPE_ARG; +newln = get_uint (cptr, 10, MUX_LINES, &r); +if ((r != SCPE_OK) || (newln == MUX_NUMLIN)) return r; +if (newln == 0) return SCPE_ARG; +if (newln < MUX_NUMLIN) { + for (i = newln, t = 0; i < MUX_NUMLIN; i++) t = t | mux_ldsc[i].conn; + if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) + return SCPE_OK; + for (i = newln; i < MUX_NUMLIN; i++) { + if (mux_ldsc[i].conn) { + tmxr_msg (mux_ldsc[i].conn, "\r\nOperator disconnected line\r\n"); + tmxr_reset_ln (&mux_ldsc[i]); } /* reset line */ + muxl_unit[i].flags = muxl_unit[i].flags | UNIT_DIS; + mux_reset_ln (i); } + } +else { + for (i = MUX_NUMLIN; i < newln; i++) { + muxl_unit[i].flags = muxl_unit[i].flags & ~UNIT_DIS; + mux_reset_ln (i); } + } +MUX_NUMLIN = newln; +return SCPE_OK; +} + +/* Reset an individual line */ + +void mux_reset_ln (int32 ln) +{ +int32 flg = ln * MUX_FLAGS; + +if (mux_ldsc[ln].conn) mux_sta[ln] = MUX_SCRO | MUX_SDSR; +else mux_sta[ln] = 0; +sim_cancel (&muxl_unit[ln]); +mux_flags[flg + MUX_FRCV] = 0; +mux_flags[flg + MUX_FXMT] = 0; +mux_flags[flg + MUX_FCRN] = 0; +mux_flags[flg + MUX_FCRF] = 0; +return; +} diff --git a/SDS/sds_rad.c b/SDS/sds_rad.c new file mode 100644 index 00000000..b1dc4125 --- /dev/null +++ b/SDS/sds_rad.c @@ -0,0 +1,290 @@ +/* sds_rad.c: SDS 940 fixed head disk simulator + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + rad fixed head disk + + The fixed head disk is a head-per-track disk, with up to four disks. Each + disk is divided into two logical units. Reads and writes cannot cross logical + unit boundaries. The fixed head disk transfers 12b characters, rather than 6b + characters. To minimize overhead, the disk is buffered in memory. +*/ + +#include "sds_defs.h" +#include + +/* Constants */ + +#define RAD_NUMWD 64 /* words/sector */ +#define RAD_NUMSC 64 /* sectors/track */ +#define RAD_NUMTR 64 /* tracks/log unit */ +#define RAD_NUMLU 8 /* log units/ctrl */ +#define RAD_SCSIZE (RAD_NUMLU*RAD_NUMTR*RAD_NUMSC) /* sectors/disk */ +#define RAD_AMASK (RAD_SCSIZE - 1) /* sec addr mask */ +#define RAD_SIZE (RAD_SCSIZE * RAD_NUMWD) /* words/disk */ +#define RAD_GETLUN(x) ((x) / (RAD_NUMTR * RAD_NUMSC)) +#define RAD_SCMASK (RAD_NUMSC - 1) /* sector mask */ +#define RAD_TRSCMASK ((RAD_NUMSC * RAD_NUMTR) - 1) /* track/sec mask */ + +#define GET_SECTOR(x) ((int) fmod (sim_gtime() / ((double) (x)), \ + ((double) RAD_NUMSC))) + +extern uint32 xfr_req; +extern uint32 alert; +extern int32 stop_invins, stop_invdev, stop_inviop; +int32 rad_err = 0; /* error */ +int32 rad_nobi = 0; /* !incr x track */ +int32 rad_da = 0; /* disk address */ +int32 rad_sba = 0; /* sec byte addr */ +int32 rad_wrp = 0; /* write prot */ +int32 rad_time = 2; /* time per 12b */ +int32 rad_stopioe = 1; /* stop on error */ +DSPT rad_tplt[] = { /* template */ + { 1, 0 }, { 1, DEV_OUT }, { 0, 0 } }; + +DEVICE rad_dev; +t_stat rad_svc (UNIT *uptr); +t_stat rad_reset (DEVICE *dptr); +t_stat rad_fill (int32 sba); +void rad_end_op (int32 fl); +int32 rad_adjda (int32 sba, int32 inc); +t_stat rad (uint32 fnc, uint32 inst, uint32 *dat); + +/* RAD data structures + + rad_dev device descriptor + rad_unit unit descriptor + rad_reg register list +*/ + +DIB rad_dib = { CHAN_E, DEV_RAD, XFR_RAD, rad_tplt, &rad }; + +UNIT rad_unit = + { UDATA (&rad_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, + RAD_SIZE) }; + +REG rad_reg[] = { + { ORDATA (DA, rad_da, 15) }, + { GRDATA (SA, rad_sba, 8, 6, 1) }, + { FLDATA (BP, rad_sba, 0) }, + { FLDATA (XFR, xfr_req, XFR_V_RAD) }, + { FLDATA (NOBD, rad_nobi, 0) }, + { FLDATA (ERR, rad_err, 0) }, + { ORDATA (PROT, rad_wrp, 8) }, + { DRDATA (TIME, rad_time, 24), REG_NZ + PV_LEFT }, + { FLDATA (STOP_IOE, rad_stopioe, 0) }, + { NULL } }; + +MTAB rad_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", + &set_chan, &show_chan, NULL }, + { 0 } }; + +DEVICE rad_dev = { + "RAD", &rad_unit, rad_reg, rad_mod, + 1, 8, 21, 1, 8, 24, + NULL, NULL, &rad_reset, + NULL, NULL, NULL, + &rad_dib, DEV_DISABLE }; + +/* Fixed head disk routine + + conn - inst = EOM0, dat = NULL + eom1 - inst = EOM1, dat = NULL + sks - inst = SKS, dat = ptr to result + disc - inst = device number, dat = NULL + wreor - inst = device number, dat = NULL + read - inst = device number, dat = ptr to data + write - inst = device number, dat = ptr to result +*/ + +t_stat rad (uint32 fnc, uint32 inst, uint32 *dat) +{ +int32 t, lun, new_ch; +uint32 *wptr; +t_addr p; + +switch (fnc) { /* case function */ +case IO_CONN: /* connect */ + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */ + if (CHC_GETCPW (inst) > 1) return STOP_INVIOP; /* 1-2 char/word? */ + if (sim_is_active (&rad_unit) || (alert == POT_RADA)) /* protocol viol? */ + return STOP_INVIOP; + rad_err = 0; /* clr error */ + rad_sba = 0; /* clr sec bptr */ + chan_set_flag (rad_dib.chan, CHF_12B); /* 12B mode */ + t = (rad_da & RAD_SCMASK) - GET_SECTOR (rad_time * RAD_NUMWD); + if (t <= 0) t = t + RAD_NUMSC; /* seek */ + sim_activate (&rad_unit, t * rad_time * (RAD_NUMWD / 2)); + xfr_req = xfr_req & ~XFR_RAD; /* clr xfr flg */ + break; + +case IO_EOM1: /* EOM mode 1 */ + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */ + if ((inst & 00600) == 00200) alert = POT_RADS; /* alert for sec */ + else if ((inst & 06600) == 0) { /* alert for addr */ + if (sim_is_active (&rad_unit)) rad_err = 1; /* busy? */ + else { + rad_nobi = (inst & 01000)? 1: 0; /* save inc type */ + alert = POT_RADA; } } /* set alert */ + break; + +case IO_DISC: /* disconnect */ + rad_end_op (0); /* normal term */ + if (inst & DEV_OUT) return rad_fill (rad_sba); /* fill write */ + break; + +case IO_WREOR: /* write eor */ + rad_end_op (CHF_EOR); /* eor term */ + return rad_fill (rad_sba); /* fill write */ + +case IO_SKS: /* SKS */ + new_ch = I_GETSKCH (inst); /* sks chan */ + if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */ + t = I_GETSKCND (inst); /* sks cond */ + lun = RAD_GETLUN (rad_da); + if (((t == 000) && !sim_is_active (&rad_unit)) || /* 10026: ready */ + ((t == 004) && !rad_err) || /* 11026: !err */ + ((t == 014) && !(rad_wrp & (1 << lun)))) /* 13026: !wrprot */ + *dat = 1; + break; + +case IO_READ: /* read */ + p = (rad_da * RAD_NUMWD) + (rad_sba >> 1); /* buf wd addr */ + xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */ + if ((rad_unit.flags & UNIT_BUF) == 0) { /* not buffered? */ + rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */ + CRETIOE (rad_stopioe, SCPE_UNATT); } + if (p >= rad_unit.capac) { /* end of disk? */ + rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */ + return SCPE_OK; } + wptr = ((uint32 *) rad_unit.filebuf) + p; /* ptr to word */ + if (rad_sba & 1) *dat = *wptr & 07777; /* odd byte? */ + else *dat = (*wptr >> 12) & 07777; /* even */ + rad_sba = rad_adjda (rad_sba, 1); /* next byte */ + break; + +case IO_WRITE: + p = (rad_da * RAD_NUMWD) + (rad_sba >> 1); + xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */ + if ((rad_unit.flags & UNIT_BUF) == 0) { /* not buffered? */ + rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */ + CRETIOE (rad_stopioe, SCPE_UNATT); } + if ((p >= rad_unit.capac) || /* end of disk? */ + (rad_wrp & (1 << RAD_GETLUN (rad_da)))) { /* write prot? */ + rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */ + return SCPE_OK; } + wptr = ((uint32 *) rad_unit.filebuf) + p; /* ptr to word */ + if (rad_sba & 1) *wptr = *wptr | (*dat & 07777); /* odd byte? */ + else *wptr = (*dat & 07777) << 12; /* even */ + if (p >= rad_unit.hwmark) rad_unit.hwmark = p + 1; /* mark hiwater */ + rad_sba = rad_adjda (rad_sba, 1); /* next byte */ + break; + +default: + CRETINS; } +return SCPE_OK; +} + +/* PIN routine */ + +t_stat pin_rads (uint32 num, uint32 *dat) +{ +*dat = GET_SECTOR (rad_time * RAD_NUMWD); /* ret curr sec */ +return SCPE_OK; +} + +/* POT routine */ + +t_stat pot_rada (uint32 num, uint32 *dat) +{ +rad_da = (*dat) & RAD_AMASK; /* save dsk addr */ +return SCPE_OK; +} + +/* Unit service and read/write */ + +t_stat rad_svc (UNIT *uptr) +{ +xfr_req = xfr_req | XFR_RAD; /* set xfr req */ +sim_activate (&rad_unit, rad_time); /* activate */ +return SCPE_OK; +} + +/* Fill incomplete sector */ + +t_stat rad_fill (int32 sba) +{ +t_addr p = rad_da * RAD_NUMWD; +int32 wa = (sba + 1) >> 1; /* whole words */ + +if (sba && (p < rad_unit.capac)) { /* fill needed? */ + for ( ; wa < RAD_NUMWD; wa++) + *(((uint32 *) rad_unit.filebuf) + p + wa) = 0; + if ((p + wa) >= rad_unit.hwmark) rad_unit.hwmark = p + wa + 1; + rad_adjda (sba, RAD_NUMWD - 1); } /* inc da */ +return SCPE_OK; +} + +/* Adjust disk address */ + +int32 rad_adjda (int32 sba, int32 inc) +{ +sba = sba + inc; +if (rad_sba >= (RAD_NUMWD * 2)) { /* next sector? */ + if (rad_nobi) rad_da = (rad_da & ~RAD_SCMASK) + /* within band? */ + ((rad_da + 1) & RAD_SCMASK); + else rad_da = (rad_da & ~RAD_TRSCMASK) + /* cross band */ + ((rad_da + 1) & RAD_TRSCMASK); + sba = 0; } /* start new sec */ +return sba; +} + +/* Terminate disk operation */ + +void rad_end_op (int32 fl) +{ +if (fl) chan_set_flag (rad_dib.chan, fl); /* set flags */ +xfr_req = xfr_req & ~XFR_RAD; /* clear xfr */ +sim_cancel (&rad_unit); /* stop */ +if (fl & CHF_ERR) { /* error? */ + chan_disc (rad_dib.chan); /* disconnect */ + rad_err = 1; } /* set rad err */ +return; +} + +/* Reset routine */ + +t_stat rad_reset (DEVICE *dptr) +{ +chan_disc (rad_dib.chan); /* disconnect */ +rad_nobi = 0; /* clear state */ +rad_da = 0; +rad_sba = 0; +xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */ +sim_cancel (&rad_unit); /* deactivate */ +return SCPE_OK; +} diff --git a/SDS/sds_stddev.c b/SDS/sds_stddev.c new file mode 100644 index 00000000..7c2eb5a2 --- /dev/null +++ b/SDS/sds_stddev.c @@ -0,0 +1,555 @@ +/* sds_stddev.c: SDS 940 standard devices + + Copyright (c) 2001-2002, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + ptr paper tape reader + ptp paper tape punch + tti keyboard + tto teleprinter +*/ + +#include "sds_defs.h" +#define TT_CR 052 /* typewriter */ +#define TT_TB 072 +#define TT_BS 032 + +extern uint32 xfr_req; +extern int32 stop_invins, stop_invdev, stop_inviop; +int32 ptr_sor = 0; /* start of rec */ +int32 ptr_stopioe = 1; /* stop on err */ +int32 ptp_ldr = 0; /* no leader */ +int32 ptp_stopioe = 1; +DSPT std_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */ + +DEVICE ptr_dev, ptp_dev; +t_stat ptr (uint32 fnc, uint32 inst, uint32 *dat); +t_stat ptr_svc (UNIT *uptr); +t_stat ptr_reset (DEVICE *dptr); +t_stat ptr_boot (int32 unitno, DEVICE *dptr); +void ptr_set_err (void); +t_stat ptp (uint32 fnc, uint32 inst, uint32 *dat); +t_stat ptp_svc (UNIT *uptr); +t_stat ptp_reset (DEVICE *dptr); +t_stat ptp_out (int32 dat); +void ptp_set_err (void); +t_stat tti (uint32 fnc, uint32 inst, uint32 *dat); +t_stat tti_svc (UNIT *uptr); +t_stat tti_reset (DEVICE *dptr); +t_stat tto (uint32 fnc, uint32 inst, uint32 *dat); +t_stat tto_svc (UNIT *uptr); +t_stat tto_reset (DEVICE *dptr); + +extern const char ascii_to_sds[128]; +extern const char sds_to_ascii[64]; +extern const char odd_par[64]; + +/* PTR data structures + + ptr_dev PTR device descriptor + ptr_unit PTR unit + ptr_reg PTR register list +*/ + +DIB ptr_dib = { CHAN_W, DEV_PTR, XFR_PTR, std_tplt, &ptr }; + +UNIT ptr_unit = { + UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), + SERIAL_IN_WAIT }; + +REG ptr_reg[] = { + { ORDATA (BUF, ptr_unit.buf, 7) }, + { FLDATA (XFR, xfr_req, XFR_V_PTR) }, + { FLDATA (SOR, ptr_sor, 0) }, + { DRDATA (POS, ptr_unit.pos, 32), PV_LEFT }, + { DRDATA (TIME, ptr_unit.wait, 24), REG_NZ + PV_LEFT }, + { FLDATA (STOP_IOE, ptr_stopioe, 0) }, + { NULL } }; + +MTAB ptr_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", + "CHANNEL", &set_chan, &show_chan, NULL }, + { 0 } }; + +DEVICE ptr_dev = { + "PTR", &ptr_unit, ptr_reg, ptr_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptr_reset, + &ptr_boot, NULL, NULL, + &ptr_dib, DEV_DISABLE }; + +/* PTP data structures + + ptp_dev PTP device descriptor + ptp_unit PTP unit + ptp_reg PTP register list +*/ + +DIB ptp_dib = { CHAN_W, DEV_PTP, XFR_PTP, std_tplt, &ptp }; + +UNIT ptp_unit = { + UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; + +REG ptp_reg[] = { + { ORDATA (BUF, ptp_unit.buf, 7) }, + { FLDATA (XFR, xfr_req, XFR_V_PTP) }, + { FLDATA (LDR, ptp_ldr, 0) }, + { DRDATA (POS, ptp_unit.pos, 32), PV_LEFT }, + { DRDATA (TIME, ptp_unit.wait, 24), REG_NZ + PV_LEFT }, + { FLDATA (STOP_IOE, ptp_stopioe, 0) }, + { NULL } }; + +MTAB ptp_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", + &set_chan, &show_chan, NULL }, + { 0 } }; + +DEVICE ptp_dev = { + "PTP", &ptp_unit, ptp_reg, ptp_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptp_reset, + NULL, NULL, NULL, + &ptp_dib, DEV_DISABLE }; + +/* TTI data structures + + tti_dev TTI device descriptor + tti_unit TTI unit + tti_reg TTI register list +*/ + +DIB tti_dib = { CHAN_W, DEV_TTI, XFR_TTI, std_tplt, &tti }; + +UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; + +REG tti_reg[] = { + { ORDATA (BUF, tti_unit.buf, 6) }, + { FLDATA (XFR, xfr_req, XFR_V_TTI) }, + { DRDATA (POS, tti_unit.pos, 32), PV_LEFT }, + { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, + { NULL } }; + +MTAB tti_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", + &set_chan, &show_chan, &tti_dib }, + { 0 } }; + +DEVICE tti_dev = { + "TTI", &tti_unit, tti_reg, tti_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &tti_reset, + NULL, NULL, NULL, + &tti_dib, 0 }; + +/* TTO data structures + + tto_dev TTO device descriptor + tto_unit TTO unit + tto_reg TTO register list +*/ + +DIB tto_dib = { CHAN_W, DEV_TTO, XFR_TTO, std_tplt, &tto }; + +UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; + +REG tto_reg[] = { + { ORDATA (BUF, tto_unit.buf, 6) }, + { FLDATA (XFR, xfr_req, XFR_V_TTO) }, + { DRDATA (POS, tto_unit.pos, 32), PV_LEFT }, + { DRDATA (TIME, tto_unit.wait, 24), REG_NZ + PV_LEFT }, + { NULL } }; + +MTAB tto_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", + &set_chan, &show_chan, &tto_dib }, + { 0 } }; + +DEVICE tto_dev = { + "TTO", &tto_unit, tto_reg, tto_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &tto_reset, + NULL, NULL, NULL, + &tto_dib, 0 }; + +/* Paper tape reader + + conn - inst = EOM0, dat = NULL + eom1 - inst = EOM1, dat = NULL + sks - inst = SKS, dat = ptr to result + disc - inst = device number, dat = NULL + wreor - inst = device number, dat = NULL + read - inst = device number, dat = ptr to data + write - inst = device number, dat = ptr to result + + The paper tape reader is a streaming input device. Once started, it + continues to read until disconnected. Leader before the current record + is ignored; leader after the current record sets channel EndOfRecord. +*/ + +t_stat ptr (uint32 fnc, uint32 inst, uint32 *dat) +{ +int32 new_ch; + +switch (fnc) { /* case function */ +case IO_CONN: /* connect */ + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != ptr_dib.chan) return SCPE_IERR; /* inv conn? err */ + ptr_sor = 1; /* start of rec */ + xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */ + sim_activate (&ptr_unit, ptr_unit.wait); /* activate */ + break; + +case IO_DISC: /* disconnect */ + ptr_sor = 0; /* clear state */ + xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */ + sim_cancel (&ptr_unit); /* deactivate unit */ + break; + +case IO_READ: /* read */ + xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */ + *dat = ptr_unit.buf & 077; /* get buf data */ + if (ptr_unit.buf != odd_par[*dat]) /* good parity? */ + chan_set_flag (ptr_dib.chan, CHF_ERR); /* no, error */ + break; + +case IO_WREOR: /* write eor */ + break; + +case IO_EOM1: /* EOM mode 1*/ +case IO_WRITE: /* write */ + CRETINS; } /* error */ +return SCPE_OK; +} + +/* Unit service */ + +t_stat ptr_svc (UNIT *uptr) +{ +int32 temp; + +if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ + ptr_set_err (); /* no, err, disc */ + CRETIOE (ptr_stopioe, SCPE_UNATT); } +if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ + ptr_set_err (); /* yes, err, disc */ + if (feof (ptr_unit.fileref)) { /* end of file? */ + if (ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; } + else perror ("PTR I/O error"); /* I/O error */ + clearerr (ptr_unit.fileref); + return SCPE_IOERR; } +ptr_unit.pos = ptr_unit.pos + 1; /* inc position */ +if (temp) { /* leader/gap? */ + ptr_unit.buf = temp & 0177; /* no, save char */ + xfr_req = xfr_req | XFR_PTR; /* set xfr flag */ + ptr_sor = 0; } /* in record */ +else if (!ptr_sor) /* end record? */ + chan_set_flag (ptr_dib.chan, CHF_EOR); /* ignore leader */ +sim_activate (&ptr_unit, ptr_unit.wait); /* get next char */ +return SCPE_OK; +} + +/* Fatal error */ + +void ptr_set_err (void) +{ +chan_set_flag (ptr_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */ +chan_disc (ptr_dib.chan); /* disconnect */ +xfr_req = xfr_req & ~XFR_PTR; /* clear xfr */ +sim_cancel (&ptr_unit); /* stop */ +return; +} + +/* Reset routine */ + +t_stat ptr_reset (DEVICE *dptr) +{ +chan_disc (ptr_dib.chan); /* disconnect */ +ptr_sor = 0; /* clear state */ +ptr_unit.buf = 0; +xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */ +sim_cancel (&ptr_unit); /* deactivate unit */ +return SCPE_OK; +} + +/* Boot routine - simulate FILL console command */ + +t_stat ptr_boot (int32 unitno, DEVICE *dptr) +{ +extern uint32 P, M[]; + +M[0] = 077777771; /* -7B */ +M[1] = 007100000; /* LDX 0 */ +M[2] = 000203604; /* EOM 3604B */ +M[3] = 003200002; /* WIM 2 */ +M[4] = 000100002; /* BRU 2 */ +P = 1; /* start at 1 */ +return SCPE_OK; +} + +/* Paper tape punch + + conn - inst = EOM0, dat = NULL + eom1 - inst = EOM1, dat = NULL + sks - inst = SKS, dat = ptr to result + disc - inst = device number, dat = NULL + wreor - inst = device number, dat = NULL + read - inst = device number, dat = ptr to data + write - inst = device number, dat = ptr to result + + The paper tape punch is an asynchronous streaming output device. That is, + it can never cause a channel rate error; if no data is available, it waits. +*/ + +t_stat ptp (uint32 fnc, uint32 inst, uint32 *dat) +{ +int32 new_ch; + +switch (fnc) { /* case function */ +case IO_CONN: + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != ptp_dib.chan) return SCPE_IERR; /* inv conn? err */ + ptp_ldr = (inst & CHC_NLDR)? 0: 1; /* leader? */ + xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */ + sim_activate (&ptp_unit, ptp_unit.wait); /* activate */ + break; + +case IO_DISC: /* disconnect */ + ptp_ldr = 0; /* clear state */ + xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */ + sim_cancel (&ptp_unit); /* deactivate unit */ + break; + +case IO_WRITE: /* write */ + xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */ + sim_activate (&ptp_unit, ptp_unit.wait); /* activate */ + ptp_unit.buf = odd_par[(*dat) & 077]; /* save data */ + return ptp_out (ptp_unit.buf); /* punch w/ par */ + +case IO_WREOR: /* write eor */ + break; + +case IO_EOM1: /* EOM mode 1*/ +case IO_READ: /* read */ + CRETINS; } /* error */ +return SCPE_OK; +} + +/* Unit service */ + +t_stat ptp_svc (UNIT *uptr) +{ +int32 i; +t_stat r = SCPE_OK; + +if (ptp_ldr) { /* need leader? */ + for (i = 0; i < 12; i++) { /* punch leader */ + if (r = ptp_out (0)) break; } } +ptp_ldr = 0; /* clear flag */ +chan_set_ordy (ptp_dib.chan); /* ptp ready */ +return r; +} + +/* Punch I/O */ + +t_stat ptp_out (int32 dat) +{ +if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */ + ptp_set_err (); /* no, disc, err */ + CRETIOE (ptp_stopioe, SCPE_UNATT); } +if (putc (dat, ptp_unit.fileref) == EOF) { /* I/O error? */ + ptp_set_err (); /* yes, disc, err */ + perror ("PTP I/O error"); /* print msg */ + clearerr (ptp_unit.fileref); + return SCPE_IOERR; } +ptp_unit.pos = ptp_unit.pos + 1; /* inc position */ +return SCPE_OK; +} + +/* Fatal error */ + +void ptp_set_err (void) +{ +chan_set_flag (ptp_dib.chan, CHF_ERR); /* error */ +chan_disc (ptp_dib.chan); /* disconnect */ +xfr_req = xfr_req & ~XFR_PTP; /* clear xfr */ +sim_cancel (&ptp_unit); /* stop */ +return; +} + +/* Reset routine */ + +t_stat ptp_reset (DEVICE *dptr) +{ +chan_disc (ptp_dib.chan); /* disconnect */ +ptp_ldr = 0; /* clear state */ +ptp_unit.buf = 0; +xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */ +sim_cancel (&ptp_unit); /* deactivate unit */ +return SCPE_OK; +} + +/* Typewriter input + + conn - inst = EOM0, dat = NULL + eom1 - inst = EOM1, dat = NULL + sks - inst = SKS, dat = ptr to result + disc - inst = device number, dat = NULL + wreor - inst = device number, dat = NULL + read - inst = device number, dat = ptr to data + write - inst = device number, dat = ptr to result + + The typewriter input is an asynchronous input device. That is, it can + never cause a channel rate error; if no data is available, it waits. +*/ + +t_stat tti (uint32 fnc, uint32 inst, uint32 *dat) +{ +int32 new_ch; + +switch (fnc) { /* case function */ +case IO_CONN: /* connect */ + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != tti_dib.chan) return SCPE_IERR; /* inv conn? err */ + xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ + break; + +case IO_DISC: /* disconnect */ + xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ + break; + +case IO_READ: /* read */ + xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ + *dat = tti_unit.buf; /* get buf data */ + break; + +case IO_WREOR: /* write eor */ + break; + +case IO_EOM1: /* EOM mode 1*/ +case IO_WRITE: /* write */ + CRETINS; } /* error */ +return SCPE_OK; +} + +/* Unit service */ + +t_stat tti_svc (UNIT *uptr) +{ +int32 temp; + +sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ +if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ +if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */ +temp = temp & 0177; +tti_unit.pos = tti_unit.pos + 1; +if (ascii_to_sds[temp] >= 0) { + tti_unit.buf = ascii_to_sds[temp]; /* internal rep */ + sim_putchar (temp); /* echo */ + if (temp == 015) sim_putchar (012); /* lf after cr */ + xfr_req = xfr_req | XFR_TTI; } /* set xfr flag */ +else sim_putchar (007); /* ding! */ +return SCPE_OK; +} + +t_stat tti_reset (DEVICE *dptr) +{ +chan_disc (tti_dib.chan); /* disconnect */ +tti_unit.buf = 0; /* clear state */ +xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ +sim_activate (&tti_unit, tti_unit.wait); /* start poll */ +return SCPE_OK; +} + +/* Typewriter output + + conn - inst = EOM0, dat = NULL + eom1 - inst = EOM1, dat = NULL + sks - inst = SKS, dat = ptr to result + disc - inst = device number, dat = NULL + wreor - inst = device number, dat = NULL + read - inst = device number, dat = ptr to data + write - inst = device number, dat = ptr to result + + The typewriter output is an asynchronous streaming output device. That is, + it can never cause a channel rate error; if no data is available, it waits. +*/ + +t_stat tto (uint32 fnc, uint32 inst, uint32 *dat) +{ +int32 asc, new_ch; + +switch (fnc) { /* case function */ +case IO_CONN: + new_ch = I_GETEOCH (inst); /* get new chan */ + if (new_ch != tto_dib.chan) return SCPE_IERR; /* inv conn? err */ + xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ + sim_activate (&tto_unit, tto_unit.wait); /* activate */ + break; + +case IO_DISC: /* disconnect */ + xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ + sim_cancel (&tto_unit); /* deactivate unit */ + break; + +case IO_WRITE: /* write */ + xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ + tto_unit.buf = (*dat) & 077; /* save data */ + if (tto_unit.buf == TT_CR) { /* control chars? */ + sim_putchar (015); /* CR generates LF */ + tto_unit.pos = tto_unit.pos + 1; + asc = 012; } + else if (tto_unit.buf == TT_BS) asc = '\b'; + else if (tto_unit.buf == TT_TB) asc = '\t'; + else asc = sds_to_ascii[tto_unit.buf]; /* translate */ + tto_unit.pos = tto_unit.pos + 1; /* inc position */ + sim_activate (&tto_unit, tto_unit.wait); /* activate */ + return sim_putchar (asc); /* output */ + +case IO_WREOR: /* write eor */ + break; + +case IO_EOM1: /* EOM mode 1*/ +case IO_READ: /* read */ + CRETINS; } /* error */ +return SCPE_OK; +} + +/* Unit service */ + +t_stat tto_svc (UNIT *uptr) +{ +chan_set_ordy (tto_dib.chan); /* tto rdy */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat tto_reset (DEVICE *dptr) +{ +chan_disc (tto_dib.chan); /* disconnect */ +tto_unit.buf = 0; /* clear state */ +xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ +sim_cancel (&tto_unit); /* deactivate unit */ +return SCPE_OK; +} diff --git a/SDS/sds_sys.c b/SDS/sds_sys.c new file mode 100644 index 00000000..f711097e --- /dev/null +++ b/SDS/sds_sys.c @@ -0,0 +1,576 @@ +/* sds_sys.c: SDS 940 simulator interface + + Copyright (c) 2001-2002, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. +*/ + +#include "sds_defs.h" +#include +#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) + +extern DEVICE cpu_dev; +extern DEVICE chan_dev; +extern DEVICE ptr_dev; +extern DEVICE ptp_dev; +extern DEVICE tti_dev; +extern DEVICE tto_dev; +extern DEVICE lpt_dev; +extern DEVICE rtc_dev; +extern DEVICE drm_dev; +extern DEVICE rad_dev; +extern DEVICE dsk_dev; +extern DEVICE mt_dev; +extern DEVICE mux_dev, muxl_dev; +extern UNIT cpu_unit; +extern REG cpu_reg[]; +extern uint32 M[MAXMEMSIZE]; + +/* SCP data structures and interface routines + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages + sim_load binary loader +*/ + +char sim_name[] = "SDS 940"; + +REG *sim_PC = &cpu_reg[0]; + +int32 sim_emax = 1; + +DEVICE *sim_devices[] = { + &cpu_dev, + &chan_dev, + &ptr_dev, + &ptp_dev, + &tti_dev, + &tto_dev, + &lpt_dev, + &rtc_dev, + &drm_dev, + &rad_dev, + &dsk_dev, + &mt_dev, + &mux_dev, + &muxl_dev, + NULL }; + +const char *sim_stop_messages[] = { + "Unknown error", + "IO device not ready", + "HALT instruction", + "Breakpoint", + "Invalid IO device", + "Invalid instruction", + "Invalid I/O operation", + "Nested indirects exceed limit", + "Nested EXU's exceed limit", + "Memory management trap during interrupt", + "Memory management trap during trap", + "Trap instruction not BRM", + "RTC instruction not MIN or SKR", + "Interrupt vector zero", + "Runaway carriage control tape" }; + +/* Character conversion tables */ + +const char sds_to_ascii[64] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ' ', '=', '\'', ':', '>', '%', /* 17 = check mark */ + '+', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', '?', '.', ')', '[', '<', '@', /* 37 = stop code */ + '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', '!', '$', '*', ']', ';', '^', /* 57 = triangle */ + '_', '/', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', '?', ',', '(', '~', '\\', '#' }; /* 72 = rec mark */ + /* 75 = squiggle, 77 = del */ + +const char ascii_to_sds[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, /* 0 - 37 */ + 032, 072, -1, -1, -1, 052, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 012, 052, -1, 077, 053, 017, -1, 014, /* 40 - 77 */ + 074, 034, 054, 020, 073, 040, 033, 061, + 000, 001, 002, 003, 004, 005, 006, 007, + 010, 011, 015, 056, 036, 013, 016, 072, + 037, 021, 022, 023, 024, 025, 026, 027, /* 100 - 137 */ + 030, 031, 041, 042, 043, 044, 045, 046, + 047, 050, 051, 062, 063, 064, 065, 066, + 067, 070, 071, 035, 076, 055, 057, 060, + 000, 021, 022, 023, 024, 025, 026, 027, /* 140 - 177 */ + 030, 031, 041, 042, 043, 044, 045, 046, + 047, 050, 051, 062, 063, 064, 065, 066, + 067, 070, 071, -1, -1, -1, -1, -1 }; + +const char odd_par[64] = { + 0100, 0001, 0002, 0103, 0004, 0105, 0106, 0007, + 0010, 0111, 0112, 0013, 0114, 0015, 0016, 0117, + 0020, 0121, 0122, 0023, 0124, 0025, 0026, 0127, + 0130, 0031, 0032, 0133, 0034, 0135, 0136, 0037, + 0040, 0141, 0142, 0043, 0144, 0045, 0046, 0147, + 0150, 0051, 0052, 0153, 0054, 0155, 0156, 0057, + 0160, 0061, 0062, 0163, 0064, 0165, 0166, 0067, + 0070, 0171, 0172, 0073, 0174, 0075, 0076, 0177 }; + +/* Load carriage control tape + + A carriage control tape consists of entries of the form + + (repeat count) column number,column number,column number,... + + The CCT entries are stored in lpt_cct[0:lnt-1], lpt_ccl contains the + number of entries +*/ + +t_stat sim_load_cct (FILE *fileref) +{ +int32 col, rpt, ptr, mask, cctbuf[CCT_LNT]; +t_stat r; +extern int32 lpt_ccl, lpt_ccp, lpt_cct[CCT_LNT]; +char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE]; + +ptr = 0; +for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */ + mask = 0; + if (*cptr == '(') { /* repeat count? */ + cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */ + rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */ + if (r != SCPE_OK) return SCPE_FMT; } + else rpt = 1; + while (*cptr != 0) { /* get col no's */ + cptr = get_glyph (cptr, gbuf, ','); /* get next field */ + col = get_uint (gbuf, 10, 7, &r); /* column number */ + if (r != SCPE_OK) return SCPE_FMT; + mask = mask | (1 << col); } /* set bit */ + for ( ; rpt > 0; rpt--) { /* store vals */ + if (ptr >= CCT_LNT) return SCPE_FMT; + cctbuf[ptr++] = mask; } } +if (ptr == 0) return SCPE_FMT; +lpt_ccl = ptr; +lpt_ccp = 0; +for (rpt = 0; rpt < lpt_ccl; rpt++) lpt_cct[rpt] = cctbuf[rpt]; +return SCPE_OK; +} + +/* Load command. -l means load a line printer tape. Otherwise, load + a bootstrap paper tape. +*/ + +int32 get_word (FILE *fileref, int32 *ldr) +{ +int32 i, c, wd; + +for (i = wd = 0; i < 4; ) { + if ((c = fgetc (fileref)) == EOF) return -1; + if ((c == 0) && (*ldr == 0)) return -1; + if (c == 0) continue; + *ldr = 0; + wd = (wd << 6) | (c & 077); + i++; } +return wd; +} + +t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +{ +int32 i, wd, buf[8]; +int32 ldr = 1; +extern int32 sim_switches; +extern uint32 P; + +if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; +if (sim_switches & SWMASK ('L')) return sim_load_cct (fileref); +for (i = 0; i < 8; i++) { /* read boot */ + if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_FMT; + buf[i] = wd; } +if ((buf[0] != 023200012) || /* 2 = WIM 12,2 */ + (buf[1] != 004100002) || /* 3 = BRX 2 */ + (buf[2] != 007100011) || /* 4 = LDX 11 */ + (buf[3] != 023200000) || /* 5 = WIM 0,2 */ + (buf[4] != 004021000) || /* 6 = SKS 21000 */ + (buf[5] != 004100005)) return SCPE_FMT; /* 7 = BRX 5 */ +for (i = 0; i < 8; i++) M[i + 2] = buf[i]; /* copy boot */ +if (I_GETOP (buf[6]) == BRU) P = buf[6] & VA_MASK; +for (i = buf[7] & VA_MASK; i <= VA_MASK; i++) { /* load data */ + if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_OK; + M[i] = wd; } +return SCPE_NXM; +} + +/* Symbol tables */ + +#define I_V_FL 24 /* inst class */ +#define I_M_FL 017 /* class mask */ +#define I_V_NPN 000 /* no operand */ +#define I_V_PPO 001 /* POP */ +#define I_V_IOI 002 /* IO */ +#define I_V_MRF 003 /* memory reference */ +#define I_V_REG 004 /* register change */ +#define I_V_SHF 005 /* shift */ +#define I_V_OPO 006 /* opcode only */ +#define I_V_CHC 007 /* chan cmd */ +#define I_V_CHT 010 /* chan test */ +#define I_NPN (I_V_NPN << I_V_FL) +#define I_PPO (I_V_PPO << I_V_FL) +#define I_IOI (I_V_IOI << I_V_FL) +#define I_MRF (I_V_MRF << I_V_FL) +#define I_REG (I_V_REG << I_V_FL) +#define I_SHF (I_V_SHF << I_V_FL) +#define I_OPO (I_V_OPO << I_V_FL) +#define I_CHC (I_V_CHC << I_V_FL) +#define I_CHT (I_V_CHT << I_V_FL) + +static const int32 masks[] = { + 037777777, 010000000, 017700000, + 017740000, 017700000, 017774000, + 017700000, 017377677, 027737677 }; + +static const char *opcode[] = { + "POP", "EIR", "DIR", + "ROV", "REO", "OTO", "OVT", + "IDT", "IET", + "BPT4", "BPT3", "BPT2", "BPT1", + "CLAB", "ABC", "BAC", "XAB", + "XXB", "STE", "LDE", "XEE", + "CLEAR", + + "HLT", "BRU", "EOM", "EOD", + "MIY", "BRI", "MIW", "POT", + "ETR", "MRG", "EOR", + "NOP", "EXU", + "YIM", "WIM", "PIN", + "STA", "STB", "STX", + "SKS", "BRX", "BRM", + "SKE", "BRR", "SKB", "SKN", + "SUB", "ADD", "SUC", "ADC", + "SKR", "MIN", "XMA", "ADM", + "MUL", "DIV", + "SKM", "LDX", "SKA", "SKG", + "SKD", "LDB", "LDA", "EAX", + + "BRU*", + "MIY*", "BRI*", "MIW*", "POT*", + "ETR*", "MRG*", "EOR*", + "EXU*", + "YIM*", "WIM*", "PIN*", + "STA*", "STB*", "STX*", + "BRX*", "BRM*", + "SKE*", "BRR*", "SKB*", "SKN*", + "SUB*", "ADD*", "SUC*", "ADC*", + "SKR*", "MIN*", "XMA*", "ADM*", + "MUL*", "DIV*", + "SKM*", "LDX*", "SKA*", "SKG*", + "SKD*", "LDB*", "LDA*", "EAX*", + + "RSH", "RCY", "LRSH", + "LSH", "NOD", "LCY", + "RSH*", "LSH*", + + "ALC", "DSC", "ASC", "TOP", + "CAT", "CET", "CZT", "CIT", + + "CLA", "CLB", "CAB", /* encode only */ + "CBA", "CBX", "CXB", + "XPO", "CXA", "CAX", + "CNA", "CLX", NULL, + NULL }; + +static const int32 opc_val[] = { + 010000000+I_PPO, 000220002+I_NPN, 000220004+I_NPN, + 002200001+I_NPN, 002200010+I_NPN, 002200100+I_NPN, 002200101+I_NPN, + 004020002+I_NPN, 004020004+I_NPN, + 004020040+I_NPN, 004020100+I_NPN, 004020200+I_NPN, 004020400+I_NPN, + 004600003+I_NPN, 004600005+I_NPN, 004600012+I_NPN, 004600014+I_NPN, + 004600060+I_NPN, 004600122+I_NPN, 004600140+I_NPN, 004600160+I_NPN, + 024600003+I_NPN, + + 000000000+I_NPN, 000100000+I_MRF, 000200000+I_IOI, 000600000+I_IOI, + 001000000+I_MRF, 001100000+I_MRF, 001200000+I_MRF, 001300000+I_MRF, + 001400000+I_MRF, 001600000+I_MRF, 001700000+I_MRF, + 002000000+I_OPO, 002300000+I_MRF, + 003000000+I_MRF, 003200000+I_MRF, 003300000+I_MRF, + 003500000+I_MRF, 003600000+I_MRF, 003700000+I_MRF, + 004000000+I_IOI, 004100000+I_MRF, 004300000+I_MRF, + 005000000+I_MRF, 005100000+I_MRF, 005200000+I_MRF, 005300000+I_MRF, + 005400000+I_MRF, 005500000+I_MRF, 005600000+I_MRF, 005700000+I_MRF, + 006000000+I_MRF, 006100000+I_MRF, 006200000+I_MRF, 006300000+I_MRF, + 006400000+I_MRF, 006500000+I_MRF, + 007000000+I_MRF, 007100000+I_MRF, 007200000+I_MRF, 007300000+I_MRF, + 007400000+I_MRF, 007500000+I_MRF, 007600000+I_MRF, 007700000+I_MRF, + + 000140000+I_MRF, + 001040000+I_MRF, 001140000+I_MRF, 001240000+I_MRF, 001340000+I_MRF, + 001440000+I_MRF, 001640000+I_MRF, 001740000+I_MRF, + 002340000+I_MRF, + 003040000+I_MRF, 003240000+I_MRF, 003340000+I_MRF, + 003540000+I_MRF, 003640000+I_MRF, 003740000+I_MRF, + 004140000+I_MRF, 004340000+I_MRF, + 005040000+I_MRF, 005140000+I_MRF, 005240000+I_MRF, 005340000+I_MRF, + 005440000+I_MRF, 005540000+I_MRF, 005640000+I_MRF, 005740000+I_MRF, + 006040000+I_MRF, 006140000+I_MRF, 006240000+I_MRF, 006340000+I_MRF, + 006440000+I_MRF, 006540000+I_MRF, + 007040000+I_MRF, 007140000+I_MRF, 007240000+I_MRF, 007340000+I_MRF, + 007440000+I_MRF, 007540000+I_MRF, 007640000+I_MRF, 007740000+I_MRF, + + 006600000+I_SHF, 006620000+I_SHF, 006624000+I_SHF, + 006700000+I_SHF, 006710000+I_SHF, 006720000+I_SHF, + 006640000+I_MRF, 006740000+I_MRF, + + 000250000+I_CHC, 000200000+I_CHC, 000212000+I_CHC, 000214000+I_CHC, + 004014000+I_CHT, 004011000+I_CHT, 004012000+I_CHT, 004010400+I_CHT, + + 004600001+I_REG, 004600002+I_REG, 004600004+I_REG, + 004600010+I_REG, 004600020+I_REG, 004600040+I_REG, + 004600100+I_REG, 004600200+I_REG, 004600400+I_REG, + 004601000+I_REG, 024600000+I_REG, 004600000+I_REG, + -1 }; + +static const char *chname[] = { + "W", "Y", "C", "D", "E", "F", "G", "H", NULL }; + +/* Register change decode + + Inputs: + *of = output stream + inst = mask bits +*/ + +void fprint_reg (FILE *of, int32 inst) +{ +int32 i, j, sp; + +inst = inst & ~(I_M_OP << I_V_OP); /* clear opcode */ +for (i = sp = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ + j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ + if ((j == I_V_REG) && (opc_val[i] & inst)) { /* reg class? */ + inst = inst & ~opc_val[i]; /* mask bit set? */ + fprintf (of, (sp? " %s": "%s"), opcode[i]); + sp = 1; } } +return; +} + +/* Symbolic decode + + Inputs: + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches + Outputs: + return = status code +*/ + +t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, + UNIT *uptr, int32 sw) +{ +int32 i, j, ch; +int32 inst, op, tag, va, shf, nonop; + +inst = val[0]; /* get inst */ +op = I_GETOP (inst); /* get fields */ +tag = (inst >> 21) & 06; +va = inst & VA_MASK; +shf = inst & I_SHFMSK; +nonop = inst & 077777; + +if (sw & SWMASK ('A')) { /* ASCII? */ + if (inst > 0377) return SCPE_ARG; + fprintf (of, FMTASC (inst & 0177)); + return SCPE_OK; } +if (sw & SWMASK ('C')) { /* character? */ + fprintf (of, "%c", sds_to_ascii[(inst >> 18) & 077]); + fprintf (of, "%c", sds_to_ascii[(inst >> 12) & 077]); + fprintf (of, "%c", sds_to_ascii[(inst >> 6) & 077]); + fprintf (of, "%c", sds_to_ascii[inst & 077]); + return SCPE_OK; } +if (!(sw & SWMASK ('M'))) return SCPE_ARG; + +/* Instruction decode */ + +for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ + j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ + if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */ + + switch (j) { /* case on class */ + case I_V_NPN: /* no operands */ + case I_V_OPO: /* opcode only */ + fprintf (of, "%s", opcode[i]); /* opcode */ + break; + case I_V_SHF: /* shift */ + fprintf (of, "%s %-o", opcode[i], shf); + if (tag) fprintf (of, ",%-o", tag); + break; + case I_V_PPO: /* pop */ + fprintf (of, "POP %-o,%-o", op, nonop); + if (tag) fprintf (of, ",%-o", tag); + break; + case I_V_IOI: /* I/O */ + fprintf (of, "%s %-o", opcode[i], nonop); + if (tag) fprintf (of, ",%-o", tag); + break; + case I_V_MRF: /* mem ref */ + fprintf (of, "%s %-o", opcode[i], va); + if (tag) fprintf (of, ",%-o", tag); + break; + case I_V_REG: /* reg change */ + fprint_reg (of, inst); /* decode */ + break; + case I_V_CHC: /* chan cmd */ + ch = I_GETEOCH (inst); /* get chan */ + fprintf (of, "%s %s", opcode[i], chname[ch]); + break; + case I_V_CHT: /* chan test */ + ch = I_GETSKCH (inst); /* get chan */ + fprintf (of, "%s %s", opcode[i], chname[ch]); + break; + } /* end case */ + return SCPE_OK; + } /* end if */ + } /* end for */ +return SCPE_ARG; +} + +/* Get (optional) tag + + Inputs: + *cptr = pointer to input string + *tag = pointer to tag + Outputs: + cptr = updated pointer to input string +*/ + +char *get_tag (char *cptr, t_value *tag) +{ +char *tptr, gbuf[CBUFSIZE]; +t_stat r; + +tptr = get_glyph (cptr, gbuf, 0); /* get next field */ +*tag = get_uint (gbuf, 8, 07, &r) << I_V_TAG; /* parse */ +if (r == SCPE_OK) return tptr; /* ok? advance */ +*tag = 0; +return cptr; /* no change */ +} + +/* Symbolic input + + Inputs: + *cptr = pointer to input string + addr = current PC + uptr = pointer to unit + *val = pointer to output values + sw = switches + Outputs: + status = error status +*/ + +t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) +{ +int32 i, j, k; +t_value d, tag; +t_stat r; +char gbuf[CBUFSIZE]; + +while (isspace (*cptr)) cptr++; +for (i = 1; (i < 4) && (cptr[i] != 0); i++) + if (cptr[i] == 0) for (j = i + 1; j <= 4; j++) cptr[j] = 0; +if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + val[0] = (t_value) cptr[0] | 0200; + return SCPE_OK; } +if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* string? */ + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + for (i = j = 0, val[0] = 0; i < 4; i++) { + if (cptr[i] == 0) j = 1; /* latch str end */ + k = ascii_to_sds[cptr[i] & 0177]; /* cvt char */ + if (j || (k < 0)) k = 0; /* bad, end? spc */ + val[0] = (val[0] << 6) | k; } + return SCPE_OK; } + +/* Symbolic input, continued */ + +cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; +if (opcode[i] == NULL) return SCPE_ARG; +val[0] = opc_val[i] & DMASK; /* get value */ +j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ + +switch (j) { /* case on class */ +case I_V_NPN: case I_V_OPO: /* opcode only */ + break; +case I_V_SHF: /* shift */ + cptr = get_glyph (cptr, gbuf, ','); /* get next field */ + d = get_uint (gbuf, 8, I_SHFMSK, &r); /* shift count */ + if (r != SCPE_OK) return SCPE_ARG; + cptr = get_tag (cptr, &tag); /* get opt tag */ + val[0] = val[0] | d | tag; + break; +case I_V_PPO: /* pop */ + cptr = get_glyph (cptr, gbuf, ','); /* get next field */ + d = get_uint (gbuf, 8, 077, &r); /* opcode */ + if (r != SCPE_OK) return SCPE_ARG; + val[0] = val[0] | d; /* fall thru */ +case I_V_IOI: /* I/O */ + cptr = get_glyph (cptr, gbuf, ','); /* get next field */ + d = get_uint (gbuf, 8, 077777, &r); /* 15b address */ + if (r != SCPE_OK) return SCPE_ARG; + cptr = get_tag (cptr, &tag); /* get opt tag */ + val[0] = val[0] | d | tag; + break; +case I_V_MRF: /* mem ref */ + cptr = get_glyph (cptr, gbuf, ','); /* get next field */ + d = get_uint (gbuf, 8, VA_MASK, &r); /* virt address */ + if (r != SCPE_OK) return SCPE_ARG; + cptr = get_tag (cptr, &tag); /* get opt tag */ + val[0] = val[0] | d | tag; + break; +case I_V_REG: /* register */ + for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; + cptr = get_glyph (cptr, gbuf, 0)) { + for (i = 0; (opcode[i] != NULL) && + (strcmp (opcode[i], gbuf) != 0); i++) ; + if (opcode[i] != NULL) { + k = opc_val[i] & DMASK;; + if (I_GETOP (k) != RCH) return SCPE_ARG; + val[0] = val[0] | k; } + else { + d = get_uint (gbuf, 8, 077777, &r); + if (r != SCPE_OK) return SCPE_ARG; + else val[0] = val[0] | d; } } + break; +case I_V_CHC: case I_V_CHT: /* channel */ + cptr = get_glyph (cptr, gbuf, ','); /* get next field */ + for (i = 0; (chname[i] != NULL) && (strcmp (chname[i], gbuf) != 0); + i++); + if (chname[i] != NULL) d = i; /* named chan */ + else { + d = get_uint (gbuf, 8, NUM_CHAN - 1, &r); + if (r != SCPE_OK) return SCPE_ARG; } /* numbered chan */ + val[0] = val[0] | ((j == I_V_CHC)? I_SETEOCH (d): I_SETSKCH (d)); + break; } /* end case */ +if (*cptr != 0) return SCPE_ARG; /* junk at end? */ +return SCPE_OK; +} diff --git a/VAX/vax_cpu.c b/VAX/vax_cpu.c index 7c7092bd..d8d1f6f3 100644 --- a/VAX/vax_cpu.c +++ b/VAX/vax_cpu.c @@ -1,6 +1,6 @@ /* vax_cpu.c: VAX CPU simulator - Copyright (c) 1998-2002, Robert M Supnik + Copyright (c) 1998-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,8 @@ cpu CVAX central processor + 05-Jan-02 RMS Added memory size restore support + 25-Dec-02 RMS Added instruction history (from Mark Pizzolato) 29-Sep-02 RMS Revised to build dib_tab dynamically 14-Jul-02 RMS Added halt to console, infinite loop detection (from Mark Pizzolato) @@ -143,6 +145,7 @@ #define UNIT_MSIZE (1u << UNIT_V_MSIZE) #define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL)) +#define OPND_SIZE 10 #define op0 opnd[0] #define op1 opnd[1] #define op2 opnd[2] @@ -167,6 +170,14 @@ Write (va + 4, rh, L_LONG, WA); } \ else { R[rn] = rl; R[rnplus1] = rh; } +#define HIST_SIZE 4096 +struct InstHistory { + int32 iPC; + int32 PSL; + int32 opc; + int32 brdest; + int32 opnd[OPND_SIZE]; }; + uint32 *M = NULL; /* memory */ int32 R[16]; /* registers */ int32 STK[5]; /* stack pointers */ @@ -191,11 +202,12 @@ int32 recq[6]; /* recovery queue */ int32 recqptr; /* recq pointer */ int32 mem_err = 0; /* mem err intr */ int32 crd_err = 0; /* CRD err intr */ +int32 hlt_pin = 0; /* HLT pin intr */ int32 p1 = 0, p2 = 0; /* fault parameters */ int32 fault_PC; /* fault PC */ -int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ +int32 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ int32 badabo = 0; int32 cpu_astop = 0; int32 dbg_stop = 0; @@ -204,6 +216,9 @@ int32 ibufl, ibufh; /* prefetch buf */ int32 ibcnt, ppc; /* prefetch ctl */ int32 cpu_log = 0; /* logging */ jmp_buf save_env; +REG *pcq_r = NULL; /* PC queue reg ptr */ +int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ +static struct InstHistory hst[HIST_SIZE] = { { 0 } }; /* instruction history */ const uint32 byte_mask[33] = { 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, @@ -225,6 +240,8 @@ const uint32 byte_sign[33] = { 0x00000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 }; const uint32 align[4] = { 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF }; + +/* External and forward references */ extern int32 sim_interval; extern int32 sim_int_char; @@ -309,7 +326,10 @@ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat cpu_show_virt (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc); int32 get_istr (int32 lnt, int32 acc); +int32 con_halt (int32 code, int32 cc); /* CPU data structures @@ -364,6 +384,7 @@ REG cpu_reg[] = { { HRDATA (TRPIRQ, trpirq, 8) }, { FLDATA (CRDERR, crd_err, 0) }, { FLDATA (MEMERR, mem_err, 0) }, + { FLDATA (HLTPIN, hlt_pin, 0) }, { HRDATA (DBGLOG, cpu_log, 16), REG_HIDDEN }, { FLDATA (DBGSTOP, dbg_stop, 0), REG_HIDDEN }, { BRDATA (PCQ, pcq, 16, 32, PCQ_SIZE), REG_RO+REG_CIRC }, @@ -381,6 +402,8 @@ MTAB cpu_mod[] = { { UNIT_CONH, UNIT_CONH, "HALT to console", "CONHALT", NULL }, { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL, NULL, &show_iospace }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, { MTAB_XTD|MTAB_VDV, 0, NULL, "VIRTUAL", &cpu_show_virt }, { 0 } }; @@ -389,7 +412,7 @@ DEVICE cpu_dev = { 1, 16, 32, 1, 16, 8, &cpu_ex, &cpu_dep, &cpu_reset, &cpu_boot, NULL, NULL, - NULL, 0 }; + NULL, DEV_DYNM, &cpu_set_size }; t_stat sim_instr (void) { @@ -416,70 +439,71 @@ if (abortval > 0) { /* sim stop? */ else if (abortval < 0) { /* mm or rsrv or int */ int32 i, temp, st1, st2, hsir; if ((PSL & PSL_FPD) == 0) { /* FPD? no recovery */ - for (i = 0; i < recqptr; i++) { /* unwind inst */ - int32 rrn, rlnt; - rrn = recq[i] & 0xF; /* recovery reg# */ - rlnt = DR_LNT ((recq[i] >> 4) & 0x3); /* recovery lnt */ - if (recq[i] & 0x800) R[rrn] = R[rrn] - rlnt; - else R[rrn] = R[rrn] + rlnt; } } + for (i = 0; i < recqptr; i++) { /* unwind inst */ + int32 rrn, rlnt; + rrn = recq[i] & 0xF; /* recovery reg# */ + rlnt = DR_LNT ((recq[i] >> 4) & 0x3); /* recovery lnt */ + if (recq[i] & 0x800) R[rrn] = R[rrn] - rlnt; + else R[rrn] = R[rrn] + rlnt; } } recqptr = 0; /* clear queue */ temp = fault_PC - PC; /* delta PC if needed */ SETPC (fault_PC); /* restore PC */ switch (-abortval) { /* case on abort code */ case SCB_RESIN: case SCB_RESAD: case SCB_RESOP: /* reserved fault */ - if (in_ie) ABORT (STOP_INIE); /* in exc? panic */ - cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ - GET_CUR; /* PSL changed */ - break; + if (in_ie) ABORT (STOP_INIE); /* in exc? panic */ + cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ + GET_CUR; /* PSL changed */ + break; case SCB_ARITH: /* arithmetic fault */ - if (in_ie) ABORT (STOP_INIE); /* in exc? panic */ - cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ + if (in_ie) ABORT (STOP_INIE); /* in exc? panic */ + cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ + GET_CUR; + in_ie = 1; + Write (SP - 4, p1, L_LONG, WA); /* write arith param */ + SP = SP - 4; + in_ie = 0; + break; + case SCB_ACV: case SCB_TNV: /* mem management */ + if (in_ie) { /* in exception? */ + if (PSL & PSL_IS) ABORT (STOP_INIE); /* on is? panic */ + cc = intexc (SCB_KSNV, cc, 0, IE_SVE); /* ksnv */ + GET_CUR; } + else { + cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ GET_CUR; in_ie = 1; - Write (SP - 4, p1, L_LONG, WA); /* write arith param */ - SP = SP - 4; - in_ie = 0; - break; - case SCB_ACV: case SCB_TNV: /* mem management */ - if (in_ie) { /* in exception? */ - if (PSL & PSL_IS) ABORT (STOP_INIE); /* on is? panic */ - cc = intexc (SCB_KSNV, cc, 0, IE_SVE); /* ksnv */ - GET_CUR; } - else { cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ - GET_CUR; - in_ie = 1; - Write (SP - 8, p1, L_LONG, WA); /* write mm params */ - Write (SP - 4, p2, L_LONG, WA); - SP = SP - 8; - in_ie = 0; } - break; + Write (SP - 8, p1, L_LONG, WA); /* write mm params */ + Write (SP - 4, p2, L_LONG, WA); + SP = SP - 8; + in_ie = 0; } + break; case SCB_MCHK: /* machine check */ - if (in_ie) ABORT (STOP_INIE); /* in exception? */ - if (p1 & 0x80) p1 = p1 + mchk_ref; /* mref? set v/p */ - p2 = mchk_va + 4; /* save vap */ - for (i = hsir = 0; i < 16; i++) { /* find hsir */ - if ((SISR >> i) & 1) hsir = i; } - st1 = ((((uint32) opc) & 0xFF) << 24) | - (hsir << 16) | - ((CADR & 0xFF) << 8) | - (MSER & 0xFF); - st2 = 0x00C07000 + (temp & 0xFF); - cc = intexc (-abortval, cc, 0, IE_SVE); /* take exception */ - GET_CUR; /* PSL changed */ - in_ie = 1; - SP = SP - 20; /* push 5 words */ - Write (SP, 16, L_LONG, WA); /* # bytes */ - Write (SP + 4, p1, L_LONG, WA); /* mcheck type */ - Write (SP + 8, p2, L_LONG, WA); /* address */ - Write (SP + 12, st1, L_LONG, WA); /* state 1 */ - Write (SP + 16, st2, L_LONG, WA); /* state 2 */ - in_ie = 0; - break; + if (in_ie) ABORT (STOP_INIE); /* in exception? */ + if (p1 & 0x80) p1 = p1 + mchk_ref; /* mref? set v/p */ + p2 = mchk_va + 4; /* save vap */ + for (i = hsir = 0; i < 16; i++) { /* find hsir */ + if ((SISR >> i) & 1) hsir = i; } + st1 = ((((uint32) opc) & 0xFF) << 24) | + (hsir << 16) | + ((CADR & 0xFF) << 8) | + (MSER & 0xFF); + st2 = 0x00C07000 + (temp & 0xFF); + cc = intexc (-abortval, cc, 0, IE_SVE); /* take exception */ + GET_CUR; /* PSL changed */ + in_ie = 1; + SP = SP - 20; /* push 5 words */ + Write (SP, 16, L_LONG, WA); /* # bytes */ + Write (SP + 4, p1, L_LONG, WA); /* mcheck type */ + Write (SP + 8, p2, L_LONG, WA); /* address */ + Write (SP + 12, st1, L_LONG, WA); /* state 1 */ + Write (SP + 16, st2, L_LONG, WA); /* state 2 */ + in_ie = 0; + break; case 1: /* interrupt */ - break; /* just proceed */ + break; /* just proceed */ default: /* other */ - badabo = abortval; /* save code */ - ABORT (STOP_UNKABO); } /* panic */ + badabo = abortval; /* save code */ + ABORT (STOP_UNKABO); } /* panic */ } /* end else */ /* Main instruction loop */ @@ -489,7 +513,7 @@ int32 spec, disp, rn, index, numspec; int32 vfldrp1, brdisp, flg, mstat; int32 i, j, r, rh, temp; t_addr va, iad; -int32 opnd[10]; /* operand queue */ +int32 opnd[OPND_SIZE]; /* operand queue */ if (cpu_astop) { cpu_astop = 0; @@ -513,29 +537,35 @@ if (sim_interval <= 0) { /* chk clock queue */ if (trpirq) { /* trap or interrupt? */ if (temp = GET_TRAP (trpirq)) { /* trap? */ - cc = intexc (SCB_ARITH, cc, 0, IE_EXC); /* take, clear trap */ - GET_CUR; /* set cur mode */ - in_ie = 1; - Write (SP - 4, temp, L_LONG, WA); /* write parameter */ - SP = SP - 4; - in_ie = 0; } + cc = intexc (SCB_ARITH, cc, 0, IE_EXC); /* take, clear trap */ + GET_CUR; /* set cur mode */ + in_ie = 1; + Write (SP - 4, temp, L_LONG, WA); /* write parameter */ + SP = SP - 4; + in_ie = 0; } else if (temp = GET_IRQL (trpirq)) { /* interrupt? */ - int32 vec; - if (temp > IPL_HMAX) { /* error req lvl? */ - if (temp == IPL_MEMERR) { /* mem error? */ - vec = SCB_MEMERR; - mem_err = 0; } - else if (temp == IPL_CRDERR) { /* CRD error? */ - vec = SCB_CRDERR; - crd_err = 0; } - else ABORT (STOP_UIPL); } /* unknown intr */ - else if (temp >= IPL_HMIN) /* hardware req? */ - vec = get_vector (temp); /* get vector */ - else if (temp > IPL_SMAX) ABORT (STOP_UIPL); - else { vec = SCB_IPLSOFT + (temp << 2); - SISR = SISR & ~(1u << temp); } - if (vec) cc = intexc (vec, cc, temp, IE_INT); /* take intr */ - GET_CUR; } /* set cur mode */ + int32 vec; + if (temp == IPL_HLTPIN) { /* console halt? */ + cc = con_halt (CON_HLTPIN, cc); /* invoke firmware */ + hlt_pin = 0; /* clear intr */ + trpirq = 0; /* clear everything */ + continue; } /* continue */ + if (temp == IPL_MEMERR) { /* mem error? */ + vec = SCB_MEMERR; + mem_err = 0; } + else if (temp == IPL_CRDERR) { /* CRD error? */ + vec = SCB_CRDERR; + crd_err = 0; } + else if (temp > IPL_HMAX) { /* error req lvl? */ + ABORT (STOP_UIPL); } /* unknown intr */ + else if (temp >= IPL_HMIN) /* hardware req? */ + vec = get_vector (temp); /* get vector */ + else if (temp > IPL_SMAX) ABORT (STOP_UIPL); + else { + vec = SCB_IPLSOFT + (temp << 2); + SISR = SISR & ~(1u << temp); } + if (vec) cc = intexc (vec, cc, temp, IE_INT);/* take intr */ + GET_CUR; } /* set cur mode */ else trpirq = 0; /* clear everything */ SET_IRQL; /* eval interrupts */ continue; } @@ -577,385 +607,407 @@ else { numspec = numspec & DR_NSPMASK; /* get # specifiers */ */ for (i = 1, j = 0; i <= numspec; i++) { /* loop thru specs */ - disp = drom[opc][i]; /* get dispatch */ - if (disp >= BB) { - GET_ISTR (brdisp, DR_LNT (disp)); - break; } - GET_ISTR (spec, L_BYTE); /* get spec byte */ - rn = spec & RGMASK; /* get reg # */ - disp = (spec & ~RGMASK) | disp; /* merge w dispatch */ - switch (disp) { /* dispatch spec */ + disp = drom[opc][i]; /* get dispatch */ + if (disp >= BB) { + GET_ISTR (brdisp, DR_LNT (disp)); + break; } + GET_ISTR (spec, L_BYTE); /* get spec byte */ + rn = spec & RGMASK; /* get reg # */ + disp = (spec & ~RGMASK) | disp; /* merge w dispatch */ + switch (disp) { /* dispatch spec */ /* Short literal - only read access permitted */ - case SH0|RB: case SH0|RW: case SH0|RL: - case SH1|RB: case SH1|RW: case SH1|RL: - case SH2|RB: case SH2|RW: case SH2|RL: - case SH3|RB: case SH3|RW: case SH3|RL: - opnd[j++] = spec; - break; - case SH0|RQ: case SH1|RQ: case SH2|RQ: case SH3|RQ: - opnd[j++] = spec; - opnd[j++] = 0; - break; - case SH0|RF: case SH1|RF: case SH2|RF: case SH3|RF: - opnd[j++] = (spec << 4) | 0x4000; - break; - case SH0|RD: case SH1|RD: case SH2|RD: case SH3|RD: - opnd[j++] = (spec << 4) | 0x4000; - opnd[j++] = 0; - break; - case SH0|RG: case SH1|RG: case SH2|RG: case SH3|RG: - opnd[j++] = (spec << 1) | 0x4000; - opnd[j++] = 0; - break; + case SH0|RB: case SH0|RW: case SH0|RL: + case SH1|RB: case SH1|RW: case SH1|RL: + case SH2|RB: case SH2|RW: case SH2|RL: + case SH3|RB: case SH3|RW: case SH3|RL: + opnd[j++] = spec; + break; + case SH0|RQ: case SH1|RQ: case SH2|RQ: case SH3|RQ: + opnd[j++] = spec; + opnd[j++] = 0; + break; + case SH0|RF: case SH1|RF: case SH2|RF: case SH3|RF: + opnd[j++] = (spec << 4) | 0x4000; + break; + case SH0|RD: case SH1|RD: case SH2|RD: case SH3|RD: + opnd[j++] = (spec << 4) | 0x4000; + opnd[j++] = 0; + break; + case SH0|RG: case SH1|RG: case SH2|RG: case SH3|RG: + opnd[j++] = (spec << 1) | 0x4000; + opnd[j++] = 0; + break; /* Register */ - case GRN|RB: case GRN|MB: - CHECK_FOR_PC; - opnd[j++] = R[rn] & BMASK; - break; - case GRN|RW: case GRN|MW: - CHECK_FOR_PC; - opnd[j++] = R[rn] & WMASK; - break; - case GRN|VB: - vfldrp1 = R[rnplus1]; - case GRN|WB: case GRN|WW: case GRN|WL: case GRN|WQ: - opnd[j++] = rn; - case GRN|RL: case GRN|RF: case GRN|ML: - CHECK_FOR_PC; - opnd[j++] = R[rn]; - break; - case GRN|RQ: case GRN|RD: case GRN|RG: case GRN|MQ: - CHECK_FOR_SP; - opnd[j++] = R[rn]; - opnd[j++] = R[rnplus1]; - break; + case GRN|RB: case GRN|MB: + CHECK_FOR_PC; + opnd[j++] = R[rn] & BMASK; + break; + case GRN|RW: case GRN|MW: + CHECK_FOR_PC; + opnd[j++] = R[rn] & WMASK; + break; + case GRN|VB: + vfldrp1 = R[rnplus1]; + case GRN|WB: case GRN|WW: case GRN|WL: case GRN|WQ: + opnd[j++] = rn; + case GRN|RL: case GRN|RF: case GRN|ML: + CHECK_FOR_PC; + opnd[j++] = R[rn]; + break; + case GRN|RQ: case GRN|RD: case GRN|RG: case GRN|MQ: + CHECK_FOR_SP; + opnd[j++] = R[rn]; + opnd[j++] = R[rnplus1]; + break; /* Register deferred, autodecrement */ - case RGD|VB: - case RGD|WB: case RGD|WW: case RGD|WL: case RGD|WQ: - opnd[j++] = OP_MEM; - case RGD|AB: case RGD|AW: case RGD|AL: case RGD|AQ: - CHECK_FOR_PC; - va = opnd[j++] = R[rn]; - break; - case ADC|VB: - case ADC|WB: case ADC|WW: case ADC|WL: case ADC|WQ: - opnd[j++] = OP_MEM; - case ADC|AB: case ADC|AW: case ADC|AL: case ADC|AQ: - CHECK_FOR_PC; - va = opnd[j++] = R[rn] = R[rn] - DR_LNT (disp); - recq[recqptr++] = RECW (disp); - break; - case ADC|RB: case ADC|RW: case ADC|RL: case ADC|RF: - case ADC|MB: case ADC|MW: case ADC|ML: - R[rn] = R[rn] - (DR_LNT (disp)); - recq[recqptr++] = RECW (disp); - case RGD|RB: case RGD|RW: case RGD|RL: case RGD|RF: - case RGD|MB: case RGD|MW: case RGD|ML: - CHECK_FOR_PC; - opnd[j++] = Read (va = R[rn], DR_LNT (disp), RA); - break; - case ADC|RQ: case ADC|RD: case ADC|RG: case ADC|MQ: - R[rn] = R[rn] - 8; - recq[recqptr++] = RECW (disp); - case RGD|RQ: case RGD|RD: case RGD|RG: case RGD|MQ: - CHECK_FOR_PC; - opnd[j++] = Read (va = R[rn], L_LONG, RA); - opnd[j++] = Read (R[rn] + 4, L_LONG, RA); - break; + case RGD|VB: + case RGD|WB: case RGD|WW: case RGD|WL: case RGD|WQ: + opnd[j++] = OP_MEM; + case RGD|AB: case RGD|AW: case RGD|AL: case RGD|AQ: + CHECK_FOR_PC; + va = opnd[j++] = R[rn]; + break; + case ADC|VB: + case ADC|WB: case ADC|WW: case ADC|WL: case ADC|WQ: + opnd[j++] = OP_MEM; + case ADC|AB: case ADC|AW: case ADC|AL: case ADC|AQ: + CHECK_FOR_PC; + va = opnd[j++] = R[rn] = R[rn] - DR_LNT (disp); + recq[recqptr++] = RECW (disp); + break; + case ADC|RB: case ADC|RW: case ADC|RL: case ADC|RF: + case ADC|MB: case ADC|MW: case ADC|ML: + R[rn] = R[rn] - (DR_LNT (disp)); + recq[recqptr++] = RECW (disp); + case RGD|RB: case RGD|RW: case RGD|RL: case RGD|RF: + case RGD|MB: case RGD|MW: case RGD|ML: + CHECK_FOR_PC; + opnd[j++] = Read (va = R[rn], DR_LNT (disp), RA); + break; + case ADC|RQ: case ADC|RD: case ADC|RG: case ADC|MQ: + R[rn] = R[rn] - 8; + recq[recqptr++] = RECW (disp); + case RGD|RQ: case RGD|RD: case RGD|RG: case RGD|MQ: + CHECK_FOR_PC; + opnd[j++] = Read (va = R[rn], L_LONG, RA); + opnd[j++] = Read (R[rn] + 4, L_LONG, RA); + break; /* Autoincrement */ - case AIN|VB: - case AIN|WB: case AIN|WW: case AIN|WL: case AIN|WQ: -/* CHECK_FOR_PC; */ - opnd[j++] = OP_MEM; - case AIN|AB: case AIN|AW: case AIN|AL: case AIN|AQ: - va = opnd[j++] = R[rn]; - if (rn == nPC) { - if (DR_LNT (disp) == L_QUAD) { - GET_ISTR (temp, L_LONG); - GET_ISTR (temp, L_LONG); } - else GET_ISTR (temp, DR_LNT (disp)); } - else { R[rn] = R[rn] + DR_LNT (disp); - recq[recqptr++] = RECW (disp); } - break; - case AIN|MB: case AIN|MW: case AIN|ML: -/* CHECK_FOR_PC; */ - case AIN|RB: case AIN|RW: case AIN|RL: case AIN|RF: - va = R[rn]; - if (rn == nPC) { GET_ISTR (opnd[j++], DR_LNT (disp)); } - else { opnd[j++] = Read (R[rn], DR_LNT (disp), RA); - R[rn] = R[rn] + DR_LNT (disp); - recq[recqptr++] = RECW (disp); } - break; - case AIN|MQ: -/* CHECK_FOR_PC; */ - case AIN|RQ: case AIN|RD: case AIN|RG: - va = R[rn]; - if (rn == nPC) { - GET_ISTR (opnd[j++], L_LONG); - GET_ISTR (opnd[j++], L_LONG); } - else { opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - R[rn] = R[rn] + 8; - recq[recqptr++] = RECW (disp); } - break; + case AIN|VB: + case AIN|WB: case AIN|WW: case AIN|WL: case AIN|WQ: +/* CHECK_FOR_PC; */ + opnd[j++] = OP_MEM; + case AIN|AB: case AIN|AW: case AIN|AL: case AIN|AQ: + va = opnd[j++] = R[rn]; + if (rn == nPC) { + if (DR_LNT (disp) == L_QUAD) { + GET_ISTR (temp, L_LONG); + GET_ISTR (temp, L_LONG); } + else GET_ISTR (temp, DR_LNT (disp)); } + else { + R[rn] = R[rn] + DR_LNT (disp); + recq[recqptr++] = RECW (disp); } + break; + case AIN|MB: case AIN|MW: case AIN|ML: +/* CHECK_FOR_PC; */ + case AIN|RB: case AIN|RW: case AIN|RL: case AIN|RF: + va = R[rn]; + if (rn == nPC) { GET_ISTR (opnd[j++], DR_LNT (disp)); } + else { + opnd[j++] = Read (R[rn], DR_LNT (disp), RA); + R[rn] = R[rn] + DR_LNT (disp); + recq[recqptr++] = RECW (disp); } + break; + case AIN|MQ: +/* CHECK_FOR_PC; */ + case AIN|RQ: case AIN|RD: case AIN|RG: + va = R[rn]; + if (rn == nPC) { + GET_ISTR (opnd[j++], L_LONG); + GET_ISTR (opnd[j++], L_LONG); } + else { + opnd[j++] = Read (va, L_LONG, RA); + opnd[j++] = Read (va + 4, L_LONG, RA); + R[rn] = R[rn] + 8; + recq[recqptr++] = RECW (disp); } + break; /* Autoincrement deferred */ - case AID|VB: - case AID|WB: case AID|WW: case AID|WL: case AID|WQ: - opnd[j++] = OP_MEM; - case AID|AB: case AID|AW: case AID|AL: case AID|AQ: - if (rn == nPC) { GET_ISTR (va = opnd[j++], L_LONG); } - else { va = opnd[j++] = Read (R[rn], L_LONG, RA); - R[rn] = R[rn] + 4; - recq[recqptr++] = RECW (AID|RL); } - break; - case AID|RB: case AID|RW: case AID|RL: case AID|RF: - case AID|MB: case AID|MW: case AID|ML: - if (rn == nPC) { GET_ISTR (va, L_LONG); } - else { va = Read (R[rn], L_LONG, RA); - R[rn] = R[rn] + 4; - recq[recqptr++] = RECW (AID|RL); } - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case AID|RQ: case AID|RD: case AID|RG: case AID|MQ: - if (rn == nPC) { GET_ISTR (va, L_LONG); } - else { va = Read (R[rn], L_LONG, RA); - R[rn] = R[rn] + 4; - recq[recqptr++] = RECW (AID|RL); } - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; + case AID|VB: + case AID|WB: case AID|WW: case AID|WL: case AID|WQ: + opnd[j++] = OP_MEM; + case AID|AB: case AID|AW: case AID|AL: case AID|AQ: + if (rn == nPC) { GET_ISTR (va = opnd[j++], L_LONG); } + else { + va = opnd[j++] = Read (R[rn], L_LONG, RA); + R[rn] = R[rn] + 4; + recq[recqptr++] = RECW (AID|RL); } + break; + case AID|RB: case AID|RW: case AID|RL: case AID|RF: + case AID|MB: case AID|MW: case AID|ML: + if (rn == nPC) { GET_ISTR (va, L_LONG); } + else { + va = Read (R[rn], L_LONG, RA); + R[rn] = R[rn] + 4; + recq[recqptr++] = RECW (AID|RL); } + opnd[j++] = Read (va, DR_LNT (disp), RA); + break; + case AID|RQ: case AID|RD: case AID|RG: case AID|MQ: + if (rn == nPC) { GET_ISTR (va, L_LONG); } + else { + va = Read (R[rn], L_LONG, RA); + R[rn] = R[rn] + 4; + recq[recqptr++] = RECW (AID|RL); } + opnd[j++] = Read (va, L_LONG, RA); + opnd[j++] = Read (va + 4, L_LONG, RA); + break; /* Byte displacement */ - case BDP|VB: - case BDP|WB: case BDP|WW: case BDP|WL: case BDP|WQ: - opnd[j++] = OP_MEM; - case BDP|AB: case BDP|AW: case BDP|AL: case BDP|AQ: - GET_ISTR (temp, L_BYTE); - va = opnd[j++] = R[rn] + SXTB (temp); - break; - case BDP|RB: case BDP|RW: case BDP|RL: case BDP|RF: - case BDP|MB: case BDP|MW: case BDP|ML: - GET_ISTR (temp, L_BYTE); - va = R[rn] + SXTB (temp); - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case BDP|RQ: case BDP|RD: case BDP|RG: case BDP|MQ: - GET_ISTR (temp, L_BYTE); - va = R[rn] + SXTB (temp); - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; + case BDP|VB: + case BDP|WB: case BDP|WW: case BDP|WL: case BDP|WQ: + opnd[j++] = OP_MEM; + case BDP|AB: case BDP|AW: case BDP|AL: case BDP|AQ: + GET_ISTR (temp, L_BYTE); + va = opnd[j++] = R[rn] + SXTB (temp); + break; + case BDP|RB: case BDP|RW: case BDP|RL: case BDP|RF: + case BDP|MB: case BDP|MW: case BDP|ML: + GET_ISTR (temp, L_BYTE); + va = R[rn] + SXTB (temp); + opnd[j++] = Read (va, DR_LNT (disp), RA); + break; + case BDP|RQ: case BDP|RD: case BDP|RG: case BDP|MQ: + GET_ISTR (temp, L_BYTE); + va = R[rn] + SXTB (temp); + opnd[j++] = Read (va, L_LONG, RA); + opnd[j++] = Read (va + 4, L_LONG, RA); + break; /* Byte displacement deferred */ - case BDD|VB: - case BDD|WB: case BDD|WW: case BDD|WL: case BDD|WQ: - opnd[j++] = OP_MEM; - case BDD|AB: case BDD|AW: case BDD|AL: case BDD|AQ: - GET_ISTR (temp, L_BYTE); - iad = R[rn] + SXTB (temp); - va = opnd[j++] = Read (iad, L_LONG, RA); - break; - case BDD|RB: case BDD|RW: case BDD|RL: case BDD|RF: - case BDD|MB: case BDD|MW: case BDD|ML: - GET_ISTR (temp, L_BYTE); - iad = R[rn] + SXTB (temp); - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case BDD|RQ: case BDD|RD: case BDD|RG: case BDD|MQ: - GET_ISTR (temp, L_BYTE); - iad = R[rn] + SXTB (temp); - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; + case BDD|VB: + case BDD|WB: case BDD|WW: case BDD|WL: case BDD|WQ: + opnd[j++] = OP_MEM; + case BDD|AB: case BDD|AW: case BDD|AL: case BDD|AQ: + GET_ISTR (temp, L_BYTE); + iad = R[rn] + SXTB (temp); + va = opnd[j++] = Read (iad, L_LONG, RA); + break; + case BDD|RB: case BDD|RW: case BDD|RL: case BDD|RF: + case BDD|MB: case BDD|MW: case BDD|ML: + GET_ISTR (temp, L_BYTE); + iad = R[rn] + SXTB (temp); + va = Read (iad, L_LONG, RA); + opnd[j++] = Read (va, DR_LNT (disp), RA); + break; + case BDD|RQ: case BDD|RD: case BDD|RG: case BDD|MQ: + GET_ISTR (temp, L_BYTE); + iad = R[rn] + SXTB (temp); + va = Read (iad, L_LONG, RA); + opnd[j++] = Read (va, L_LONG, RA); + opnd[j++] = Read (va + 4, L_LONG, RA); + break; /* Word displacement */ - case WDP|VB: - case WDP|WB: case WDP|WW: case WDP|WL: case WDP|WQ: - opnd[j++] = OP_MEM; - case WDP|AB: case WDP|AW: case WDP|AL: case WDP|AQ: - GET_ISTR (temp, L_WORD); - va = opnd[j++] = R[rn] + SXTW (temp); - break; - case WDP|MB: case WDP|MW: case WDP|ML: - case WDP|RB: case WDP|RW: case WDP|RL: case WDP|RF: - GET_ISTR (temp, L_WORD); - va = R[rn] + SXTW (temp); - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case WDP|MQ: case WDP|RQ: case WDP|RD: case WDP|RG: - GET_ISTR (temp, L_WORD); - va = R[rn] + SXTW (temp); - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; + case WDP|VB: + case WDP|WB: case WDP|WW: case WDP|WL: case WDP|WQ: + opnd[j++] = OP_MEM; + case WDP|AB: case WDP|AW: case WDP|AL: case WDP|AQ: + GET_ISTR (temp, L_WORD); + va = opnd[j++] = R[rn] + SXTW (temp); + break; + case WDP|MB: case WDP|MW: case WDP|ML: + case WDP|RB: case WDP|RW: case WDP|RL: case WDP|RF: + GET_ISTR (temp, L_WORD); + va = R[rn] + SXTW (temp); + opnd[j++] = Read (va, DR_LNT (disp), RA); + break; + case WDP|MQ: case WDP|RQ: case WDP|RD: case WDP|RG: + GET_ISTR (temp, L_WORD); + va = R[rn] + SXTW (temp); + opnd[j++] = Read (va, L_LONG, RA); + opnd[j++] = Read (va + 4, L_LONG, RA); + break; /* Word displacement deferred */ - case WDD|VB: - case WDD|WB: case WDD|WW: case WDD|WL: case WDD|WQ: - opnd[j++] = OP_MEM; - case WDD|AB: case WDD|AW: case WDD|AL: case WDD|AQ: - GET_ISTR (temp, L_WORD); - iad = R[rn] + SXTW (temp); - va = opnd[j++] = Read (iad, L_LONG, RA); - break; - case WDD|MB: case WDD|MW: case WDD|ML: - case WDD|RB: case WDD|RW: case WDD|RL: case WDD|RF: - GET_ISTR (temp, L_WORD); - iad = R[rn] + SXTW (temp); - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case WDD|MQ: case WDD|RQ: case WDD|RD: case WDD|RG: - GET_ISTR (temp, L_WORD); - iad = R[rn] + SXTW (temp); - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; + case WDD|VB: + case WDD|WB: case WDD|WW: case WDD|WL: case WDD|WQ: + opnd[j++] = OP_MEM; + case WDD|AB: case WDD|AW: case WDD|AL: case WDD|AQ: + GET_ISTR (temp, L_WORD); + iad = R[rn] + SXTW (temp); + va = opnd[j++] = Read (iad, L_LONG, RA); + break; + case WDD|MB: case WDD|MW: case WDD|ML: + case WDD|RB: case WDD|RW: case WDD|RL: case WDD|RF: + GET_ISTR (temp, L_WORD); + iad = R[rn] + SXTW (temp); + va = Read (iad, L_LONG, RA); + opnd[j++] = Read (va, DR_LNT (disp), RA); + break; + case WDD|MQ: case WDD|RQ: case WDD|RD: case WDD|RG: + GET_ISTR (temp, L_WORD); + iad = R[rn] + SXTW (temp); + va = Read (iad, L_LONG, RA); + opnd[j++] = Read (va, L_LONG, RA); + opnd[j++] = Read (va + 4, L_LONG, RA); + break; /* Longword displacement */ - case LDP|VB: - case LDP|WB: case LDP|WW: case LDP|WL: case LDP|WQ: - opnd[j++] = OP_MEM; - case LDP|AB: case LDP|AW: case LDP|AL: case LDP|AQ: - GET_ISTR (temp, L_LONG); - va = opnd[j++] = R[rn] + temp; - break; - case LDP|MB: case LDP|MW: case LDP|ML: - case LDP|RB: case LDP|RW: case LDP|RL: case LDP|RF: - GET_ISTR (temp, L_LONG); - va = R[rn] + temp; - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case LDP|MQ: case LDP|RQ: case LDP|RD: case LDP|RG: - GET_ISTR (temp, L_LONG); - va = R[rn] + temp; - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; + case LDP|VB: + case LDP|WB: case LDP|WW: case LDP|WL: case LDP|WQ: + opnd[j++] = OP_MEM; + case LDP|AB: case LDP|AW: case LDP|AL: case LDP|AQ: + GET_ISTR (temp, L_LONG); + va = opnd[j++] = R[rn] + temp; + break; + case LDP|MB: case LDP|MW: case LDP|ML: + case LDP|RB: case LDP|RW: case LDP|RL: case LDP|RF: + GET_ISTR (temp, L_LONG); + va = R[rn] + temp; + opnd[j++] = Read (va, DR_LNT (disp), RA); + break; + case LDP|MQ: case LDP|RQ: case LDP|RD: case LDP|RG: + GET_ISTR (temp, L_LONG); + va = R[rn] + temp; + opnd[j++] = Read (va, L_LONG, RA); + opnd[j++] = Read (va + 4, L_LONG, RA); + break; /* Longword displacement deferred */ - case LDD|VB: - case LDD|WB: case LDD|WW: case LDD|WL: case LDD|WQ: - opnd[j++] = OP_MEM; - case LDD|AB: case LDD|AW: case LDD|AL: case LDD|AQ: - GET_ISTR (temp, L_LONG); - iad = R[rn] + temp; - va = opnd[j++] = Read (iad, L_LONG, RA); - break; - case LDD|MB: case LDD|MW: case LDD|ML: - case LDD|RB: case LDD|RW: case LDD|RL: case LDD|RF: - GET_ISTR (temp, L_LONG); - iad = R[rn] + temp; - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, DR_LNT (disp), RA); - break; - case LDD|MQ: case LDD|RQ: case LDD|RD: case LDD|RG: - GET_ISTR (temp, L_LONG); - iad = R[rn] + temp; - va = Read (iad, L_LONG, RA); - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; + case LDD|VB: + case LDD|WB: case LDD|WW: case LDD|WL: case LDD|WQ: + opnd[j++] = OP_MEM; + case LDD|AB: case LDD|AW: case LDD|AL: case LDD|AQ: + GET_ISTR (temp, L_LONG); + iad = R[rn] + temp; + va = opnd[j++] = Read (iad, L_LONG, RA); + break; + case LDD|MB: case LDD|MW: case LDD|ML: + case LDD|RB: case LDD|RW: case LDD|RL: case LDD|RF: + GET_ISTR (temp, L_LONG); + iad = R[rn] + temp; + va = Read (iad, L_LONG, RA); + opnd[j++] = Read (va, DR_LNT (disp), RA); + break; + case LDD|MQ: case LDD|RQ: case LDD|RD: case LDD|RG: + GET_ISTR (temp, L_LONG); + iad = R[rn] + temp; + va = Read (iad, L_LONG, RA); + opnd[j++] = Read (va, L_LONG, RA); + opnd[j++] = Read (va + 4, L_LONG, RA); + break; /* Index */ - case IDX|VB: - case IDX|WB: case IDX|WW: case IDX|WL: case IDX|WQ: - case IDX|AB: case IDX|AW: case IDX|AL: case IDX|AQ: - case IDX|MB: case IDX|MW: case IDX|ML: case IDX|MQ: - case IDX|RB: case IDX|RW: case IDX|RL: case IDX|RQ: - case IDX|RF: case IDX|RD: case IDX|RG: - index = R[rn] << (disp & 03); - CHECK_FOR_PC; - GET_ISTR (spec, L_BYTE); - rn = spec & RGMASK; - switch (spec & ~RGMASK) { - case ADC: - R[rn] = R[rn] - DR_LNT (disp); - recq[recqptr++] = RECW (ADC | (disp & DR_LNMASK)); - case RGD: - CHECK_FOR_PC; - index = index + R[rn]; - break; - case AIN: - CHECK_FOR_PC; - index = index + R[rn]; - R[rn] = R[rn] + DR_LNT (disp); - recq[recqptr++] = RECW (AIN | (disp & DR_LNMASK)); - break; - case AID: - if (rn == nPC) { GET_ISTR (temp, L_LONG); } - else { temp = Read (R[rn], L_LONG, RA); - R[rn] = R[rn] + 4; - recq[recqptr++] = RECW (AID|RL); } - index = temp + index; - break; - case BDP: - GET_ISTR (temp, L_BYTE); - index = index + R[rn] + SXTB (temp); - break; - case BDD: - GET_ISTR (temp, L_BYTE); - index = index + Read (R[rn] + SXTB (temp), L_LONG, RA); - break; - case WDP: - GET_ISTR (temp, L_WORD); - index = index + R[rn] + SXTW (temp); - break; - case WDD: - GET_ISTR (temp, L_WORD); - index = index + Read (R[rn] + SXTW (temp), L_LONG, RA); - break; - case LDP: - GET_ISTR (temp, L_LONG); - index = index + R[rn] + temp; - break; - case LDD: - GET_ISTR (temp, L_LONG); - index = index + Read (R[rn] + temp, L_LONG, RA); - break; - default: - RSVD_ADDR_FAULT; } /* end case idxspec */ - switch (disp & 0xF) { /* case disp type */ - case WB: case WW: case WL: case WQ: - opnd[j++] = OP_MEM; - case AB: case AW: case AL: case AQ: - va = opnd[j++] = index; - break; - case MB: case MW: case ML: - case RB: case RW: case RL: - opnd[j++] = Read (va = index, DR_LNT (disp), RA); - break; - case RQ: case MQ: - opnd[j++] = Read (va = index, L_LONG, RA); - opnd[j++] = Read (index + 4, L_LONG, RA); - break; } /* end case access/lnt */ - break; /* end index */ - default: /* all others */ - RSVD_ADDR_FAULT; /* fault */ - break; - } /* end case spec */ + case IDX|VB: + case IDX|WB: case IDX|WW: case IDX|WL: case IDX|WQ: + case IDX|AB: case IDX|AW: case IDX|AL: case IDX|AQ: + case IDX|MB: case IDX|MW: case IDX|ML: case IDX|MQ: + case IDX|RB: case IDX|RW: case IDX|RL: case IDX|RQ: + case IDX|RF: case IDX|RD: case IDX|RG: + index = R[rn] << (disp & 03); + CHECK_FOR_PC; + GET_ISTR (spec, L_BYTE); + rn = spec & RGMASK; + switch (spec & ~RGMASK) { + case ADC: + R[rn] = R[rn] - DR_LNT (disp); + recq[recqptr++] = RECW (ADC | (disp & DR_LNMASK)); + case RGD: + CHECK_FOR_PC; + index = index + R[rn]; + break; + case AIN: + CHECK_FOR_PC; + index = index + R[rn]; + R[rn] = R[rn] + DR_LNT (disp); + recq[recqptr++] = RECW (AIN | (disp & DR_LNMASK)); + break; + case AID: + if (rn == nPC) { GET_ISTR (temp, L_LONG); } + else { + temp = Read (R[rn], L_LONG, RA); + R[rn] = R[rn] + 4; + recq[recqptr++] = RECW (AID|RL); } + index = temp + index; + break; + case BDP: + GET_ISTR (temp, L_BYTE); + index = index + R[rn] + SXTB (temp); + break; + case BDD: + GET_ISTR (temp, L_BYTE); + index = index + Read (R[rn] + SXTB (temp), L_LONG, RA); + break; + case WDP: + GET_ISTR (temp, L_WORD); + index = index + R[rn] + SXTW (temp); + break; + case WDD: + GET_ISTR (temp, L_WORD); + index = index + Read (R[rn] + SXTW (temp), L_LONG, RA); + break; + case LDP: + GET_ISTR (temp, L_LONG); + index = index + R[rn] + temp; + break; + case LDD: + GET_ISTR (temp, L_LONG); + index = index + Read (R[rn] + temp, L_LONG, RA); + break; + default: + RSVD_ADDR_FAULT; } /* end case idxspec */ + switch (disp & 0xF) { /* case disp type */ + case WB: case WW: case WL: case WQ: + opnd[j++] = OP_MEM; + case AB: case AW: case AL: case AQ: + va = opnd[j++] = index; + break; + case MB: case MW: case ML: + case RB: case RW: case RL: + opnd[j++] = Read (va = index, DR_LNT (disp), RA); + break; + case RQ: case MQ: + opnd[j++] = Read (va = index, L_LONG, RA); + opnd[j++] = Read (index + 4, L_LONG, RA); + break; } /* end case access/lnt */ + break; /* end index */ + default: /* all others */ + RSVD_ADDR_FAULT; /* fault */ + break; + } /* end case spec */ } /* end for */ -} /* end if not FPD */ +} + /* end if not FPD */ +/* Optionally record instruction history */ + +if (hst_lnt) { + struct InstHistory *h = &hst[hst_p]; + int32 i; + + hst_p = (hst_p + 1) % HIST_SIZE; + h->iPC = fault_PC; + h->PSL = PSL | cc; + h->opc = opc; + h->brdest = brdisp + PC; + for (i = 0; i < (numspec & DR_NSPMASK); i++) + h->opnd[i] = opnd[i]; + } /* Dispatch to instructions */ @@ -1139,12 +1191,13 @@ case CVTWB: case ADAWI: if (op1 >= 0) { /* reg? ADDW2 */ - temp = R[op1]; - r = R[op1] = (op0 + temp) & WMASK; } - else { if (op2 & 1) RSVD_OPND_FAULT; /* mem? chk align */ - temp = Read (op2, L_WORD, WA); /* ok, ADDW2 */ - r = (op0 + temp) & WMASK; - WRITE_W (r); } + temp = R[op1]; + r = R[op1] = (op0 + temp) & WMASK; } + else { + if (op2 & 1) RSVD_OPND_FAULT; /* mem? chk align */ + temp = Read (op2, L_WORD, WA); /* ok, ADDW2 */ + r = (op0 + temp) & WMASK; + WRITE_W (r); } CC_ADD_W (r, op0, temp); /* set cc's */ break; @@ -1250,45 +1303,48 @@ case MULL2: case MULL3: break; case DIVB2: case DIVB3: if (op0 == 0) { /* div by zero? */ - r = op1; - temp = CC_V; - SET_TRAP (TRAP_DIVZRO); } + r = op1; + temp = CC_V; + SET_TRAP (TRAP_DIVZRO); } else if ((op0 == BMASK) && (op1 == BSIGN)) { /* overflow? */ - r = op1; - temp = CC_V; - INTOV; } - else { r = SXTB (op1) / SXTB (op0); /* ok, divide */ - temp = 0; } + r = op1; + temp = CC_V; + INTOV; } + else { + r = SXTB (op1) / SXTB (op0); /* ok, divide */ + temp = 0; } WRITE_B (r); /* write result */ CC_IIZZ_B (r); /* set cc's */ cc = cc | temp; /* error? set V */ break; case DIVW2: case DIVW3: if (op0 == 0) { /* div by zero? */ - r = op1; - temp = CC_V; - SET_TRAP (TRAP_DIVZRO); } + r = op1; + temp = CC_V; + SET_TRAP (TRAP_DIVZRO); } else if ((op0 == WMASK) && (op1 == WSIGN)) { /* overflow? */ - r = op1; - temp = CC_V; - INTOV; } - else { r = SXTW (op1) / SXTW (op0); /* ok, divide */ - temp = 0; } + r = op1; + temp = CC_V; + INTOV; } + else { + r = SXTW (op1) / SXTW (op0); /* ok, divide */ + temp = 0; } WRITE_W (r); /* write result */ CC_IIZZ_W (r); /* set cc's */ cc = cc | temp; /* error? set V */ break; case DIVL2: case DIVL3: if (op0 == 0) { /* div by zero? */ - r = op1; - temp = CC_V; - SET_TRAP (TRAP_DIVZRO); } + r = op1; + temp = CC_V; + SET_TRAP (TRAP_DIVZRO); } else if ((op0 == LMASK) && (op1 == LSIGN)) { /* overflow? */ - r = op1; - temp = CC_V; - INTOV; } - else { r = op1 / op0; /* ok, divide */ - temp = 0; } + r = op1; + temp = CC_V; + INTOV; } + else { + r = op1 / op0; /* ok, divide */ + temp = 0; } WRITE_L (r); /* write result */ CC_IIZZ_L (r); /* set cc's */ cc = cc | temp; /* error? set V */ @@ -1366,25 +1422,27 @@ case MOVQ: case ROTL: j = op0 % 32; /* reduce sc, mod 32 */ if (j) r = ((((uint32) op1) << j) | - (((uint32) op1) >> (32 - j))) & LMASK; + (((uint32) op1) >> (32 - j))) & LMASK; else r = op1; WRITE_L (r); /* store result */ CC_IIZP_L (r); /* set cc's */ break; case ASHL: if (op0 & BSIGN) { /* right shift? */ - temp = 0x100 - op0; /* get |shift| */ - if (temp > 31) r = (op1 & LSIGN)? -1: 0; /* sc > 31? */ - else r = op1 >> temp; /* shift */ - WRITE_L (r); /* store result */ - CC_IIZZ_L (r); /* set cc's */ + temp = 0x100 - op0; /* get |shift| */ + if (temp > 31) r = (op1 & LSIGN)? -1: 0; /* sc > 31? */ + else r = op1 >> temp; /* shift */ + WRITE_L (r); /* store result */ + CC_IIZZ_L (r); /* set cc's */ break; } - else { if (op0 > 31) r = temp = 0; /* sc > 31? */ - else { r = ((uint32) op1) << op0; /* shift */ - temp = r >> op0; } /* shift back */ - WRITE_L (r); /* store result */ - CC_IIZZ_L (r); /* set cc's */ - if (op1 != temp) { V_INTOV; } } /* bits lost? */ + else { + if (op0 > 31) r = temp = 0; /* sc > 31? */ + else { + r = ((uint32) op1) << op0; /* shift */ + temp = r >> op0; } /* shift back */ + WRITE_L (r); /* store result */ + CC_IIZZ_L (r); /* set cc's */ + if (op1 != temp) { V_INTOV; } } /* bits lost? */ break; case ASHQ: r = op_ashq (opnd, &rh, &flg); /* do qw shift */ @@ -1405,7 +1463,7 @@ case EMUL: r = op_emul (op0, op1, &rh); /* calc 64b result */ r = r + op2; /* add 32b value */ rh = rh + (((uint32) r) < ((uint32) op2)) - /* into 64b result */ - ((op2 & LSIGN)? 1: 0); + ((op2 & LSIGN)? 1: 0); WRITE_Q (r, rh); /* write result */ CC_IIZZ_Q (r, rh); /* set cc's */ break; @@ -1421,12 +1479,13 @@ case EMUL: case EDIV: if (op5 < 0) Read (op6, L_LONG, WA); /* wtest remainder */ if (op0 == 0) { /* divide by zero? */ - flg = CC_V; /* set V */ - r = opnd[1]; /* quo = low divd */ - rh = 0; /* rem = 0 */ - SET_TRAP (TRAP_DIVZRO); } /* set trap */ - else { r = op_ediv (opnd, &rh, &flg); /* extended divide */ - if (flg) { INTOV; } } /* if ovf+IV, set trap */ + flg = CC_V; /* set V */ + r = opnd[1]; /* quo = low divd */ + rh = 0; /* rem = 0 */ + SET_TRAP (TRAP_DIVZRO); } /* set trap */ + else { + r = op_ediv (opnd, &rh, &flg); /* extended divide */ + if (flg) { INTOV; } } /* if ovf+IV, set trap */ if (op3 >= 0) R[op3] = r; /* store quotient */ else Write (op4, r, L_LONG, WA); if (op5 >= 0) R[op5] = rh; /* store remainder */ @@ -1442,13 +1501,13 @@ case EDIV: case BRB: BRANCHB (brdisp); /* branch */ if ((PC == fault_PC) && (PSL_GETIPL (PSL) == 0x1F)) - ABORT (STOP_LOOP); + ABORT (STOP_LOOP); break; case BRW: BRANCHW (brdisp); /* branch */ if ((PC == fault_PC) && (PSL_GETIPL (PSL) == 0x1F)) - ABORT (STOP_LOOP); + ABORT (STOP_LOOP); break; case BSBB: @@ -1581,7 +1640,7 @@ case ACBB: CC_IIZP_B (r); /* set cc's */ V_ADD_B (r, op1, op2); /* test for ovflo */ if ((op1 & BSIGN)? (SXTB (r) >= SXTB (op0)): - (SXTB (r) <= SXTB (op0))) BRANCHW (brdisp); + (SXTB (r) <= SXTB (op0))) BRANCHW (brdisp); break; case ACBW: r = (op2 + op1) & WMASK; /* calc result */ @@ -1589,7 +1648,7 @@ case ACBW: CC_IIZP_W (r); /* set cc's */ V_ADD_W (r, op1, op2); /* test for ovflo */ if ((op1 & WSIGN)? (SXTW (r) >= SXTW (op0)): - (SXTW (r) <= SXTW (op0))) BRANCHW (brdisp); + (SXTW (r) <= SXTW (op0))) BRANCHW (brdisp); break; case ACBL: r = (op2 + op1) & LMASK; /* calc result */ @@ -1597,7 +1656,7 @@ case ACBL: CC_IIZP_L (r); /* set cc's */ V_ADD_L (r, op1, op2); /* test for ovflo */ if ((op1 & LSIGN)? (r >= op0): (r <= op0)) - BRANCHW (brdisp); + BRANCHW (brdisp); break; /* CASE instructions - casex sel.rx,base.rx,lim.rx @@ -1611,23 +1670,26 @@ case CASEB: r = (op0 - op1) & BMASK; /* sel - base */ CC_CMP_B (r, op2); /* r:limit, set cc's */ if (r > op2) JUMP (PC + ((op2 + 1) * 2)); /* r > limit (unsgnd)? */ - else { temp = Read (PC + (r * 2), L_WORD, RA); - BRANCHW (temp); } + else { + temp = Read (PC + (r * 2), L_WORD, RA); + BRANCHW (temp); } break; case CASEW: r = (op0 - op1) & WMASK; /* sel - base */ CC_CMP_W (r, op2); /* r:limit, set cc's */ if (r > op2) JUMP (PC + ((op2 + 1) * 2)); /* r > limit (unsgnd)? */ - else { temp = Read (PC + (r * 2), L_WORD, RA); - BRANCHW (temp); } + else { + temp = Read (PC + (r * 2), L_WORD, RA); + BRANCHW (temp); } break; case CASEL: r = (op0 - op1) & LMASK; /* sel - base */ CC_CMP_L (r, op2); /* r:limit, set cc's */ if (((uint32) r) > ((uint32) op2)) /* r > limit (unsgnd)? */ JUMP (PC + ((op2 + 1) * 2)); - else { temp = Read (PC + (r * 2), L_WORD, RA); - BRANCHW (temp); } + else { + temp = Read (PC + (r * 2), L_WORD, RA); + BRANCHW (temp); } break; /* Branch on bit instructions - bbxy pos.rl,op.wb,disp.bb @@ -1762,19 +1824,10 @@ case RET: case HALT: if (PSL & PSL_CUR) RSVD_INST_FAULT; /* not kern? rsvd inst */ - else if (cpu_unit.flags & UNIT_CONH) { /* halt to console? */ - conpc = PC; /* save PC */ - conpsl = ((PSL | cc) & 0xFFFF00FF) | CON_HLTINS; /* PSL, param */ - temp = (PSL >> PSL_V_CUR) & 0x7; /* get is'cur */ - if (temp > 4) conpsl = conpsl | CON_BADPSL; /* invalid? */ - else STK[temp] = SP; /* save stack */ - if (mapen) conpsl = conpsl | CON_MAPON; /* mapping on? */ - mapen = 0; /* turn off map */ - SP = IS; /* set SP from IS */ - PSL = PSL_IS | PSL_IPL1F; /* PSL = 41F0000 */ - cc = 0; - JUMP (ROMBASE); } /* PC = 20040000 */ - else { ABORT (STOP_HALT); } /* halt to simulator */ + else if (cpu_unit.flags & UNIT_CONH) /* halt to console? */ + cc = con_halt (CON_HLTINS, cc); /* enter firmware */ + else { + ABORT (STOP_HALT); } /* halt to simulator */ case NOP: break; case BPT: @@ -2046,7 +2099,7 @@ case ACBF: WRITE_L (r); /* write result */ CC_IIZP_FP (r); /* set cc's */ if ((temp & CC_Z) || ((op1 & FPSIGN)? /* test br cond */ - !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); + !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); break; case ACBD: r = op_addd (opnd + 2, &rh, FALSE); @@ -2054,7 +2107,7 @@ case ACBD: WRITE_Q (r, rh); CC_IIZP_FP (r); if ((temp & CC_Z) || ((op1 & FPSIGN)? /* test br cond */ - !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); + !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); break; case ACBG: r = op_addg (opnd + 2, &rh, FALSE); @@ -2062,7 +2115,7 @@ case ACBG: WRITE_Q (r, rh); CC_IIZP_FP (r); if ((temp & CC_Z) || ((op1 & FPSIGN)? /* test br cond */ - !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); + !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); break; /* EMODF @@ -2204,27 +2257,46 @@ int32 bo = PC & 3; int32 sc, val, t; while ((bo + lnt) > ibcnt) { /* until enuf bytes */ - if ((ppc < 0) || (VA_GETOFF (ppc) == 0)) { /* PPC inv, xpg? */ - ppc = Test ((PC + ibcnt) & ~03, RD, &t); /* xlate PC */ - if (ppc < 0) Read ((PC + ibcnt) & ~03, L_LONG, RA); } - if (ibcnt == 0) ibufl = ReadLP (ppc); /* fill low */ - else ibufh = ReadLP (ppc); /* or high */ - ppc = ppc + 4; /* incr phys PC */ - ibcnt = ibcnt + 4; } /* incr ibuf cnt */ + if ((ppc < 0) || (VA_GETOFF (ppc) == 0)) { /* PPC inv, xpg? */ + ppc = Test ((PC + ibcnt) & ~03, RD, &t); /* xlate PC */ + if (ppc < 0) Read ((PC + ibcnt) & ~03, L_LONG, RA); } + if (ibcnt == 0) ibufl = ReadLP (ppc); /* fill low */ + else ibufh = ReadLP (ppc); /* or high */ + ppc = ppc + 4; /* incr phys PC */ + ibcnt = ibcnt + 4; } /* incr ibuf cnt */ PC = PC + lnt; /* incr PC */ if (lnt == L_BYTE) val = (ibufl >> (bo << 3)) & BMASK; /* byte? */ else if (lnt == L_WORD) { /* word? */ - if (bo == 3) val = ((ibufl >> 24) & 0xFF) | ((ibufh & 0xFF) << 8); - else val = (ibufl >> (bo << 3)) & WMASK; } + if (bo == 3) val = ((ibufl >> 24) & 0xFF) | ((ibufh & 0xFF) << 8); + else val = (ibufl >> (bo << 3)) & WMASK; } else if (bo) { /* unaligned lw? */ - sc = bo << 3; - val = (((ibufl >> sc) & align[bo]) | (((uint32) ibufh) << (32 - sc))); } + sc = bo << 3; + val = (((ibufl >> sc) & align[bo]) | (((uint32) ibufh) << (32 - sc))); } else val = ibufl; /* aligned lw */ if ((bo + lnt) >= 4) { /* retire ibufl? */ - ibufl = ibufh; - ibcnt = ibcnt - 4; } + ibufl = ibufh; + ibcnt = ibcnt - 4; } return val; } + +/* Console entry */ + +int32 con_halt (int32 code, int32 cc) +{ +int32 temp; + +conpc = PC; /* save PC */ +conpsl = ((PSL | cc) & 0xFFFF00FF) | CON_HLTINS; /* PSL, param */ +temp = (PSL >> PSL_V_CUR) & 0x7; /* get is'cur */ +if (temp > 4) conpsl = conpsl | CON_BADPSL; /* invalid? */ +else STK[temp] = SP; /* save stack */ +if (mapen) conpsl = conpsl | CON_MAPON; /* mapping on? */ +mapen = 0; /* turn off map */ +SP = IS; /* set SP from IS */ +PSL = PSL_IS | PSL_IPL1F; /* PSL = 41F0000 */ +JUMP (ROMBASE); /* PC = 20040000 */ +return 0; /* new cc = 0 */ +} /* To do list: Examine/deposit I/O @@ -2236,6 +2308,7 @@ t_stat cpu_reset (DEVICE *dptr) { mem_err = 0; crd_err = 0; +hlt_pin = 0; PSL = PSL_IS | PSL_IPL1F; SISR = 0; ASTLVL = 4; @@ -2275,7 +2348,7 @@ if (rom == NULL) return SCPE_IERR; if (*rom == 0) { /* no boot? */ printf ("Loading boot code from ka655.bin\n"); if (sim_log) fprintf (sim_log, - "Loading boot code from ka655.bin\n"); + "Loading boot code from ka655.bin\n"); r = load_cmd (0, "-R ka655.bin"); if (r != SCPE_OK) return r; } return SCPE_OK; @@ -2360,3 +2433,69 @@ if (st == PR_OK) printf ("Virtual %-X = physical %-X\n", va, pa); else printf ("Virtual %-X: %s\n", va, mm_str[st]); return SCPE_OK; } + +/* Set history */ + +t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 i, lnt; +t_stat r; + +if (cptr == NULL) { + for (i = 0; i < HIST_SIZE; i++) hst[i].iPC = 0; + return SCPE_OK; } +lnt = (int32) get_uint (cptr, 10, HIST_SIZE, &r); +if (r != SCPE_OK) return SCPE_ARG; +hst_lnt = lnt; +return SCPE_OK; +} + +/* Show history */ + +t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +int32 i, j, k, di, disp, numspec; +struct InstHistory *h; +extern char *opcode[]; + +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +di = hst_p + HIST_SIZE - hst_lnt; /* work forward */ +for (k = 0; k < hst_lnt; k++) { /* print specified */ + h = &hst[(di++) % HIST_SIZE]; /* entry pointer */ + if (h->iPC == 0) continue; /* filled in? */ + fprintf(st, "%08X %08X ", h->iPC, h->PSL); /* PC, PSL */ + numspec = drom[h->opc][0] & DR_NSPMASK; /* #specifiers */ + if (opcode[h->opc] == NULL) /* undefined? */ + fprintf (st, "%03X (undefined)", h->opc); + else if (h->PSL & PSL_FPD) /* FPD set? */ + fprintf (st, "%s FPD set", opcode[h->opc]); + else { /* normal */ + fprintf (st, "%s", opcode[h->opc]); /* print opcode */ + for (i = 1, j = 0; i <= numspec; i++) { /* loop thru specs */ + fputc ((i == 1)? ' ': ',', st); /* separator */ + disp = drom[h->opc][i]; /* specifier type */ + if (disp == RG) disp = RQ; /* fix specials */ + else if (disp >= BB) fprintf (st, "%X", h->brdest); + else switch (disp & 0xF) { /* case on type */ + case RB: case RW: case RL: /* read */ + case AB: case AW: case AL: case AQ: /* address */ + case MB: case MW: case ML: /* modify */ + fprintf (st, "%X", h->opnd[j++]); + break; + case RQ: /* read quad */ + case MQ: /* modify quad */ + fprintf (st, "%X%08X", h->opnd[j], h->opnd[j + 1]); + j = j + 2; + break; + case WB: case WW: case WL: case WQ: /* write */ + if (h->opnd[j] < 0) fprintf (st, "%X", h->opnd[j + 1]); + else fprintf (st, "R%d", h->opnd[j]); + j = j + 2; + break; + } /* end case */ + } /* end for */ + } /* end else */ + fputc ('\n', st); /* end line */ + } /* end for */ +return SCPE_OK; +} diff --git a/VAX/vax_cpu1.c b/VAX/vax_cpu1.c index cde3efed..502b1135 100644 --- a/VAX/vax_cpu1.c +++ b/VAX/vax_cpu1.c @@ -214,10 +214,10 @@ if (size > 32) RSVD_OPND_FAULT; /* size > 32? fault */ if (rn >= 0) { /* in registers? */ if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ if ((pos + size) > 32) { /* span two reg? */ - if (rn >= nSP) RSVD_OPND_FAULT; /* if PC, fault */ - mask = byte_mask[pos + size - 32]; /* insert fragment */ - val = ins >> (32 - pos); - R[rnplus1] = (vfldrp1 & ~mask) | (val & mask); } + if (rn >= nSP) RSVD_OPND_FAULT; /* if PC, fault */ + mask = byte_mask[pos + size - 32]; /* insert fragment */ + val = ins >> (32 - pos); + R[rnplus1] = (vfldrp1 & ~mask) | (val & mask); } mask = byte_mask[size] << pos; /* insert field */ val = ins << pos; R[rn] = (R[rn] & ~mask) | (val & mask); } @@ -226,10 +226,10 @@ else { ba = opnd[4] + (pos >> 3); /* base byte addr */ ba = ba & ~03; /* lw align base */ wd = Read (ba, L_LONG, WA); /* read field */ if ((size + pos) > 32) { /* field span lw? */ - wd1 = Read (ba + 4, L_LONG, WA); /* read 2nd lw */ - mask = byte_mask[pos + size - 32]; /* insert fragment */ - val = ins >> (32 - pos); - Write (ba + 4, (wd1 & ~mask) | (val & mask), L_LONG, WA); } + wd1 = Read (ba + 4, L_LONG, WA); /* read 2nd lw */ + mask = byte_mask[pos + size - 32]; /* insert fragment */ + val = ins >> (32 - pos); + Write (ba + 4, (wd1 & ~mask) | (val & mask), L_LONG, WA); } mask = byte_mask[size] << pos; /* insert field */ val = ins << pos; Write (ba, (wd & ~mask) | (val & mask), L_LONG, WA); } @@ -664,13 +664,13 @@ a = ar + h; /* abs addr of a */ if (ar) { /* queue not empty? */ Write (h, ar | 1, L_LONG, WA); /* acquire interlock */ if (Test (a, RA, &t) < 0) /* read tst a */ - Write (h, ar, L_LONG, WA); /* release if error */ + Write (h, ar, L_LONG, WA); /* release if error */ b = Read (a, L_LONG, RA) + a; /* b <- (a)+a, flt ok */ if (b & 07) { /* b quad aligned? */ - Write (h, ar, L_LONG, WA); /* release interlock */ - RSVD_OPND_FAULT; } /* fault */ + Write (h, ar, L_LONG, WA); /* release interlock */ + RSVD_OPND_FAULT; } /* fault */ if (Test (b, WA, &t) < 0) /* write test b */ - Write (h, ar, L_LONG, WA); /* release if err */ + Write (h, ar, L_LONG, WA); /* release if err */ Write (b + 4, h - b, L_LONG, WA); /* (b+4) <- h-b, flt ok */ Write (h, b - h, L_LONG, WA); } /* (h) <- b-h, rls int */ if (opnd[1] >= 0) R[opnd[1]] = a; /* store result */ @@ -695,20 +695,20 @@ if (ar) { /* queue not empty */ Write (h, ar | 1, L_LONG, WA); /* acquire interlock */ c = Read (h + 4, L_LONG, RA); /* c <- (h+4) */ if (ar == c) { /* single entry? */ - Write (h, ar, L_LONG, WA); /* release interlock */ - return op_remqhi (opnd, acc); } /* treat as remqhi */ + Write (h, ar, L_LONG, WA); /* release interlock */ + return op_remqhi (opnd, acc); } /* treat as remqhi */ if (c & 07) { /* c quad aligned? */ - Write (h, ar, L_LONG, WA); /* release interlock */ - RSVD_OPND_FAULT; } /* fault */ + Write (h, ar, L_LONG, WA); /* release interlock */ + RSVD_OPND_FAULT; } /* fault */ c = c + h; /* abs addr of c */ if (Test (c + 4, RA, &t) < 0) /* read test c+4 */ - Write (h, ar, L_LONG, WA); /* release if error */ + Write (h, ar, L_LONG, WA); /* release if error */ b = Read (c + 4, L_LONG, RA) + c; /* b <- (c+4)+c, flt ok */ if (b & 07) { /* b quad aligned? */ - Write (h, ar, L_LONG, WA); /* release interlock */ - RSVD_OPND_FAULT; } /* fault */ + Write (h, ar, L_LONG, WA); /* release interlock */ + RSVD_OPND_FAULT; } /* fault */ if (Test (b, WA, &t) < 0) /* write test b */ - Write (h, ar, L_LONG, WA); /* release if error */ + Write (h, ar, L_LONG, WA); /* release if error */ Write (b, h - b, L_LONG, WA); /* (b) <- h-b */ Write (h + 4, b - h, L_LONG, WA); /* (h+4) <- b-h */ Write (h, ar, L_LONG, WA); } /* release interlock */ @@ -772,22 +772,23 @@ if (PSL & PSL_FPD) { /* FPD set? */ if (R[4] > 0) R[4] = R[4] & STR_LNMASK; } else { R[1] = opnd[1]; /* src addr */ if (movc5) { /* MOVC5? */ - R[2] = (opnd[0] < opnd[3])? opnd[0]: opnd[3]; - R[3] = opnd[4]; /* dst addr */ - R[4] = opnd[3] - opnd[0]; /* dstlen - srclen */ - fill = opnd[2]; /* set fill */ - CC_CMP_W (opnd[0], opnd[3]); } /* set cc's */ - else { R[2] = opnd[0]; /* mvlen = srclen */ - R[3] = opnd[2]; /* dst addr */ - R[4] = fill = 0; /* no fill */ - cc = CC_Z; } /* set cc's */ + R[2] = (opnd[0] < opnd[3])? opnd[0]: opnd[3]; + R[3] = opnd[4]; /* dst addr */ + R[4] = opnd[3] - opnd[0]; /* dstlen - srclen */ + fill = opnd[2]; /* set fill */ + CC_CMP_W (opnd[0], opnd[3]); } /* set cc's */ + else { + R[2] = opnd[0]; /* mvlen = srclen */ + R[3] = opnd[2]; /* dst addr */ + R[4] = fill = 0; /* no fill */ + cc = CC_Z; } /* set cc's */ R[0] = STR_PACK (fill, R[2]); /* initial mvlen */ if (R[2]) { /* any move? */ - if (((uint32) R[1]) < ((uint32) R[3])) { - R[1] = R[1] + R[2]; /* backward, adjust */ - R[3] = R[3] + R[2]; /* addr to end */ - R[5] = MVC_BACK; } /* set state */ - else R[5] = MVC_FRWD; } /* fwd, set state */ + if (((uint32) R[1]) < ((uint32) R[3])) { + R[1] = R[1] + R[2]; /* backward, adjust */ + R[3] = R[3] + R[2]; /* addr to end */ + R[5] = MVC_BACK; } /* set state */ + else R[5] = MVC_FRWD; } /* fwd, set state */ else R[5] = MVC_FILL; /* fill, set state */ R[5] = R[5] | (cc << MVC_V_CC); /* pack with state */ PSL = PSL | PSL_FPD; } /* set FPD */ @@ -809,14 +810,14 @@ case MVC_FRWD: /* move forward */ mlnt[1] = (R[2] - mlnt[0]) & ~03; /* aligned length */ mlnt[2] = R[2] - mlnt[0] - mlnt[1]; /* tail */ for (i = 0; i < 3; i++) { /* head, align, tail */ - lnt = looplnt[i]; /* length for loop */ - for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) { -/* if (sim_interval == 0) ABORT (ABORT_INTR); */ - wd = Read (R[1], lnt, RA); /* read src */ - Write (R[3], wd, lnt, WA); /* write dst */ - R[1] = R[1] + lnt; /* inc src addr */ - R[3] = R[3] + lnt; /* inc dst addr */ - R[2] = R[2] - lnt; } } /* dec move lnt */ + lnt = looplnt[i]; /* length for loop */ + for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) { +/* if (sim_interval == 0) ABORT (ABORT_INTR); */ + wd = Read (R[1], lnt, RA); /* read src */ + Write (R[3], wd, lnt, WA); /* write dst */ + R[1] = R[1] + lnt; /* inc src addr */ + R[3] = R[3] + lnt; /* inc dst addr */ + R[2] = R[2] - lnt; } } /* dec move lnt */ goto FILL; /* check for fill */ case MVC_BACK: /* move backward */ mlnt[0] = R[3] & 03; /* length to align */ @@ -824,14 +825,14 @@ case MVC_BACK: /* move backward */ mlnt[1] = (R[2] - mlnt[0]) & ~03; /* aligned length */ mlnt[2] = R[2] - mlnt[0] - mlnt[1]; /* tail */ for (i = 0; i < 3; i++) { /* head, align, tail */ - lnt = looplnt[i]; /* length for loop */ - for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) { -/* if (sim_interval == 0) ABORT (ABORT_INTR); */ - wd = Read (R[1] - lnt, lnt, RA); /* read src */ - Write (R[3] - lnt, wd, lnt, WA); /* write dst */ - R[1] = R[1] - lnt; /* dec src addr */ - R[3] = R[3] - lnt; /* dec dst addr */ - R[2] = R[2] - lnt; } } /* dec move lnt */ + lnt = looplnt[i]; /* length for loop */ + for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) { +/* if (sim_interval == 0) ABORT (ABORT_INTR); */ + wd = Read (R[1] - lnt, lnt, RA); /* read src */ + Write (R[3] - lnt, wd, lnt, WA); /* write dst */ + R[1] = R[1] - lnt; /* dec src addr */ + R[3] = R[3] - lnt; /* dec dst addr */ + R[2] = R[2] - lnt; } } /* dec move lnt */ R[1] = R[1] + (R[0] & STR_LNMASK); /* final src addr */ R[3] = R[3] + (R[0] & STR_LNMASK); /* final dst addr */ case MVC_FILL: /* fill */ @@ -843,15 +844,15 @@ FILL: mlnt[1] = (R[4] - mlnt[0]) & ~03; /* aligned length */ mlnt[2] = R[4] - mlnt[0] - mlnt[1]; /* tail */ for (i = 0; i < 3; i++) { /* head, align, tail */ - lnt = looplnt[i]; /* length for loop */ - fill = fill & BMASK; /* fill for loop */ - if (lnt == L_LONG) fill = - (((uint32) fill) << 24) | (fill << 16) | (fill << 8) | fill; - for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) { -/* if (sim_interval == 0) ABORT (ABORT_INTR); */ - Write (R[3], fill, lnt, WA); /* write fill */ - R[3] = R[3] + lnt; /* inc dst addr */ - R[4] = R[4] - lnt; } } /* dec fill lnt */ + lnt = looplnt[i]; /* length for loop */ + fill = fill & BMASK; /* fill for loop */ + if (lnt == L_LONG) fill = + (((uint32) fill) << 24) | (fill << 16) | (fill << 8) | fill; + for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) { +/* if (sim_interval == 0) ABORT (ABORT_INTR); */ + Write (R[3], fill, lnt, WA); /* write fill */ + R[3] = R[3] + lnt; /* inc dst addr */ + R[4] = R[4] - lnt; } } /* dec fill lnt */ break; default: /* bad state */ RSVD_OPND_FAULT; } /* you lose */ @@ -892,12 +893,13 @@ if (PSL & PSL_FPD) { /* FPD set? */ fill = STR_GETCHR (R[0]); } /* get fill */ else { R[1] = opnd[1]; /* src1len */ if (cmpc5) { /* CMPC5? */ - R[2] = opnd[3]; /* get src2 opnds */ - R[3] = opnd[4]; - fill = opnd[2]; } - else { R[2] = opnd[0]; /* src2len = src1len */ - R[3] = opnd[2]; - fill = 0; } + R[2] = opnd[3]; /* get src2 opnds */ + R[3] = opnd[4]; + fill = opnd[2]; } + else { + R[2] = opnd[0]; /* src2len = src1len */ + R[3] = opnd[2]; + fill = 0; } R[0] = STR_PACK (fill, opnd[0]); /* src1len + FPD data */ PSL = PSL | PSL_FPD; } R[2] = R[2] & STR_LNMASK; /* mask src2len */ @@ -909,11 +911,11 @@ for (s1 = s2 = 0; ((R[0] | R[2]) & STR_LNMASK) != 0; sim_interval--) { else s2 = fill; /* no, use fill */ if (s1 != s2) break; /* src1 = src2? */ if (R[0] & STR_LNMASK) { /* if src1, decr */ - R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); - R[1] = R[1] + 1; } + R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); + R[1] = R[1] + 1; } if (R[2]) { /* if src2, decr */ - R[2] = (R[2] - 1) & STR_LNMASK; - R[3] = R[3] + 1; } } + R[2] = (R[2] - 1) & STR_LNMASK; + R[3] = R[3] + 1; } } PSL = PSL & ~PSL_FPD; /* clear FPD */ CC_CMP_B (s1, s2); /* set cc's */ R[0] = R[0] & STR_LNMASK; /* clear packup */ @@ -1022,10 +1024,11 @@ if (newpc & 2) ABORT (STOP_ILLVEC); /* bad flags? */ if (oldpsl & PSL_IS) newpsl = PSL_IS; /* on int stk? */ else { STK[oldcur] = SP; /* no, save cur stk */ if (newpc & 1) { /* to int stk? */ - newpsl = PSL_IS; /* flag */ - SP = IS; } /* new stack */ - else { newpsl = 0; /* to ker stk */ - SP = KSP; } } /* new stack */ + newpsl = PSL_IS; /* flag */ + SP = IS; } /* new stack */ + else { + newpsl = 0; /* to ker stk */ + SP = KSP; } } /* new stack */ if (ei > 0) PSL = newpsl | (ipl << PSL_V_IPL); /* if int, new IPL */ else PSL = newpsl | ((newpc & 1)? PSL_IPL1F: (oldpsl & PSL_IPL)) | (oldcur << PSL_V_PRV); @@ -1108,12 +1111,12 @@ if ((newpsl & PSL_MBZ) || /* rule 8 */ if (newcur) { /* to esu, skip 2,4,7 */ if ((newpsl & (PSL_IS | PSL_IPL)) || /* rules 3,5 */ (newcur > PSL_GETPRV (newpsl))) /* rule 6 */ - RSVD_OPND_FAULT; } /* end rei to esu */ + RSVD_OPND_FAULT; } /* end rei to esu */ else { /* to k, skip 3,5,6 */ newipl = PSL_GETIPL (newpsl); /* get new ipl */ if ((newpsl & PSL_IS) && /* setting IS? */ (((PSL & PSL_IS) == 0) || (newipl == 0))) /* test rules 2,4 */ - RSVD_OPND_FAULT; /* else skip 2,4 */ + RSVD_OPND_FAULT; /* else skip 2,4 */ if (newipl > PSL_GETIPL (PSL)) RSVD_OPND_FAULT; /* test rule 7 */ } /* end if kernel */ SP = SP + 8; /* pop stack */ @@ -1126,9 +1129,9 @@ PSL = (PSL & PSL_TP) | (newpsl & ~CC_MASK); /* set new PSL */ if (PSL & PSL_IS) SP = IS; /* set new stack */ else { SP = STK[newcur]; /* if ~IS, chk AST */ if (newcur >= ASTLVL) { - if (DBG_LOG (LOG_CPU_R)) fprintf (sim_log, - ">>REI: AST delivered\n"); - SISR = SISR | SISR_2; } } + if (DBG_LOG (LOG_CPU_R)) fprintf (sim_log, + ">>REI: AST delivered\n"); + SISR = SISR | SISR_2; } } JUMP (newpc); /* set new PC */ return newpsl & CC_MASK; /* set new cc */ } diff --git a/VAX/vax_defs.h b/VAX/vax_defs.h index ef5d5206..6c28df71 100644 --- a/VAX/vax_defs.h +++ b/VAX/vax_defs.h @@ -42,11 +42,11 @@ #define STOP_INIE 5 /* exc in intexc */ #define STOP_PPTE 6 /* proc pte in Px */ #define STOP_UIPL 7 /* undefined IPL */ -#define STOP_UNKNOWN 8 /* unknown reason */ -#define STOP_RQ 9 /* fatal RQ err */ -#define STOP_LOOP 10 /* infinite loop */ -#define STOP_UNKABO 11 /* unknown abort */ -#define STOP_SANITY 12 /* sanity timer exp */ +#define STOP_RQ 8 /* fatal RQ err */ +#define STOP_LOOP 9 /* infinite loop */ +#define STOP_SANITY 10 /* sanity timer exp */ +#define STOP_UNKNOWN 11 /* unknown reason */ +#define STOP_UNKABO 12 /* unknown abort */ #define ABORT_INTR -1 /* interrupt */ #define ABORT_MCHK (-SCB_MCHK) /* machine check */ #define ABORT_RESIN (-SCB_RESIN) /* rsvd instruction */ @@ -247,6 +247,7 @@ #define SCB_TTO 0xFC /* console output */ #define SCB_INTR 0x100 /* hardware intr */ +#define IPL_HLTPIN 0x1F /* halt pin IPL */ #define IPL_MEMERR 0x1D /* mem err IPL */ #define IPL_CRDERR 0x1A /* CRD err IPL */ diff --git a/VAX/vax_doc.txt b/VAX/vax_doc.txt index 6553fb2c..1c8be55e 100644 --- a/VAX/vax_doc.txt +++ b/VAX/vax_doc.txt @@ -144,6 +144,11 @@ The LOAD command recognizes one switch: -o Origin argument follows file name The CPU supports the BOOT command and is the only VAX device to do so. +Note that the behavior of the bootstrap depends on the capabilities of +the console terminator emulator. If the terminal window supports full +VT100 emulation (including Multilanguage Character Set support), the +bootstrap will ask the user to specify the language; otherwise, it will +default to English. These switches are recognized when examining or depositing in CPU memory (or any other byte oriented device): @@ -193,6 +198,16 @@ control registers for the interrupt system. most recent PC change first WRU 8 interrupt character +The CPU can maintain a history of the most recently executed instructions. +This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands: + + SET CPU HISTORY -- clear history buffer + SET CPU HISTORY=0 -- disable history + SET CPU HISTORY=n -- enable history, display length = n + SHOW CPU HISTORY -- print CPU history + +The maximum length for the history is 4096 entries. + 2.1.2 Translation Buffer (TLB) The translation buffer consists of two units, representing the system @@ -252,6 +267,13 @@ to allow the patched bootstrap code to run. The SYSD registers are: ADSK1 32 SSC address match 1 mask CDGDAT[0:16383] 32 cache diagnostic data store +BDR<7> is the halt-enabled switch. It controls how the console firmware +responds to a BOOT command, a kernel halt (if option CONHALT is set), or +a console halt (BREAK typed on the console terminal). If BDR<7> is set, +the console firmware responds to all these conditions by entering its +interactive command mode. If BDR<7> is clear, the console firmware +boots the operating system in response to these conditions. + 2.1.6 Qbus Adapter (QBA) The QBA represents the CQBIC Qbus adapter chip. The QBA registers are: @@ -374,6 +396,11 @@ The terminal interfaces (TTI, TTO) can be set to one of two modes: bits. In 8B mode, characters are not modified. Changing the mode of either interface changes both. The default mode is 8B. +When the console terminal is attached to a Telnet session, it +recognizes BREAK. If BREAK is entered, and BDR<7> is set, control +returns to the console firmware; otherwise, BREAK is treated as a +normal terminal input condition. + The terminal input (TTI) polls the console keyboard for input. It implements these registers: diff --git a/VAX/vax_fpa.c b/VAX/vax_fpa.c index 44560dd9..fe0fefbe 100644 --- a/VAX/vax_fpa.c +++ b/VAX/vax_fpa.c @@ -129,10 +129,11 @@ if (sc & BSIGN) { /* right shift? */ if (sc > 63) r = (opnd[2] & LSIGN)? -1: 0; /* sc > 63? */ else r = src >> sc; } else { if (sc > 63) { /* left shift */ - r = 0; /* sc > 63? */ - *flg = (src != 0); } /* ovflo test */ - else { r = src << sc; /* do shift */ - *flg = (src != (r >> sc)); } } /* ovflo test */ + r = 0; /* sc > 63? */ + *flg = (src != 0); } /* ovflo test */ + else { + r = src << sc; /* do shift */ + *flg = (src != (r >> sc)); } } /* ovflo test */ *rh = (int32) (r >> 32); /* hi result */ return ((int32) r); /* lo result */ } @@ -377,22 +378,23 @@ if (a->exp < b->exp) { /* s1 < s2? swap */ ediff = a->exp - b->exp; /* exp diff */ if (a->sign ^ b->sign) { /* eff sub? */ if (ediff) { /* exp diff? */ - b->frac = (ediff > 63)? ONES: /* shift b */ - ((-((t_int64) b->frac) >> ediff) | - (ONES << (64 - ediff))); /* preserve sign */ - a->frac = a->frac + b->frac; } /* add frac */ - else { if (a->frac < b->frac) { /* same, check magn */ - a->frac = b->frac - a->frac; /* b > a */ - a->sign = b->sign; } - else a->frac = a->frac - b->frac; } /* a >= b */ + b->frac = (ediff > 63)? ONES: /* shift b */ + ((-((t_int64) b->frac) >> ediff) | + (ONES << (64 - ediff))); /* preserve sign */ + a->frac = a->frac + b->frac; } /* add frac */ + else { + if (a->frac < b->frac) { /* same, check magn */ + a->frac = b->frac - a->frac; /* b > a */ + a->sign = b->sign; } + else a->frac = a->frac - b->frac; } /* a >= b */ a->frac = a->frac & ~mask; norm (a); } /* normalize */ else { if (ediff >= 64) b->frac = 0; else b->frac = b->frac >> ediff; /* add, denorm */ a->frac = a->frac + b->frac; /* add frac */ if (a->frac < b->frac) { /* chk for carry */ - a->frac = UF_NM | (a->frac >> 1); /* shift in carry */ - a->exp = a->exp + 1; } /* skip norm */ + a->frac = UF_NM | (a->frac >> 1); /* shift in carry */ + a->exp = a->exp + 1; } /* skip norm */ a->frac = a->frac & ~mask; } return; } @@ -517,8 +519,8 @@ b->frac = b->frac >> 1; for (i = 0; (i < prec) && b->frac; i++) { /* divide loop */ quo = quo << 1; /* shift quo */ if (b->frac >= a->frac) { /* div step ok? */ - b->frac = b->frac - a->frac; /* subtract */ - quo = quo + 1; } /* quo bit = 1 */ + b->frac = b->frac - a->frac; /* subtract */ + quo = quo + 1; } /* quo bit = 1 */ b->frac = b->frac << 1; } /* shift divd */ b->frac = quo << (UF_V_NM - i + 1); /* shift quo */ norm (b); /* normalize */ @@ -734,7 +736,7 @@ if (r->frac == 0) { /* if fraction = 0 */ return; } while ((r->frac & UF_NM) == 0) { /* normalized? */ for (i = 0; i < 5; i++) { /* find first 1 */ - if (r->frac & normmask[i]) break; } + if (r->frac & normmask[i]) break; } r->frac = r->frac << normtab[i]; /* shift frac */ r->exp = r->exp - normtab[i]; } /* decr exp */ return; diff --git a/VAX/vax_io.c b/VAX/vax_io.c index 7b56c5ae..ab3d2a11 100644 --- a/VAX/vax_io.c +++ b/VAX/vax_io.c @@ -25,6 +25,7 @@ qba Qbus adapter + 22-Dec-02 RMS Addec console halt support 12-Oct-02 RMS Added autoconfigure support Added SHOW IO space routine 29-Sep-02 RMS Added dynamic table support @@ -94,7 +95,7 @@ int32 cq_ipc = 0; /* IPC */ extern uint32 *M; extern UNIT cpu_unit; -extern int32 PSL, SISR, trpirq, mem_err; +extern int32 PSL, SISR, trpirq, mem_err, hlt_pin; extern int32 p1; extern int32 ssc_bto; extern jmp_buf save_env; @@ -172,8 +173,8 @@ DIB *dibp; for (i = 0; dibp = dib_tab[i]; i++ ) { if ((pa >= dibp->ba) && (pa < (dibp->ba + dibp->lnt))) { - dibp->rd (&val, pa, READ); - return val; } } + dibp->rd (&val, pa, READ); + return val; } } cq_merr (pa); MACH_CHECK (MCHK_READ); return 0; @@ -187,8 +188,8 @@ DIB *dibp; for (i = 0; dibp = dib_tab[i]; i++ ) { if ((pa >= dibp->ba) && (pa < (dibp->ba + dibp->lnt))) { - dibp->wr (val, pa, mode); - return; } } + dibp->wr (val, pa, mode); + return; } } cq_merr (pa); mem_err = 1; return; @@ -247,6 +248,7 @@ static const int32 sw_int_mask[IPL_SMAX] = { 0xFE00, 0xFC00, 0xF800, 0xF000, /* 8 - B */ 0xE000, 0xC000, 0x8000 }; /* C - E */ +if (hlt_pin) return IPL_HLTPIN; /* hlt pin int */ if ((ipl < IPL_MEMERR) && mem_err) return IPL_MEMERR; /* mem err int */ for (i = IPL_HMAX; i >= IPL_HMIN; i--) { /* chk hwre int */ if (i <= ipl) return 0; /* at ipl? no int */ @@ -267,9 +269,9 @@ int32 l = lvl - IPL_HMIN; for (i = 0; int_req[l] && (i < 32); i++) { if ((int_req[l] >> i) & 1) { - int_req[l] = int_req[l] & ~(1u << i); - if (int_ack[l][i]) return int_ack[l][i](); - return int_vec[l][i]; } } + int_req[l] = int_req[l] & ~(1u << i); + if (int_ack[l][i]) return int_ack[l][i](); + return int_vec[l][i]; } } return 0; } @@ -389,10 +391,10 @@ int32 ma = (pa & CQMAPAMASK) + cq_mbr; /* mem addr */ if (ADDR_IS_MEM (ma)) { if (lnt < L_LONG) { - int32 sc = (pa & 3) << 3; - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - int32 t = M[ma >> 2]; - val = ((val & mask) << sc) | (t & ~(mask << sc)); } + int32 sc = (pa & 3) << 3; + int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; + int32 t = M[ma >> 2]; + val = ((val & mask) << sc) | (t & ~(mask << sc)); } M[ma >> 2] = val; } else { cq_serr (ma); /* error */ mem_err = 1; } @@ -419,12 +421,12 @@ void cqmem_wr (int32 pa, int32 val, int32 lnt) int32 qa = pa & CQMAMASK; /* Qbus addr */ t_addr ma; -if (map_addr (qa, &ma)) { /* map addr */ +if (map_addr (qa, &ma)) { /* map addr */ if (lnt < L_LONG) { - int32 sc = (pa & 3) << 3; - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - int32 t = M[ma >> 2]; - val = ((val & mask) << sc) | (t & ~(mask << sc)); } + int32 sc = (pa & 3) << 3; + int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; + int32 t = M[ma >> 2]; + val = ((val & mask) << sc) | (t & ~(mask << sc)); } M[ma >> 2] = val; } else mem_err = 1; return; @@ -440,10 +442,10 @@ int32 qmma = ((qblk << 2) & CQMAPAMASK) + cq_mbr; /* map entry */ if (ADDR_IS_MEM (qmma)) { /* legit? */ int32 qmap = M[qmma >> 2]; /* get map */ if (qmap & CQMAP_VLD) { /* valid? */ - *ma = ((qmap & CQMAP_PAG) << VA_V_VPN) + VA_GETOFF (qa); - if (ADDR_IS_MEM (*ma)) return 1; /* legit addr */ - cq_serr (*ma); /* slave nxm */ - return 0; } + *ma = ((qmap & CQMAP_PAG) << VA_V_VPN) + VA_GETOFF (qa); + if (ADDR_IS_MEM (*ma)) return 1; /* legit addr */ + cq_serr (*ma); /* slave nxm */ + return 0; } cq_merr (qa); /* master nxm */ return 0; } cq_serr (0); /* inv mem */ @@ -516,8 +518,8 @@ t_addr ma; for (i = ma = 0; i < bc; i++, buf++) { /* by bytes */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } + if (!map_addr (ba + i, &ma) || /* inv or NXM? */ + !ADDR_IS_MEM (ma)) return (bc - i); } *buf = ReadB (ma); ma = ma + 1; } return 0; @@ -532,8 +534,8 @@ ba = ba & ~01; bc = bc & ~01; for (i = ma = 0; i < bc; i = i + 2, buf++) { /* by words */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } + if (!map_addr (ba + i, &ma) || /* inv or NXM? */ + !ADDR_IS_MEM (ma)) return (bc - i); } *buf = ReadW (ma); ma = ma + 2; } return 0; @@ -548,8 +550,8 @@ ba = ba & ~03; bc = bc & ~03; for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by lw */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } + if (!map_addr (ba + i, &ma) || /* inv or NXM? */ + !ADDR_IS_MEM (ma)) return (bc - i); } *buf = ReadL (ma); ma = ma + 4; } return 0; @@ -562,8 +564,8 @@ t_addr ma; for (i = ma = 0; i < bc; i++, buf++) { /* by bytes */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } + if (!map_addr (ba + i, &ma) || /* inv or NXM? */ + !ADDR_IS_MEM (ma)) return (bc - i); } WriteB (ma, *buf); ma = ma + 1; } return 0; @@ -578,8 +580,8 @@ ba = ba & ~01; bc = bc & ~01; for (i = ma = 0; i < bc; i = i + 2, buf++) { /* by words */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } + if (!map_addr (ba + i, &ma) || /* inv or NXM? */ + !ADDR_IS_MEM (ma)) return (bc - i); } WriteW (ma, *buf); ma = ma + 2; } return 0; @@ -594,8 +596,8 @@ ba = ba & ~03; bc = bc & ~03; for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by lw */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } + if (!map_addr (ba + i, &ma) || /* inv or NXM? */ + !ADDR_IS_MEM (ma)) return (bc - i); } WriteL (ma, *buf); ma = ma + 4; } return 0; diff --git a/VAX/vax_mmu.c b/VAX/vax_mmu.c index d27b522a..87c81acb 100644 --- a/VAX/vax_mmu.c +++ b/VAX/vax_mmu.c @@ -169,8 +169,8 @@ if (mapen) { /* mapping on? */ tbi = VA_GETTBI (vpn); xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; /* access tlb */ if (((xpte.pte & acc) == 0) || (xpte.tag != vpn) || - ((acc & TLB_WACC) && ((xpte.pte & TLB_M) == 0))) - xpte = fill (va, lnt, acc, NULL); /* fill if needed */ + ((acc & TLB_WACC) && ((xpte.pte & TLB_M) == 0))) + xpte = fill (va, lnt, acc, NULL); /* fill if needed */ pa = (xpte.pte & TLB_PFN) | off; } /* get phys addr */ else pa = va & PAMASK; if ((pa & (lnt - 1)) == 0) { /* aligned? */ @@ -182,8 +182,8 @@ if (mapen && ((off + lnt) > VA_PAGSIZE)) { /* cross page? */ tbi = VA_GETTBI (vpn); xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; /* access tlb */ if (((xpte.pte & acc) == 0) || (xpte.tag != vpn) || - ((acc & TLB_WACC) && ((xpte.pte & TLB_M) == 0))) - xpte = fill (va + lnt, lnt, acc, NULL); /* fill if needed */ + ((acc & TLB_WACC) && ((xpte.pte & TLB_M) == 0))) + xpte = fill (va + lnt, lnt, acc, NULL); /* fill if needed */ pa1 = (xpte.pte & TLB_PFN) | VA_GETOFF (va + 4); } else pa1 = (pa + 4) & PAMASK; /* not cross page */ bo = pa & 3; @@ -222,7 +222,8 @@ if (mapen) { tbi = VA_GETTBI (vpn); xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; /* access tlb */ if (((xpte.pte & acc) == 0) || (xpte.tag != vpn) || - ((xpte.pte & TLB_M) == 0)) xpte = fill (va, lnt, acc, NULL); + ((xpte.pte & TLB_M) == 0)) + xpte = fill (va, lnt, acc, NULL); pa = (xpte.pte & TLB_PFN) | off; } else pa = va & PAMASK; if ((pa & (lnt - 1)) == 0) { /* aligned? */ @@ -235,8 +236,8 @@ if (mapen && ((off + lnt) > VA_PAGSIZE)) { tbi = VA_GETTBI (vpn); xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; /* access tlb */ if (((xpte.pte & acc) == 0) || (xpte.tag != vpn) || - ((xpte.pte & TLB_M) == 0)) - xpte = fill (va + lnt, lnt, acc, NULL); + ((xpte.pte & TLB_M) == 0)) + xpte = fill (va + lnt, lnt, acc, NULL); pa1 = (xpte.pte & TLB_PFN) | VA_GETOFF (va + 4); } else pa1 = (pa + 4) & PAMASK; bo = pa & 3; @@ -273,7 +274,7 @@ if (mapen) { /* mapping on? */ tbi = VA_GETTBI (vpn); xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; /* access tlb */ if ((xpte.pte & acc) && (xpte.tag == vpn)) /* TB hit, acc ok? */ - return (xpte.pte & TLB_PFN) | off; + return (xpte.pte & TLB_PFN) | off; xpte = fill (va, L_BYTE, acc, status); /* fill TB */ if (*status == PR_OK) return (xpte.pte & TLB_PFN) | off; else return -1; } @@ -354,7 +355,7 @@ void WriteW (t_addr pa, int32 val) if (ADDR_IS_MEM (pa)) { int32 id = pa >> 2; M[id] = (pa & 2)? (M[id] & 0xFFFF) | (val << 16): - (M[id] & ~0xFFFF) | val; } + (M[id] & ~0xFFFF) | val; } else { mchk_ref = REF_V; if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_WORD); else WriteReg (pa, val, L_WORD); } @@ -407,23 +408,24 @@ if (va & VA_S0) { /* system space? */ if (ptidx >= slr) MM_ERR (PR_LNV); /* system */ ptead = sbr + ptidx; } else { if (va & VA_P1) { /* P1? */ - if (ptidx < p1lr) MM_ERR (PR_LNV); - ptead = p1br + ptidx; } - else { if (ptidx >= p0lr) - MM_ERR (PR_LNV); /* P0 */ - ptead = p0br + ptidx; } + if (ptidx < p1lr) MM_ERR (PR_LNV); + ptead = p1br + ptidx; } + else { /* P0 */ + if (ptidx >= p0lr) + MM_ERR (PR_LNV); + ptead = p0br + ptidx; } if ((ptead & VA_S0) == 0) - ABORT (STOP_PPTE); /* ppte must be sys */ + ABORT (STOP_PPTE); /* ppte must be sys */ vpn = VA_GETVPN (ptead); /* get vpn, tbi */ tbi = VA_GETTBI (vpn); if (stlb[tbi].tag != vpn) { /* in sys tlb? */ - ptidx = ((uint32) ptead) >> 7; /* xlate like sys */ - if (ptidx >= slr) MM_ERR (PR_PLNV); - pte = ReadLP (sbr + ptidx); /* get system pte */ - if ((pte & PTE_V) == 0) MM_ERR (PR_PTNV); /* spte TNV? */ - stlb[tbi].tag = vpn; /* set stlb tag */ - stlb[tbi].pte = cvtacc[PTE_GETACC (pte)] | - ((pte << VA_N_OFF) & TLB_PFN); } /* set stlb data */ + ptidx = ((uint32) ptead) >> 7; /* xlate like sys */ + if (ptidx >= slr) MM_ERR (PR_PLNV); + pte = ReadLP (sbr + ptidx); /* get system pte */ + if ((pte & PTE_V) == 0) MM_ERR (PR_PTNV); /* spte TNV? */ + stlb[tbi].tag = vpn; /* set stlb tag */ + stlb[tbi].pte = cvtacc[PTE_GETACC (pte)] | + ((pte << VA_N_OFF) & TLB_PFN); } /* set stlb data */ ptead = (stlb[tbi].pte & TLB_PFN) | VA_GETOFF (ptead); } pte = ReadL (ptead); /* read pte */ tlbpte = cvtacc[PTE_GETACC (pte)] | /* cvt access */ diff --git a/VAX/vax_stddev.c b/VAX/vax_stddev.c index e009835c..68022469 100644 --- a/VAX/vax_stddev.c +++ b/VAX/vax_stddev.c @@ -27,6 +27,7 @@ tto terminal output clk 100Hz and TODR clock + 22-Dec-02 RMS Added console halt capability 01-Nov-02 RMS Added 7B/8B capability to terminal 12-Sep-02 RMS Removed paper tape, added variable vector support 30-May-02 RMS Widened POS to 32b @@ -38,6 +39,10 @@ #define TTICSR_IMP (CSR_DONE + CSR_IE) /* terminal input */ #define TTICSR_RW (CSR_IE) +#define TTIBUF_ERR 0x8000 /* error */ +#define TTIBUF_OVR 0x4000 /* overrun */ +#define TTIBUF_FRM 0x2000 /* framing error */ +#define TTIBUF_RBR 0x0400 /* receive break */ #define TTOCSR_IMP (CSR_DONE + CSR_IE) /* terminal output */ #define TTOCSR_RW (CSR_IE) #define CLKCSR_IMP (CSR_IE) /* real-time clock */ @@ -49,6 +54,7 @@ #define UNIT_8B (1 << UNIT_V_8B) extern int32 int_req[IPL_HLVL]; +extern int32 hlt_pin; int32 tti_csr = 0; /* control/status */ int32 tto_csr = 0; /* control/status */ @@ -65,6 +71,8 @@ t_stat clk_svc (UNIT *uptr); t_stat tti_reset (DEVICE *dptr); t_stat tto_reset (DEVICE *dptr); t_stat clk_reset (DEVICE *dptr); + +extern int32 sysd_hlt_enb (void); /* TTI data structures @@ -78,7 +86,7 @@ DIB tti_dib = { 0, 0, NULL, NULL, 1, IVCL (TTI), SCB_TTI, { NULL } }; UNIT tti_unit = { UDATA (&tti_svc, UNIT_8B, 0), KBD_POLL_WAIT }; REG tti_reg[] = { - { HRDATA (BUF, tti_unit.buf, 8) }, + { HRDATA (BUF, tti_unit.buf, 16) }, { HRDATA (CSR, tti_csr, 16) }, { FLDATA (INT, int_req[IPL_TTI], INT_V_TTI) }, { FLDATA (DONE, tti_csr, CSR_V_DONE) }, @@ -193,9 +201,12 @@ return (tti_csr & TTICSR_IMP); int32 rxdb_rd (void) { -tti_csr = tti_csr & ~CSR_DONE; +int32 t = tti_unit.buf; /* char + error */ + +tti_csr = tti_csr & ~CSR_DONE; /* clr done */ +tti_unit.buf = tti_unit.buf & 0377; /* clr errors */ CLR_INT (TTI); -return (tti_unit.buf & 0377); +return t; } int32 txcs_rd (void) @@ -256,7 +267,10 @@ int32 c; sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); +if (c & SCPE_BREAK) { /* break? */ + if (sysd_hlt_enb ()) hlt_pin = 1; /* if enabled, halt */ + tti_unit.buf = TTIBUF_ERR | TTIBUF_FRM | TTIBUF_RBR; } +else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); tti_unit.pos = tti_unit.pos + 1; tti_csr = tti_csr | CSR_DONE; if (tti_csr & CSR_IE) SET_INT (TTI); diff --git a/VAX/vax_sys.c b/VAX/vax_sys.c index d97ae530..e05c4526 100644 --- a/VAX/vax_sys.c +++ b/VAX/vax_sys.c @@ -114,11 +114,11 @@ const char *sim_stop_messages[] = { "Exception in interrupt or exception", "Process PTE in P0 or P1 space", "Interrupt at undefined IPL", - "Unknown error", "Fatal RQDX3 error", "Infinite loop", - "Unknown abort code", - "Sanity timer expired" }; + "Sanity timer expired", + "Unknown error", + "Unknown abort code" }; /* Binary loader @@ -156,7 +156,7 @@ else { origin = 0; /* memory */ while ((i = getc (fileref)) != EOF) { /* read byte stream */ if (origin >= limit) return SCPE_NXM; /* NXM? */ if (sim_switches & SWMASK ('R')) /* ROM? */ - rom_wr (origin, i, L_BYTE); /* not writeable */ + rom_wr (origin, i, L_BYTE); /* not writeable */ else WriteB (origin, i); /* store byte */ origin = origin + 1; } return SCPE_OK; @@ -726,7 +726,7 @@ const uint16 drom[NUM_INST][MAX_SPEC + 1] = { /* Opcode mnemonics table */ -static const char *opcode[] = { +const char *opcode[] = { "HALT", "NOP", "REI", "BPT", "RET", "RSB", "LDPCTX", "SVPCTX", "CVTPS", "CVTSP", "INDEX", "CRC", "PROBER", "PROBEW", "INSQUE", "REMQUE", "BSBB", "BRB", "BNEQ", "BEQL", "BGTR", "BLEQ", "JSB", "JMP", @@ -845,8 +845,8 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ if ((val[0] & 0x7F) == 0) return SCPE_ARG; while (vp < lnt) { /* print string */ - if ((c = (int32) val[vp++] & 0x7F) == 0) break; - fprintf (of, (c < 0x20)? "<%02X>": "%c", c); } + if ((c = (int32) val[vp++] & 0x7F) == 0) break; + fprintf (of, (c < 0x20)? "<%02X>": "%c", c); } return -(vp - 1); } /* return # chars */ if (sw & SWMASK ('M') && (uptr == &cpu_unit)) { /* inst format? */ @@ -885,73 +885,77 @@ for (i = 0; i < numspec; i++) { /* loop thru spec */ fputc (i? ',': ' ', of); /* separator */ disp = drom[inst][i + 1]; /* get drom value */ if (disp == BB) { /* byte br disp? */ - GETNUM (num, 1); - fprintf (of, "%-X", SXTB (num) + addr + vp); } + GETNUM (num, 1); + fprintf (of, "%-X", SXTB (num) + addr + vp); } else if (disp == BW) { /* word br disp? */ + GETNUM (num, 2); + fprintf (of, "%-X", SXTW (num) + addr + vp); } + else { + spec = (int32) val[vp++]; /* get specifier */ + if ((spec & 0xF0) == IDX) { /* index? */ + index = spec; /* copy, get next */ + spec = (int32) val[vp++]; } + else index = 0; + rn = spec & 0xF; /* get reg # */ + switch (spec & 0xF0) { /* case on mode */ + case SH0: case SH1: case SH2: case SH3: /* s^# */ + fprintf (of, "#%-X", spec); + break; + case GRN: /* Rn */ + fprintf (of, "%-s", regname[rn]); + break; + case RGD: /* (Rn) */ + fprintf (of, "(%-s)", regname[rn]); + break; + case ADC: /* -(Rn) */ + fprintf (of, "-(%-s)", regname[rn]); + break; + case AIN: /* (Rn)+, #n */ + if (rn != nPC) fprintf (of, "(%-s)+", regname[rn]); + else { + if (disp == OC) + vp = fprint_sym_qoimm (of, val, vp, 4); + else if (DR_LNT (disp) == L_QUAD) + vp = fprint_sym_qoimm (of, val, vp, 2); + else { + GETNUM (num, DR_LNT (disp)); + fprintf (of, "#%-X", num); } } + break; + case AID: /* @(Rn)+, @#n */ + if (rn != nPC) fprintf (of, "@(%-s)+", regname[rn]); + else { + GETNUM (num, 4); + fprintf (of, "@#%-X", num); } + break; + case BDD: /* @b^d(r),@b^n */ + fputc ('@', of); + case BDP: /* b^d(r), b^n */ + GETNUM (num, 1); + if (rn == nPC) fprintf (of, "%-X", addr + vp + SXTB (num)); + else if (num & BSIGN) fprintf (of, "-%-X(%-s)", + -num & BMASK, regname[rn]); + else fprintf (of, "%-X(%-s)", num, regname[rn]); + break; + case WDD: /* @w^d(r),@w^n */ + fputc ('@', of); + case WDP: /* w^d(r), w^n */ GETNUM (num, 2); - fprintf (of, "%-X", SXTW (num) + addr + vp); } - else { spec = (int32) val[vp++]; /* get specifier */ - if ((spec & 0xF0) == IDX) { /* index? */ - index = spec; /* copy, get next */ - spec = (int32) val[vp++]; } - else index = 0; - rn = spec & 0xF; /* get reg # */ - switch (spec & 0xF0) { /* case on mode */ - case SH0: case SH1: case SH2: case SH3: /* s^# */ - fprintf (of, "#%-X", spec); - break; - case GRN: /* Rn */ - fprintf (of, "%-s", regname[rn]); - break; - case RGD: /* (Rn) */ - fprintf (of, "(%-s)", regname[rn]); - break; - case ADC: /* -(Rn) */ - fprintf (of, "-(%-s)", regname[rn]); - break; - case AIN: /* (Rn)+, #n */ - if (rn != nPC) fprintf (of, "(%-s)+", regname[rn]); - else { if (disp == OC) - vp = fprint_sym_qoimm (of, val, vp, 4); - else if (DR_LNT (disp) == L_QUAD) - vp = fprint_sym_qoimm (of, val, vp, 2); - else { GETNUM (num, DR_LNT (disp)); - fprintf (of, "#%-X", num); } } - break; - case AID: /* @(Rn)+, @#n */ - if (rn != nPC) fprintf (of, "@(%-s)+", regname[rn]); - else { GETNUM (num, 4); - fprintf (of, "@#%-X", num); } - break; - case BDD: /* @b^d(r),@b^n */ - fputc ('@', of); - case BDP: /* b^d(r), b^n */ - GETNUM (num, 1); - if (rn == nPC) fprintf (of, "%-X", addr + vp + SXTB (num)); - else if (num & BSIGN) fprintf (of, "-%-X(%-s)", - -num & BMASK, regname[rn]); - else fprintf (of, "%-X(%-s)", num, regname[rn]); - break; - case WDD: /* @w^d(r),@w^n */ - fputc ('@', of); - case WDP: /* w^d(r), w^n */ - GETNUM (num, 2); - if (rn == nPC) fprintf (of, "%-X", addr + vp + SXTW (num)); - else if (num & WSIGN) fprintf (of, "-%-X(%-s)", - -num & WMASK, regname[rn]); - else fprintf (of, "%-X(%-s)", num, regname[rn]); - break; - case LDD: /* @l^d(r),@l^n */ - fputc ('@', of); - case LDP: /* l^d(r),l^n */ - GETNUM (num, 4); - if (rn == nPC) fprintf (of, "%-X", addr + vp + num); - else if (num & LSIGN) fprintf (of, "-%-X(%-s)", - -num, regname[rn]); - else fprintf (of, "%-X(%-s)", num, regname[rn]); - break; } /* end case */ - if (index) fprintf (of, "[%-s]", regname[index & 0xF]); - } /* end else */ + if (rn == nPC) fprintf (of, "%-X", addr + vp + SXTW (num)); + else if (num & WSIGN) fprintf (of, "-%-X(%-s)", + -num & WMASK, regname[rn]); + else fprintf (of, "%-X(%-s)", num, regname[rn]); + break; + case LDD: /* @l^d(r),@l^n */ + fputc ('@', of); + case LDP: /* l^d(r),l^n */ + GETNUM (num, 4); + if (rn == nPC) fprintf (of, "%-X", addr + vp + num); + else if (num & LSIGN) fprintf (of, "-%-X(%-s)", + -num, regname[rn]); + else fprintf (of, "%-X(%-s)", num, regname[rn]); + break; } /* end case */ + if (index) fprintf (of, "[%-s]", regname[index & 0xF]); + } /* end else */ } /* end for */ return -(vp - 1); } @@ -975,8 +979,8 @@ for (i = 0; i < lnt; i++) { GETNUM (num[lnt - 1 - i], 4); } for (i = startp = 0; i < lnt; i++) { if (startp) fprintf (of, "%08X", num[i]); else if (num[i] || (i == (lnt - 1))) { - fprintf (of, "#%-X", num[i]); - startp = 1; } } + fprintf (of, "#%-X", num[i]); + startp = 1; } } return vp; } @@ -1019,7 +1023,7 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */ if (*cptr == 0) return SCPE_ARG; while ((vp < lnt) && *cptr) { /* get chars */ - val[vp++] = *cptr++; } + val[vp++] = *cptr++; } return -(vp - 1); } /* return # chars */ if (uptr == &cpu_unit) { /* cpu only */ @@ -1054,7 +1058,7 @@ for (i = 0, opc = -1; (i < NUM_INST) && (opc < 0); i++) { if (opcode[i] && strcmp (gbuf, opcode[i]) == 0) opc = i; } if (opc < 0) { /* check alternates */ for (i = 0; altcod[i] && (opc < 0); i++) { - if (strcmp (gbuf, altcod[i]) == 0) opc = altop[i]; } } + if (strcmp (gbuf, altcod[i]) == 0) opc = altop[i]; } } if (opc < 0) return SCPE_ARG; /* undefined? */ vp = 0; if (opc >= 0x100) val[vp++] = 0xFD; /* 2 byte? */ @@ -1129,7 +1133,7 @@ return vp; #define PARSE_LOSE { *r = SCPE_ARG; return vp; } #define SEL_LIM(p,m,u) ((fl & SP_PLUS)? (p): ((fl & SP_MINUS)? (m): (u))) -parse_spec (char *cptr, t_addr addr, t_value *val, int32 vp, int32 disp, t_stat *r) +int32 parse_spec (char *cptr, t_addr addr, t_value *val, int32 vp, int32 disp, t_stat *r) { int32 i, k, litsize, rn, index; int32 num, dispsize, mode; @@ -1142,30 +1146,30 @@ const char *force[] = { "S^", "I^", "B^", "W^", "L^", NULL }; M1C ('@', SP_IND); /* look for @ */ if (tptr = parse_rnum (cptr, &rn)) { /* look for Rn */ if (*cptr == '[') { /* look for [Rx] */ - cptr = parse_rnum (++cptr, &index); - if ((cptr == NULL) || (*cptr++ != ']')) PARSE_LOSE; - val[vp++] = index | IDX; } + cptr = parse_rnum (++cptr, &index); + if ((cptr == NULL) || (*cptr++ != ']')) PARSE_LOSE; + val[vp++] = index | IDX; } else val[vp++] = rn | GRN | (fl? 1: 0); /* Rn or @Rn */ if (*tptr != 0) *r = SCPE_ARG; /* must be done */ return vp; } for (i = 0; force[i]; i++) { /* look for x^ */ if (strncmp (cptr, force[i], 2) == 0) { - cptr = cptr + 2; - fl = fl | ((i + 1) << SP_V_FORCE); - break; } } + cptr = cptr + 2; + fl = fl | ((i + 1) << SP_V_FORCE); + break; } } M1C ('#', SP_LIT); /* look for # */ M1C ('+', SP_PLUS); /* look for + */ M1C ('-', SP_MINUS); /* look for - */ -for (litsize = 0;; cptr++) { /* look for mprec int */ +for (litsize = 0;; cptr++) { /* look for mprec int */ c = *cptr; if ((c < '0') || (c > 'F') || ((c > '9') && (c < 'A'))) break; num = (c <= '9')? c - '0': c - 'A' + 10; fl = fl | SP_NUM; for (i = 3; i >= 0; i--) { - lit[i] = lit[i] << 4; - if (i > 0) lit[i] = lit[i] | ((lit[i - 1] >> 28) & 0xF); - else lit[i] = lit[i] | num; - if (lit[i] && (i > litsize)) litsize = i; } } + lit[i] = lit[i] << 4; + if (i > 0) lit[i] = lit[i] | ((lit[i - 1] >> 28) & 0xF); + else lit[i] = lit[i] | num; + if (lit[i] && (i > litsize)) litsize = i; } } if (*cptr == '(') { /* look for (Rn) */ cptr = parse_rnum (++cptr, &rn); if ((cptr == NULL) || (*cptr++ != ')')) PARSE_LOSE; @@ -1193,8 +1197,8 @@ case SP_IDX|SP_POSTP: /* (Rn)+ */ case SP_LIT|SP_NUM: /* #n */ case SP_LIT|SP_PLUS|SP_NUM: /* #+n */ if ((litsize == 0) && ((lit[0] & ~0x3F) == 0)) { - val[vp++] = lit[0]; - break; } + val[vp++] = lit[0]; + break; } case SP_LIT|SP_MINUS|SP_NUM: /* #-n */ case SP_FI|SP_LIT|SP_NUM: /* I^#n */ case SP_FI|SP_LIT|SP_PLUS|SP_NUM: /* I^#+n */ @@ -1203,26 +1207,26 @@ case SP_FI|SP_LIT|SP_MINUS|SP_NUM: /* I^#-n */ disp = (disp == OC)? DR_LNMASK + 1: disp & DR_LNMASK; switch (disp) { /* case spec lnt */ case 00: /* check fit */ - if ((litsize > 0) || (lit[0] < 0) || - (lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) PARSE_LOSE; - SPUTNUM (lit[0], 1); /* store */ - break; + if ((litsize > 0) || (lit[0] < 0) || + (lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) PARSE_LOSE; + SPUTNUM (lit[0], 1); /* store */ + break; case 01: /* check fit */ - if ((litsize > 0) || (lit[0] < 0) || - (lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) PARSE_LOSE; - SPUTNUM (lit[0], 2); - break; + if ((litsize > 0) || (lit[0] < 0) || + (lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) PARSE_LOSE; + SPUTNUM (lit[0], 2); + break; case 02: /* check 1 lw */ - if (litsize > 0) PARSE_LOSE; - SPUTNUM (lit[0], 4); - break; + if (litsize > 0) PARSE_LOSE; + SPUTNUM (lit[0], 4); + break; case 03: /* check 2 lw */ - if (litsize > 1) PARSE_LOSE; - vp = parse_sym_qoimm (lit, val, vp, 2, fl & SP_MINUS); - break; + if (litsize > 1) PARSE_LOSE; + vp = parse_sym_qoimm (lit, val, vp, 2, fl & SP_MINUS); + break; case DR_LNMASK + 1: - vp = parse_sym_qoimm (lit, val, vp, 4, fl & SP_MINUS); - break; } /* end case disp */ + vp = parse_sym_qoimm (lit, val, vp, 4, fl & SP_MINUS); + break; } /* end case disp */ break; case SP_IND|SP_IDX|SP_POSTP: /* @(Rn)+ */ val[vp++] = rn | AID; @@ -1242,12 +1246,12 @@ case SP_IND|SP_MINUS|SP_NUM|SP_IDX: /* @-d(rn) */ dispsize = 4; /* find fit for */ mode = LDP; /* displacement */ if (lit[0] >= 0) { - if (lit[0] <= SEL_LIM (0x7F, 0x80, 0xFF)) { - dispsize = 1; - mode = BDP; } - else if (lit[0] <= SEL_LIM (0x7FFF, 0x8000, 0xFFFF)) { - dispsize = 2; - mode = WDP; } } + if (lit[0] <= SEL_LIM (0x7F, 0x80, 0xFF)) { + dispsize = 1; + mode = BDP; } + else if (lit[0] <= SEL_LIM (0x7FFF, 0x8000, 0xFFFF)) { + dispsize = 2; + mode = WDP; } } val[vp++] = mode | rn | ((fl & SP_IND)? 1: 0); SPUTNUM (lit[0], dispsize); break; @@ -1258,7 +1262,7 @@ case SP_IND|SP_FB|SP_NUM|SP_IDX: /* @B^d(rn) */ case SP_IND|SP_FB|SP_PLUS|SP_NUM|SP_IDX: /* @B^+d(rn) */ case SP_IND|SP_FB|SP_MINUS|SP_NUM|SP_IDX: /* @B^-d(rn) */ if ((litsize > 0) || (lit[0] < 0) || - (lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) PARSE_LOSE; + (lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) PARSE_LOSE; val[vp++] = rn | BDP | ((fl & SP_IND)? 1: 0); SPUTNUM (lit[0], 1); break; @@ -1269,7 +1273,7 @@ case SP_IND|SP_FW|SP_NUM|SP_IDX: /* @W^d(rn) */ case SP_IND|SP_FW|SP_PLUS|SP_NUM|SP_IDX: /* @W^+d(rn) */ case SP_IND|SP_FW|SP_MINUS|SP_NUM|SP_IDX: /* @W^-d(rn) */ if ((litsize > 0) || (lit[0] < 0) || - (lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) PARSE_LOSE; + (lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) PARSE_LOSE; val[vp++] = rn | WDP | ((fl & SP_IND)? 1: 0); SPUTNUM (lit[0], 2); break; @@ -1288,15 +1292,17 @@ case SP_IND|SP_NUM: /* @n */ if (litsize > 0) PARSE_LOSE; num = lit[0] - (addr + vp + 2); /* fit in byte? */ if ((num >= -128) && (num <= 127)) { - mode = BDP; - dispsize = 1; } - else { num = lit[0] - (addr + vp + 3); /* fit in word? */ - if ((num >= -32768) && (num <= 32767)) { - mode = WDP; - dispsize = 2; } - else { num = lit[0] - (addr + vp + 5); /* no, use lw */ - mode = LDP; - dispsize = 4; } } + mode = BDP; + dispsize = 1; } + else { + num = lit[0] - (addr + vp + 3); /* fit in word? */ + if ((num >= -32768) && (num <= 32767)) { + mode = WDP; + dispsize = 2; } + else { + num = lit[0] - (addr + vp + 5); /* no, use lw */ + mode = LDP; + dispsize = 4; } } val[vp++] = mode | nPC | ((fl & SP_IND)? 1: 0); PUTNUM (num, dispsize); break; @@ -1336,8 +1342,8 @@ char *tptr; for (i = 15; i >= 0; i--) { /* chk named reg */ lnt = strlen (regname[i]); if (strncmp (cptr, regname[i], lnt) == 0) { - *rn = i; - return cptr + lnt; } } + *rn = i; + return cptr + lnt; } } if (*cptr++ != 'R') return NULL; /* look for R */ regnum = strtotv (cptr, &tptr, 10); /* look for reg # */ if ((cptr == tptr) || (regnum > 15)) return NULL; diff --git a/VAX/vax_sysdev.c b/VAX/vax_sysdev.c index 63438c0a..943c96fb 100644 --- a/VAX/vax_sysdev.c +++ b/VAX/vax_sysdev.c @@ -84,6 +84,10 @@ #define CMCSR_MASK (CMCSR_PMI | CMCSR_CRD | CMCSR_DET | \ CMCSR_FDT | CMCSR_DCM | CMCSR_SYN) +/* KA655 boot/diagnostic register */ + +#define BDR_BRKENB 0x00000080 /* break enable */ + /* KA655 cache control register */ #define CACR_DRO 0x00FFFF00 /* diag bits RO */ @@ -164,7 +168,7 @@ int32 csi_csr = 0; /* control/status */ int32 cso_csr = 0; /* control/status */ int32 cmctl_reg[CMCTLSIZE >> 2] = { 0 }; /* CMCTL reg */ int32 ka_cacr = 0; /* KA655 cache ctl */ -int32 ka_bdr = 0x80; /* KA655 boot diag */ +int32 ka_bdr = BDR_BRKENB; /* KA655 boot diag */ int32 ssc_base = SSCBASE; /* SSC base */ int32 ssc_cnf = 0; /* SSC conf */ int32 ssc_bto = 0; /* SSC timeout */ @@ -738,7 +742,7 @@ struct reglink *p; for (p = ®table[0]; p->low != 0; p++) { if ((pa >= p->low) && (pa < p->high) && p->read) - return p->read (pa); } + return p->read (pa); } ssc_bto = ssc_bto | SSCBTO_BTO | SSCBTO_RWT; MACH_CHECK (MCHK_READ); return 0; @@ -760,8 +764,8 @@ struct reglink *p; for (p = ®table[0]; p->low != 0; p++) { if ((pa >= p->low) && (pa < p->high) && p->write) { - p->write (pa, val, lnt); - return; } } + p->write (pa, val, lnt); + return; } } ssc_bto = ssc_bto | SSCBTO_BTO | SSCBTO_RWT; MACH_CHECK (MCHK_WRITE); return; @@ -804,10 +808,10 @@ if (lnt < L_LONG) { /* LW write only */ switch (rg) { default: /* config reg */ if (val & CMCNF_SRQ) { /* sig request? */ - for (i = rg; i < (rg + 4); i++) { - cmctl_reg[i] = cmctl_reg[i] & ~CMCNF_SIG; - if (ADDR_IS_MEM (i * MEM_BANK)) - cmctl_reg[i] = cmctl_reg[i] | MEM_SIG; } } + for (i = rg; i < (rg + 4); i++) { + cmctl_reg[i] = cmctl_reg[i] & ~CMCNF_SIG; + if (ADDR_IS_MEM (i * MEM_BANK)) + cmctl_reg[i] = cmctl_reg[i] | MEM_SIG; } } cmctl_reg[rg] = (cmctl_reg[rg] & ~CMCNF_RW) | (val & CMCNF_RW); break; case 16: /* err status */ @@ -843,6 +847,11 @@ if ((rg == 0) && ((pa & 3) == 0)) { /* lo byte only */ ka_cacr = (ka_cacr & ~CACR_RW) | (val & CACR_RW); } return; } + +int32 sysd_hlt_enb (void) +{ +return ka_bdr & BDR_BRKENB; +} /* Cache diagnostic space - byte/word merges done in WriteReg */ @@ -1055,13 +1064,13 @@ tmr_csr[tmr] = (tmr_csr[tmr] & ~TMR_CSR_RW) | /* new r/w */ if (val & TMR_CSR_XFR) tmr_tir[tmr] = tmr_tnir[tmr]; /* xfr set? */ if (val & TMR_CSR_RUN) { /* run? */ if (val & TMR_CSR_XFR) /* new tir? */ - sim_cancel (&sysd_unit[tmr]); /* stop prev */ + sim_cancel (&sysd_unit[tmr]); /* stop prev */ if (!sim_is_active (&sysd_unit[tmr])) /* not running? */ - tmr_sched (tmr); } /* activate */ + tmr_sched (tmr); } /* activate */ else if (val & TMR_CSR_SGL) { /* single step? */ tmr_incr (tmr, 1); /* incr tmr */ if (tmr_tir[tmr] == 0) /* if ovflo, */ - tmr_tir[tmr] = tmr_tnir[tmr]; } /* reload tir */ + tmr_tir[tmr] = tmr_tnir[tmr]; } /* reload tir */ if ((tmr_csr[tmr] & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */ (TMR_CSR_DON | TMR_CSR_IE)) { if (tmr) CLR_INT (TMR1); @@ -1088,19 +1097,19 @@ uint32 new_tir = tmr_tir[tmr] + inc; /* add incr */ if (new_tir < tmr_tir[tmr]) { /* ovflo? */ tmr_tir[tmr] = 0; /* now 0 */ if (tmr_csr[tmr] & TMR_CSR_DON) /* done? set err */ - tmr_csr[tmr] = tmr_csr[tmr] | TMR_CSR_ERR; + tmr_csr[tmr] = tmr_csr[tmr] | TMR_CSR_ERR; else tmr_csr[tmr] = tmr_csr[tmr] | TMR_CSR_DON; /* set done */ if (tmr_csr[tmr] & TMR_CSR_STP) /* stop? */ - tmr_csr[tmr] = tmr_csr[tmr] & ~TMR_CSR_RUN; /* clr run */ + tmr_csr[tmr] = tmr_csr[tmr] & ~TMR_CSR_RUN; /* clr run */ if (tmr_csr[tmr] & TMR_CSR_RUN) { /* run? */ - tmr_tir[tmr] = tmr_tnir[tmr]; /* reload */ - tmr_sched (tmr); } /* reactivate */ + tmr_tir[tmr] = tmr_tnir[tmr]; /* reload */ + tmr_sched (tmr); } /* reactivate */ if (tmr_csr[tmr] & TMR_CSR_IE) { /* set int req */ - if (tmr) SET_INT (TMR1); - else SET_INT (TMR0); } } + if (tmr) SET_INT (TMR1); + else SET_INT (TMR0); } } else { tmr_tir[tmr] = new_tir; /* no, upd tir */ if (tmr_csr[tmr] & TMR_CSR_RUN) /* still running? */ - tmr_sched (tmr); } /* reactivate */ + tmr_sched (tmr); } /* reactivate */ return; } @@ -1159,7 +1168,6 @@ for (i = 0; i < 2; i++) { tmr_tivr[i] = 0; ssc_adsm[i] = ssc_adsk[i] = 0; } ka_cacr = 0; -ka_bdr = 0x80; ssc_base = SSCBASE; ssc_cnf = ssc_cnf & SSCCNF_BLO; ssc_bto = 0; diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index ccc82566..8dc75397 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 22-Dec-02 RMS Added BDR halt enable definition 11-Nov-02 RMS Added log bits for XQ 10-Oct-02 RMS Added DEQNA/DELQA, multiple RQ, autoconfigure support 29-Sep-02 RMS Revamped bus support macros @@ -371,7 +372,7 @@ typedef struct pdp_dib DIB; #define LOG_CPU_I 0x0001 /* intexc */ #define LOG_CPU_R 0x0002 /* REI */ #define LOG_CPU_P 0x0004 /* context */ -#define LOG_CPU_A 0x0008 +#define LOG_CPU_H 0x0008 /* history */ #define LOG_RP 0x0010 #define LOG_TS 0x0020 #define LOG_RQ 0x0040 diff --git a/build_mingw.bat b/build_mingw.bat index 873e73bd..eaad7353 100644 --- a/build_mingw.bat +++ b/build_mingw.bat @@ -1,85 +1,14 @@ -rem 22-Aug-02 rms Telnet console support -rem 18-May-02 rms VT emulation support -rem -rem Compile all of SIMH using MINGW gcc environment +@echo off +rem Compile all of SIMH using MINGW make and gcc environment rem Individual simulator sources are in .\simulator_name rem Individual simulator executables are to .\bin rem rem If needed, define the path for the MINGW bin directory. rem (this should already be set if MINGW was installed correctly) rem -path c:\mingw\bin;%path% -rem -rem PDP-1 -rem -gcc -O0 -o .\bin\pdp1 -I. -I.\pdp1 scp*.c sim*.c .\pdp1\pdp1*.c -lwsock32 -rem -rem PDP-11 -rem -gcc -O0 -o .\bin\pdp11 -I. -I.\pdp11 scp*.c sim*.c .\pdp11\pdp11*.c -lm -lwsock32 -rem -rem PDP-8 -rem -gcc -O0 -o .\bin\pdp8 -I. -I.\pdp8 scp*.c sim*.c .\pdp8\pdp8*.c -lm -lwsock32 -rem -rem PDP-4, PDP-7, PDP-9, PDP-15 -rem -gcc -O0 -DPDP4 -o .\bin\pdp4 -I. -I.\pdp18b scp*.c sim*.c .\pdp18b\pdp18b*.c -lm -lwsock32 -gcc -O0 -DPDP7 -o .\bin\pdp7 -I. -I.\pdp18b scp*.c sim*.c .\pdp18b\pdp18b*.c -lm -lwsock32 -gcc -O0 -DPDP9 -o .\bin\pdp9 -I. -I.\pdp18b scp*.c sim*.c .\pdp18b\pdp18b*.c -lm -lwsock32 -gcc -O0 -DPDP15 -o .\bin\pdp15 -I. -I.\pdp18b scp*.c sim*.c .\pdp18b\pdp18b*.c -lm -lwsock32 -rem -rem PDP-10 -rem -gcc -O0 -DUSE_INT64 -o .\bin\pdp10 -I.\pdp11 -I. -I.\pdp10 scp*.c sim*.c .\pdp10\pdp10*.c .\pdp11\pdp11_ry.c -lm -lwsock32 -rem -rem Nova, Eclipse -rem -gcc -O0 -o .\bin\nova -I. -I.\nova scp*.c sim*.c .\nova\nova*.c -lm -lwsock32 -gcc -O0 -DECLIPSE -o .\bin\eclipse -I. -I.\nova scp*.c sim*.c .\nova\eclipse_cpu.c .\nova\nova_clk.c .\nova\nova_dkp.c .\nova\nova_dsk.c .\nova\nova_lp.c .\nova\nova_mta.c .\nova\nova_plt.c .\nova\nova_pt.c .\nova\nova_sys.c .\nova\nova_tt.c .\nova\nova_tt1.c -lm -lwsock32 -rem -rem Altair -rem -gcc -O0 -o .\bin\altair -I. -I.\altair scp*.c sim*.c .\altair\altair*.c -lwsock32 -rem -rem AltairZ80 -rem -gcc -O0 -o .\bin\altairz80 -I. -I.\altairz80 scp*.c sim*.c .\altairz80\altair*.c -lwsock32 -rem -rem H316 -rem -gcc -O0 -o .\bin\h316 -I. -I.\h316 scp*.c sim*.c .\h316\h316*.c -lwsock32 -rem -rem HP2100 -rem -gcc -O0 -o .\bin\hp2100 -I. -I.\hp2100 scp*.c sim*.c .\hp2100\hp2100*.c -lwsock32 -rem -rem IBM 1401 -rem -gcc -O0 -o .\bin\i1401 -I. -I.\i1401 scp*.c sim*.c .\i1401\i1401*.c -lwsock32 -rem -rem IBM 1620 -rem -gcc -O0 -o .\bin\i1620 -I. -I.\i1620 scp*.c sim*.c .\i1620\i1620*.c -lwsock32 -rem -rem IBM System 3 -rem -gcc -O0 -o .\bin\s3 -I. -I.\s3 scp*.c sim*.c .\s3\s3*.c -lwsock32 -rem -rem IBM 1130 -rem -gcc -O0 -o .\bin\ibm1130 -I. -I.\ibm1130 scp*.c sim*.c .\ibm1130\ibm1130*.c -lwsock32 -rem -rem VAX -rem -gcc -O0 -DUSE_INT64 -o .\bin\vax -I. -I.\vax -I.\pdp11 scp*.c sim*.c .\pdp11\pdp11_pt.c .\pdp11\pdp11_rl.c .\pdp11\pdp11_rq.c .\pdp11\pdp11_dz.c .\pdp11\pdp11_lp.c .\pdp11\pdp11_ts.c .\pdp11\pdp11_tq.c .\pdp11\pdp11_xq.c .\vax\vax*.c -lm -lwsock32 -rem -rem GRI -rem -gcc -O0 -o .\bin\gri -I. -I.\gri scp*.c sim*.c .\gri\gri*.c -lwsock32 -rem -rem Placeholders for future simulators -rem -rem gcc -O0 -o .\bin\sds -I. -I.\sds scp*.c sim*.c .\sds\sds*.c -lm -lwsock32 -rem gcc -O0 -o .\bin\id16 -I. -I.\interdata scp*.c sim*.c .\interdata\id16*.c .\interdata\id_*.c -lwsock32 -rem gcc -O0 -o .\bin\id32 -I. -I.\interdata scp*.c sim*.c .\interdata\id32*.c .\interdata\id_*.c -lwsock32 +gcc -v 1>NUL 2>NUL +if ERRORLEVEL 1 path C:\MinGW\bin;%path% +mkdir BIN +gcc -v 1>NUL 2>NUL +if ERRORLEVEL 1 echo "MinGW Environment Unavailable" +mingw32-make WIN32=1 -f makefile %1 %2 %3 %4 diff --git a/build_mingw_ether.bat b/build_mingw_ether.bat index ee7a9f57..6d7b9282 100644 --- a/build_mingw_ether.bat +++ b/build_mingw_ether.bat @@ -1,86 +1,15 @@ +@echo off rem 12-Nov-02 rms Ethernet support -rem 22-Aug-02 rms Telnet console support -rem 18-May-02 rms VT emulation support -rem -rem Compile all of SIMH using MINGW gcc environment +rem Compile all of SIMH using MINGW make and gcc environment rem Individual simulator sources are in .\simulator_name rem Individual simulator executables are to .\bin rem rem If needed, define the path for the MINGW bin directory. rem (this should already be set if MINGW was installed correctly) rem -path c:\mingw\bin;%path% -rem -rem PDP-1 -rem -gcc -O0 -o .\bin\pdp1 -I. -I.\pdp1 scp*.c sim*.c .\pdp1\pdp1*.c -lwsock32 -rem -rem PDP-11 -rem -gcc -O0 -DUSE_NETWORK -o .\bin\pdp11 -I. -I.\pdp11 scp*.c sim*.c .\pdp11\pdp11*.c -lm -lwsock32 -lwpcap -lpacket -rem -rem PDP-8 -rem -gcc -O0 -o .\bin\pdp8 -I. -I.\pdp8 scp*.c sim*.c .\pdp8\pdp8*.c -lm -lwsock32 -rem -rem PDP-4, PDP-7, PDP-9, PDP-15 -rem -gcc -O0 -DPDP4 -o .\bin\pdp4 -I. -I.\pdp18b scp*.c sim*.c .\pdp18b\pdp18b*.c -lm -lwsock32 -gcc -O0 -DPDP7 -o .\bin\pdp7 -I. -I.\pdp18b scp*.c sim*.c .\pdp18b\pdp18b*.c -lm -lwsock32 -gcc -O0 -DPDP9 -o .\bin\pdp9 -I. -I.\pdp18b scp*.c sim*.c .\pdp18b\pdp18b*.c -lm -lwsock32 -gcc -O0 -DPDP15 -o .\bin\pdp15 -I. -I.\pdp18b scp*.c sim*.c .\pdp18b\pdp18b*.c -lm -lwsock32 -rem -rem PDP-10 -rem -gcc -O0 -DUSE_INT64 -o .\bin\pdp10 -I.\pdp11 -I. -I.\pdp10 scp*.c sim*.c .\pdp10\pdp10*.c .\pdp11\pdp11_ry.c -lm -lwsock32 -rem -rem Nova, Eclipse -rem -gcc -O0 -o .\bin\nova -I. -I.\nova scp*.c sim*.c .\nova\nova*.c -lm -lwsock32 -gcc -O0 -DECLIPSE -o .\bin\eclipse -I. -I.\nova scp*.c sim*.c .\nova\eclipse_cpu.c .\nova\nova_clk.c .\nova\nova_dkp.c .\nova\nova_dsk.c .\nova\nova_lp.c .\nova\nova_mta.c .\nova\nova_plt.c .\nova\nova_pt.c .\nova\nova_sys.c .\nova\nova_tt.c .\nova\nova_tt1.c -lm -lwsock32 -rem -rem Altair -rem -gcc -O0 -o .\bin\altair -I. -I.\altair scp*.c sim*.c .\altair\altair*.c -lwsock32 -rem -rem AltairZ80 -rem -gcc -O0 -o .\bin\altairz80 -I. -I.\altairz80 scp*.c sim*.c .\altairz80\altair*.c -lwsock32 -rem -rem H316 -rem -gcc -O0 -o .\bin\h316 -I. -I.\h316 scp*.c sim*.c .\h316\h316*.c -lwsock32 -rem -rem HP2100 -rem -gcc -O0 -o .\bin\hp2100 -I. -I.\hp2100 scp*.c sim*.c .\hp2100\hp2100*.c -lwsock32 -rem -rem IBM 1401 -rem -gcc -O0 -o .\bin\i1401 -I. -I.\i1401 scp*.c sim*.c .\i1401\i1401*.c -lwsock32 -rem -rem IBM 1620 -rem -gcc -O0 -o .\bin\i1620 -I. -I.\i1620 scp*.c sim*.c .\i1620\i1620*.c -lwsock32 -rem -rem IBM System 3 -rem -gcc -O0 -o .\bin\s3 -I. -I.\s3 scp*.c sim*.c .\s3\s3*.c -lwsock32 -rem -rem IBM 1130 -rem -gcc -O0 -o .\bin\ibm1130 -I. -I.\ibm1130 scp*.c sim*.c .\ibm1130\ibm1130*.c -lwsock32 -rem -rem VAX -rem -gcc -O0 -DUSE_INT64 -DUSE_NETWORK -o .\bin\vax -I. -I.\vax -I.\pdp11 scp*.c sim*.c .\pdp11\pdp11_pt.c .\pdp11\pdp11_rl.c .\pdp11\pdp11_rq.c .\pdp11\pdp11_dz.c .\pdp11\pdp11_lp.c .\pdp11\pdp11_ts.c .\pdp11\pdp11_tq.c .\pdp11\pdp11_xq.c .\vax\vax*.c -lm -lwsock32 -lwpcap -lpacket -rem -rem GRI -rem -gcc -O0 -o .\bin\gri -I. -I.\gri scp*.c sim*.c .\gri\gri*.c -lwsock32 -rem -rem Placeholders for future simulators -rem -rem gcc -O0 -o .\bin\sds -I. -I.\sds scp*.c sim*.c .\sds\sds*.c -lm -lwsock32 -rem gcc -O0 -o .\bin\id16 -I. -I.\interdata scp*.c sim*.c .\interdata\id16*.c .\interdata\id_*.c -lwsock32 -rem gcc -O0 -o .\bin\id32 -I. -I.\interdata scp*.c sim*.c .\interdata\id32*.c .\interdata\id_*.c -lwsock32 +gcc -v 1>NUL 2>NUL +if ERRORLEVEL 1 path C:\MinGW\bin;%path% +mkdir BIN +gcc -v 1>NUL 2>NUL +if ERRORLEVEL 1 echo "MinGW Environment Unavailable" +mingw32-make WIN32=1 USE_NETWORK=1 -f makefile %1 %2 %3 %4 diff --git a/dec_dz.h b/dec_dz.h index dce6482b..fd9318c0 100644 --- a/dec_dz.h +++ b/dec_dz.h @@ -28,6 +28,7 @@ dz DZ11 terminal multiplexor + 22-Dec-02 RMS Added break (framing error) support 31-Oct-02 RMS Added 8b support 12-Oct-02 RMS Added autoconfigure support 29-Sep-02 RMS Fixed bug in set number of lines routine @@ -104,7 +105,7 @@ #define RBUF_CHAR 0000377 /* rcv char */ #define RBUF_V_RLINE 8 /* rcv line */ #define RBUF_PARE 0010000 /* parity err - NI */ -#define RBUF_FRME 0020000 /* frame err - NI */ +#define RBUF_FRME 0020000 /* frame err */ #define RBUF_OVRE 0040000 /* overrun err - NI */ #define RBUF_VALID 0100000 /* rcv valid */ #define RBUF_MBZ 0004000 @@ -244,12 +245,13 @@ case 00: /* CSR */ case 01: /* RBUF */ dz_csr[dz] = dz_csr[dz] & ~CSR_SA; /* clr silo alarm */ if (dz_csr[dz] & CSR_MSE) { /* scanner on? */ - dz_rbuf[dz] = dz_getc (dz); /* get top of silo */ - if (!dz_rbuf[dz]) dz_sae[dz] = 1; /* empty? re-enable */ - tmxr_poll_rx (&dz_desc); /* poll input */ - dz_update_rcvi (); } /* update rx intr */ - else { dz_rbuf[dz] = 0; /* no data */ - dz_update_rcvi (); } /* no rx intr */ + dz_rbuf[dz] = dz_getc (dz); /* get top of silo */ + if (!dz_rbuf[dz]) dz_sae[dz] = 1; /* empty? re-enable */ + tmxr_poll_rx (&dz_desc); /* poll input */ + dz_update_rcvi (); } /* update rx intr */ + else { + dz_rbuf[dz] = 0; /* no data */ + dz_update_rcvi (); } /* no rx intr */ *data = dz_rbuf[dz]; break; case 02: /* TCR */ @@ -270,19 +272,19 @@ TMLN *lp; switch ((PA >> 1) & 03) { /* case on PA<2:1> */ case 00: /* CSR */ if (access == WRITEB) data = (PA & 1)? /* byte? merge */ - (dz_csr[dz] & 0377) | (data << 8): - (dz_csr[dz] & ~0377) | data; + (dz_csr[dz] & 0377) | (data << 8): + (dz_csr[dz] & ~0377) | data; if (data & CSR_CLR) dz_clear (dz, FALSE); /* clr? reset */ if (data & CSR_MSE) sim_activate (&dz_unit, tmxr_poll); else dz_csr[dz] &= ~(CSR_SA | CSR_RDONE | CSR_TRDY); if ((data & CSR_RIE) == 0) dz_clr_rxint (dz); /* RIE = 0? */ else if (((dz_csr[dz] & CSR_IE) == 0) && /* RIE 0->1? */ - ((dz_csr[dz] & CSR_SAE)? - (dz_csr[dz] & CSR_SA): (dz_csr[dz] & CSR_RDONE))) - dz_set_rxint (dz); + ((dz_csr[dz] & CSR_SAE)? + (dz_csr[dz] & CSR_SA): (dz_csr[dz] & CSR_RDONE))) + dz_set_rxint (dz); if ((data & CSR_TIE) == 0) dz_clr_txint (dz); /* TIE = 0? */ else if (((dz_csr[dz] & CSR_TIE) == 0) && (dz_csr[dz] & CSR_TRDY)) - dz_set_txint (dz); + dz_set_txint (dz); dz_csr[dz] = (dz_csr[dz] & ~CSR_RW) | (data & CSR_RW); break; case 01: /* LPR */ @@ -296,42 +298,42 @@ case 01: /* LPR */ break; case 02: /* TCR */ if (access == WRITEB) data = (PA & 1)? /* byte? merge */ - (dz_tcr[dz] & 0377) | (data << 8): - (dz_tcr[dz] & ~0377) | data; + (dz_tcr[dz] & 0377) | (data << 8): + (dz_tcr[dz] & ~0377) | data; if (dz_mctl) { /* modem ctl? */ - dz_msr[dz] |= ((data & 0177400) & /* dcd |= dtr & ring */ - ((dz_msr[dz] & DZ_LMASK) << MSR_V_CD)); - dz_msr[dz] &= ~(data >> TCR_V_DTR); /* ring &= ~dtr */ - if (dz_auto) { /* auto disconnect? */ - int32 drop; - drop = (dz_tcr[dz] & ~data) >> TCR_V_DTR; /* drop = dtr & ~data */ - for (i = 0; i < DZ_LINES; i++) { /* drop hangups */ - line = (dz * DZ_LINES) + i; /* get line num */ - lp = &dz_ldsc[line]; /* get line desc */ - if (lp->conn && (drop & (1 << i))) { - tmxr_msg (lp->conn, "\r\nLine hangup\r\n"); - tmxr_reset_ln (lp); /* reset line, cdet */ - dz_msr[dz] &= ~(1 << (i + MSR_V_CD)); - } /* end if drop */ - } /* end for */ - } /* end if auto */ - } /* end if modem */ + dz_msr[dz] |= ((data & 0177400) & /* dcd |= dtr & ring */ + ((dz_msr[dz] & DZ_LMASK) << MSR_V_CD)); + dz_msr[dz] &= ~(data >> TCR_V_DTR); /* ring &= ~dtr */ + if (dz_auto) { /* auto disconnect? */ + int32 drop; + drop = (dz_tcr[dz] & ~data) >> TCR_V_DTR; /* drop = dtr & ~data */ + for (i = 0; i < DZ_LINES; i++) { /* drop hangups */ + line = (dz * DZ_LINES) + i; /* get line num */ + lp = &dz_ldsc[line]; /* get line desc */ + if (lp->conn && (drop & (1 << i))) { + tmxr_msg (lp->conn, "\r\nLine hangup\r\n"); + tmxr_reset_ln (lp); /* reset line, cdet */ + dz_msr[dz] &= ~(1 << (i + MSR_V_CD)); + } /* end if drop */ + } /* end for */ + } /* end if auto */ + } /* end if modem */ dz_tcr[dz] = data; tmxr_poll_tx (&dz_desc); /* poll output */ dz_update_xmti (); /* update int */ break; case 03: /* TDR */ if (PA & 1) { /* odd byte? */ - dz_tdr[dz] = (dz_tdr[dz] & 0377) | (data << 8); /* just save */ - break; } + dz_tdr[dz] = (dz_tdr[dz] & 0377) | (data << 8); /* just save */ + break; } dz_tdr[dz] = data; if (dz_csr[dz] & CSR_MSE) { /* enabled? */ - line = (dz * DZ_LINES) + CSR_GETTL (dz_csr[dz]); - lp = &dz_ldsc[line]; /* get line desc */ - tmxr_putc_ln (lp, dz_tdr[dz] & /* store char */ - ((dz_unit.flags & UNIT_8B)? 0377: 0177)); - tmxr_poll_tx (&dz_desc); /* poll output */ - dz_update_xmti (); } /* update int */ + line = (dz * DZ_LINES) + CSR_GETTL (dz_csr[dz]); + lp = &dz_ldsc[line]; /* get line desc */ + tmxr_putc_ln (lp, dz_tdr[dz] & /* store char */ + ((dz_unit.flags & UNIT_8B)? 0377: 0177)); + tmxr_poll_tx (&dz_desc); /* poll output */ + dz_update_xmti (); } /* update int */ break; } return SCPE_OK; } @@ -356,10 +358,10 @@ for (dz = t = 0; dz < DZ_MUXES; dz++) /* check enabled */ if (t) { /* any enabled? */ newln = tmxr_poll_conn (&dz_desc); /* poll connect */ if ((newln >= 0) && dz_mctl) { /* got a live one? */ - dz = newln / DZ_LINES; /* get mux num */ - if (dz_tcr[dz] & (1 << (newln + TCR_V_DTR))) /* DTR set? */ - dz_msr[dz] |= (1 << (newln + MSR_V_CD)); /* set cdet */ - else dz_msr[dz] |= (1 << newln); } /* set ring */ + dz = newln / DZ_LINES; /* get mux num */ + if (dz_tcr[dz] & (1 << (newln + TCR_V_DTR))) /* DTR set? */ + dz_msr[dz] |= (1 << (newln + MSR_V_CD)); /* set cdet */ + else dz_msr[dz] |= (1 << newln); } /* set ring */ tmxr_poll_rx (&dz_desc); /* poll input */ dz_update_rcvi (); /* upd rcv intr */ tmxr_poll_tx (&dz_desc); /* poll output */ @@ -377,6 +379,7 @@ uint32 i, line, c; for (i = c = 0; (i < DZ_LINES) && (c == 0); i++) { /* loop thru lines */ line = (dz * DZ_LINES) + i; /* get line num */ c = tmxr_getc_ln (&dz_ldsc[line]); /* test for input */ + if (c & SCPE_BREAK) c = RBUF_VALID | RBUF_FRME; /* break? frame err */ if (c) c = c | (i << RBUF_V_RLINE); /* or in line # */ } /* end for */ return c; @@ -462,8 +465,8 @@ int32 dz; for (dz = 0; dz < DZ_MUXES; dz++) { /* find 1st mux */ if (dz_rxi & (1 << dz)) { - dz_clr_rxint (dz); /* clear intr */ - return (dz_dib.vec + (dz * 010)); } } /* return vector */ + dz_clr_rxint (dz); /* clear intr */ + return (dz_dib.vec + (dz * 010)); } } /* return vector */ return 0; } @@ -488,8 +491,8 @@ int32 dz; for (dz = 0; dz < DZ_MUXES; dz++) { /* find 1st mux */ if (dz_txi & (1 << dz)) { - dz_clr_txint (dz); /* clear intr */ - return (dz_dib.vec + 4 + (dz * 010)); } } /* return vector */ + dz_clr_txint (dz); /* clear intr */ + return (dz_dib.vec + 4 + (dz * 010)); } } /* return vector */ return 0; } @@ -545,10 +548,10 @@ if (sim_switches & SWMASK ('M')) { /* modem control? */ printf ("Modem control activated\n"); if (sim_log) fprintf (sim_log, "Modem control activated\n"); if (sim_switches & SWMASK ('A')) { /* autodisconnect? */ - dz_auto = 1; - printf ("Auto disconnect activated\n"); - if (sim_log) fprintf (sim_log, "Auto disconnect activated\n"); - } + dz_auto = 1; + printf ("Auto disconnect activated\n"); + if (sim_log) fprintf (sim_log, "Auto disconnect activated\n"); + } } return SCPE_OK; } @@ -580,10 +583,10 @@ t_stat dz_show (FILE *st, UNIT *uptr, int32 val, void *desc) int32 i, t; for (i = t = 0; i < dz_desc.lines; i++) { /* loop thru conn */ - if (dz_ldsc[i].conn) { - t = 1; - if (val) tmxr_fconns (st, &dz_ldsc[i], i); - else tmxr_fstats (st, &dz_ldsc[i], i); } } + if (dz_ldsc[i].conn) { + t = 1; + if (val) tmxr_fconns (st, &dz_ldsc[i], i); + else tmxr_fstats (st, &dz_ldsc[i], i); } } if (t == 0) fprintf (st, "all disconnected\n"); return SCPE_OK; } diff --git a/dec_pt.h b/dec_pt.h index f73fbfe5..3900f5ab 100644 --- a/dec_pt.h +++ b/dec_pt.h @@ -157,13 +157,13 @@ case 0: /* ptr csr */ if (PA & 1) return SCPE_OK; if ((data & CSR_IE) == 0) CLR_INT (PTR); else if (((ptr_csr & CSR_IE) == 0) && (ptr_csr & (CSR_ERR | CSR_DONE))) - SET_INT (PTR); + SET_INT (PTR); if (data & CSR_GO) { - ptr_csr = (ptr_csr & ~CSR_DONE) | CSR_BUSY; - CLR_INT (PTR); - if (ptr_unit.flags & UNIT_ATT) /* data to read? */ - sim_activate (&ptr_unit, ptr_unit.wait); - else sim_activate (&ptr_unit, 0); } /* error if not */ + ptr_csr = (ptr_csr & ~CSR_DONE) | CSR_BUSY; + CLR_INT (PTR); + if (ptr_unit.flags & UNIT_ATT) /* data to read? */ + sim_activate (&ptr_unit, ptr_unit.wait); + else sim_activate (&ptr_unit, 0); } /* error if not */ ptr_csr = (ptr_csr & ~PTRCSR_RW) | (data & PTRCSR_RW); return SCPE_OK; case 1: /* ptr buf */ @@ -183,8 +183,8 @@ if ((ptr_unit.flags & UNIT_ATT) == 0) return IORETURN (ptr_stopioe, SCPE_UNATT); if ((temp = getc (ptr_unit.fileref)) == EOF) { if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } + if (ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; } else perror ("PTR I/O error"); clearerr (ptr_unit.fileref); return SCPE_IOERR; } @@ -243,7 +243,7 @@ case 0: /* ptp csr */ if (PA & 1) return SCPE_OK; if ((data & CSR_IE) == 0) CLR_INT (PTP); else if (((ptp_csr & CSR_IE) == 0) && (ptp_csr & (CSR_ERR | CSR_DONE))) - SET_INT (PTP); + SET_INT (PTP); ptp_csr = (ptp_csr & ~PTPCSR_RW) | (data & PTPCSR_RW); return SCPE_OK; case 1: /* ptp buf */ @@ -251,7 +251,7 @@ case 1: /* ptp buf */ ptp_csr = ptp_csr & ~CSR_DONE; CLR_INT (PTP); if (ptp_unit.flags & UNIT_ATT) /* file to write? */ - sim_activate (&ptp_unit, ptp_unit.wait); + sim_activate (&ptp_unit, ptp_unit.wait); else sim_activate (&ptp_unit, 0); /* error if not */ return SCPE_OK; } /* end switch PA */ return SCPE_NXM; /* can't get here */ diff --git a/descrip.mms b/descrip.mms index cd76486d..0b505ec8 100644 --- a/descrip.mms +++ b/descrip.mms @@ -1,1000 +1,1006 @@ -# -# DESCRIP.MMS -# Written By: Robert Alan Byer -# byer@mail.ourservers.net -# -# This MMS/MMK build script is used to compile the various simulators in -# the SIMH package for OpenVMS using DEC C v6.0-001. -# -# Note: On VAX, the PDP-10 and VAX simulator will not be built due to the -# fact that INT64 is required for those simulators. -# -# -# This build script will accept the following build options. -# -# ALL Just Build "Everything". -# ALTAIR Just Build The MITS Altair. -# ALTAIRZ80 Just Build The MITS Altair Z80. -# ECLIPSE Just Build The Data General Eclipse. -# GRI Just Build The GRI Corporation GRI-909. -# H316 Just Build The Honewell 316/516. -# HP2100 Just Build The Hewlett-Packard HP-2100. -# I1401 Just Build The IBM 1401. -# IBM1130 Just Build The IBM 1130. -# ID16 Just Build The Interdata 16-bit CPU. -# ID32 Just Build The Interdata 32-bit CPU. -# NOVA Just Build The Data General Nova. -# PDP1 Just Build The DEC PDP-1. -# PDP4 Just Build The DEC PDP-4. -# PDP7 Just Build The DEC PDP-7. -# PDP8 Just Build The DEC PDP-8. -# PDP9 Just Build The DEC PDP-9. -# PDP10 Just Build The DEC PDP-10. -# PDP11 Just Build The DEC PDP-11. -# PDP15 Just Build The DEC PDP-15. -# S3 Just Build The IBM System 3. -# SDS Just Build The SDS 940. -# VAX Just Build The DEC VAX. -# -# To build with debugging enabled (which will also enable traceback -# information) use.. -# -# MMK/FORCE/MACRO=(DEBUG=1) -# - -# -# Define The BIN Directory Where The Executables Will Go. -# -BIN_DIR = SYS$DISK:[.BIN] - -# -# Define Our Library Directory. -# -LIB_DIR = SYS$DISK:[.LIB] - -# -# Let's See If We Are Going To Build With DEBUG Enabled. -# -.IFDEF DEBUG -CC_DEBUG = /DEBUG -LINK_DEBUG = /DEBUG/TRACEBACK -CC_OPTIMIZE = /NOOPTIMIZE -.ELSE -CC_DEBUG = /NODEBUG -LINK_DEBUG = /NODEBUG/NOTRACEBACK -.IFDEF __ALPHA__ -CC_OPTIMIZE = /OPTIMIZE=(LEVEL=5,TUNE=HOST)/ARCH=HOST -CC_FLAGS = /PREFIX=ALL -ARCH = AXP -.ELSE -CC_OPTIMIZE = /OPTIMIZE -ARCH = VAX -.ENDIF -.ENDIF - -# -# Define Our Compiler Flags. -# -CC_FLAGS = $(CC_FLAGS)$(CC_OPTIMIZE)/NEST=PRIMARY/NAME=(AS_IS,SHORTENED) - -# -# Define The Compile Command. -# -CC = CC $(CC_FLAGS) - -# -# First, Let's Check To Make Sure We Have A SYS$DISK:[.BIN] And -# SYS$DISK:[.LIB] Directory. -# -.FIRST - @ IF (F$SEARCH("SYS$DISK:[]BIN.DIR").EQS."") THEN CREATE/DIRECTORY $(BIN_DIR) - @ IF (F$SEARCH("SYS$DISK:[]LIB.DIR").EQS."") THEN CREATE/DIRECTORY $(LIB_DIR) - -# -# Core SIMH File Definitions. -# -SIMH_DIR = SYS$DISK:[] -SIMH_LIB = $(LIB_DIR)SIMH-$(ARCH).OLB -SIMH_SOURCE = $(SIMH_DIR)SCP_TTY.C,$(SIMH_DIR)SIM_SOCK.C,\ - $(SIMH_DIR)SIM_TMXR.C,$(SIMH_DIR)SIM_ETHER.C -SIMH_OBJS = $(SIMH_DIR)SCP_TTY.OBJ,$(SIMH_DIR)SIM_SOCK.OBJ,\ - $(SIMH_DIR)SIM_TMXR.OBJ,$(SIMH_DIR)SIM_ETHER.OBJ - -# -# MITS Altair Simulator Definitions. -# -ALTAIR_DIR = SYS$DISK:[.ALTAIR] -ALTAIR_LIB = $(LIB_DIR)ALTAIR-$(ARCH).OLB -ALTAIR_SOURCE = $(ALTAIR_DIR)ALTAIR_SIO.C,$(ALTAIR_DIR)ALTAIR_CPU.C,\ - $(ALTAIR_DIR)ALTAIR_DSK.C,$(ALTAIR_DIR)ALTAIR_SYS.C -ALTAIR_OBJS = $(ALTAIR_DIR)ALTAIR_SIO.OBJ,$(ALTAIR_DIR)ALTAIR_CPU.OBJ,\ - $(ALTAIR_DIR)ALTAIR_DSK.OBJ,$(ALTAIR_DIR)ALTAIR_SYS.OBJ -ALTAIR_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIR_DIR)) - -# -# MITS Altair Z80 Simulator Definitions. -# -ALTAIRZ80_DIR = SYS$DISK:[.ALTAIRZ80] -ALTAIRZ80_LIB = $(LIB_DIR)ALTAIRZ80-$(ARCH).OLB -ALTAIRZ80_SOURCE = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_DSK.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SIO.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SYS.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.C -ALTAIRZ80_OBJS = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_DSK.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SIO.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SYS.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.OBJ -ALTAIRZ80_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIRZ80_DIR)) - -# -# Data General Nova Simulator Definitions. -# -NOVA_DIR = SYS$DISK:[.NOVA] -NOVA_LIB = $(LIB_DIR)NOVA-$(ARCH).OLB -NOVA_SOURCE = $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_CPU.C,\ - $(NOVA_DIR)NOVA_DKP.C,$(NOVA_DIR)NOVA_DSK.C,\ - $(NOVA_DIR)NOVA_LP.C,$(NOVA_DIR)NOVA_MTA.C,\ - $(NOVA_DIR)NOVA_PLT.C,$(NOVA_DIR)NOVA_PT.C,\ - $(NOVA_DIR)NOVA_CLK.C,$(NOVA_DIR)NOVA_TT.C,\ - $(NOVA_DIR)NOVA_TT1.C -NOVA_OBJS = $(NOVA_DIR)NOVA_SYS.OBJ,$(NOVA_DIR)NOVA_CPU.OBJ,\ - $(NOVA_DIR)NOVA_DKP.OBJ,$(NOVA_DIR)NOVA_DSK.OBJ,\ - $(NOVA_DIR)NOVA_LP.OBJ,$(NOVA_DIR)NOVA_MTA.OBJ,\ - $(NOVA_DIR)NOVA_PLT.OBJ,$(NOVA_DIR)NOVA_PT.OBJ,\ - $(NOVA_DIR)NOVA_CLK.OBJ,$(NOVA_DIR)NOVA_TT.OBJ,\ - $(NOVA_DIR)NOVA_TT1.OBJ -NOVA_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR)) - -# -# Data General Eclipse Simulator Definitions. -# -ECLIPSE_LIB = $(LIB_DIR)ECLIPSE-$(ARCH).OLB -ECLIPSE_SOURCE = $(NOVA_DIR)ECLIPSE_CPU.C,$(NOVA_DIR)ECLIPSE_TT.C,\ - $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_DKP.C,\ - $(NOVA_DIR)NOVA_DSK.C,$(NOVA_DIR)NOVA_LP.C,\ - $(NOVA_DIR)NOVA_MTA.C,$(NOVA_DIR)NOVA_PLT.C,\ - $(NOVA_DIR)NOVA_PT.C,$(NOVA_DIR)NOVA_CLK.C,\ - $(NOVA_DIR)NOVA_TT1.C -ECLIPSE_OBJS = $(NOVA_DIR)ECLIPSE_CPU.OBJ,$(NOVA_DIR)ECLIPSE_TT.OBJ,\ - $(NOVA_DIR)NOVA_SYS.OBJ,$(NOVA_DIR)NOVA_DKP.OBJ,\ - $(NOVA_DIR)NOVA_DSK.OBJ,$(NOVA_DIR)NOVA_LP.OBJ,\ - $(NOVA_DIR)NOVA_MTA.OBJ,$(NOVA_DIR)NOVA_PLT.OBJ,\ - $(NOVA_DIR)NOVA_PT.OBJ,$(NOVA_DIR)NOVA_CLK.OBJ,\ - $(NOVA_DIR)NOVA_TT1.OBJ -ECLIPSE_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR))/DEFINE=("ECLIPSE=1") - -# -# GRI Corporation GRI-909 Simulator Definitions. -# -GRI_DIR = SYS$DISK:[.GRI] -GRI_LIB = $(LIB_DIR)GRI-$(ARCH).OLB -GRI_SOURCE = $(GRI_DIR)GRI_CPU.C,$(GRI_DIR)GRI_STDDEV.C,$(GRI_DIR)GRI_SYS.C -GRI_OBJS = $(GRI_DIR)GRI_CPU.OBJ,$(GRI_DIR)GRI_STDDEV.OBJ,\ - $(GRI_DIR)GRI_SYS.OBJ -GRI_OPTIONS = /INCLUDE=($(SIMH_DIR),$(GRI_DIR)) - -# -# Honeywell 316/516 Simulator Definitions. -# -H316_DIR = SYS$DISK:[.H316] -H316_LIB = $(LIB_DIR)H316-$(ARCH).OLB -H316_SOURCE = $(H316_DIR)H316_STDDEV.C,$(H316_DIR)H316_LP.C,\ - $(H316_DIR)H316_CPU.C,$(H316_DIR)H316_SYS.C -H316_OBJS = $(H316_DIR)H316_STDDEV.OBJ,$(H316_DIR)H316_LP.OBJ,\ - $(H316_DIR)H316_CPU.OBJ,$(H316_DIR)H316_SYS.OBJ -H316_OPTIONS = /INCLUDE=($(SIMH_DIR),$(H316_DIR)) - -# -# Hewlett-Packard HP-2100 Simulator Definitions. -# -HP2100_DIR = SYS$DISK:[.HP2100] -HP2100_LIB = $(LIB_DIR)HP2100-$(ARCH).OLB -HP2100_SOURCE = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.C,\ - $(HP2100_DIR)HP2100_DQ.C,$(HP2100_DIR)HP2100_DR.C,\ - $(HP2100_DIR)HP2100_LPS.C,$(HP2100_DIR)HP2100_MS.C,\ - $(HP2100_DIR)HP2100_MT.C,$(HP2100_DIR)HP2100_MUX.C,\ - $(HP2100_DIR)HP2100_CPU.C,$(HP2100_DIR)HP2100_FP.C,\ - $(HP2100_DIR)HP2100_SYS.C,$(HP2100_DIR)HP2100_LPT.C -HP2100_OBJS = $(HP2100_DIR)HP2100_STDDEV.OBJ,$(HP2100_DIR)HP2100_DP.OBJ,\ - $(HP2100_DIR)HP2100_DQ.OBJ,$(HP2100_DIR)HP2100_DR.OBJ,\ - $(HP2100_DIR)HP2100_LPS.OBJ,$(HP2100_DIR)HP2100_MS.OBJ,\ - $(HP2100_DIR)HP2100_MT.OBJ,$(HP2100_DIR)HP2100_MUX.OBJ,\ - $(HP2100_DIR)HP2100_CPU.OBJ,$(HP2100_DIR)HP2100_FP.OBJ,\ - $(HP2100_DIR)HP2100_SYS.OBJ,$(HP2100_DIR)HP2100_LPT.OBJ -HP2100_OPTIONS = /INCLUDE=($(SIMH_DIR),$(HP2100_DIR)) - -# -# Interdata 16-bit CPU. -# -ID16_DIR = SYS$DISK:[.INTERDATA] -ID16_LIB = $(LIB_DIR)ID16-$(ARCH).OLB -ID16_SOURCE = $(ID16_DIR)ID16_CPU.C,$(ID16_DIR)ID16_SYS.C,$(ID16_DIR)ID_DP.C,\ - $(ID16_DIR)ID_FD.C,$(ID16_DIR)ID_FP.C,$(ID16_DIR)ID_IDC.C,\ - $(ID16_DIR)ID_IO.C,$(ID16_DIR)ID_LP.C,$(ID16_DIR)ID_MT.C,\ - $(ID16_DIR)ID_PAS.C,$(ID16_DIR)ID_PT.C,$(ID16_DIR)ID_TT.C,\ - $(ID16_DIR)ID_UVC.C -ID16_OBJS = $(ID16_DIR)ID16_CPU.OBJ,$(ID16_DIR)ID16_SYS.OBJ,$(ID16_DIR)ID_DP.OBJ,\ - $(ID16_DIR)ID_FD.OBJ,$(ID16_DIR)ID_FP.OBJ,$(ID16_DIR)ID_IDC.OBJ,\ - $(ID16_DIR)ID_IO.OBJ,$(ID16_DIR)ID_LP.OBJ,$(ID16_DIR)ID_MT.OBJ,\ - $(ID16_DIR)ID_PAS.OBJ,$(ID16_DIR)ID_PT.OBJ,$(ID16_DIR)ID_TT.OBJ,\ - $(ID16_DIR)ID_UVC.OBJ -ID16_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID16_DIR)) - -# -# Interdata 32-bit CPU. -# -ID32_DIR = SYS$DISK:[.INTERDATA] -ID32_LIB = $(LIB_DIR)ID32-$(ARCH).OLB -ID32_SOURCE = $(ID32_DIR)ID32_CPU.C,$(ID32_DIR)ID32_SYS.C,$(ID32_DIR)ID_DP.C,\ - $(ID32_DIR)ID_FD.C,$(ID32_DIR)ID_FP.C,$(ID32_DIR)ID_IDC.C,\ - $(ID32_DIR)ID_IO.C,$(ID32_DIR)ID_LP.C,$(ID32_DIR)ID_MT.C,\ - $(ID32_DIR)ID_PAS.C,$(ID32_DIR)ID_PT.C,$(ID32_DIR)ID_TT.C,\ - $(ID32_DIR)ID_UVC.C -ID32_OBJS = $(ID32_DIR)ID32_CPU.OBJ,$(ID32_DIR)ID32_SYS.OBJ,\ - $(ID32_DIR)ID_DP.OBJ,$(ID32_DIR)ID_FD.OBJ,\ - $(ID32_DIR)ID_FP.OBJ,$(ID32_DIR)ID_IDC.OBJ,\ - $(ID32_DIR)ID_IO.OBJ,$(ID32_DIR)ID_LP.OBJ,$(ID32_DIR)ID_MT.OBJ,\ - $(ID32_DIR)ID_PAS.OBJ,$(ID32_DIR)ID_PT.OBJ,$(ID32_DIR)ID_TT.OBJ,\ - $(ID32_DIR)ID_UVC.OBJ -ID32_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID32_DIR)) - -# -# IBM 1130 Simulator Definitions. -# -IBM1130_DIR = SYS$DISK:[.IBM1130] -IBM1130_LIB = $(LIB_DIR)IBM1130-$(ARCH).OLB -IBM1130_SOURCE = $(IBM1130_DIR)IBM1130_CPU.C,$(IBM1130_DIR)IBM1130_CR.C,\ - $(IBM1130_DIR)IBM1130_DISK.C,$(IBM1130_DIR)IBM1130_STDDEV.C,\ - $(IBM1130_DIR)IBM1130_SYS.C,$(IBM1130_DIR)IBM1130_GDU.C,\ - $(IBM1130_DIR)IBM1130_GUI.C,$(IBM1130_DIR)IBM1130_PRT.C -IBM1130_OBJS = $(IBM1130_DIR)IBM1130_CPU.OBJ,$(IBM1130_DIR)IBM1130_CR.OBJ,\ - $(IBM1130_DIR)IBM1130_DISK.OBJ,$(IBM1130_DIR)IBM1130_STDDEV.OBJ,\ - $(IBM1130_DIR)IBM1130_SYS.OBJ,$(IBM1130_DIR)IBM1130_GDU.OBJ,\ - $(IBM1130_DIR)IBM1130_GUI.OBJ,$(IBM1130_DIR)IBM1130_PRT.OBJ -IBM1130_OPTIONS = /INCLUDE=($(SIMH_DIR),$(IBM1130_DIR)) - -# -# IBM 1401 Simulator Definitions. -# -I1401_DIR = SYS$DISK:[.I1401] -I1401_LIB = $(LIB_DIR)I1401-$(ARCH).OLB -I1401_SOURCE = $(I1401_DIR)I1401_LP.C,$(I1401_DIR)I1401_CPU.C,\ - $(I1401_DIR)I1401_IQ.C,$(I1401_DIR)I1401_CD.C,\ - $(I1401_DIR)I1401_MT.C,$(I1401_DIR)I1401_DP.C,\ - $(I1401_DIR)I1401_SYS.C -I1401_OBJS = $(I1401_DIR)I1401_LP.OBJ,$(I1401_DIR)I1401_CPU.OBJ,\ - $(I1401_DIR)I1401_IQ.OBJ,$(I1401_DIR)I1401_CD.OBJ,\ - $(I1401_DIR)I1401_MT.OBJ,$(I1401_DIR)I1401_DP.OBJ,\ - $(I1401_DIR)I1401_SYS.OBJ -I1401_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1401_DIR)) - - -# -# IBM 1620 Simulators Definitions. -# -I1620_DIR = SYS$DISK:[.I1620] -I1620_LIB = $(LIB_DIR)I1620-$(ARCH).OLB -I1620_SOURCE = $(I1620_DIR)I1620_CD.C,$(I1620_DIR)I1620_DP.C,\ - $(I1620_DIR)I1620_PT.C,$(I1620_DIR)I1620_TTY.C,\ - $(I1620_DIR)I1620_CPU.C,$(I1620_DIR)I1620_LP.C,\ - $(I1620_DIR)I1620_FP.C,$(I1620_DIR)I1620_SYS.C -I1620_OBJS = $(I1620_DIR)I1620_CD.OBJ,$(I1620_DIR)I1620_DP.OBJ,\ - $(I1620_DIR)I1620_PT.OBJ,$(I1620_DIR)I1620_TTY.OBJ,\ - $(I1620_DIR)I1620_CPU.OBJ,$(I1620_DIR)I1620_LP.OBJ,\ - $(I1620_DIR)I1620_FP.OBJ,$(I1620_DIR)I1620_SYS.OBJ -I1620_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1620_DIR)) - -# -# PDP-1 Simulator Definitions. -# -PDP1_DIR = SYS$DISK:[.PDP1] -PDP1_LIB = $(LIB_DIR)PDP1-$(ARCH).OLB -PDP1_SOURCE = $(PDP1_DIR)PDP1_LP.C,$(PDP1_DIR)PDP1_CPU.C,\ - $(PDP1_DIR)PDP1_STDDEV.C,$(PDP1_DIR)PDP1_SYS.C,\ - $(PDP1_DIR)PDP1_DT.C -PDP1_OBJS = $(PDP1_DIR)PDP1_LP.OBJ,$(PDP1_DIR)PDP1_CPU.OBJ,\ - $(PDP1_DIR)PDP1_STDDEV.OBJ,$(PDP1_DIR)PDP1_SYS.OBJ,\ - $(PDP1_DIR)PDP1_DT.OBJ -PDP1_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP1_DIR)) - -# -# Digital Equipment PDP-8 Simulator Definitions. -# -PDP8_DIR = SYS$DISK:[.PDP8] -PDP8_LIB = $(LIB_DIR)PDP8-$(ARCH).OLB -PDP8_SOURCE = $(PDP8_DIR)PDP8_CPU.C,$(PDP8_DIR)PDP8_CLK.C,\ - $(PDP8_DIR)PDP8_DF.C,$(PDP8_DIR)PDP8_DT.C,\ - $(PDP8_DIR)PDP8_LP.C,$(PDP8_DIR)PDP8_MT.C,\ - $(PDP8_DIR)PDP8_PT.C,$(PDP8_DIR)PDP8_RF.C,\ - $(PDP8_DIR)PDP8_RK.C,$(PDP8_DIR)PDP8_RX.C,\ - $(PDP8_DIR)PDP8_SYS.C,$(PDP8_DIR)PDP8_TT.C,\ - $(PDP8_DIR)PDP8_TTX.C,$(PDP8_DIR)PDP8_RL.C -PDP8_OBJS = $(PDP8_DIR)PDP8_CPU.OBJ,$(PDP8_DIR)PDP8_CLK.OBJ,\ - $(PDP8_DIR)PDP8_DF.OBJ,$(PDP8_DIR)PDP8_DT.OBJ,\ - $(PDP8_DIR)PDP8_LP.OBJ,$(PDP8_DIR)PDP8_MT.OBJ,\ - $(PDP8_DIR)PDP8_PT.OBJ,$(PDP8_DIR)PDP8_RF.OBJ,\ - $(PDP8_DIR)PDP8_RK.OBJ,$(PDP8_DIR)PDP8_RX.OBJ,\ - $(PDP8_DIR)PDP8_SYS.OBJ,$(PDP8_DIR)PDP8_TT.OBJ,\ - $(PDP8_DIR)PDP8_TTX.OBJ,$(PDP8_DIR)PDP8_RL.OBJ -PDP8_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP8_DIR)) - -# -# Digital Equipment PDP-4, PDP-7, PDP-9 And PDP-15 Simulator Definitions. -# -PDP18B_DIR = SYS$DISK:[.PDP18B] -PDP4_LIB = $(LIB_DIR)PDP4-$(ARCH).OLB -PDP7_LIB = $(LIB_DIR)PDP7-$(ARCH).OLB -PDP9_LIB = $(LIB_DIR)PDP9-$(ARCH).OLB -PDP15_LIB = $(LIB_DIR)PDP15-$(ARCH).OLB -PDP18B_SOURCE = $(PDP18B_DIR)PDP18B_DT.C,$(PDP18B_DIR)PDP18B_DRM.C,\ - $(PDP18B_DIR)PDP18B_CPU.C,$(PDP18B_DIR)PDP18B_LP.C,\ - $(PDP18B_DIR)PDP18B_MT.C,$(PDP18B_DIR)PDP18B_RF.C,\ - $(PDP18B_DIR)PDP18B_RP.C,$(PDP18B_DIR)PDP18B_STDDEV.C,\ - $(PDP18B_DIR)PDP18B_SYS.C,$(PDP18B_DIR)PDP18B_TT1.C -PDP18B_OBJS = $(PDP18B_DIR)PDP18B_DT.OBJ,$(PDP18B_DIR)PDP18B_DRM.OBJ,\ - $(PDP18B_DIR)PDP18B_CPU.OBJ,$(PDP18B_DIR)PDP18B_LP.OBJ,\ - $(PDP18B_DIR)PDP18B_MT.OBJ,$(PDP18B_DIR)PDP18B_RF.OBJ,\ - $(PDP18B_DIR)PDP18B_RP.OBJ,$(PDP18B_DIR)PDP18B_STDDEV.OBJ,\ - $(PDP18B_DIR)PDP18B_SYS.OBJ,$(PDP18B_DIR)PDP18B_TT1.OBJ -PDP4_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP4=1") -PDP7_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP7=1") -PDP9_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP9=1") -PDP15_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP15=1") - -# -# Digital Equipment PDP-11 Simulator Definitions. -# -PDP11_DIR = SYS$DISK:[.PDP11] -PDP11_LIB = $(LIB_DIR)PDP11-$(ARCH).OLB -PDP11_SOURCE = $(PDP11_DIR)PDP11_FP.C,$(PDP11_DIR)PDP11_CPU.C,\ - $(PDP11_DIR)PDP11_DZ.C,$(PDP11_DIR)PDP11_CIS.C,\ - $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_RK.C,\ - $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RP.C,\ - $(PDP11_DIR)PDP11_RX.C,$(PDP11_DIR)PDP11_STDDEV.C,\ - $(PDP11_DIR)PDP11_SYS.C,$(PDP11_DIR)PDP11_TC.C,\ - $(PDP11_DIR)PDP11_TM.C,$(PDP11_DIR)PDP11_TS.C,\ - $(PDP11_DIR)PDP11_IO.C,$(PDP11_DIR)PDP11_RQ.C,\ - $(PDP11_DIR)PDP11_TQ.C,$(PDP11_DIR)PDP11_PCLK.C,\ - $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_PT.C,\ - $(PDP11_DIR)PDP11_HK.C,$(PDP11_DIR)PDP11_XQ.C -PDP11_OBJS = $(PDP11_DIR)PDP11_FP.OBJ,$(PDP11_DIR)PDP11_CPU.OBJ,\ - $(PDP11_DIR)PDP11_DZ.OBJ,$(PDP11_DIR)PDP11_CIS.OBJ,\ - $(PDP11_DIR)PDP11_LP.OBJ,$(PDP11_DIR)PDP11_RK.OBJ,\ - $(PDP11_DIR)PDP11_RL.OBJ,$(PDP11_DIR)PDP11_RP.OBJ,\ - $(PDP11_DIR)PDP11_RX.OBJ,$(PDP11_DIR)PDP11_STDDEV.OBJ,\ - $(PDP11_DIR)PDP11_SYS.OBJ,$(PDP11_DIR)PDP11_TC.OBJ,\ - $(PDP11_DIR)PDP11_TM.OBJ,$(PDP11_DIR)PDP11_TS.OBJ,\ - $(PDP11_DIR)PDP11_IO.OBJ,$(PDP11_DIR)PDP11_RQ.OBJ,\ - $(PDP11_DIR)PDP11_TQ.OBJ,$(PDP11_DIR)PDP11_PCLK.OBJ,\ - $(PDP11_DIR)PDP11_RY.OBJ,$(PDP11_DIR)PDP11_PT.OBJ,\ - $(PDP11_DIR)PDP11_HK.OBJ,$(PDP11_DIR)PDP11_XQ.OBJ -PDP11_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP11_DIR))/DEFINE=("USE_NETWORK=1") - -# -# Digital Equipment PDP-10 Simulator Definitions. -# -PDP10_DIR = SYS$DISK:[.PDP10] -PDP10_LIB = $(LIB_DIR)PDP10-$(ARCH).OLB -PDP10_SOURCE = $(PDP10_DIR)PDP10_FE.C,$(PDP10_DIR)PDP10_DZ.C,\ - $(PDP10_DIR)PDP10_CPU.C,$(PDP10_DIR)PDP10_KSIO.C,\ - $(PDP10_DIR)PDP10_LP20.C,$(PDP10_DIR)PDP10_MDFP.C,\ - $(PDP10_DIR)PDP10_PAG.C,$(PDP10_DIR)PDP10_PT.C,\ - $(PDP10_DIR)PDP10_RP.C,$(PDP10_DIR)PDP10_SYS.C,\ - $(PDP10_DIR)PDP10_TIM.C,$(PDP10_DIR)PDP10_TU.C,\ - $(PDP10_DIR)PDP10_XTND.C,$(PDP10_DIR)PDP10_PT.C,\ - $(PDP11_DIR)PDP11_RY.C -PDP10_OBJS = $(PDP10_DIR)PDP10_FE.OBJ,$(PDP10_DIR)PDP10_DZ.OBJ,\ - $(PDP10_DIR)PDP10_CPU.OBJ,$(PDP10_DIR)PDP10_KSIO.OBJ,\ - $(PDP10_DIR)PDP10_LP20.OBJ,$(PDP10_DIR)PDP10_MDFP.OBJ,\ - $(PDP10_DIR)PDP10_PAG.OBJ,$(PDP10_DIR)PDP10_PT.OBJ,\ - $(PDP10_DIR)PDP10_RP.OBJ,$(PDP10_DIR)PDP10_SYS.OBJ,\ - $(PDP10_DIR)PDP10_TIM.OBJ,$(PDP10_DIR)PDP10_TU.OBJ,\ - $(PDP10_DIR)PDP10_XTND.OBJ,$(PDP10_DIR)PDP10_PT.OBJ,\ - $(PDP10_DIR)PDP11_RY.OBJ -PDP10_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP10_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1") - -# -# IBM System 3 Simulator Definitions. -# -S3_DIR = SYS$DISK:[.S3] -S3_LIB = $(LIB_DIR)S3-$(ARCH).OLB -S3_SOURCE = $(S3_DIR)S3_CD.C,$(S3_DIR)S3_CPU.C,$(S3_DIR)S3_DISK.C,\ - $(S3_DIR)S3_LP.C,$(S3_DIR)S3_PKB.C,$(S3_DIR)S3_SYS.C -S3_OBJS = $(S3_DIR)S3_CD.OBJ,$(S3_DIR)S3_CPU.OBJ,$(S3_DIR)S3_DISK.OBJ,\ - $(S3_DIR)S3_LP.OBJ,$(S3_DIR)S3_PKB.OBJ,$(S3_DIR)S3_SYS.OBJ -S3_OPTIONS = /INCLUDE=($(SIMH_DIR),$(S3_DIR)) - -# -# SDS 940 -# -SDS_DIR = SYS$DISK:[.SDS] -SDS_LIB = $(LIB_DIR)SDS-$(ARCH).OLB -SDS_SOURCE = $(SDS_DIR)SDS_CPU.C,$(SDS_DIR)SDS_DRM.C,$(SDS_DIR)SDS_DSK.C,\ - $(SDS_DIR)SDS_IO.C,$(SDS_DIR)SDS_LP.C,$(SDS_DIR)SDS_MT.C,\ - $(SDS_DIR)SDS_MUX.C,$(SDS_DIR)SDS_RAD.C,$(SDS_DIR)SDS_STDDEV.C,\ - $(SDS_DIR)SDS_SYS.C -SDS_OBJS = $(SDS_DIR)SDS_CPU.OBJ,$(SDS_DIR)SDS_DRM.OBJ,$(SDS_DIR)SDS_DSK.OBJ,\ - $(SDS_DIR)SDS_IO.OBJ,$(SDS_DIR)SDS_LP.OBJ,$(SDS_DIR)SDS_MT.OBJ,\ - $(SDS_DIR)SDS_MUX.OBJ,$(SDS_DIR)SDS_RAD.OBJ,$(SDS_DIR)SDS_STDDEV.OBJ,\ - $(SDS_DIR)SDS_SYS.OBJ -SDS_OPTIONS = /INCLUDE=($(SIMH_DIR),$(SDS_DIR)) - -# -# Digital Equipment VAX Simulator Definitions. -# -VAX_DIR = SYS$DISK:[.VAX] -VAX_LIB = $(LIB_DIR)VAX-$(ARCH).OLB -VAX_SOURCE = $(VAX_DIR)VAX_CPU1.C,$(VAX_DIR)VAX_CPU.C,\ - $(VAX_DIR)VAX_FPA.C,$(VAX_DIR)VAX_IO.C,\ - $(VAX_DIR)VAX_MMU.C,$(VAX_DIR)VAX_STDDEV.C,\ - $(VAX_DIR)VAX_SYS.C,$(VAX_DIR)VAX_SYSDEV.C,\ - $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ - $(PDP11_DIR)PDP11_TS.C,$(PDP11_DIR)PDP11_DZ.C,\ - $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_TQ.C,\ - $(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_XQ.C -VAX_OBJS = $(VAX_DIR)VAX_CPU1.OBJ,$(VAX_DIR)VAX_CPU.OBJ,\ - $(VAX_DIR)VAX_FPA.OBJ,$(VAX_DIR)VAX_IO.OBJ,\ - $(VAX_DIR)VAX_MMU.OBJ,$(VAX_DIR)VAX_STDDEV.OBJ,\ - $(VAX_DIR)VAX_SYS.OBJ,$(VAX_DIR)VAX_SYSDEV.OBJ,\ - $(VAX_DIR)PDP11_RL.OBJ,$(VAX_DIR)PDP11_RQ.OBJ,\ - $(VAX_DIR)PDP11_TS.OBJ,$(VAX_DIR)PDP11_DZ.OBJ,\ - $(VAX_DIR)PDP11_LP.OBJ,$(VAX_DIR)PDP11_TQ.OBJ,\ - $(VAX_DIR)PDP11_PT.OBJ,$(VAX_DIR)PDP11_XQ.OBJ -VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1","USE_NETWORK=1") - -# -# If On Alpha, Build Everything. -# -.IFDEF __ALPHA__ -ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ - NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP10 PDP11 PDP15 S3 SDS VAX -.ELSE -# -# Else We Are On VAX And Build Everything EXCEPT PDP-10 And VAX Since VAX -# Dosen't Have INT64 -# -ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ - NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 SDS -.ENDIF - -# -# Build The Libraries. -# -$(LIB_DIR)SIMH-$(ARCH).OLB : $(SIMH_SOURCE) - $! - $! Building The $(SIMH_LIB) Library. - $! - $ $(CC)/OBJECT=$(SIMH_DIR) $(SIMH_SOURCE) - $ IF (F$SEARCH("$(SIMH_LIB)").EQS."") THEN - - LIBRARY/CREATE $(SIMH_LIB) - $ LIBRARY/REPLACE $(SIMH_LIB) $(SIMH_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -$(LIB_DIR)ALTAIR-$(ARCH).OLB : $(ALTAIR_SOURCE) - $! - $! Building The $(ALTAIR_LIB) Library. - $! - $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(ALTAIR_DIR) - - $(ALTAIR_SOURCE) - $ IF (F$SEARCH("$(ALTAIR_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ALTAIR_LIB) - $ LIBRARY/REPLACE $(ALTAIR_LIB) - - $(ALTAIR_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(ALTAIR_DIR)*.OBJ;* - -$(LIB_DIR)ALTAIRZ80-$(ARCH).OLB : $(ALTAIRZ80_SOURCE) - $! - $! Building The $(ALTAIRZ80_LIB) Library. - $! - $ $(CC)$(ALTAIRZ80_OPTIONS) - - /OBJECT=$(ALTAIRZ80_DIR) - - $(ALTAIRZ80_SOURCE) - $ IF (F$SEARCH("$(ALTAIRZ80_LIB)").EQS."") - - THEN LIBRARY/CREATE $(ALTAIRZ80_LIB) - $ LIBRARY/REPLACE $(ALTAIRZ80_LIB) - - $(ALTAIRZ80_OBJS) - $ DELETE/NOLOG/NOCONFIRM - - $(ALTAIRZ80_DIR)*.OBJ;* - -$(LIB_DIR)ECLIPSE-$(ARCH).OLB : $(ECLIPSE_SOURCE) - $! - $! Building The $(ECLIPSE_LIB) Library. - $! - $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(NOVA_DIR) - - $(ECLIPSE_SOURCE) - $ IF (F$SEARCH("$(ECLIPSE_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ECLIPSE_LIB) - $ LIBRARY/REPLACE $(ECLIPSE_LIB) - - $(ECLIPSE_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(NOVA_DIR)*.OBJ;* - -$(LIB_DIR)GRI-$(ARCH).OLB : $(GRI_SOURCE) - $! - $! Building The $(GRI_LIB) Library. - $! - $ $(CC)$(GRI_OPTIONS)/OBJECT=$(GRI_DIR) - - $(GRI_SOURCE) - $ IF (F$SEARCH("$(GRI_LIB)").EQS."") THEN - - LIBRARY/CREATE $(GRI_LIB) - $ LIBRARY/REPLACE $(GRI_LIB) $(GRI_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(GRI_DIR)*.OBJ;* - -$(LIB_DIR)H316-$(ARCH).OLB : $(H316_SOURCE) - $! - $! Building The $(H316_LIB) Library. - $! - $ $(CC)$(H316_OPTIONS)/OBJECT=$(H316_DIR) - - $(H316_SOURCE) - $ IF (F$SEARCH("$(H316_LIB)").EQS."") THEN - - LIBRARY/CREATE $(H316_LIB) - $ LIBRARY/REPLACE $(H316_LIB) $(H316_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(H316_DIR)*.OBJ;* - -$(LIB_DIR)HP2100-$(ARCH).OLB : $(HP2100_SOURCE) - $! - $! Building The $(HP2100_LIB) Library. - $! - $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(HP2100_DIR) - - $(HP2100_SOURCE) - $ IF (F$SEARCH("$(HP2100_LIB)").EQS."") THEN - - LIBRARY/CREATE $(HP2100_LIB) - $ LIBRARY/REPLACE $(HP2100_LIB) $(HP2100_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(HP2100_DIR)*.OBJ;* - -$(LIB_DIR)I1401-$(ARCH).OLB : $(I1401_SOURCE) - $! - $! Building The $(I1401_LIB) Library. - $! - $ $(CC)$(I1401_OPTIONS)/OBJECT=$(I1401_DIR) - - $(I1401_SOURCE) - $ IF (F$SEARCH("$(I1401_LIB)").EQS."") THEN - - LIBRARY/CREATE $(I1401_LIB) - $ LIBRARY/REPLACE $(I1401_LIB) $(I1401_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(I1401_DIR)*.OBJ;* - -$(LIB_DIR)I1620-$(ARCH).OLB : $(I1620_SOURCE) - $! - $! Building The $(I1620_LIB) Library. - $! - $ $(CC)$(I1620_OPTIONS)/OBJECT=$(I1620_DIR) - - $(I1620_SOURCE) - $ IF (F$SEARCH("$(I1620_LIB)").EQS."") THEN - - LIBRARY/CREATE $(I1620_LIB) - $ LIBRARY/REPLACE $(I1620_LIB) $(I1620_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(I1620_DIR)*.OBJ;* - -$(LIB_DIR)IBM1130-$(ARCH).OLB : $(IBM1130_SOURCE) - $! - $! Building The $(IBM1130_LIB) Library. - $! - $ $(CC)$(IBM1130_OPTIONS) - - /OBJECT=$(IBM1130_DIR) - - $(IBM1130_SOURCE) - $ IF (F$SEARCH("$(IBM1130_LIB)").EQS."") THEN - - LIBRARY/CREATE $(IBM1130_LIB) - $ LIBRARY/REPLACE $(IBM1130_LIB) $(IBM1130_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(IBM1130_DIR)*.OBJ;* - -$(LIB_DIR)ID16-$(ARCH).OLB : $(ID16_SOURCE) - $! - $! Building The $(ID16_LIB) Library. - $! - $ $(CC)$(ID16_OPTIONS)/OBJECT=$(ID16_DIR) - - $(ID16_SOURCE) - $ IF (F$SEARCH("$(ID16_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ID16_LIB) - $ LIBRARY/REPLACE $(ID16_LIB) $(ID16_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(ID16_DIR)*.OBJ;* - -$(LIB_DIR)ID32-$(ARCH).OLB : $(ID32_SOURCE) - $! - $! Building The $(ID32_LIB) Library. - $! - $ $(CC)$(ID32_OPTIONS)/OBJECT=$(ID32_DIR) - - $(ID32_SOURCE) - $ IF (F$SEARCH("$(ID32_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ID32_LIB) - $ LIBRARY/REPLACE $(ID32_LIB) $(ID32_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(ID32_DIR)*.OBJ;* - -$(LIB_DIR)NOVA-$(ARCH).OLB : $(NOVA_SOURCE) - $! - $! Building The $(NOVA_LIB) Library. - $! - $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(NOVA_DIR) - - $(NOVA_SOURCE) - $ IF (F$SEARCH("$(NOVA_LIB)").EQS."") THEN - - LIBRARY/CREATE $(NOVA_LIB) - $ LIBRARY/REPLACE $(NOVA_LIB) $(NOVA_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(NOVA_DIR)*.OBJ;* - -$(LIB_DIR)PDP1-$(ARCH).OLB : $(PDP1_SOURCE) - $! - $! Building The $(PDP1_LIB) Library. - $! - $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(PDP1_DIR) - - $(PDP1_SOURCE) - $ IF (F$SEARCH("$(PDP1_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP1_LIB) - $ LIBRARY/REPLACE $(PDP1_LIB) $(PDP1_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP1_DIR)*.OBJ;* - -$(LIB_DIR)PDP4-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP4_LIB) Library. - $! - $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP4_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP4_LIB) - $ LIBRARY/REPLACE $(PDP4_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -$(LIB_DIR)PDP7-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP7_LIB) Library. - $! - $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP7_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP7_LIB) - $ LIBRARY/REPLACE $(PDP7_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -$(LIB_DIR)PDP8-$(ARCH).OLB : $(PDP8_SOURCE) - $! - $! Building The $(PDP8_LIB) Library. - $! - $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(PDP8_DIR) - - $(PDP8_SOURCE) - $ IF (F$SEARCH("$(PDP8_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP8_LIB) - $ LIBRARY/REPLACE $(PDP8_LIB) $(PDP8_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP8_DIR)*.OBJ;* - -$(LIB_DIR)PDP9-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP9_LIB) Library. - $! - $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP9_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP9_LIB) - $ LIBRARY/REPLACE $(PDP9_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -# -# If On Alpha, Build The PDP-10 Library. -# -.IFDEF __ALPHA__ -$(LIB_DIR)PDP10-$(ARCH).OLB : $(PDP10_SOURCE) - $! - $! Building The $(PDP10_LIB) Library. - $! - $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(PDP10_DIR) - - $(PDP10_SOURCE) - $ IF (F$SEARCH("$(PDP10_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP10_LIB) - $ LIBRARY/REPLACE $(PDP10_LIB) $(PDP10_OBJS) - DELETE/NOLOG/NOCONFIRM $(PDP10_DIR)*.OBJ;* -.ELSE -# -# We Are On VAX And Due To The Use of INT64 We Can't Build It. -# -$(LIB_DIR)PDP10-$(ARCH).OLB : - $! - $! Due To The Use Of INT64 We Can't Build The - $! $(LIB_DIR)PDP10-$(ARCH).OLB Library On VAX. - $! -.ENDIF - -$(LIB_DIR)PDP11-$(ARCH).OLB : $(PDP11_SOURCE) - $! - $! Building The $(PDP11_LIB) Library. - $! - $(CC)$(PDP11_OPTIONS)/OBJECT=$(PDP11_DIR) - - $(PDP11_SOURCE) - $ IF (F$SEARCH("$(PDP11_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP11_LIB) - $ LIBRARY/REPLACE $(PDP11_LIB) $(PDP11_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP11_DIR)*.OBJ;* - -$(LIB_DIR)PDP15-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP15_LIB) Library. - $! - $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP15_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP15_LIB) - $ LIBRARY/REPLACE $(PDP15_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -$(LIB_DIR)S3-$(ARCH).OLB : $(S3_SOURCE) - $! - $! Building The $(S3_LIB) Library. - $! - $ $(CC)$(S3_OPTIONS)/OBJECT=$(S3_DIR) $(S3_SOURCE) - $ IF (F$SEARCH("$(S3_LIB)").EQS."") THEN - - LIBRARY/CREATE $(S3_LIB) - $ LIBRARY/REPLACE $(S3_LIB) $(S3_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(S3_DIR)*.OBJ;* - -$(LIB_DIR)SDS-$(ARCH).OLB : $(SDS_SOURCE) - $! - $! Building The $(SDS_LIB) Library. - $! - $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SDS_DIR) - - $(SDS_SOURCE) - $ IF (F$SEARCH("$(SDS_LIB)").EQS."") THEN - - LIBRARY/CREATE $(SDS_LIB) - $ LIBRARY/REPLACE $(SDS_LIB) $(SDS_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(SDS_DIR)*.OBJ;* - -# -# If On Alpha, Build The VAX Library. -# -.IFDEF __ALPHA__ -$(LIB_DIR)VAX-$(ARCH).OLB : $(VAX_SOURCE) - $! - $! Building The $(VAX_LIB) Library. - $! - $ $(CC)$(VAX_OPTIONS)/OBJECT=$(VAX_DIR) - - $(VAX_SOURCE) - $ IF (F$SEARCH("$(VAX_LIB)").EQS."") THEN - - LIBRARY/CREATE $(VAX_LIB) - $ LIBRARY/REPLACE $(VAX_LIB) $(VAX_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(VAX_DIR)*.OBJ;* -.ELSE -# -# We Are On VAX And Due To The Use of INT64 We Can't Build It. -# -$(LIB_DIR)VAX-$(ARCH).OLB : - $! - $! Due To The Use Of INT64 We Can't Build The - $! $(LIB_DIR)VAX-$(ARCH).OLB Library On VAX. - $! -.ENDIF - -# -# Individual Simulator Builds. -# -ALTAIR : $(SIMH_LIB) $(ALTAIR_LIB) - $! - $! Building The $(BIN_DIR)ALTAIR-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIR-$(ARCH).EXE - - SCP.OBJ,$(ALTAIR_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ALTAIRZ80 : $(SIMH_LIB) $(ALTAIRZ80_LIB) - $! - $! Building The $(BIN_DIR)ALTAIRZ80-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ALTAIRZ80_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIRZ80-$(ARCH).EXE - - SCP.OBJ,$(ALTAIRZ80_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ECLIPSE : $(SIMH_LIB) $(ECLIPSE_LIB) - $! - $! Building The $(BIN_DIR)ECLPISE-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ECLIPSE-$(ARCH).EXE - - SCP.OBJ,$(ECLIPSE_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -GRI : $(SIMH_LIB) $(GRI_LIB) - $! - $! Building The $(BIN_DIR)GRI-$(ARCH).EXE Simulator. - $! - $ $(CC)$(GRI_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)GRI-$(ARCH).EXE - - SCP.OBJ,$(GRI_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -H316 : $(SIMH_LIB) $(H316_LIB) - $! - $! Building The $(BIN_DIR)H316-$(ARCH).EXE Simulator. - $! - $ $(CC)$(H316_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)H316-$(ARCH).EXE - - SCP.OBJ,$(H316_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -HP2100 : $(SIMH_LIB) $(HP2100_LIB) - $! - $! Building The $(BIN_DIR)HP2100-$(ARCH).EXE Simulator. - $! - $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)HP2100-$(ARCH).EXE - - SCP.OBJ,$(HP2100_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -I1401 : $(SIMH_LIB) $(I1401_LIB) - $! - $! Building The $(BIN_DIR)I1401-$(ARCH).EXE Simulator. - $! - $ $(CC)$(I1401_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)I1401-$(ARCH).EXE - - SCP.OBJ,$(I1401_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -I1620 : $(SIMH_LIB) $(I1620_LIB) - $! - $! Building The $(BIN_DIR)I1620-$(ARCH).EXE Simulator. - $! - $ $(CC)$(I1620_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)I1620-$(ARCH).EXE - - SCP.OBJ,$(I1620_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -IBM1130 : $(SIMH_LIB) $(IBM1130_LIB) - $! - $! Building The $(BIN_DIR)IBM1130-$(ARCH).EXE Simulator. - $! - $ $(CC)$(IBM1130_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)IBM1130-$(ARCH).EXE - - SCP.OBJ,$(IBM1130_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ID16 : $(SIMH_LIB) $(ID16_LIB) - $! - $! Building The $(BIN_DIR)ID16-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ID16_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ID16-$(ARCH).EXE - - SCP.OBJ,$(ID16_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ID32 : $(SIMH_LIB) $(ID32_LIB) - $! - $! Building The $(BIN_DIR)ID32-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ID32_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ID32-$(ARCH).EXE - - SCP.OBJ,$(ID32_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -NOVA : $(SIMH_LIB) $(NOVA_LIB) - $! - $! Building The $(BIN_DIR)NOVA-$(ARCH).EXE Simulator. - $! - $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)NOVA-$(ARCH).EXE - - SCP.OBJ,$(NOVA_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP1 : $(SIMH_LIB) $(PDP1_LIB) - $! - $! Building The $(BIN_DIR)PDP1-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP1-$(ARCH).EXE - - SCP.OBJ,$(PDP1_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP4 : $(SIMH_LIB) $(PDP4_LIB) - $! - $! Building The $(BIN_DIR)PDP4-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP4-$(ARCH).EXE - - SCP.OBJ,$(PDP4_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP7 : $(SIMH_LIB) $(PDP7_LIB) - $! - $! Building The $(BIN_DIR)PDP7-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP7-$(ARCH).EXE - - SCP.OBJ,$(PDP7_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP8 : $(SIMH_LIB) $(PDP8_LIB) - $! - $! Building The $(BIN_DIR)PDP8-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP8-$(ARCH).EXE - - SCP.OBJ,$(PDP8_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP9 : $(SIMH_LIB) $(PDP9_LIB) - $! - $! Building The $(BIN_DIR)PDP9-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP9-$(ARCH).EXE - - SCP.OBJ,$(PDP9_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -# -# If On Alpha, Build The PDP-10 Simulator. -# -.IFDEF __ALPHA__ -PDP10 : $(SIMH_LIB) $(PDP10_LIB) - $! - $! Building The $(BIN_DIR)PDP10-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP10-$(ARCH).EXE - - SCP.OBJ,$(PDP10_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* -.ELSE -# -# Else We Are On VAX And Tell The User We Can't Build On VAX -# Due To The Use Of INT64. -# -PDP10 : - $! - $! Sorry, Can't Build $(BIN_DIR)PDP10-$(ARCH).EXE Simulator - $! Because It Requires The Use Of INT64. - $! -.ENDIF - -PDP11 : $(SIMH_LIB) $(PDP11_LIB) - $! - $! Building The $(BIN_DIR)PDP11-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP11_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP11-$(ARCH).EXE - - SCP.OBJ,$(PDP11_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP15 : $(SIMH_LIB) $(PDP15_LIB) - $! - $! Building The $(BIN_DIR)PDP15-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP15-$(ARCH).EXE - - SCP.OBJ,$(PDP15_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -S3 : $(SIMH_LIB) $(S3_LIB) - $! - $! Building The $(BIN_DIR)S3-$(ARCH).EXE Simulator. - $! - $ $(CC)$(S3_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)S3-$(ARCH).EXE - - SCP.OBJ,$(S3_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -SDS : $(SIMH_LIB) $(SDS_LIB) - $! - $! Building The $(BIN_DIR)SDS-$(ARCH).EXE Simulator. - $! - $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)SDS-$(ARCH).EXE - - SCP.OBJ,$(SDS_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -# -# If On Alpha, Build The VAX Simulator. -# -.IFDEF __ALPHA__ -VAX : $(SIMH_LIB) $(VAX_LIB) - $! - $! Building The $(BIN_DIR)VAX-$(ARCH).EXE Simulator. - $! - $ $(CC)$(VAX_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)VAX-$(ARCH).EXE - - SCP.OBJ,$(VAX_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* -.ELSE -# -# Else We Are On VAX And Tell The User We Can't Build On VAX -# Due To The Use Of INT64. -# -VAX : - $! - $! Sorry, Can't Build $(BIN_DIR)VAX-$(ARCH).EXE Simulator - $! Because It Requires The Use Of INT64. - $! -.ENDIF - +# +# DESCRIP.MMS +# Written By: Robert Alan Byer +# byer@mail.ourservers.net +# +# This MMS/MMK build script is used to compile the various simulators in +# the SIMH package for OpenVMS using DEC C v6.0-001. +# +# Notes: On VAX, the PDP-10 and VAX simulator will not be built due to the +# fact that INT64 is required for those simulators. +# +# When using DEC's MMS on an Alpha you must use +# /MACRO=("__ALPHA__=1") to compile properly. +# +# This build script will accept the following build options. +# +# ALL Just Build "Everything". +# ALTAIR Just Build The MITS Altair. +# ALTAIRZ80 Just Build The MITS Altair Z80. +# ECLIPSE Just Build The Data General Eclipse. +# GRI Just Build The GRI Corporation GRI-909. +# H316 Just Build The Honewell 316/516. +# HP2100 Just Build The Hewlett-Packard HP-2100. +# I1401 Just Build The IBM 1401. +# IBM1130 Just Build The IBM 1130. +# ID16 Just Build The Interdata 16-bit CPU. +# ID32 Just Build The Interdata 32-bit CPU. +# NOVA Just Build The Data General Nova. +# PDP1 Just Build The DEC PDP-1. +# PDP4 Just Build The DEC PDP-4. +# PDP7 Just Build The DEC PDP-7. +# PDP8 Just Build The DEC PDP-8. +# PDP9 Just Build The DEC PDP-9. +# PDP10 Just Build The DEC PDP-10. +# PDP11 Just Build The DEC PDP-11. +# PDP15 Just Build The DEC PDP-15. +# S3 Just Build The IBM System 3. +# SDS Just Build The SDS 940. +# VAX Just Build The DEC VAX. +# +# To build with debugging enabled (which will also enable traceback +# information) use.. +# +# MMK/FORCE/MACRO=(DEBUG=1) +# + +# +# Define The BIN Directory Where The Executables Will Go. +# +BIN_DIR = SYS$DISK:[.BIN] + +# +# Define Our Library Directory. +# +LIB_DIR = SYS$DISK:[.LIB] + +# +# Let's See If We Are Going To Build With DEBUG Enabled. +# +.IFDEF DEBUG +CC_DEBUG = /DEBUG +LINK_DEBUG = /DEBUG/TRACEBACK +CC_OPTIMIZE = /NOOPTIMIZE +.ELSE +CC_DEBUG = /NODEBUG +LINK_DEBUG = /NODEBUG/NOTRACEBACK +.IFDEF __ALPHA__ +CC_OPTIMIZE = /OPTIMIZE=(LEVEL=5,TUNE=HOST)/ARCH=HOST +CC_FLAGS = /PREFIX=ALL +ARCH = AXP +.ELSE +CC_OPTIMIZE = /OPTIMIZE +ARCH = VAX +.ENDIF +.ENDIF + +# +# Define Our Compiler Flags. +# +CC_FLAGS = $(CC_FLAGS)$(CC_OPTIMIZE)/NEST=PRIMARY/NAME=(AS_IS,SHORTENED) + +# +# Define The Compile Command. +# +CC = CC $(CC_FLAGS) + +# +# First, Let's Check To Make Sure We Have A SYS$DISK:[.BIN] And +# SYS$DISK:[.LIB] Directory. +# +.FIRST + @ IF (F$SEARCH("SYS$DISK:[]BIN.DIR").EQS."") THEN CREATE/DIRECTORY $(BIN_DIR) + @ IF (F$SEARCH("SYS$DISK:[]LIB.DIR").EQS."") THEN CREATE/DIRECTORY $(LIB_DIR) + +# +# Core SIMH File Definitions. +# +SIMH_DIR = SYS$DISK:[] +SIMH_LIB = $(LIB_DIR)SIMH-$(ARCH).OLB +SIMH_SOURCE = $(SIMH_DIR)SCP_TTY.C,$(SIMH_DIR)SIM_SOCK.C,\ + $(SIMH_DIR)SIM_TMXR.C,$(SIMH_DIR)SIM_ETHER.C +SIMH_OBJS = $(SIMH_DIR)SCP_TTY.OBJ,$(SIMH_DIR)SIM_SOCK.OBJ,\ + $(SIMH_DIR)SIM_TMXR.OBJ,$(SIMH_DIR)SIM_ETHER.OBJ + +# +# MITS Altair Simulator Definitions. +# +ALTAIR_DIR = SYS$DISK:[.ALTAIR] +ALTAIR_LIB = $(LIB_DIR)ALTAIR-$(ARCH).OLB +ALTAIR_SOURCE = $(ALTAIR_DIR)ALTAIR_SIO.C,$(ALTAIR_DIR)ALTAIR_CPU.C,\ + $(ALTAIR_DIR)ALTAIR_DSK.C,$(ALTAIR_DIR)ALTAIR_SYS.C +ALTAIR_OBJS = $(ALTAIR_DIR)ALTAIR_SIO.OBJ,$(ALTAIR_DIR)ALTAIR_CPU.OBJ,\ + $(ALTAIR_DIR)ALTAIR_DSK.OBJ,$(ALTAIR_DIR)ALTAIR_SYS.OBJ +ALTAIR_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIR_DIR)) + +# +# MITS Altair Z80 Simulator Definitions. +# +ALTAIRZ80_DIR = SYS$DISK:[.ALTAIRZ80] +ALTAIRZ80_LIB = $(LIB_DIR)ALTAIRZ80-$(ARCH).OLB +ALTAIRZ80_SOURCE = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.C,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_DSK.C,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_SIO.C,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_SYS.C,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.C +ALTAIRZ80_OBJS = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.OBJ,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_DSK.OBJ,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_SIO.OBJ,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_SYS.OBJ,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.OBJ +ALTAIRZ80_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIRZ80_DIR)) + +# +# Data General Nova Simulator Definitions. +# +NOVA_DIR = SYS$DISK:[.NOVA] +NOVA_LIB = $(LIB_DIR)NOVA-$(ARCH).OLB +NOVA_SOURCE = $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_CPU.C,\ + $(NOVA_DIR)NOVA_DKP.C,$(NOVA_DIR)NOVA_DSK.C,\ + $(NOVA_DIR)NOVA_LP.C,$(NOVA_DIR)NOVA_MTA.C,\ + $(NOVA_DIR)NOVA_PLT.C,$(NOVA_DIR)NOVA_PT.C,\ + $(NOVA_DIR)NOVA_CLK.C,$(NOVA_DIR)NOVA_TT.C,\ + $(NOVA_DIR)NOVA_TT1.C +NOVA_OBJS = $(NOVA_DIR)NOVA_SYS.OBJ,$(NOVA_DIR)NOVA_CPU.OBJ,\ + $(NOVA_DIR)NOVA_DKP.OBJ,$(NOVA_DIR)NOVA_DSK.OBJ,\ + $(NOVA_DIR)NOVA_LP.OBJ,$(NOVA_DIR)NOVA_MTA.OBJ,\ + $(NOVA_DIR)NOVA_PLT.OBJ,$(NOVA_DIR)NOVA_PT.OBJ,\ + $(NOVA_DIR)NOVA_CLK.OBJ,$(NOVA_DIR)NOVA_TT.OBJ,\ + $(NOVA_DIR)NOVA_TT1.OBJ +NOVA_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR)) + +# +# Data General Eclipse Simulator Definitions. +# +ECLIPSE_LIB = $(LIB_DIR)ECLIPSE-$(ARCH).OLB +ECLIPSE_SOURCE = $(NOVA_DIR)ECLIPSE_CPU.C,$(NOVA_DIR)ECLIPSE_TT.C,\ + $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_DKP.C,\ + $(NOVA_DIR)NOVA_DSK.C,$(NOVA_DIR)NOVA_LP.C,\ + $(NOVA_DIR)NOVA_MTA.C,$(NOVA_DIR)NOVA_PLT.C,\ + $(NOVA_DIR)NOVA_PT.C,$(NOVA_DIR)NOVA_CLK.C,\ + $(NOVA_DIR)NOVA_TT1.C +ECLIPSE_OBJS = $(NOVA_DIR)ECLIPSE_CPU.OBJ,$(NOVA_DIR)ECLIPSE_TT.OBJ,\ + $(NOVA_DIR)NOVA_SYS.OBJ,$(NOVA_DIR)NOVA_DKP.OBJ,\ + $(NOVA_DIR)NOVA_DSK.OBJ,$(NOVA_DIR)NOVA_LP.OBJ,\ + $(NOVA_DIR)NOVA_MTA.OBJ,$(NOVA_DIR)NOVA_PLT.OBJ,\ + $(NOVA_DIR)NOVA_PT.OBJ,$(NOVA_DIR)NOVA_CLK.OBJ,\ + $(NOVA_DIR)NOVA_TT1.OBJ +ECLIPSE_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR))/DEFINE=("ECLIPSE=1") + +# +# GRI Corporation GRI-909 Simulator Definitions. +# +GRI_DIR = SYS$DISK:[.GRI] +GRI_LIB = $(LIB_DIR)GRI-$(ARCH).OLB +GRI_SOURCE = $(GRI_DIR)GRI_CPU.C,$(GRI_DIR)GRI_STDDEV.C,$(GRI_DIR)GRI_SYS.C +GRI_OBJS = $(GRI_DIR)GRI_CPU.OBJ,$(GRI_DIR)GRI_STDDEV.OBJ,\ + $(GRI_DIR)GRI_SYS.OBJ +GRI_OPTIONS = /INCLUDE=($(SIMH_DIR),$(GRI_DIR)) + +# +# Honeywell 316/516 Simulator Definitions. +# +H316_DIR = SYS$DISK:[.H316] +H316_LIB = $(LIB_DIR)H316-$(ARCH).OLB +H316_SOURCE = $(H316_DIR)H316_STDDEV.C,$(H316_DIR)H316_LP.C,\ + $(H316_DIR)H316_CPU.C,$(H316_DIR)H316_SYS.C +H316_OBJS = $(H316_DIR)H316_STDDEV.OBJ,$(H316_DIR)H316_LP.OBJ,\ + $(H316_DIR)H316_CPU.OBJ,$(H316_DIR)H316_SYS.OBJ +H316_OPTIONS = /INCLUDE=($(SIMH_DIR),$(H316_DIR)) + +# +# Hewlett-Packard HP-2100 Simulator Definitions. +# +HP2100_DIR = SYS$DISK:[.HP2100] +HP2100_LIB = $(LIB_DIR)HP2100-$(ARCH).OLB +HP2100_SOURCE = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.C,\ + $(HP2100_DIR)HP2100_DQ.C,$(HP2100_DIR)HP2100_DR.C,\ + $(HP2100_DIR)HP2100_LPS.C,$(HP2100_DIR)HP2100_MS.C,\ + $(HP2100_DIR)HP2100_MT.C,$(HP2100_DIR)HP2100_MUX.C,\ + $(HP2100_DIR)HP2100_CPU.C,$(HP2100_DIR)HP2100_FP.C,\ + $(HP2100_DIR)HP2100_SYS.C,$(HP2100_DIR)HP2100_LPT.C,\ + $(HP2100_DIR)HP2100_IPL.C +HP2100_OBJS = $(HP2100_DIR)HP2100_STDDEV.OBJ,$(HP2100_DIR)HP2100_DP.OBJ,\ + $(HP2100_DIR)HP2100_DQ.OBJ,$(HP2100_DIR)HP2100_DR.OBJ,\ + $(HP2100_DIR)HP2100_LPS.OBJ,$(HP2100_DIR)HP2100_MS.OBJ,\ + $(HP2100_DIR)HP2100_MT.OBJ,$(HP2100_DIR)HP2100_MUX.OBJ,\ + $(HP2100_DIR)HP2100_CPU.OBJ,$(HP2100_DIR)HP2100_FP.OBJ,\ + $(HP2100_DIR)HP2100_SYS.OBJ,$(HP2100_DIR)HP2100_LPT.OBJ, + $(HP2100_DIR)HP2100_IPL.OBJ +HP2100_OPTIONS = /INCLUDE=($(SIMH_DIR),$(HP2100_DIR)) + +# +# Interdata 16-bit CPU. +# +ID16_DIR = SYS$DISK:[.INTERDATA] +ID16_LIB = $(LIB_DIR)ID16-$(ARCH).OLB +ID16_SOURCE = $(ID16_DIR)ID16_CPU.C,$(ID16_DIR)ID16_SYS.C,$(ID16_DIR)ID_DP.C,\ + $(ID16_DIR)ID_FD.C,$(ID16_DIR)ID_FP.C,$(ID16_DIR)ID_IDC.C,\ + $(ID16_DIR)ID_IO.C,$(ID16_DIR)ID_LP.C,$(ID16_DIR)ID_MT.C,\ + $(ID16_DIR)ID_PAS.C,$(ID16_DIR)ID_PT.C,$(ID16_DIR)ID_TT.C,\ + $(ID16_DIR)ID_UVC.C,$(ID16_DIR)ID16_DBOOT.C,$(ID16_DIR)ID_TTP.C +ID16_OBJS = $(ID16_DIR)ID16_CPU.OBJ,$(ID16_DIR)ID16_SYS.OBJ,$(ID16_DIR)ID_DP.OBJ,\ + $(ID16_DIR)ID_FD.OBJ,$(ID16_DIR)ID_FP.OBJ,$(ID16_DIR)ID_IDC.OBJ,\ + $(ID16_DIR)ID_IO.OBJ,$(ID16_DIR)ID_LP.OBJ,$(ID16_DIR)ID_MT.OBJ,\ + $(ID16_DIR)ID_PAS.OBJ,$(ID16_DIR)ID_PT.OBJ,$(ID16_DIR)ID_TT.OBJ,\ + $(ID16_DIR)ID_UVC.OBJ,$(ID16_DIR)ID16_DBOOT.OBJ,$(ID16)DIR)ID_TTP.OBJ +ID16_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID16_DIR)) + +# +# Interdata 32-bit CPU. +# +ID32_DIR = SYS$DISK:[.INTERDATA] +ID32_LIB = $(LIB_DIR)ID32-$(ARCH).OLB +ID32_SOURCE = $(ID32_DIR)ID32_CPU.C,$(ID32_DIR)ID32_SYS.C,$(ID32_DIR)ID_DP.C,\ + $(ID32_DIR)ID_FD.C,$(ID32_DIR)ID_FP.C,$(ID32_DIR)ID_IDC.C,\ + $(ID32_DIR)ID_IO.C,$(ID32_DIR)ID_LP.C,$(ID32_DIR)ID_MT.C,\ + $(ID32_DIR)ID_PAS.C,$(ID32_DIR)ID_PT.C,$(ID32_DIR)ID_TT.C,\ + $(ID32_DIR)ID_UVC.C,$(ID32_DIR)ID32_DBOOT.C,$(ID32_DIR)ID_TTP.C +ID32_OBJS = $(ID32_DIR)ID32_CPU.OBJ,$(ID32_DIR)ID32_SYS.OBJ,\ + $(ID32_DIR)ID_DP.OBJ,$(ID32_DIR)ID_FD.OBJ,\ + $(ID32_DIR)ID_FP.OBJ,$(ID32_DIR)ID_IDC.OBJ,\ + $(ID32_DIR)ID_IO.OBJ,$(ID32_DIR)ID_LP.OBJ,$(ID32_DIR)ID_MT.OBJ,\ + $(ID32_DIR)ID_PAS.OBJ,$(ID32_DIR)ID_PT.OBJ,$(ID32_DIR)ID_TT.OBJ,\ + $(ID32_DIR)ID_UVC.OBJ,$(ID32_DIR)ID32_DBOOT.C,$(ID32_DIR)ID_TTP.OBJ +ID32_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID32_DIR)) + +# +# IBM 1130 Simulator Definitions. +# +IBM1130_DIR = SYS$DISK:[.IBM1130] +IBM1130_LIB = $(LIB_DIR)IBM1130-$(ARCH).OLB +IBM1130_SOURCE = $(IBM1130_DIR)IBM1130_CPU.C,$(IBM1130_DIR)IBM1130_CR.C,\ + $(IBM1130_DIR)IBM1130_DISK.C,$(IBM1130_DIR)IBM1130_STDDEV.C,\ + $(IBM1130_DIR)IBM1130_SYS.C,$(IBM1130_DIR)IBM1130_GDU.C,\ + $(IBM1130_DIR)IBM1130_GUI.C,$(IBM1130_DIR)IBM1130_PRT.C +IBM1130_OBJS = $(IBM1130_DIR)IBM1130_CPU.OBJ,$(IBM1130_DIR)IBM1130_CR.OBJ,\ + $(IBM1130_DIR)IBM1130_DISK.OBJ,$(IBM1130_DIR)IBM1130_STDDEV.OBJ,\ + $(IBM1130_DIR)IBM1130_SYS.OBJ,$(IBM1130_DIR)IBM1130_GDU.OBJ,\ + $(IBM1130_DIR)IBM1130_GUI.OBJ,$(IBM1130_DIR)IBM1130_PRT.OBJ +IBM1130_OPTIONS = /INCLUDE=($(SIMH_DIR),$(IBM1130_DIR)) + +# +# IBM 1401 Simulator Definitions. +# +I1401_DIR = SYS$DISK:[.I1401] +I1401_LIB = $(LIB_DIR)I1401-$(ARCH).OLB +I1401_SOURCE = $(I1401_DIR)I1401_LP.C,$(I1401_DIR)I1401_CPU.C,\ + $(I1401_DIR)I1401_IQ.C,$(I1401_DIR)I1401_CD.C,\ + $(I1401_DIR)I1401_MT.C,$(I1401_DIR)I1401_DP.C,\ + $(I1401_DIR)I1401_SYS.C +I1401_OBJS = $(I1401_DIR)I1401_LP.OBJ,$(I1401_DIR)I1401_CPU.OBJ,\ + $(I1401_DIR)I1401_IQ.OBJ,$(I1401_DIR)I1401_CD.OBJ,\ + $(I1401_DIR)I1401_MT.OBJ,$(I1401_DIR)I1401_DP.OBJ,\ + $(I1401_DIR)I1401_SYS.OBJ +I1401_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1401_DIR)) + + +# +# IBM 1620 Simulators Definitions. +# +I1620_DIR = SYS$DISK:[.I1620] +I1620_LIB = $(LIB_DIR)I1620-$(ARCH).OLB +I1620_SOURCE = $(I1620_DIR)I1620_CD.C,$(I1620_DIR)I1620_DP.C,\ + $(I1620_DIR)I1620_PT.C,$(I1620_DIR)I1620_TTY.C,\ + $(I1620_DIR)I1620_CPU.C,$(I1620_DIR)I1620_LP.C,\ + $(I1620_DIR)I1620_FP.C,$(I1620_DIR)I1620_SYS.C +I1620_OBJS = $(I1620_DIR)I1620_CD.OBJ,$(I1620_DIR)I1620_DP.OBJ,\ + $(I1620_DIR)I1620_PT.OBJ,$(I1620_DIR)I1620_TTY.OBJ,\ + $(I1620_DIR)I1620_CPU.OBJ,$(I1620_DIR)I1620_LP.OBJ,\ + $(I1620_DIR)I1620_FP.OBJ,$(I1620_DIR)I1620_SYS.OBJ +I1620_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1620_DIR)) + +# +# PDP-1 Simulator Definitions. +# +PDP1_DIR = SYS$DISK:[.PDP1] +PDP1_LIB = $(LIB_DIR)PDP1-$(ARCH).OLB +PDP1_SOURCE = $(PDP1_DIR)PDP1_LP.C,$(PDP1_DIR)PDP1_CPU.C,\ + $(PDP1_DIR)PDP1_STDDEV.C,$(PDP1_DIR)PDP1_SYS.C,\ + $(PDP1_DIR)PDP1_DT.C,${PDP1_DIR}PDP1_DRM.C +PDP1_OBJS = $(PDP1_DIR)PDP1_LP.OBJ,$(PDP1_DIR)PDP1_CPU.OBJ,\ + $(PDP1_DIR)PDP1_STDDEV.OBJ,$(PDP1_DIR)PDP1_SYS.OBJ,\ + $(PDP1_DIR)PDP1_DT.OBJ,{PDP1_DIR}PDP1_DRM.OBJ +PDP1_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP1_DIR)) + +# +# Digital Equipment PDP-8 Simulator Definitions. +# +PDP8_DIR = SYS$DISK:[.PDP8] +PDP8_LIB = $(LIB_DIR)PDP8-$(ARCH).OLB +PDP8_SOURCE = $(PDP8_DIR)PDP8_CPU.C,$(PDP8_DIR)PDP8_CLK.C,\ + $(PDP8_DIR)PDP8_DF.C,$(PDP8_DIR)PDP8_DT.C,\ + $(PDP8_DIR)PDP8_LP.C,$(PDP8_DIR)PDP8_MT.C,\ + $(PDP8_DIR)PDP8_PT.C,$(PDP8_DIR)PDP8_RF.C,\ + $(PDP8_DIR)PDP8_RK.C,$(PDP8_DIR)PDP8_RX.C,\ + $(PDP8_DIR)PDP8_SYS.C,$(PDP8_DIR)PDP8_TT.C,\ + $(PDP8_DIR)PDP8_TTX.C,$(PDP8_DIR)PDP8_RL.C +PDP8_OBJS = $(PDP8_DIR)PDP8_CPU.OBJ,$(PDP8_DIR)PDP8_CLK.OBJ,\ + $(PDP8_DIR)PDP8_DF.OBJ,$(PDP8_DIR)PDP8_DT.OBJ,\ + $(PDP8_DIR)PDP8_LP.OBJ,$(PDP8_DIR)PDP8_MT.OBJ,\ + $(PDP8_DIR)PDP8_PT.OBJ,$(PDP8_DIR)PDP8_RF.OBJ,\ + $(PDP8_DIR)PDP8_RK.OBJ,$(PDP8_DIR)PDP8_RX.OBJ,\ + $(PDP8_DIR)PDP8_SYS.OBJ,$(PDP8_DIR)PDP8_TT.OBJ,\ + $(PDP8_DIR)PDP8_TTX.OBJ,$(PDP8_DIR)PDP8_RL.OBJ +PDP8_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP8_DIR)) + +# +# Digital Equipment PDP-4, PDP-7, PDP-9 And PDP-15 Simulator Definitions. +# +PDP18B_DIR = SYS$DISK:[.PDP18B] +PDP4_LIB = $(LIB_DIR)PDP4-$(ARCH).OLB +PDP7_LIB = $(LIB_DIR)PDP7-$(ARCH).OLB +PDP9_LIB = $(LIB_DIR)PDP9-$(ARCH).OLB +PDP15_LIB = $(LIB_DIR)PDP15-$(ARCH).OLB +PDP18B_SOURCE = $(PDP18B_DIR)PDP18B_DT.C,$(PDP18B_DIR)PDP18B_DRM.C,\ + $(PDP18B_DIR)PDP18B_CPU.C,$(PDP18B_DIR)PDP18B_LP.C,\ + $(PDP18B_DIR)PDP18B_MT.C,$(PDP18B_DIR)PDP18B_RF.C,\ + $(PDP18B_DIR)PDP18B_RP.C,$(PDP18B_DIR)PDP18B_STDDEV.C,\ + $(PDP18B_DIR)PDP18B_SYS.C,$(PDP18B_DIR)PDP18B_TT1.C +PDP18B_OBJS = $(PDP18B_DIR)PDP18B_DT.OBJ,$(PDP18B_DIR)PDP18B_DRM.OBJ,\ + $(PDP18B_DIR)PDP18B_CPU.OBJ,$(PDP18B_DIR)PDP18B_LP.OBJ,\ + $(PDP18B_DIR)PDP18B_MT.OBJ,$(PDP18B_DIR)PDP18B_RF.OBJ,\ + $(PDP18B_DIR)PDP18B_RP.OBJ,$(PDP18B_DIR)PDP18B_STDDEV.OBJ,\ + $(PDP18B_DIR)PDP18B_SYS.OBJ,$(PDP18B_DIR)PDP18B_TT1.OBJ +PDP4_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP4=1") +PDP7_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP7=1") +PDP9_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP9=1") +PDP15_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP15=1") + +# +# Digital Equipment PDP-11 Simulator Definitions. +# +PDP11_DIR = SYS$DISK:[.PDP11] +PDP11_LIB = $(LIB_DIR)PDP11-$(ARCH).OLB +PDP11_SOURCE = $(PDP11_DIR)PDP11_FP.C,$(PDP11_DIR)PDP11_CPU.C,\ + $(PDP11_DIR)PDP11_DZ.C,$(PDP11_DIR)PDP11_CIS.C,\ + $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_RK.C,\ + $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RP.C,\ + $(PDP11_DIR)PDP11_RX.C,$(PDP11_DIR)PDP11_STDDEV.C,\ + $(PDP11_DIR)PDP11_SYS.C,$(PDP11_DIR)PDP11_TC.C,\ + $(PDP11_DIR)PDP11_TM.C,$(PDP11_DIR)PDP11_TS.C,\ + $(PDP11_DIR)PDP11_IO.C,$(PDP11_DIR)PDP11_RQ.C,\ + $(PDP11_DIR)PDP11_TQ.C,$(PDP11_DIR)PDP11_PCLK.C,\ + $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_PT.C,\ + $(PDP11_DIR)PDP11_HK.C,$(PDP11_DIR)PDP11_XQ.C,\ + $(PDP11_DIR)PDP11_XU.C +PDP11_OBJS = $(PDP11_DIR)PDP11_FP.OBJ,$(PDP11_DIR)PDP11_CPU.OBJ,\ + $(PDP11_DIR)PDP11_DZ.OBJ,$(PDP11_DIR)PDP11_CIS.OBJ,\ + $(PDP11_DIR)PDP11_LP.OBJ,$(PDP11_DIR)PDP11_RK.OBJ,\ + $(PDP11_DIR)PDP11_RL.OBJ,$(PDP11_DIR)PDP11_RP.OBJ,\ + $(PDP11_DIR)PDP11_RX.OBJ,$(PDP11_DIR)PDP11_STDDEV.OBJ,\ + $(PDP11_DIR)PDP11_SYS.OBJ,$(PDP11_DIR)PDP11_TC.OBJ,\ + $(PDP11_DIR)PDP11_TM.OBJ,$(PDP11_DIR)PDP11_TS.OBJ,\ + $(PDP11_DIR)PDP11_IO.OBJ,$(PDP11_DIR)PDP11_RQ.OBJ,\ + $(PDP11_DIR)PDP11_TQ.OBJ,$(PDP11_DIR)PDP11_PCLK.OBJ,\ + $(PDP11_DIR)PDP11_RY.OBJ,$(PDP11_DIR)PDP11_PT.OBJ,\ + $(PDP11_DIR)PDP11_HK.OBJ,$(PDP11_DIR)PDP11_XQ.OBJ, + $(PDP11_DIR)PDP11_XU.OBJ +PDP11_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP11_DIR)) + +# +# Digital Equipment PDP-10 Simulator Definitions. +# +PDP10_DIR = SYS$DISK:[.PDP10] +PDP10_LIB = $(LIB_DIR)PDP10-$(ARCH).OLB +PDP10_SOURCE = $(PDP10_DIR)PDP10_FE.C,$(PDP10_DIR)PDP10_DZ.C,\ + $(PDP10_DIR)PDP10_CPU.C,$(PDP10_DIR)PDP10_KSIO.C,\ + $(PDP10_DIR)PDP10_LP20.C,$(PDP10_DIR)PDP10_MDFP.C,\ + $(PDP10_DIR)PDP10_PAG.C,$(PDP10_DIR)PDP10_PT.C,\ + $(PDP10_DIR)PDP10_RP.C,$(PDP10_DIR)PDP10_SYS.C,\ + $(PDP10_DIR)PDP10_TIM.C,$(PDP10_DIR)PDP10_TU.C,\ + $(PDP10_DIR)PDP10_XTND.C,$(PDP10_DIR)PDP10_PT.C,\ + $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_XU.C +PDP10_OBJS = $(PDP10_DIR)PDP10_FE.OBJ,$(PDP10_DIR)PDP10_DZ.OBJ,\ + $(PDP10_DIR)PDP10_CPU.OBJ,$(PDP10_DIR)PDP10_KSIO.OBJ,\ + $(PDP10_DIR)PDP10_LP20.OBJ,$(PDP10_DIR)PDP10_MDFP.OBJ,\ + $(PDP10_DIR)PDP10_PAG.OBJ,$(PDP10_DIR)PDP10_PT.OBJ,\ + $(PDP10_DIR)PDP10_RP.OBJ,$(PDP10_DIR)PDP10_SYS.OBJ,\ + $(PDP10_DIR)PDP10_TIM.OBJ,$(PDP10_DIR)PDP10_TU.OBJ,\ + $(PDP10_DIR)PDP10_XTND.OBJ,$(PDP10_DIR)PDP10_PT.OBJ,\ + $(PDP10_DIR)PDP11_RY.OBJ,(PDP10_DIR)PDP11_XU.OBJ +PDP10_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP10_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1") + +# +# IBM System 3 Simulator Definitions. +# +S3_DIR = SYS$DISK:[.S3] +S3_LIB = $(LIB_DIR)S3-$(ARCH).OLB +S3_SOURCE = $(S3_DIR)S3_CD.C,$(S3_DIR)S3_CPU.C,$(S3_DIR)S3_DISK.C,\ + $(S3_DIR)S3_LP.C,$(S3_DIR)S3_PKB.C,$(S3_DIR)S3_SYS.C +S3_OBJS = $(S3_DIR)S3_CD.OBJ,$(S3_DIR)S3_CPU.OBJ,$(S3_DIR)S3_DISK.OBJ,\ + $(S3_DIR)S3_LP.OBJ,$(S3_DIR)S3_PKB.OBJ,$(S3_DIR)S3_SYS.OBJ +S3_OPTIONS = /INCLUDE=($(SIMH_DIR),$(S3_DIR)) + +# +# SDS 940 +# +SDS_DIR = SYS$DISK:[.SDS] +SDS_LIB = $(LIB_DIR)SDS-$(ARCH).OLB +SDS_SOURCE = $(SDS_DIR)SDS_CPU.C,$(SDS_DIR)SDS_DRM.C,$(SDS_DIR)SDS_DSK.C,\ + $(SDS_DIR)SDS_IO.C,$(SDS_DIR)SDS_LP.C,$(SDS_DIR)SDS_MT.C,\ + $(SDS_DIR)SDS_MUX.C,$(SDS_DIR)SDS_RAD.C,$(SDS_DIR)SDS_STDDEV.C,\ + $(SDS_DIR)SDS_SYS.C +SDS_OBJS = $(SDS_DIR)SDS_CPU.OBJ,$(SDS_DIR)SDS_DRM.OBJ,$(SDS_DIR)SDS_DSK.OBJ,\ + $(SDS_DIR)SDS_IO.OBJ,$(SDS_DIR)SDS_LP.OBJ,$(SDS_DIR)SDS_MT.OBJ,\ + $(SDS_DIR)SDS_MUX.OBJ,$(SDS_DIR)SDS_RAD.OBJ,$(SDS_DIR)SDS_STDDEV.OBJ,\ + $(SDS_DIR)SDS_SYS.OBJ +SDS_OPTIONS = /INCLUDE=($(SIMH_DIR),$(SDS_DIR)) + +# +# Digital Equipment VAX Simulator Definitions. +# +VAX_DIR = SYS$DISK:[.VAX] +VAX_LIB = $(LIB_DIR)VAX-$(ARCH).OLB +VAX_SOURCE = $(VAX_DIR)VAX_CPU1.C,$(VAX_DIR)VAX_CPU.C,\ + $(VAX_DIR)VAX_FPA.C,$(VAX_DIR)VAX_IO.C,\ + $(VAX_DIR)VAX_MMU.C,$(VAX_DIR)VAX_STDDEV.C,\ + $(VAX_DIR)VAX_SYS.C,$(VAX_DIR)VAX_SYSDEV.C,\ + $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ + $(PDP11_DIR)PDP11_TS.C,$(PDP11_DIR)PDP11_DZ.C,\ + $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_TQ.C,\ + $(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_XQ.C +VAX_OBJS = $(VAX_DIR)VAX_CPU1.OBJ,$(VAX_DIR)VAX_CPU.OBJ,\ + $(VAX_DIR)VAX_FPA.OBJ,$(VAX_DIR)VAX_IO.OBJ,\ + $(VAX_DIR)VAX_MMU.OBJ,$(VAX_DIR)VAX_STDDEV.OBJ,\ + $(VAX_DIR)VAX_SYS.OBJ,$(VAX_DIR)VAX_SYSDEV.OBJ,\ + $(VAX_DIR)PDP11_RL.OBJ,$(VAX_DIR)PDP11_RQ.OBJ,\ + $(VAX_DIR)PDP11_TS.OBJ,$(VAX_DIR)PDP11_DZ.OBJ,\ + $(VAX_DIR)PDP11_LP.OBJ,$(VAX_DIR)PDP11_TQ.OBJ,\ + $(VAX_DIR)PDP11_PT.OBJ,$(VAX_DIR)PDP11_XQ.OBJ +VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1") + +# +# If On Alpha, Build Everything. +# +.IFDEF __ALPHA__ +ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 NOVA PDP1 \ + PDP4 PDP7 PDP8 PDP9 PDP10 PDP11 PDP15 S3 VAX +.ELSE +# +# Else We Are On VAX And Build Everything EXCEPT PDP-10 And VAX Since VAX +# Dosen't Have INT64 +# +ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 NOVA PDP1 \ + PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 +.ENDIF + +# +# Build The Libraries. +# +$(LIB_DIR)SIMH-$(ARCH).OLB : $(SIMH_SOURCE) + $! + $! Building The $(SIMH_LIB) Library. + $! + $ $(CC)/OBJECT=$(SIMH_DIR) $(SIMH_SOURCE) + $ IF (F$SEARCH("$(SIMH_LIB)").EQS."") THEN - + LIBRARY/CREATE $(SIMH_LIB) + $ LIBRARY/REPLACE $(SIMH_LIB) $(SIMH_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +$(LIB_DIR)ALTAIR-$(ARCH).OLB : $(ALTAIR_SOURCE) + $! + $! Building The $(ALTAIR_LIB) Library. + $! + $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(ALTAIR_DIR) - + $(ALTAIR_SOURCE) + $ IF (F$SEARCH("$(ALTAIR_LIB)").EQS."") THEN - + LIBRARY/CREATE $(ALTAIR_LIB) + $ LIBRARY/REPLACE $(ALTAIR_LIB) - + $(ALTAIR_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(ALTAIR_DIR)*.OBJ;* + +$(LIB_DIR)ALTAIRZ80-$(ARCH).OLB : $(ALTAIRZ80_SOURCE) + $! + $! Building The $(ALTAIRZ80_LIB) Library. + $! + $ $(CC)$(ALTAIRZ80_OPTIONS) - + /OBJECT=$(ALTAIRZ80_DIR) - + $(ALTAIRZ80_SOURCE) + $ IF (F$SEARCH("$(ALTAIRZ80_LIB)").EQS."") - + THEN LIBRARY/CREATE $(ALTAIRZ80_LIB) + $ LIBRARY/REPLACE $(ALTAIRZ80_LIB) - + $(ALTAIRZ80_OBJS) + $ DELETE/NOLOG/NOCONFIRM - + $(ALTAIRZ80_DIR)*.OBJ;* + +$(LIB_DIR)ECLIPSE-$(ARCH).OLB : $(ECLIPSE_SOURCE) + $! + $! Building The $(ECLIPSE_LIB) Library. + $! + $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(NOVA_DIR) - + $(ECLIPSE_SOURCE) + $ IF (F$SEARCH("$(ECLIPSE_LIB)").EQS."") THEN - + LIBRARY/CREATE $(ECLIPSE_LIB) + $ LIBRARY/REPLACE $(ECLIPSE_LIB) - + $(ECLIPSE_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(NOVA_DIR)*.OBJ;* + +$(LIB_DIR)GRI-$(ARCH).OLB : $(GRI_SOURCE) + $! + $! Building The $(GRI_LIB) Library. + $! + $ $(CC)$(GRI_OPTIONS)/OBJECT=$(GRI_DIR) - + $(GRI_SOURCE) + $ IF (F$SEARCH("$(GRI_LIB)").EQS."") THEN - + LIBRARY/CREATE $(GRI_LIB) + $ LIBRARY/REPLACE $(GRI_LIB) $(GRI_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(GRI_DIR)*.OBJ;* + +$(LIB_DIR)H316-$(ARCH).OLB : $(H316_SOURCE) + $! + $! Building The $(H316_LIB) Library. + $! + $ $(CC)$(H316_OPTIONS)/OBJECT=$(H316_DIR) - + $(H316_SOURCE) + $ IF (F$SEARCH("$(H316_LIB)").EQS."") THEN - + LIBRARY/CREATE $(H316_LIB) + $ LIBRARY/REPLACE $(H316_LIB) $(H316_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(H316_DIR)*.OBJ;* + +$(LIB_DIR)HP2100-$(ARCH).OLB : $(HP2100_SOURCE) + $! + $! Building The $(HP2100_LIB) Library. + $! + $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(HP2100_DIR) - + $(HP2100_SOURCE) + $ IF (F$SEARCH("$(HP2100_LIB)").EQS."") THEN - + LIBRARY/CREATE $(HP2100_LIB) + $ LIBRARY/REPLACE $(HP2100_LIB) $(HP2100_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(HP2100_DIR)*.OBJ;* + +$(LIB_DIR)I1401-$(ARCH).OLB : $(I1401_SOURCE) + $! + $! Building The $(I1401_LIB) Library. + $! + $ $(CC)$(I1401_OPTIONS)/OBJECT=$(I1401_DIR) - + $(I1401_SOURCE) + $ IF (F$SEARCH("$(I1401_LIB)").EQS."") THEN - + LIBRARY/CREATE $(I1401_LIB) + $ LIBRARY/REPLACE $(I1401_LIB) $(I1401_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(I1401_DIR)*.OBJ;* + +$(LIB_DIR)I1620-$(ARCH).OLB : $(I1620_SOURCE) + $! + $! Building The $(I1620_LIB) Library. + $! + $ $(CC)$(I1620_OPTIONS)/OBJECT=$(I1620_DIR) - + $(I1620_SOURCE) + $ IF (F$SEARCH("$(I1620_LIB)").EQS."") THEN - + LIBRARY/CREATE $(I1620_LIB) + $ LIBRARY/REPLACE $(I1620_LIB) $(I1620_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(I1620_DIR)*.OBJ;* + +$(LIB_DIR)IBM1130-$(ARCH).OLB : $(IBM1130_SOURCE) + $! + $! Building The $(IBM1130_LIB) Library. + $! + $ $(CC)$(IBM1130_OPTIONS) - + /OBJECT=$(IBM1130_DIR) - + $(IBM1130_SOURCE) + $ IF (F$SEARCH("$(IBM1130_LIB)").EQS."") THEN - + LIBRARY/CREATE $(IBM1130_LIB) + $ LIBRARY/REPLACE $(IBM1130_LIB) $(IBM1130_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(IBM1130_DIR)*.OBJ;* + +$(LIB_DIR)ID16-$(ARCH).OLB : $(ID16_SOURCE) + $! + $! Building The $(ID16_LIB) Library. + $! + $ $(CC)$(ID16_OPTIONS)/OBJECT=$(ID16_DIR) - + $(ID16_SOURCE) + $ IF (F$SEARCH("$(ID16_LIB)").EQS."") THEN - + LIBRARY/CREATE $(ID16_LIB) + $ LIBRARY/REPLACE $(ID16_LIB) $(ID16_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(ID16_DIR)*.OBJ;* + +$(LIB_DIR)ID32-$(ARCH).OLB : $(ID32_SOURCE) + $! + $! Building The $(ID32_LIB) Library. + $! + $ $(CC)$(ID32_OPTIONS)/OBJECT=$(ID32_DIR) - + $(ID32_SOURCE) + $ IF (F$SEARCH("$(ID32_LIB)").EQS."") THEN - + LIBRARY/CREATE $(ID32_LIB) + $ LIBRARY/REPLACE $(ID32_LIB) $(ID32_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(ID32_DIR)*.OBJ;* + +$(LIB_DIR)NOVA-$(ARCH).OLB : $(NOVA_SOURCE) + $! + $! Building The $(NOVA_LIB) Library. + $! + $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(NOVA_DIR) - + $(NOVA_SOURCE) + $ IF (F$SEARCH("$(NOVA_LIB)").EQS."") THEN - + LIBRARY/CREATE $(NOVA_LIB) + $ LIBRARY/REPLACE $(NOVA_LIB) $(NOVA_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(NOVA_DIR)*.OBJ;* + +$(LIB_DIR)PDP1-$(ARCH).OLB : $(PDP1_SOURCE) + $! + $! Building The $(PDP1_LIB) Library. + $! + $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(PDP1_DIR) - + $(PDP1_SOURCE) + $ IF (F$SEARCH("$(PDP1_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP1_LIB) + $ LIBRARY/REPLACE $(PDP1_LIB) $(PDP1_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP1_DIR)*.OBJ;* + +$(LIB_DIR)PDP4-$(ARCH).OLB : $(PDP18B_SOURCE) + $! + $! Building The $(PDP4_LIB) Library. + $! + $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(PDP18B_DIR) - + $(PDP18B_SOURCE) + $ IF (F$SEARCH("$(PDP4_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP4_LIB) + $ LIBRARY/REPLACE $(PDP4_LIB) $(PDP18B_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* + +$(LIB_DIR)PDP7-$(ARCH).OLB : $(PDP18B_SOURCE) + $! + $! Building The $(PDP7_LIB) Library. + $! + $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(PDP18B_DIR) - + $(PDP18B_SOURCE) + $ IF (F$SEARCH("$(PDP7_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP7_LIB) + $ LIBRARY/REPLACE $(PDP7_LIB) $(PDP18B_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* + +$(LIB_DIR)PDP8-$(ARCH).OLB : $(PDP8_SOURCE) + $! + $! Building The $(PDP8_LIB) Library. + $! + $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(PDP8_DIR) - + $(PDP8_SOURCE) + $ IF (F$SEARCH("$(PDP8_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP8_LIB) + $ LIBRARY/REPLACE $(PDP8_LIB) $(PDP8_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP8_DIR)*.OBJ;* + +$(LIB_DIR)PDP9-$(ARCH).OLB : $(PDP18B_SOURCE) + $! + $! Building The $(PDP9_LIB) Library. + $! + $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(PDP18B_DIR) - + $(PDP18B_SOURCE) + $ IF (F$SEARCH("$(PDP9_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP9_LIB) + $ LIBRARY/REPLACE $(PDP9_LIB) $(PDP18B_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* + +# +# If On Alpha, Build The PDP-10 Library. +# +.IFDEF __ALPHA__ +$(LIB_DIR)PDP10-$(ARCH).OLB : $(PDP10_SOURCE) + $! + $! Building The $(PDP10_LIB) Library. + $! + $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(PDP10_DIR) - + $(PDP10_SOURCE) + $ IF (F$SEARCH("$(PDP10_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP10_LIB) + $ LIBRARY/REPLACE $(PDP10_LIB) $(PDP10_OBJS) + DELETE/NOLOG/NOCONFIRM $(PDP10_DIR)*.OBJ;* +.ELSE +# +# We Are On VAX And Due To The Use of INT64 We Can't Build It. +# +$(LIB_DIR)PDP10-$(ARCH).OLB : + $! + $! Due To The Use Of INT64 We Can't Build The + $! $(LIB_DIR)PDP10-$(ARCH).OLB Library On VAX. + $! +.ENDIF + +$(LIB_DIR)PDP11-$(ARCH).OLB : $(PDP11_SOURCE) + $! + $! Building The $(PDP11_LIB) Library. + $! + $(CC)$(PDP11_OPTIONS)/OBJECT=$(PDP11_DIR) - + $(PDP11_SOURCE) + $ IF (F$SEARCH("$(PDP11_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP11_LIB) + $ LIBRARY/REPLACE $(PDP11_LIB) $(PDP11_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP11_DIR)*.OBJ;* + +$(LIB_DIR)PDP15-$(ARCH).OLB : $(PDP18B_SOURCE) + $! + $! Building The $(PDP15_LIB) Library. + $! + $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(PDP18B_DIR) - + $(PDP18B_SOURCE) + $ IF (F$SEARCH("$(PDP15_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP15_LIB) + $ LIBRARY/REPLACE $(PDP15_LIB) $(PDP18B_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* + +$(LIB_DIR)S3-$(ARCH).OLB : $(S3_SOURCE) + $! + $! Building The $(S3_LIB) Library. + $! + $ $(CC)$(S3_OPTIONS)/OBJECT=$(S3_DIR) $(S3_SOURCE) + $ IF (F$SEARCH("$(S3_LIB)").EQS."") THEN - + LIBRARY/CREATE $(S3_LIB) + $ LIBRARY/REPLACE $(S3_LIB) $(S3_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(S3_DIR)*.OBJ;* + +$(LIB_DIR)SDS-$(ARCH).OLB : $(SDS_SOURCE) + $! + $! Building The $(SDS_LIB) Library. + $! + $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SDS_DIR) - + $(SDS_SOURCE) + $ IF (F$SEARCH("$(SDS_LIB)").EQS."") THEN - + LIBRARY/CREATE $(SDS_LIB) + $ LIBRARY/REPLACE $(SDS_LIB) $(SDS_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(SDS_DIR)*.OBJ;* + +# +# If On Alpha, Build The VAX Library. +# +.IFDEF __ALPHA__ +$(LIB_DIR)VAX-$(ARCH).OLB : $(VAX_SOURCE) + $! + $! Building The $(VAX_LIB) Library. + $! + $ $(CC)$(VAX_OPTIONS)/OBJECT=$(VAX_DIR) - + $(VAX_SOURCE) + $ IF (F$SEARCH("$(VAX_LIB)").EQS."") THEN - + LIBRARY/CREATE $(VAX_LIB) + $ LIBRARY/REPLACE $(VAX_LIB) $(VAX_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(VAX_DIR)*.OBJ;* +.ELSE +# +# We Are On VAX And Due To The Use of INT64 We Can't Build It. +# +$(LIB_DIR)VAX-$(ARCH).OLB : + $! + $! Due To The Use Of INT64 We Can't Build The + $! $(LIB_DIR)VAX-$(ARCH).OLB Library On VAX. + $! +.ENDIF + +# +# Individual Simulator Builds. +# +ALTAIR : $(SIMH_LIB) $(ALTAIR_LIB) + $! + $! Building The $(BIN_DIR)ALTAIR-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIR-$(ARCH).EXE - + SCP.OBJ,$(ALTAIR_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +ALTAIRZ80 : $(SIMH_LIB) $(ALTAIRZ80_LIB) + $! + $! Building The $(BIN_DIR)ALTAIRZ80-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ALTAIRZ80_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIRZ80-$(ARCH).EXE - + SCP.OBJ,$(ALTAIRZ80_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +ECLIPSE : $(SIMH_LIB) $(ECLIPSE_LIB) + $! + $! Building The $(BIN_DIR)ECLPISE-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ECLIPSE-$(ARCH).EXE - + SCP.OBJ,$(ECLIPSE_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +GRI : $(SIMH_LIB) $(GRI_LIB) + $! + $! Building The $(BIN_DIR)GRI-$(ARCH).EXE Simulator. + $! + $ $(CC)$(GRI_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)GRI-$(ARCH).EXE - + SCP.OBJ,$(GRI_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +H316 : $(SIMH_LIB) $(H316_LIB) + $! + $! Building The $(BIN_DIR)H316-$(ARCH).EXE Simulator. + $! + $ $(CC)$(H316_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)H316-$(ARCH).EXE - + SCP.OBJ,$(H316_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +HP2100 : $(SIMH_LIB) $(HP2100_LIB) + $! + $! Building The $(BIN_DIR)HP2100-$(ARCH).EXE Simulator. + $! + $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)HP2100-$(ARCH).EXE - + SCP.OBJ,$(HP2100_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +I1401 : $(SIMH_LIB) $(I1401_LIB) + $! + $! Building The $(BIN_DIR)I1401-$(ARCH).EXE Simulator. + $! + $ $(CC)$(I1401_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)I1401-$(ARCH).EXE - + SCP.OBJ,$(I1401_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +I1620 : $(SIMH_LIB) $(I1620_LIB) + $! + $! Building The $(BIN_DIR)I1620-$(ARCH).EXE Simulator. + $! + $ $(CC)$(I1620_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)I1620-$(ARCH).EXE - + SCP.OBJ,$(I1620_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +IBM1130 : $(SIMH_LIB) $(IBM1130_LIB) + $! + $! Building The $(BIN_DIR)IBM1130-$(ARCH).EXE Simulator. + $! + $ $(CC)$(IBM1130_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)IBM1130-$(ARCH).EXE - + SCP.OBJ,$(IBM1130_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +ID16 : $(SIMH_LIB) $(ID16_LIB) + $! + $! Building The $(BIN_DIR)ID16-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ID16_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ID16-$(ARCH).EXE - + SCP.OBJ,$(ID16_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +ID32 : $(SIMH_LIB) $(ID32_LIB) + $! + $! Building The $(BIN_DIR)ID32-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ID32_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ID32-$(ARCH).EXE - + SCP.OBJ,$(ID32_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +NOVA : $(SIMH_LIB) $(NOVA_LIB) + $! + $! Building The $(BIN_DIR)NOVA-$(ARCH).EXE Simulator. + $! + $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)NOVA-$(ARCH).EXE - + SCP.OBJ,$(NOVA_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP1 : $(SIMH_LIB) $(PDP1_LIB) + $! + $! Building The $(BIN_DIR)PDP1-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP1-$(ARCH).EXE - + SCP.OBJ,$(PDP1_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP4 : $(SIMH_LIB) $(PDP4_LIB) + $! + $! Building The $(BIN_DIR)PDP4-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP4-$(ARCH).EXE - + SCP.OBJ,$(PDP4_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP7 : $(SIMH_LIB) $(PDP7_LIB) + $! + $! Building The $(BIN_DIR)PDP7-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP7-$(ARCH).EXE - + SCP.OBJ,$(PDP7_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP8 : $(SIMH_LIB) $(PDP8_LIB) + $! + $! Building The $(BIN_DIR)PDP8-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP8-$(ARCH).EXE - + SCP.OBJ,$(PDP8_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP9 : $(SIMH_LIB) $(PDP9_LIB) + $! + $! Building The $(BIN_DIR)PDP9-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP9-$(ARCH).EXE - + SCP.OBJ,$(PDP9_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +# +# If On Alpha, Build The PDP-10 Simulator. +# +.IFDEF __ALPHA__ +PDP10 : $(SIMH_LIB) $(PDP10_LIB) + $! + $! Building The $(BIN_DIR)PDP10-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP10-$(ARCH).EXE - + SCP.OBJ,$(PDP10_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* +.ELSE +# +# Else We Are On VAX And Tell The User We Can't Build On VAX +# Due To The Use Of INT64. +# +PDP10 : + $! + $! Sorry, Can't Build $(BIN_DIR)PDP10-$(ARCH).EXE Simulator + $! Because It Requires The Use Of INT64. + $! +.ENDIF + +PDP11 : $(SIMH_LIB) $(PDP11_LIB) + $! + $! Building The $(BIN_DIR)PDP11-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP11_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP11-$(ARCH).EXE - + SCP.OBJ,$(PDP11_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP15 : $(SIMH_LIB) $(PDP15_LIB) + $! + $! Building The $(BIN_DIR)PDP15-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP15-$(ARCH).EXE - + SCP.OBJ,$(PDP15_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +S3 : $(SIMH_LIB) $(S3_LIB) + $! + $! Building The $(BIN_DIR)S3-$(ARCH).EXE Simulator. + $! + $ $(CC)$(S3_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)S3-$(ARCH).EXE - + SCP.OBJ,$(S3_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +SDS : $(SIMH_LIB) $(SDS_LIB) + $! + $! Building The $(BIN_DIR)SDS-$(ARCH).EXE Simulator. + $! + $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)SDS-$(ARCH).EXE - + SCP.OBJ,$(SDS_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +# +# If On Alpha, Build The VAX Simulator. +# +.IFDEF __ALPHA__ +VAX : $(SIMH_LIB) $(VAX_LIB) + $! + $! Building The $(BIN_DIR)VAX-$(ARCH).EXE Simulator. + $! + $ $(CC)$(VAX_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)VAX-$(ARCH).EXE - + SCP.OBJ,$(VAX_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* +.ELSE +# +# Else We Are On VAX And Tell The User We Can't Build On VAX +# Due To The Use Of INT64. +# +VAX : + $! + $! Sorry, Can't Build $(BIN_DIR)VAX-$(ARCH).EXE Simulator + $! Because It Requires The Use Of INT64. + $! +.ENDIF + diff --git a/makefile b/makefile index bfeeb013..380c20ee 100644 --- a/makefile +++ b/makefile @@ -3,9 +3,24 @@ # Note: -O2 is sometimes broken in GCC when setjump/longjump is being # used. Try -O2 only with released simulators. # -CC = gcc -O2 -lm -I . -#CC = gcc -O2 -g -lm -I . - +ifeq ($(WIN32),) +#Unix Environments +CC = gcc -O2 -lm -I . +#CC = gcc -O2 -g -lm -I . +ifeq ($(USE_NETWORK),) +else +NETWORK_OPT = -DUSE_NETWORK -lpcap +endif +else +#Win32 Environments +LDFLAGS = -lm -lwsock32 +CC = gcc -O0 -I. +EXE = .exe +ifeq ($(USE_NETWORK),) +else +NETWORK_OPT = -DUSE_NETWORK -lwpcap -lpacket +endif +endif # @@ -21,7 +36,7 @@ SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c sim_ether.c # PDP1D = PDP1/ PDP1 = ${PDP1D}pdp1_lp.c ${PDP1D}pdp1_cpu.c ${PDP1D}pdp1_stddev.c \ - ${PDP1D}pdp1_sys.c ${PDP1D}pdp1_dt.c + ${PDP1D}pdp1_sys.c ${PDP1D}pdp1_dt.c ${PDP1D}pdp1_drm.c PDP1_OPT = -I ${PDP1D} @@ -62,8 +77,8 @@ PDP11 = ${PDP11D}pdp11_fp.c ${PDP11D}pdp11_cpu.c ${PDP11D}pdp11_dz.c \ ${PDP11D}pdp11_tm.c ${PDP11D}pdp11_ts.c ${PDP11D}pdp11_io.c \ ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_tq.c ${PDP11D}pdp11_pclk.c \ ${PDP11D}pdp11_ry.c ${PDP11D}pdp11_pt.c ${PDP11D}pdp11_hk.c \ - ${PDP11D}pdp11_xq.c -PDP11_OPT = -I ${PDP11D} + ${PDP11D}pdp11_xq.c ${PDP11D}pdp11_xu.c +PDP11_OPT = -I ${PDP11D} ${NETWORK_OPT} @@ -74,7 +89,7 @@ VAX = ${VAXD}vax_cpu1.c ${VAXD}vax_cpu.c ${VAXD}vax_fpa.c ${VAXD}vax_io.c \ ${PDP11D}pdp11_rl.c ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_ts.c \ ${PDP11D}pdp11_dz.c ${PDP11D}pdp11_lp.c ${PDP11D}pdp11_tq.c \ ${PDP11D}pdp11_pt.c ${PDP11D}pdp11_xq.c -VAX_OPT = -I ${VAXD} -I ${PDP11D} -DUSE_INT64 +VAX_OPT = -I ${VAXD} -I ${PDP11D} -DUSE_INT64 ${NETWORK_OPT} @@ -83,7 +98,7 @@ PDP10 = ${PDP10D}pdp10_fe.c ${PDP10D}pdp10_dz.c ${PDP10D}pdp10_cpu.c \ ${PDP10D}pdp10_ksio.c ${PDP10D}pdp10_lp20.c ${PDP10D}pdp10_mdfp.c \ ${PDP10D}pdp10_pag.c ${PDP10D}pdp10_rp.c ${PDP10D}pdp10_sys.c \ ${PDP10D}pdp10_tim.c ${PDP10D}pdp10_tu.c ${PDP10D}pdp10_xtnd.c \ - ${PDP10D}pdp10_pt.c ${PDP11D}pdp11_ry.c + ${PDP10D}pdp10_pt.c ${PDP11D}pdp11_ry.c ${PDP11D}pdp11_xu.c PDP10_OPT = -DUSE_INT64 -I ${PDP10D} -I ${PDP11D} -I ${VAXD} @@ -109,7 +124,8 @@ HP2100D = HP2100/ HP2100 = ${HP2100D}hp2100_stddev.c ${HP2100D}hp2100_dp.c ${HP2100D}hp2100_dq.c \ ${HP2100D}hp2100_dr.c ${HP2100D}hp2100_lps.c ${HP2100D}hp2100_ms.c \ ${HP2100D}hp2100_mt.c ${HP2100D}hp2100_mux.c ${HP2100D}hp2100_cpu.c \ - ${HP2100D}hp2100_fp.c ${HP2100D}hp2100_sys.c ${HP2100D}hp2100_lpt.c + ${HP2100D}hp2100_fp.c ${HP2100D}hp2100_sys.c ${HP2100D}hp2100_lpt.c \ + ${HP2100D}hp2100_ipl.c HP2100_OPT = -I ${HP2100D} @@ -143,7 +159,7 @@ ID16D = Interdata/ ID16 = ${ID16D}id16_cpu.c ${ID16D}id16_sys.c ${ID16D}id_dp.c \ ${ID16D}id_fd.c ${ID16D}id_fp.c ${ID16D}id_idc.c ${ID16D}id_io.c \ ${ID16D}id_lp.c ${ID16D}id_mt.c ${ID16D}id_pas.c ${ID16D}id_pt.c \ - ${ID16D}id_tt.c ${ID16D}id_uvc.c + ${ID16D}id_tt.c ${ID16D}id_uvc.c ${ID16D}id16_dboot.c ${ID16D}id_ttp.c ID16_OPT = -I ${ID16D} @@ -152,7 +168,7 @@ ID32D = Interdata/ ID32 = ${ID32D}id32_cpu.c ${ID32D}id32_sys.c ${ID32D}id_dp.c \ ${ID32D}id_fd.c ${ID32D}id_fp.c ${ID32D}id_idc.c ${ID32D}id_io.c \ ${ID32D}id_lp.c ${ID32D}id_mt.c ${ID32D}id_pas.c ${ID32D}id_pt.c \ - ${ID32D}id_tt.c ${ID32D}id_uvc.c + ${ID32D}id_tt.c ${ID32D}id_uvc.c ${ID32D}id32_dboot.c ${ID32D}id_ttp.c ID32_OPT = -I ${ID32D} @@ -196,118 +212,121 @@ SDS_OPT = -I ${SDSD} # # Build everything # -all : ${BIN}pdp1 ${BIN}pdp4 ${BIN}pdp7 ${BIN}pdp8 ${BIN}pdp9 ${BIN}pdp15 \ - ${BIN}pdp11 ${BIN}pdp10 ${BIN}vax ${BIN}nova ${BIN}eclipse ${BIN}h316 \ - ${BIN}hp2100 ${BIN}i1401 ${BIN}i1620 ${BIN}s3 ${BIN}altair \ - ${BIN}altairz80 ${BIN}gri ${BIN}i1620 ${BIN}ibm1130 \ - ${BIN}id16 ${BIN}id32 ${BIN}sds - +all : ${BIN}pdp1${EXE} ${BIN}pdp4${EXE} ${BIN}pdp7${EXE} ${BIN}pdp8${EXE} \ + ${BIN}pdp9${EXE} ${BIN}pdp15${EXE} ${BIN}pdp11${EXE} ${BIN}pdp10${EXE} \ + ${BIN}vax${EXE} ${BIN}nova${EXE} ${BIN}eclipse${EXE} ${BIN}h316${EXE} \ + ${BIN}hp2100${EXE} ${BIN}i1401${EXE} ${BIN}i1620${EXE} ${BIN}s3${EXE} \ + ${BIN}altair${EXE} ${BIN}altairz80${EXE} ${BIN}gri${EXE} \ + ${BIN}i1620${EXE} ${BIN}ibm1130${EXE} ${BIN}id16${EXE} \ + ${BIN}id32${EXE} ${BIN}sds${EXE} # # Individual builds # -${BIN}pdp1 : ${PDP1} ${SIM} - ${CC} ${PDP1} ${SIM} ${PDP1_OPT} -o $@ +${BIN}pdp1${EXE} : ${PDP1} ${SIM} + ${CC} ${PDP1} ${SIM} ${PDP1_OPT} -o $@ ${LDFLAGS} -${BIN}pdp4 : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP4_OPT} -o $@ +${BIN}pdp4${EXE} : ${PDP18B} ${SIM} + ${CC} ${PDP18B} ${SIM} ${PDP4_OPT} -o $@ ${LDFLAGS} -${BIN}pdp7 : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP7_OPT} -o $@ +${BIN}pdp7${EXE} : ${PDP18B} ${SIM} + ${CC} ${PDP18B} ${SIM} ${PDP7_OPT} -o $@ ${LDFLAGS} -${BIN}pdp8 : ${PDP8} ${SIM} - ${CC} ${PDP8} ${SIM} ${PDP8_OPT} -o $@ +${BIN}pdp8${EXE} : ${PDP8} ${SIM} + ${CC} ${PDP8} ${SIM} ${PDP8_OPT} -o $@ ${LDFLAGS} -${BIN}pdp9 : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP9_OPT} -o $@ +${BIN}pdp9${EXE} : ${PDP18B} ${SIM} + ${CC} ${PDP18B} ${SIM} ${PDP9_OPT} -o $@ ${LDFLAGS} -${BIN}pdp15 : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP15_OPT} -o $@ +${BIN}pdp15${EXE} : ${PDP18B} ${SIM} + ${CC} ${PDP18B} ${SIM} ${PDP15_OPT} -o $@ ${LDFLAGS} -${BIN}pdp10 : ${PDP10} ${SIM} - ${CC} ${PDP10} ${SIM} ${PDP10_OPT} -o $@ +${BIN}pdp10${EXE} : ${PDP10} ${SIM} + ${CC} ${PDP10} ${SIM} ${PDP10_OPT} -o $@ ${LDFLAGS} -${BIN}pdp11 : ${PDP11} ${SIM} - ${CC} ${PDP11} ${SIM} ${PDP11_OPT} -o $@ +${BIN}pdp11${EXE} : ${PDP11} ${SIM} + ${CC} ${PDP11} ${SIM} ${PDP11_OPT} -o $@ ${LDFLAGS} -${BIN}vax : ${VAX} ${SIM} - ${CC} ${VAX} ${SIM} ${VAX_OPT} -o $@ +${BIN}vax${EXE} : ${VAX} ${SIM} + ${CC} ${VAX} ${SIM} ${VAX_OPT} -o $@ ${LDFLAGS} -${BIN}nova : ${NOVA} ${SIM} - ${CC} ${NOVA} ${SIM} ${NOVA_OPT} -o $@ +${BIN}nova${EXE} : ${NOVA} ${SIM} + ${CC} ${NOVA} ${SIM} ${NOVA_OPT} -o $@ ${LDFLAGS} -${BIN}eclipse : ${ECLIPSE} ${SIM} - ${CC} ${ECLIPSE} ${SIM} ${ECLIPSE_OPT} -o $@ +${BIN}eclipse${EXE} : ${ECLIPSE} ${SIM} + ${CC} ${ECLIPSE} ${SIM} ${ECLIPSE_OPT} -o $@ ${LDFLAGS} -${BIN}h316 : ${H316} ${SIM} - ${CC} ${H316} ${SIM} ${H316_OPT} -o $@ +${BIN}h316${EXE} : ${H316} ${SIM} + ${CC} ${H316} ${SIM} ${H316_OPT} -o $@ ${LDFLAGS} -${BIN}hp2100 : ${HP2100} ${SIM} - ${CC} ${HP2100} ${SIM} ${HP2100_OPT} -o $@ +${BIN}hp2100${EXE} : ${HP2100} ${SIM} + ${CC} ${HP2100} ${SIM} ${HP2100_OPT} -o $@ ${LDFLAGS} -${BIN}i1401 : ${I1401} ${SIM} - ${CC} ${I1401} ${SIM} ${I1401_OPT} -o $@ +${BIN}i1401${EXE} : ${I1401} ${SIM} + ${CC} ${I1401} ${SIM} ${I1401_OPT} -o $@ ${LDFLAGS} -${BIN}i1620 : ${I1620} ${SIM} - ${CC} ${I1620} ${SIM} ${I1620_OPT} -o $@ +${BIN}i1620${EXE} : ${I1620} ${SIM} + ${CC} ${I1620} ${SIM} ${I1620_OPT} -o $@ ${LDFLAGS} -${BIN}ibm1130 : ${IBM1130} - ${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} -o $@ +${BIN}ibm1130${EXE} : ${IBM1130} + ${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} -o $@ ${LDFLAGS} -${BIN}s3 : ${S3} ${SIM} - ${CC} ${S3} ${SIM} ${S3_OPT} -o $@ +${BIN}s3${EXE} : ${S3} ${SIM} + ${CC} ${S3} ${SIM} ${S3_OPT} -o $@ ${LDFLAGS} -${BIN}altair : ${ALTAIR} ${SIM} - ${CC} ${ALTAIR} ${SIM} ${ALTAIR_OPT} -o $@ +${BIN}altair${EXE} : ${ALTAIR} ${SIM} + ${CC} ${ALTAIR} ${SIM} ${ALTAIR_OPT} -o $@ ${LDFLAGS} -${BIN}altairz80 : ${ALTAIRZ80} ${SIM} ${ALTAIRZ80D}altairZ80_defs.h - ${CC} ${ALTAIRZ80_OPT} ${ALTAIRZ80} ${SIM} -o $@ -${ALTAIRZ80D}altairZ80_defs.h : ${ALTAIRZ80D}altairz80_defs.h - cp ${ALTAIRZ80D}altairz80_defs.h ${ALTAIRZ80D}altairZ80_defs.h - -${BIN}gri : ${GRI} ${SIM} - ${CC} ${GRI} ${SIM} ${GRI_OPT} -o $@ - -${BIN}id16 : ${ID16} ${SIM} - ${CC} ${ID16} ${SIM} ${ID16_OPT} -o $@ - -${BIN}id32 : ${ID32} ${SIM} - ${CC} ${ID32} ${SIM} ${ID32_OPT} -o $@ - -${BIN}sds : ${SDS} ${SIM} - ${CC} ${SDS} ${SIM} ${SDS_OPT} -o $@ +${BIN}altairz80${EXE} : ${ALTAIRZ80} ${SIM} + ${CC} ${ALTAIRZ80} ${SIM} ${ALTAIRZ80_OPT} -o $@ ${LDFLAGS} + + +${BIN}gri${EXE} : ${GRI} ${SIM} + ${CC} ${GRI} ${SIM} ${GRI_OPT} -o $@ ${LDFLAGS} + + +${BIN}id16${EXE} : ${ID16} ${SIM} + ${CC} ${ID16} ${SIM} ${ID16_OPT} -o $@ ${LDFLAGS} + + +${BIN}id32${EXE} : ${ID32} ${SIM} + ${CC} ${ID32} ${SIM} ${ID32_OPT} -o $@ ${LDFLAGS} + + +${BIN}sds${EXE} : ${SDS} ${SIM} + ${CC} ${SDS} ${SIM} ${SDS_OPT} -o $@ ${LDFLAGS} diff --git a/makefile_ether b/makefile_ether deleted file mode 100644 index 62634608..00000000 --- a/makefile_ether +++ /dev/null @@ -1,313 +0,0 @@ -# CC Command -# -# Note: -O2 is sometimes broken in GCC when setjump/longjump is being -# used. Try -O2 only with released simulators. -# -CC = gcc -O2 -lm -I . -#CC = gcc -O2 -g -lm -I . - - - -# -# Common Libraries -# -BIN = BIN/ -SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c sim_ether.c - - - -# -# Emulator source files and compile time options -# -PDP1D = PDP1/ -PDP1 = ${PDP1D}pdp1_lp.c ${PDP1D}pdp1_cpu.c ${PDP1D}pdp1_stddev.c \ - ${PDP1D}pdp1_sys.c ${PDP1D}pdp1_dt.c -PDP1_OPT = -I ${PDP1D} - - -NOVAD = NOVA/ -NOVA = ${NOVAD}nova_sys.c ${NOVAD}nova_cpu.c ${NOVAD}nova_dkp.c \ - ${NOVAD}nova_dsk.c ${NOVAD}nova_lp.c ${NOVAD}nova_mta.c \ - ${NOVAD}nova_plt.c ${NOVAD}nova_pt.c ${NOVAD}nova_clk.c \ - ${NOVAD}nova_tt.c ${NOVAD}nova_tt1.c -NOVA_OPT = -I ${NOVAD} - - - -ECLIPSE = ${NOVAD}eclipse_cpu.c ${NOVAD}eclipse_tt.c ${NOVAD}nova_sys.c \ - ${NOVAD}nova_dkp.c ${NOVAD}nova_dsk.c ${NOVAD}nova_lp.c \ - ${NOVAD}nova_mta.c ${NOVAD}nova_plt.c ${NOVAD}nova_pt.c \ - ${NOVAD}nova_clk.c ${NOVAD}nova_tt1.c -ECLIPSE_OPT = -I ${NOVAD} -DECLIPSE - - - -PDP18BD = PDP18B/ -PDP18B = ${PDP18BD}pdp18b_dt.c ${PDP18BD}pdp18b_drm.c ${PDP18BD}pdp18b_cpu.c \ - ${PDP18BD}pdp18b_lp.c ${PDP18BD}pdp18b_mt.c ${PDP18BD}pdp18b_rf.c \ - ${PDP18BD}pdp18b_rp.c ${PDP18BD}pdp18b_stddev.c ${PDP18BD}pdp18b_sys.c \ - ${PDP18BD}pdp18b_tt1.c -PDP4_OPT = -DPDP4 -I ${PDP18BD} -PDP7_OPT = -DPDP7 -I ${PDP18BD} -PDP9_OPT = -DPDP9 -I ${PDP18BD} -PDP15_OPT = -DPDP15 -I ${PDP18BD} - - - -PDP11D = PDP11/ -PDP11 = ${PDP11D}pdp11_fp.c ${PDP11D}pdp11_cpu.c ${PDP11D}pdp11_dz.c \ - ${PDP11D}pdp11_cis.c ${PDP11D}pdp11_lp.c ${PDP11D}pdp11_rk.c \ - ${PDP11D}pdp11_rl.c ${PDP11D}pdp11_rp.c ${PDP11D}pdp11_rx.c \ - ${PDP11D}pdp11_stddev.c ${PDP11D}pdp11_sys.c ${PDP11D}pdp11_tc.c \ - ${PDP11D}pdp11_tm.c ${PDP11D}pdp11_ts.c ${PDP11D}pdp11_io.c \ - ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_tq.c ${PDP11D}pdp11_pclk.c \ - ${PDP11D}pdp11_ry.c ${PDP11D}pdp11_pt.c ${PDP11D}pdp11_hk.c \ - ${PDP11D}pdp11_xq.c -PDP11_OPT = -I ${PDP11D} -DUSE_NETWORK -lpcap - - - -VAXD = VAX/ -VAX = ${VAXD}vax_cpu1.c ${VAXD}vax_cpu.c ${VAXD}vax_fpa.c ${VAXD}vax_io.c \ - ${VAXD}vax_mmu.c ${VAXD}vax_stddev.c ${VAXD}vax_sys.c \ - ${VAXD}vax_sysdev.c \ - ${PDP11D}pdp11_rl.c ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_ts.c \ - ${PDP11D}pdp11_dz.c ${PDP11D}pdp11_lp.c ${PDP11D}pdp11_tq.c \ - ${PDP11D}pdp11_pt.c ${PDP11D}pdp11_xq.c -VAX_OPT = -I ${VAXD} -I ${PDP11D} -DUSE_INT64 -DUSE_NETWORK -lpcap - - - -PDP10D = PDP10/ -PDP10 = ${PDP10D}pdp10_fe.c ${PDP10D}pdp10_dz.c ${PDP10D}pdp10_cpu.c \ - ${PDP10D}pdp10_ksio.c ${PDP10D}pdp10_lp20.c ${PDP10D}pdp10_mdfp.c \ - ${PDP10D}pdp10_pag.c ${PDP10D}pdp10_rp.c ${PDP10D}pdp10_sys.c \ - ${PDP10D}pdp10_tim.c ${PDP10D}pdp10_tu.c ${PDP10D}pdp10_xtnd.c \ - ${PDP10D}pdp10_pt.c ${PDP11D}pdp11_ry.c -PDP10_OPT = -DUSE_INT64 -I ${PDP10D} -I ${PDP11D} -I ${VAXD} - - - -PDP8D = PDP8/ -PDP8 = ${PDP8D}pdp8_cpu.c ${PDP8D}pdp8_clk.c ${PDP8D}pdp8_df.c \ - ${PDP8D}pdp8_dt.c ${PDP8D}pdp8_lp.c ${PDP8D}pdp8_mt.c \ - ${PDP8D}pdp8_pt.c ${PDP8D}pdp8_rf.c ${PDP8D}pdp8_rk.c \ - ${PDP8D}pdp8_rx.c ${PDP8D}pdp8_sys.c ${PDP8D}pdp8_tt.c \ - ${PDP8D}pdp8_ttx.c ${PDP8D}pdp8_rl.c -PDP8_OPT = -I ${PDP8D} - - - -H316D = H316/ -H316 = ${H316D}h316_stddev.c ${H316D}h316_lp.c ${H316D}h316_cpu.c \ - ${H316D}h316_sys.c -H316_OPT = -I ${H316D} - - - -HP2100D = HP2100/ -HP2100 = ${HP2100D}hp2100_stddev.c ${HP2100D}hp2100_dp.c ${HP2100D}hp2100_dq.c \ - ${HP2100D}hp2100_dr.c ${HP2100D}hp2100_lps.c ${HP2100D}hp2100_ms.c \ - ${HP2100D}hp2100_mt.c ${HP2100D}hp2100_mux.c ${HP2100D}hp2100_cpu.c \ - ${HP2100D}hp2100_fp.c ${HP2100D}hp2100_sys.c ${HP2100D}hp2100_lpt.c -HP2100_OPT = -I ${HP2100D} - - - -I1401D = I1401/ -I1401 = ${I1401D}i1401_lp.c ${I1401D}i1401_cpu.c ${I1401D}i1401_iq.c \ - ${I1401D}i1401_cd.c ${I1401D}i1401_mt.c ${I1401D}i1401_dp.c \ - ${I1401D}i1401_sys.c -I1401_OPT = -I ${I1401D} - - - -I1620D = I1620/ -I1620 = ${I1620D}i1620_cd.c ${I1620D}i1620_dp.c ${I1620D}i1620_pt.c \ - ${I1620D}i1620_tty.c ${I1620D}i1620_cpu.c ${I1620D}i1620_lp.c \ - ${I1620D}i1620_fp.c ${I1620D}i1620_sys.c -I1620_OPT = -I ${I1620D} - - - -IBM1130D = Ibm1130/ -IBM1130 = ${IBM1130D}ibm1130_cpu.c ${IBM1130D}ibm1130_cr.c \ - ${IBM1130D}ibm1130_disk.c ${IBM1130D}ibm1130_stddev.c \ - ${IBM1130D}ibm1130_sys.c ${IBM1130D}ibm1130_gdu.c \ - ${IBM1130D}ibm1130_gui.c ${IBM1130D}ibm1130_prt.c -IBM1130_OPT = -I ${IBM1130D} - - - -ID16D = Interdata/ -ID16 = ${ID16D}id16_cpu.c ${ID16D}id16_sys.c ${ID16D}id_dp.c \ - ${ID16D}id_fd.c ${ID16D}id_fp.c ${ID16D}id_idc.c ${ID16D}id_io.c \ - ${ID16D}id_lp.c ${ID16D}id_mt.c ${ID16D}id_pas.c ${ID16D}id_pt.c \ - ${ID16D}id_tt.c ${ID16D}id_uvc.c -ID16_OPT = -I ${ID16D} - - - -ID32D = Interdata/ -ID32 = ${ID32D}id32_cpu.c ${ID32D}id32_sys.c ${ID32D}id_dp.c \ - ${ID32D}id_fd.c ${ID32D}id_fp.c ${ID32D}id_idc.c ${ID32D}id_io.c \ - ${ID32D}id_lp.c ${ID32D}id_mt.c ${ID32D}id_pas.c ${ID32D}id_pt.c \ - ${ID32D}id_tt.c ${ID32D}id_uvc.c -ID32_OPT = -I ${ID32D} - - - -S3D = S3/ -S3 = ${S3D}s3_cd.c ${S3D}s3_cpu.c ${S3D}s3_disk.c ${S3D}s3_lp.c \ - ${S3D}s3_pkb.c ${S3D}s3_sys.c -S3_OPT = -I ${S3D} - - - -ALTAIRD = ALTAIR/ -ALTAIR = ${ALTAIRD}altair_sio.c ${ALTAIRD}altair_cpu.c ${ALTAIRD}altair_dsk.c \ - ${ALTAIRD}altair_sys.c -ALTAIR_OPT = -I ${ALTAIRD} - - - -ALTAIRZ80D = AltairZ80/ -ALTAIRZ80 = ${ALTAIRZ80D}altairz80_cpu.c ${ALTAIRZ80D}altairz80_dsk.c \ - ${ALTAIRZ80D}altairz80_sio.c ${ALTAIRZ80D}altairz80_sys.c \ - ${ALTAIRZ80D}altairz80_hdsk.c -ALTAIRZ80_OPT = -I ${ALTAIRZ80D} - - - -GRID = GRI/ -GRI = ${GRID}gri_cpu.c ${GRID}gri_stddev.c ${GRID}gri_sys.c -GRI_OPT = -I ${GRID} - - - -SDSD = SDS/ -SDS = ${SDSD}sds_cpu.c ${SDSD}sds_drm.c ${SDSD}sds_dsk.c ${SDSD}sds_io.c \ - ${SDSD}sds_lp.c ${SDSD}sds_mt.c ${SDSD}sds_mux.c ${SDSD}sds_rad.c \ - ${SDSD}sds_stddev.c ${SDSD}sds_sys.c -SDS_OPT = -I ${SDSD} - - - -# -# Build everything -# -all : ${BIN}pdp1 ${BIN}pdp4 ${BIN}pdp7 ${BIN}pdp8 ${BIN}pdp9 ${BIN}pdp15 \ - ${BIN}pdp11 ${BIN}pdp10 ${BIN}vax ${BIN}nova ${BIN}eclipse ${BIN}h316 \ - ${BIN}hp2100 ${BIN}i1401 ${BIN}i1620 ${BIN}s3 ${BIN}altair \ - ${BIN}altairz80 ${BIN}gri ${BIN}i1620 ${BIN}ibm1130 \ - ${BIN}id16 ${BIN}id32 ${BIN}sds - - - -# -# Individual builds -# -${BIN}pdp1 : ${PDP1} ${SIM} - ${CC} ${PDP1} ${SIM} ${PDP1_OPT} -o $@ - - - -${BIN}pdp4 : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP4_OPT} -o $@ - - - -${BIN}pdp7 : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP7_OPT} -o $@ - - - -${BIN}pdp8 : ${PDP8} ${SIM} - ${CC} ${PDP8} ${SIM} ${PDP8_OPT} -o $@ - - - -${BIN}pdp9 : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP9_OPT} -o $@ - - - -${BIN}pdp15 : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP15_OPT} -o $@ - - - -${BIN}pdp10 : ${PDP10} ${SIM} - ${CC} ${PDP10} ${SIM} ${PDP10_OPT} -o $@ - - - -${BIN}pdp11 : ${PDP11} ${SIM} - ${CC} ${PDP11} ${SIM} ${PDP11_OPT} -o $@ - - - -${BIN}vax : ${VAX} ${SIM} - ${CC} ${VAX} ${SIM} ${VAX_OPT} -o $@ - - - -${BIN}nova : ${NOVA} ${SIM} - ${CC} ${NOVA} ${SIM} ${NOVA_OPT} -o $@ - - - -${BIN}eclipse : ${ECLIPSE} ${SIM} - ${CC} ${ECLIPSE} ${SIM} ${ECLIPSE_OPT} -o $@ - - - -${BIN}h316 : ${H316} ${SIM} - ${CC} ${H316} ${SIM} ${H316_OPT} -o $@ - - - -${BIN}hp2100 : ${HP2100} ${SIM} - ${CC} ${HP2100} ${SIM} ${HP2100_OPT} -o $@ - - - -${BIN}i1401 : ${I1401} ${SIM} - ${CC} ${I1401} ${SIM} ${I1401_OPT} -o $@ - - - -${BIN}i1620 : ${I1620} ${SIM} - ${CC} ${I1620} ${SIM} ${I1620_OPT} -o $@ - - -${BIN}ibm1130 : ${IBM1130} - ${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} -o $@ - - -${BIN}s3 : ${S3} ${SIM} - ${CC} ${S3} ${SIM} ${S3_OPT} -o $@ - - -${BIN}altair : ${ALTAIR} ${SIM} - ${CC} ${ALTAIR} ${SIM} ${ALTAIR_OPT} -o $@ - - -${BIN}altairz80 : ${ALTAIRZ80} ${SIM} ${ALTAIRZ80D}altairZ80_defs.h - ${CC} ${ALTAIRZ80_OPT} ${ALTAIRZ80} ${SIM} -o $@ -${ALTAIRZ80D}altairZ80_defs.h : ${ALTAIRZ80D}altairz80_defs.h - cp ${ALTAIRZ80D}altairz80_defs.h ${ALTAIRZ80D}altairZ80_defs.h - -${BIN}gri : ${GRI} ${SIM} - ${CC} ${GRI} ${SIM} ${GRI_OPT} -o $@ - -${BIN}id16 : ${ID16} ${SIM} - ${CC} ${ID16} ${SIM} ${ID16_OPT} -o $@ - -${BIN}id32 : ${ID32} ${SIM} - ${CC} ${ID32} ${SIM} ${ID32_OPT} -o $@ - -${BIN}sds : ${SDS} ${SIM} - ${CC} ${SDS} ${SIM} ${SDS_OPT} -o $@ - - diff --git a/scp.c b/scp.c index 021ffbbd..35dba2de 100644 --- a/scp.c +++ b/scp.c @@ -1,6 +1,6 @@ /* scp.c: simulator control program - Copyright (c) 1993-2002, Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,12 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 14-Jan-03 RMS Added missing function prototypes + 10-Jan-03 RMS Added attach/restore flag, dynamic memory size support, + case sensitive SET options + 22-Dec-02 RMS Added ! (OS command) feature (from Mark Pizzolato) + 17-Dec-02 RMS Added get_ipaddr + 02-Dec-02 RMS Added EValuate command 16-Nov-02 RMS Fixed bug in register name match algorithm 13-Oct-02 RMS Fixed Borland compiler warnings (found by Hans Pufal) 05-Oct-02 RMS Fixed bugs in set_logon, ssh_break (found by David Hittner) @@ -123,7 +129,6 @@ #define RU_CONT 3 /* continue */ #define RU_BOOT 4 /* boot */ -#define SWHIDE (1u << 26) /* enable hiding */ #define SRBSIZ 1024 /* save/restore buffer */ #define SIM_BRK_INILNT 16384 /* bpt tbl length */ #define SIM_BRK_ALLTYP 0xFFFFFFFF @@ -218,7 +223,6 @@ extern t_stat ttclose (void); extern t_stat sim_os_poll_kbd (void); extern t_stat sim_os_putchar (int32 out); extern uint32 sim_os_msec (void); -extern int sim_os_sleep (unsigned int sec); /* Prototypes */ @@ -250,12 +254,16 @@ t_stat show_unit (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag); t_stat show_all_mods (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flg); t_stat show_one_mod (FILE *st, DEVICE *dptr, UNIT *uptr, MTAB *mptr, int32 flag); t_stat sim_check_console (int32 sec); +char *get_glyph_gen (char *iptr, char *optr, char mchar, t_bool uc); +t_bool match_ext (char *fnam, char *ext); int32 get_switches (char *cptr); t_value get_rval (REG *rptr, int32 idx); void put_rval (REG *rptr, int32 idx, t_value val); t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr); t_value strtotv (char *inptr, char **endptr, int32 radix); -void fprint_stopped (FILE *stream, t_stat r); +void fprint_help (FILE *st); +void fprint_stopped (FILE *st, t_stat r); +void fprint_capac (FILE *st, DEVICE *dptr, UNIT *uptr); char *read_line (char *ptr, int32 size, FILE *stream); CTAB *find_ctab (CTAB *tab, char *gbuf); CTAB *find_cmd (char *gbuf); @@ -266,6 +274,10 @@ t_bool restore_skip_val (FILE *rfile); t_bool qdisable (DEVICE *dptr); t_stat attach_err (UNIT *uptr, t_stat stat); t_stat detach_all (int32 start_device, t_bool shutdown); +t_stat exdep_reg_loop (FILE *ofile, SCHTAB *schptr, int flag, char *cptr, + REG *lowr, REG *highr, t_addr lows, t_addr highs); +t_stat exdep_addr_loop (FILE *ofile, SCHTAB *schptr, int flag, char *cptr, + t_addr low, t_addr high, DEVICE *dptr, UNIT *uptr); t_stat ex_reg (FILE *ofile, t_value val, int32 flag, REG *rptr, t_addr idx); t_stat dep_reg (int32 flag, char *cptr, REG *rptr, t_addr idx); t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr); @@ -276,9 +288,13 @@ char *get_range (char *cptr, t_addr *lo, t_addr *hi, int32 rdx, SCHTAB *get_search (char *cptr, DEVICE *dptr, SCHTAB *schptr); int32 test_search (t_value val, SCHTAB *schptr); t_stat step_svc (UNIT *ptr); +void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *do_arg[]); +BRKTAB *sim_brk_fnd (t_addr loc); +BRKTAB *sim_brk_new (t_addr loc); t_stat reset_cmd (int32 flag, char *ptr); t_stat exdep_cmd (int32 flag, char *ptr); +t_stat eval_cmd (int32 flag, char *ptr); t_stat load_cmd (int32 flag, char *ptr); t_stat run_cmd (int32 flag, char *ptr); t_stat attach_cmd (int32 flag, char *ptr); @@ -291,6 +307,7 @@ t_stat show_cmd (int32 flag, char *ptr); t_stat brk_cmd (int32 flag, char *ptr); t_stat do_cmd (int32 flag, char *ptr); t_stat help_cmd (int32 flag, char *ptr); +t_stat spawn_cmd (int32 flag, char *ptr); /* Global data */ @@ -411,6 +428,8 @@ static CTAB cmd_table[] = { "d{eposit} deposit in memory or registers\n" }, { "IDEPOSIT", &exdep_cmd, EX_D+EX_I, "id{eposit} interactive deposit in memory or registers\n" }, + { "EVALUATE", &eval_cmd, 0, + "ev{aluate} evaluate symbolic expression\n" }, { "RUN", &run_cmd, RU_RUN, "ru{n} {new PC} reset and start simulation\n" }, { "GO", &run_cmd, RU_GO, @@ -470,6 +489,9 @@ static CTAB cmd_table[] = { { "HELP", &help_cmd, 0, "h{elp} type this message\n" "h{elp} type help for command\n" }, + { "!", &spawn_cmd, 0, + "! execute local command interpreter\n" + "! execute local host command\n" }, { NULL, NULL, 0 } }; /* Main command loop */ @@ -520,18 +542,18 @@ if (sim_emax <= 0) sim_emax = 1; if ((stat = ttinit ()) != SCPE_OK) { printf ("Fatal terminal initialization error\n%s\n", - scp_error_messages[stat - SCPE_BASE]); + scp_error_messages[stat - SCPE_BASE]); return 0; } if ((sim_eval = calloc (sim_emax, sizeof (t_value))) == NULL) { printf ("Unable to allocate examine buffer\n"); return 0; }; if ((stat = reset_all (0)) != SCPE_OK) { printf ("Fatal simulator initialization error\n%s\n", - scp_error_messages[stat - SCPE_BASE]); + scp_error_messages[stat - SCPE_BASE]); return 0; } if ((stat = sim_brk_init ()) != SCPE_OK) { printf ("Fatal breakpoint table initialization error\n%s\n", - scp_error_messages[stat - SCPE_BASE]); + scp_error_messages[stat - SCPE_BASE]); return 0; } if (!sim_quiet) { printf ("\n"); @@ -540,25 +562,25 @@ if (!sim_quiet) { if (*cbuf) { /* cmd file arg? */ stat = do_cmd (1, cbuf); /* proc cmd file */ if (stat == SCPE_OPENERR) /* error? */ - fprintf (stderr, "Can't open file %s\n", cbuf); } + fprintf (stderr, "Can't open file %s\n", cbuf); } else stat = SCPE_OK; while (stat != SCPE_EXIT) { /* in case exit */ printf ("sim> "); /* prompt */ if (sim_vm_read != NULL) /* sim routine? */ - cptr = (*sim_vm_read) (cbuf, CBUFSIZE, stdin); + cptr = (*sim_vm_read) (cbuf, CBUFSIZE, stdin); else cptr = read_line (cbuf, CBUFSIZE, stdin); /* read command line */ if (cptr == NULL) continue; /* ignore EOF */ if (*cptr == 0) continue; /* ignore blank */ if (sim_log) fprintf (sim_log, "sim> %s\n", cbuf); /* log cmd */ cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ if (cmdp = find_cmd (gbuf)) /* lookup command */ - stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */ + stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */ else stat = SCPE_UNK; if (stat >= SCPE_BASE) { /* error? */ - printf ("%s\n", scp_error_messages[stat - SCPE_BASE]); - if (sim_log) fprintf (sim_log, "%s\n", - scp_error_messages[stat - SCPE_BASE]); } + printf ("%s\n", scp_error_messages[stat - SCPE_BASE]); + if (sim_log) fprintf (sim_log, "%s\n", + scp_error_messages[stat - SCPE_BASE]); } if (sim_vm_post != NULL) (*sim_vm_post) (TRUE); } /* end while */ @@ -609,13 +631,24 @@ if (*cptr) { cptr = get_glyph (cptr, gbuf, 0); if (*cptr) return SCPE_2MARG; if (cmdp = find_cmd (gbuf)) { - printf (cmdp->help); - if (sim_log) fprintf (sim_log, cmdp->help); } + printf (cmdp->help); + if (sim_log) fprintf (sim_log, cmdp->help); } else return SCPE_ARG; } else { fprint_help (stdout); if (sim_log) fprint_help (sim_log); } return SCPE_OK; } + +/* Spawn command */ + +t_stat spawn_cmd (int32 flag, char *cptr) +{ +if ((cptr == NULL) || (strlen(cptr) == 0)) cptr = getenv("SHELL"); +if ((cptr == NULL) || (strlen(cptr) == 0)) cptr = getenv("ComSpec"); +system (cptr); +return SCPE_OK; +} + /* Do command */ @@ -703,7 +736,7 @@ t_stat set_cmd (int32 flag, char *cptr) { int32 lvl; t_stat r; -char gbuf[CBUFSIZE], *cvptr; +char gbuf[CBUFSIZE], *cvptr, *svptr; DEVICE *dptr; UNIT *uptr; MTAB *mptr; @@ -745,7 +778,7 @@ else return SCPE_NXDEV; /* no match */ if (*cptr == 0) return SCPE_2FARG; /* must be more */ while (*cptr != 0) { /* do all mods */ - cptr = get_glyph (cptr, gbuf, ','); /* get modifier */ + cptr = get_glyph (svptr = cptr, gbuf, ','); /* get modifier */ if (cvptr = strchr (gbuf, '=')) *cvptr++ = 0; /* = value? */ for (mptr = dptr->modifiers; mptr && (mptr->mask != 0); mptr++) { if ((mptr->mstring) && /* match string */ @@ -755,6 +788,8 @@ while (*cptr != 0) { /* do all mods */ if ((lvl & MTAB_VUN) && (uptr->flags & UNIT_DIS)) return SCPE_UDIS; /* unit disabled? */ if (mptr->valid) { /* validation rtn? */ + if (cvptr && (mptr->mask & MTAB_NC)) + get_glyph_nc (svptr, gbuf, ','); r = mptr->valid (uptr, mptr->match, cvptr, mptr->desc); if (r != SCPE_OK) return r; } else if (!mptr->desc) break; /* value desc? */ @@ -965,23 +1000,19 @@ if (flag) return SCPE_OK; /* dev only? */ for (j = 0; j < dptr->numunits; j++) { /* loop thru units */ uptr = (dptr->units) + j; if ((uptr->flags & UNIT_DIS) == 0) - show_unit (st, dptr, uptr, ucnt); } + show_unit (st, dptr, uptr, ucnt); } return SCPE_OK; } t_stat show_unit (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag) { -t_addr kval = (uptr->flags & UNIT_BINK)? 1024: 1000; int32 u = uptr - dptr->units; if (flag > 1) fprintf (st, " %s%d", dptr->name, u); else if (flag < 0) fprintf (st, "%s%d", dptr->name, u); if (uptr->flags & UNIT_FIX) { - if (uptr->capac < kval) - fprintf (st, ", %d%s", uptr->capac, - ((dptr->dwidth / dptr->aincr) > 8)? "W": "B"); - else fprintf (st, ", %dK%s", uptr->capac / kval, - ((dptr->dwidth / dptr->aincr) > 8)? "W": "B"); } + fprintf (st, ", "); + fprint_capac (st, dptr, uptr); } if (uptr->flags & UNIT_ATT) { fprintf (st, ", attached to %s", uptr->filename); if (uptr->flags & UNIT_RO) fprintf (st, ", read only"); } @@ -991,6 +1022,17 @@ show_all_mods (st, dptr, uptr, MTAB_VUN); /* show unit mods */ fprintf (st, "\n"); return SCPE_OK; } + +void fprint_capac (FILE *st, DEVICE *dptr, UNIT *uptr) +{ +t_addr kval = (uptr->flags & UNIT_BINK)? 1024: 1000; + +if (uptr->capac < kval) fprintf (st, "%d%s", uptr->capac, + ((dptr->dwidth / dptr->aincr) > 8)? "W": "B"); +else fprintf (st, "%dK%s", uptr->capac / kval, + ((dptr->dwidth / dptr->aincr) > 8)? "W": "B"); +return; +} /* Show processors */ @@ -1024,7 +1066,7 @@ int32 accum; if (cptr && (*cptr != 0)) return SCPE_2MARG; if (sim_clock_queue == NULL) { fprintf (st, "%s event queue empty, time = %-16.0f\n", - sim_name, sim_time); + sim_name, sim_time); return SCPE_OK; } fprintf (st, "%s event queue status, time = %-16.0f\n", sim_name, sim_time); @@ -1032,9 +1074,9 @@ accum = 0; for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) { if (uptr == &step_unit) fprintf (st, " Step timer"); else if ((dptr = find_dev_from_unit (uptr)) != NULL) { - fprintf (st, " %s", dptr->name); - if (dptr->numunits > 1) fprintf (st, " unit %d", - uptr - dptr->units); } + fprintf (st, " %s", dptr->name); + if (dptr->numunits > 1) fprintf (st, " unit %d", + uptr - dptr->units); } else fprintf (st, " Unknown"); fprintf (st, " at %d\n", accum + uptr->time); accum = accum + uptr->time; } @@ -1116,7 +1158,7 @@ else if ((mptr->mask & MTAB_XTD) && (mptr->mask & MTAB_VAL)) { fprintf (st, "%s=", mptr->pstring); val = get_rval (rptr, 0); fprint_val (st, val, rptr->radix, rptr->width, - rptr->flags & REG_FMT); } + rptr->flags & REG_FMT); } else fputs (mptr->pstring, st); if (flag && !((mptr->mask & MTAB_XTD) && (mptr->mask & MTAB_NMO))) fputc ('\n', st); @@ -1216,8 +1258,8 @@ for (i = 0; i < start; i++) { if (sim_devices[i] == NULL) return SCPE_IERR; } for (i = start; (dptr = sim_devices[i]) != NULL; i++) { if (dptr->reset != NULL) { - reason = dptr->reset (dptr); - if (reason != SCPE_OK) return reason; } } + reason = dptr->reset (dptr); + if (reason != SCPE_OK) return reason; } } return SCPE_OK; } @@ -1573,20 +1615,31 @@ for ( ;; ) { /* device loop */ READ_S (buf); /* attached file */ if (buf[0] != 0) { /* any file? */ uptr->flags = uptr->flags & ~UNIT_DIS; + sim_switches = SIM_SW_REST; /* attach/rest */ if (v210 && (flg & UNIT_RO)) /* saved flgs & RO? */ - sim_switches = SWMASK ('R'); /* RO attach */ - else sim_switches = 0; /* no, normal att */ + sim_switches |= SWMASK ('R'); /* RO attach */ if (dptr->attach != NULL) r = dptr->attach (uptr, buf); else r = attach_unit (uptr, buf); if (r != SCPE_OK) return r; } READ_I (high); /* memory capacity */ if (high > 0) { /* [V2.5+] any memory? */ if (((uptr->flags & (UNIT_FIX + UNIT_ATTABLE)) != UNIT_FIX) || - (high > uptr->capac) || (dptr->deposit == NULL)) { - printf ("Invalid memory bound: %s%d = %u\n", - dptr->name, unitno, high); + (dptr->deposit == NULL)) { + printf ("Can't restore memory: %s%d\n", dptr->name, unitno); fclose (rfile); return SCPE_INCOMP; } + if (high != uptr->capac) { + if ((dptr->flags & DEV_DYNM) && + ((dptr->msize == NULL) || + (dptr->msize (uptr, high, NULL, NULL) != SCPE_OK))) { + printf ("Can't change memory size: %s%d\n", + dptr->name, unitno); + fclose (rfile); + return SCPE_INCOMP; } + uptr->capac = high; + printf ("Memory size changed: %s%d = ", dptr->name, unitno); + fprint_capac (stdout, dptr, uptr); + printf ("\n"); } sz = SZ_D (dptr); /* allocate buffer */ if ((mbuf = calloc (SRBSIZ, sz)) == NULL) { fclose (rfile); @@ -1692,9 +1745,10 @@ if (((flag == RU_RUN) || (flag == RU_GO)) && (*cptr != 0)) { /* run or go */ if (flag == RU_STEP) { /* step */ if (*cptr == 0) step = 1; - else { cptr = get_glyph (cptr, gbuf, 0); - step = (int32) get_uint (gbuf, 10, INT_MAX, &r); - if ((r != SCPE_OK) || (step == 0)) return SCPE_ARG; } } + else { + cptr = get_glyph (cptr, gbuf, 0); + step = (int32) get_uint (gbuf, 10, INT_MAX, &r); + if ((r != SCPE_OK) || (step == 0)) return SCPE_ARG; } } if (flag == RU_BOOT) { /* boot */ if (*cptr == 0) return SCPE_2FARG; /* must be more */ @@ -1719,10 +1773,10 @@ if ((flag == RU_RUN) || (flag == RU_BOOT)) { /* run or boot */ if ((r = reset_all (0)) != SCPE_OK) return r; } for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { for (j = 0; j < dptr->numunits; j++) { - uptr = (dptr->units) + j; - if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == - (UNIT_ATT + UNIT_SEQ)) - fseek (uptr->fileref, uptr->pos, SEEK_SET); } } + uptr = (dptr->units) + j; + if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == + (UNIT_ATT + UNIT_SEQ)) + fseek (uptr->fileref, uptr->pos, SEEK_SET); } } stop_cpu = 0; if (signal (SIGINT, int_handler) == SIG_ERR) { /* set WRU */ return SCPE_SIGERR; } @@ -1852,25 +1906,25 @@ uptr = dptr->units; for (;;) { /* loop through modifiers */ if (*cptr == 0) return SCPE_2FARG; /* must be more */ if (*cptr == '@') { /* output file spec? */ - if (flag != EX_E) return SCPE_ARG; /* examine only */ - if (exd2f) { /* already got one? */ - fclose (ofile); /* one per customer */ - return SCPE_ARG; } - cptr = get_glyph_nc (cptr + 1, gbuf, 0); - ofile = FOPEN (gbuf, "a"); /* open for append */ - if (ofile == NULL) return SCPE_OPENERR; - exd2f = TRUE; - continue; } /* look for more */ + if (flag != EX_E) return SCPE_ARG; /* examine only */ + if (exd2f) { /* already got one? */ + fclose (ofile); /* one per customer */ + return SCPE_ARG; } + cptr = get_glyph_nc (cptr + 1, gbuf, 0); + ofile = FOPEN (gbuf, "a"); /* open for append */ + if (ofile == NULL) return SCPE_OPENERR; + exd2f = TRUE; + continue; } /* look for more */ cptr = get_glyph (cptr, gbuf, 0); if ((t = get_switches (gbuf)) != 0) { /* try for switches */ - if (t < 0) return SCPE_INVSW; /* err if bad switch */ - sim_switches = sim_switches | t; } /* or in new switches */ + if (t < 0) return SCPE_INVSW; /* err if bad switch */ + sim_switches = sim_switches | t; } /* or in new switches */ else if (get_search (gbuf, dptr, &stab) != NULL) { /* try for search */ - schptr = &stab; } /* set search */ + schptr = &stab; } /* set search */ else if (((tdptr = find_unit (gbuf, &tuptr)) != NULL) && - (tuptr != NULL)) { /* try for unit */ - dptr = tdptr; /* set as default */ - uptr = tuptr; } + (tuptr != NULL)) { /* try for unit */ + dptr = tdptr; /* set as default */ + uptr = tuptr; } else break; } /* not rec, break out */ if (uptr == NULL) return SCPE_NXUN; /* got a unit? */ if ((*cptr == 0) == (flag == 0)) return SCPE_ARG; /* eol if needed? */ @@ -1880,39 +1934,40 @@ for (gptr = gbuf, reason = SCPE_OK; (*gptr != 0) && (reason == SCPE_OK); gptr = tptr) { tdptr = dptr; /* working dptr */ if (strncmp (gptr, "STATE", strlen ("STATE")) == 0) { - tptr = gptr + strlen ("STATE"); - if (*tptr && (*tptr++ != ',')) return SCPE_ARG; - if ((lowr = dptr->registers) == NULL) return SCPE_NXREG; - for (highr = lowr; highr->name != NULL; highr++) ; - sim_switches = sim_switches | SWHIDE; - reason = exdep_reg_loop (ofile, schptr, flag, cptr, - lowr, --highr, 0, 0); - continue; } + tptr = gptr + strlen ("STATE"); + if (*tptr && (*tptr++ != ',')) return SCPE_ARG; + if ((lowr = dptr->registers) == NULL) return SCPE_NXREG; + for (highr = lowr; highr->name != NULL; highr++) ; + sim_switches = sim_switches | SIM_SW_HIDE; + reason = exdep_reg_loop (ofile, schptr, flag, cptr, + lowr, --highr, 0, 0); + continue; } if ((lowr = find_reg (gptr, &tptr, tdptr)) || (lowr = find_reg_glob (gptr, &tptr, &tdptr))) { - low = high = 0; - if ((*tptr == '-') || (*tptr == ':')) { - highr = find_reg (tptr + 1, &tptr, tdptr); - if (highr == NULL) return SCPE_NXREG; } - else { highr = lowr; - if (*tptr == '[') { - if (lowr->depth <= 1) return SCPE_ARG; - tptr = get_range (tptr + 1, &low, &high, - 10, lowr->depth - 1, ']'); - if (tptr == NULL) return SCPE_ARG; } } - if (*tptr && (*tptr++ != ',')) return SCPE_ARG; - reason = exdep_reg_loop (ofile, schptr, flag, cptr, - lowr, highr, low, high); - continue; } + low = high = 0; + if ((*tptr == '-') || (*tptr == ':')) { + highr = find_reg (tptr + 1, &tptr, tdptr); + if (highr == NULL) return SCPE_NXREG; } + else { + highr = lowr; + if (*tptr == '[') { + if (lowr->depth <= 1) return SCPE_ARG; + tptr = get_range (tptr + 1, &low, &high, + 10, lowr->depth - 1, ']'); + if (tptr == NULL) return SCPE_ARG; } } + if (*tptr && (*tptr++ != ',')) return SCPE_ARG; + reason = exdep_reg_loop (ofile, schptr, flag, cptr, + lowr, highr, low, high); + continue; } tptr = get_range (gptr, &low, &high, dptr->aradix, - (((uptr->capac == 0) || (flag == EX_E))? 0: - uptr->capac - dptr->aincr), 0); + (((uptr->capac == 0) || (flag == EX_E))? 0: + uptr->capac - dptr->aincr), 0); if (tptr == NULL) return SCPE_ARG; if (*tptr && (*tptr++ != ',')) return SCPE_ARG; reason = exdep_addr_loop (ofile, schptr, flag, cptr, low, high, - dptr, uptr); + dptr, uptr); } /* end for */ if (exd2f) fclose (ofile); /* close output file */ return reason; @@ -1935,20 +1990,20 @@ REG *rptr; if ((lowr == NULL) || (highr == NULL)) return SCPE_IERR; if (lowr > highr) return SCPE_ARG; for (rptr = lowr; rptr <= highr; rptr++) { - if ((sim_switches & SWHIDE) && + if ((sim_switches & SIM_SW_HIDE) && (rptr->flags & REG_HIDDEN)) continue; for (idx = lows; idx <= highs; idx++) { - if (idx >= (t_addr) rptr->depth) return SCPE_SUB; - val = get_rval (rptr, idx); - if (schptr && !test_search (val, schptr)) continue; - if (flag != EX_D) { - reason = ex_reg (ofile, val, flag, rptr, idx); - if (reason != SCPE_OK) return reason; - if (sim_log && (ofile == stdout)) - ex_reg (sim_log, val, flag, rptr, idx); } - if (flag != EX_E) { - reason = dep_reg (flag, cptr, rptr, idx); - if (reason != SCPE_OK) return reason; } } } + if (idx >= (t_addr) rptr->depth) return SCPE_SUB; + val = get_rval (rptr, idx); + if (schptr && !test_search (val, schptr)) continue; + if (flag != EX_D) { + reason = ex_reg (ofile, val, flag, rptr, idx); + if (reason != SCPE_OK) return reason; + if (sim_log && (ofile == stdout)) + ex_reg (sim_log, val, flag, rptr, idx); } + if (flag != EX_E) { + reason = dep_reg (flag, cptr, rptr, idx); + if (reason != SCPE_OK) return reason; } } } return SCPE_OK; } @@ -1966,13 +2021,13 @@ for (i = low; i <= high; i = i + (dptr->aincr)) { if (reason != SCPE_OK) return reason; /* return if error */ if (schptr && !test_search (sim_eval[0], schptr)) continue; if (flag != EX_D) { - reason = ex_addr (ofile, flag, i, dptr, uptr); - if (reason > SCPE_OK) return reason; - if (sim_log && (ofile == stdout)) - ex_addr (sim_log, flag, i, dptr, uptr); } + reason = ex_addr (ofile, flag, i, dptr, uptr); + if (reason > SCPE_OK) return reason; + if (sim_log && (ofile == stdout)) + ex_addr (sim_log, flag, i, dptr, uptr); } if (flag != EX_E) { - reason = dep_addr (flag, cptr, i, dptr, uptr, reason); - if (reason > SCPE_OK) return reason; } + reason = dep_addr (flag, cptr, i, dptr, uptr, reason); + if (reason > SCPE_OK) return reason; } if (reason < SCPE_OK) i = i - (reason * dptr->aincr); } return SCPE_OK; } @@ -2177,26 +2232,28 @@ mask = width_mask[dptr->dwidth]; for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; for (i = 0, j = addr; i < sim_emax; i++, j = j + dptr->aincr) { if (dptr->examine != NULL) { - reason = dptr->examine (&sim_eval[i], j, uptr, sim_switches); - if (reason != SCPE_OK) break; } - else { if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; - if ((uptr->flags & UNIT_FIX) && (j >= uptr->capac)) { - reason = SCPE_NXM; - break; } - sz = SZ_D (dptr); - loc = j / dptr->aincr; - if (uptr->flags & UNIT_BUF) { - SZ_LOAD (sz, sim_eval[i], uptr->filebuf, loc); } - else { fseek (uptr->fileref, sz * loc, SEEK_SET); - fxread (&sim_eval[i], sz, 1, uptr->fileref); - if ((feof (uptr->fileref)) && - !(uptr->flags & UNIT_FIX)) { - reason = SCPE_EOF; - break; } - else if (ferror (uptr->fileref)) { - clearerr (uptr->fileref); - reason = SCPE_IOERR; - break; } } } + reason = dptr->examine (&sim_eval[i], j, uptr, sim_switches); + if (reason != SCPE_OK) break; } + else { + if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; + if ((uptr->flags & UNIT_FIX) && (j >= uptr->capac)) { + reason = SCPE_NXM; + break; } + sz = SZ_D (dptr); + loc = j / dptr->aincr; + if (uptr->flags & UNIT_BUF) { + SZ_LOAD (sz, sim_eval[i], uptr->filebuf, loc); } + else { + fseek (uptr->fileref, sz * loc, SEEK_SET); + fxread (&sim_eval[i], sz, 1, uptr->fileref); + if ((feof (uptr->fileref)) && + !(uptr->flags & UNIT_FIX)) { + reason = SCPE_EOF; + break; } + else if (ferror (uptr->fileref)) { + clearerr (uptr->fileref); + reason = SCPE_IOERR; + break; } } } sim_eval[i] = sim_eval[i] & mask; } if ((reason != SCPE_OK) && (i == 0)) return reason; return SCPE_OK; @@ -2244,24 +2301,60 @@ count = 1 - reason; for (i = 0, j = addr; i < count; i++, j = j + dptr->aincr) { sim_eval[i] = sim_eval[i] & mask; if (dptr->deposit != NULL) { - r = dptr->deposit (sim_eval[i], j, uptr, sim_switches); - if (r != SCPE_OK) return r; } - else { if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; - if ((uptr->flags & UNIT_FIX) && (j >= uptr->capac)) - return SCPE_NXM; - sz = SZ_D (dptr); - loc = j / dptr->aincr; - if (uptr->flags & UNIT_BUF) { - SZ_STORE (sz, sim_eval[i], uptr->filebuf, loc); - if (loc >= uptr->hwmark) uptr->hwmark = loc + 1; } - else { fseek (uptr->fileref, sz * loc, SEEK_SET); - fxwrite (sim_eval, sz, 1, uptr->fileref); - if (ferror (uptr->fileref)) { - clearerr (uptr->fileref); - return SCPE_IOERR; } } } } + r = dptr->deposit (sim_eval[i], j, uptr, sim_switches); + if (r != SCPE_OK) return r; } + else { + if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; + if ((uptr->flags & UNIT_FIX) && (j >= uptr->capac)) + return SCPE_NXM; + sz = SZ_D (dptr); + loc = j / dptr->aincr; + if (uptr->flags & UNIT_BUF) { + SZ_STORE (sz, sim_eval[i], uptr->filebuf, loc); + if (loc >= uptr->hwmark) uptr->hwmark = loc + 1; } + else { + fseek (uptr->fileref, sz * loc, SEEK_SET); + fxwrite (sim_eval, sz, 1, uptr->fileref); + if (ferror (uptr->fileref)) { + clearerr (uptr->fileref); + return SCPE_IOERR; } } } } return reason; } +/* Evaluate command */ + +t_stat eval_cmd (int32 flg, char *cptr) +{ +char gbuf[CBUFSIZE]; +DEVICE *dptr = sim_devices[0]; +int32 i, count, rdx; +t_stat r; + +GET_SWITCHES (cptr, gbuf); +GET_RADIX (rdx, dptr->dradix); +for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; +if (*cptr == 0) return SCPE_2FARG; +if ((r = parse_sym (cptr, 0, dptr->units, sim_eval, sim_switches)) > 0) { + sim_eval[0] = get_uint (cptr, rdx, width_mask[dptr->dwidth], &r); + if (r != SCPE_OK) return r; } +count = 1 - r; +for (i = 0; count > 0; i++, count = count - dptr->aincr) { + printf ("%d:\t", i); + if ((r = fprint_sym (stdout, 0, &sim_eval[i], dptr->units, sim_switches)) > 0) + r = fprint_val (stdout, sim_eval[i], rdx, dptr->dwidth, PV_RZRO); + printf ("\n"); + if (sim_log) { + fprintf (sim_log, "%d\t", i); + if ((r = fprint_sym (sim_log, 0, &sim_eval[i], dptr->units, sim_switches)) > 0) + r = fprint_val (sim_log, sim_eval[i], rdx, dptr->dwidth, PV_RZRO); + fprintf (sim_log, "\n"); } + if (r < 0) { + i = i - r; + count = count + (r * dptr->aincr); } + } +return SCPE_OK; +} + /* String processing routines read_line read line @@ -2395,16 +2488,62 @@ else { errno = 0; *lo = strtoul (cptr, &tptr, rdx); /* get low */ if (errno || (cptr == tptr)) return NULL; /* error? */ if ((*tptr == '-') || (*tptr == ':') || (*tptr == '/')) { - if (*tptr == '/') hb = *lo; /* relative? */ - cptr = tptr + 1; - errno = 0; - *hi = hb + strtoul (cptr, &tptr, rdx); /* get high */ - if (errno || (cptr == tptr)) return NULL; - if (*lo > *hi) return NULL; } + if (*tptr == '/') hb = *lo; /* relative? */ + cptr = tptr + 1; + errno = 0; + *hi = hb + strtoul (cptr, &tptr, rdx); /* get high */ + if (errno || (cptr == tptr)) return NULL; + if (*lo > *hi) return NULL; } else *hi = *lo; } if (term && (*tptr++ != term)) return NULL; return tptr; } + +/* get_ipaddr IP address:port + + Inputs: + cptr = pointer to input string + Outputs: + ipa = pointer to IP address (may be NULL), 0 = none + ipp = pointer to IP port (may be NULL) + result = status +*/ + +t_stat get_ipaddr (char *cptr, uint32 *ipa, uint32 *ipp) +{ +char gbuf[CBUFSIZE]; +char *addrp, *portp, *octetp; +uint32 i, addr, port, octet; +t_stat r; + +if ((cptr == NULL) || (*cptr == 0) || (ipa == NULL) || (ipp == NULL)) + return SCPE_ARG; +strncpy (gbuf, cptr, CBUFSIZE); +addrp = gbuf; /* default addr */ +if (portp = strchr (gbuf, ':')) *portp++ = '.'; /* x:y? */ +else if (strchr (gbuf, '.')) portp = NULL; /* x.y...? */ +else { portp = gbuf; /* port only */ + addrp = NULL; } /* x is port */ +if (portp) { /* port string? */ + port = (int32) get_uint (portp, 10, 65535, &r); + if ((r != SCPE_OK) || (port == 0)) return SCPE_ARG; + *ipp = port; } +else *ipp = 0; +if (addrp) { + for (i = addr = 0; i < 4; i++) { + octetp = strchr (addrp, '.'); + if (octetp == NULL) return SCPE_ARG; + *octetp++ = 0; + octet = (int32) get_uint (addrp, 10, 255, &r); + if (r != SCPE_OK) return SCPE_ARG; + addr = (addr << 8) | octet; + addrp = octetp; } + if (((addr & 0377) == 0) || ((addr & 0377) == 255)) + return SCPE_ARG; + *ipa = addr; } +else *ipa = 0; +return SCPE_OK; +} /* Find_device find device matching input string @@ -2444,9 +2583,9 @@ DEVICE *dptr; if (uptr == NULL) return NULL; /* arg error? */ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* exact match? */ if (strcmp (cptr, dptr->name) == 0) { - if (qdisable (dptr)) return NULL; /* disabled? */ - *uptr = dptr->units; /* unit 0 */ - return dptr; } } + if (qdisable (dptr)) return NULL; /* disabled? */ + *uptr = dptr->units; /* unit 0 */ + return dptr; } } for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* base + unit#? */ if ((dptr->numunits == 0) || /* no units? */ @@ -2477,7 +2616,7 @@ int32 i, j; if (uptr == NULL) return NULL; for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { for (j = 0; j < dptr->numunits; j++) { - if (uptr == (dptr->units + j)) return dptr; } } + if (uptr == (dptr->units + j)) return dptr; } } return NULL; } @@ -2508,9 +2647,9 @@ REG *rptr, *srptr = NULL; for (i = 0; (dptr = sim_devices[i]) != 0; i++) { /* all dev */ if (rptr = find_reg (cptr, optr, dptr)) { /* found? */ - if (srptr) return NULL; /* ambig? err */ - srptr = rptr; /* save reg */ - *gdptr = dptr; } } /* save unit */ + if (srptr) return NULL; /* ambig? err */ + srptr = rptr; /* save reg */ + *gdptr = dptr; } } /* save unit */ return srptr; } @@ -2540,8 +2679,8 @@ slnt = tptr - cptr; for (rptr = dptr->registers; rptr->name != NULL; rptr++) { if ((slnt == strlen (rptr->name)) && (strncmp (cptr, rptr->name, slnt) == 0)) { - if (optr != NULL) *optr = tptr; - return rptr; } } + if (optr != NULL) *optr = tptr; + return rptr; } } return NULL; } @@ -2600,18 +2739,18 @@ const char logstr[] = "|&^", cmpstr[] = "=!><"; if (*cptr == 0) return NULL; /* check for clause */ for (logop = cmpop = -1; c = *cptr++; ) { /* loop thru clauses */ if (sptr = strchr (logstr, c)) { /* check for mask */ - logop = sptr - logstr; - logval = strtotv (cptr, &tptr, dptr->dradix); - if (cptr == tptr) return NULL; - cptr = tptr; } + logop = sptr - logstr; + logval = strtotv (cptr, &tptr, dptr->dradix); + if (cptr == tptr) return NULL; + cptr = tptr; } else if (sptr = strchr (cmpstr, c)) { /* check for bool */ - cmpop = sptr - cmpstr; - if (*cptr == '=') { - cmpop = cmpop + strlen (cmpstr); - cptr++; } - cmpval = strtotv (cptr, &tptr, dptr->dradix); - if (cptr == tptr) return NULL; - cptr = tptr; } + cmpop = sptr - cmpstr; + if (*cptr == '=') { + cmpop = cmpop + strlen (cmpstr); + cptr++; } + cmpval = strtotv (cptr, &tptr, dptr->dradix); + if (cptr == tptr) return NULL; + cptr = tptr; } else return NULL; } /* end while */ if (logop >= 0) { schptr->logic = logop; @@ -2730,9 +2869,9 @@ if (format != PV_LEFT) { wtest = owtest = radix; ndigits = 1; while ((wtest < width_mask[width]) && (wtest >= owtest)) { - owtest = wtest; - wtest = wtest * radix; - ndigits = ndigits + 1; } + owtest = wtest; + wtest = wtest * radix; + ndigits = ndigits + 1; } if ((MAX_WIDTH - ndigits) < d) d = MAX_WIDTH - ndigits; } if (fputs (&dbuf[d], stream) == EOF) return SCPE_IOERR; return SCPE_OK; @@ -2848,9 +2987,9 @@ UPDATE_SIM_TIME (sim_clock_queue->time); /* update sim time */ nptr = NULL; if (sim_clock_queue == uptr) nptr = sim_clock_queue = uptr->next; else { for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr->next) { - if (cptr->next == uptr) { - nptr = cptr->next = uptr->next; - break; } } } /* end queue scan */ + if (cptr->next == uptr) { + nptr = cptr->next = uptr->next; + break; } } } /* end queue scan */ if (nptr != NULL) nptr->time = nptr->time + uptr->time; uptr->next = NULL; /* hygiene */ uptr->time = 0; @@ -2956,8 +3095,8 @@ for (i = nbuf; i > 0; i--) { if (c == 0) return total; total = total + c; for (j = 0, sptr = sim_flip; j < c; j++) { - for (k = size - 1; k >= 0; k--) *(dptr + k) = *sptr++; - dptr = dptr + size; } } + for (k = size - 1; k >= 0; k--) *(dptr + k) = *sptr++; + dptr = dptr + size; } } return total; } @@ -2980,8 +3119,8 @@ sptr = bptr; /* init input ptr */ for (i = nbuf; i > 0; i--) { c = (i == 1)? lcnt: nelem; for (j = 0, dptr = sim_flip; j < c; j++) { - for (k = size - 1; k >= 0; k--) *(dptr + k) = *sptr++; - dptr = dptr + size; } + for (k = size - 1; k >= 0; k--) *(dptr + k) = *sptr++; + dptr = dptr + size; } c = fwrite (sim_flip, size, c, fptr); if (c == 0) return total; total = total + c; } @@ -3004,6 +3143,7 @@ extern t_bool rtc_avail; int32 sim_rtcn_init (int32 time, int32 tmr) { +if (time == 0) time = 1; if ((tmr < 0) || (tmr >= SIM_NTIMERS)) return time; rtc_rtime[tmr] = sim_os_msec (); rtc_vtime[tmr] = rtc_rtime[tmr]; @@ -3133,7 +3273,7 @@ if (sim_brk_ent >= sim_brk_lnt) return NULL; if (sim_brk_ins != sim_brk_ent) { /* move needed? */ for (bp = sim_brk_tab + sim_brk_ent; bp > sim_brk_tab + sim_brk_ins; bp--) - *bp = *(bp - 1); } + *bp = *(bp - 1); } bp = sim_brk_tab + sim_brk_ins; bp->addr = loc; bp->typ = 0; @@ -3208,9 +3348,9 @@ fprint_val (st, loc, dptr->aradix, dptr->awidth, PV_LEFT); fprintf (st, ":\t"); for (i = any = 0; i < 26; i++) { if ((bp->typ >> i) & 1) { - if (any) fprintf (st, ", "); - fputc (i + 'A', st); - any = 1; } } + if (any) fprintf (st, ", "); + fputc (i + 'A', st); + any = 1; } } if (bp->cnt > 0) fprintf (st, " [%d]", bp->cnt); fprintf (st, "\n"); return SCPE_OK; @@ -3290,7 +3430,7 @@ if (sim_con_tmxr.master == 0) else if (sim_con_ldsc.conn == 0) fprintf (st, "Listening on port %d\n", sim_con_tmxr.port); else { fprintf (st, "Listening on port %d, connected to socket %d\n", - sim_con_tmxr.port, sim_con_ldsc.conn); + sim_con_tmxr.port, sim_con_ldsc.conn); tmxr_fconns (st, &sim_con_ldsc, -1); tmxr_fstats (st, &sim_con_ldsc, -1); } return SCPE_OK; @@ -3308,16 +3448,16 @@ if (sim_con_ldsc.conn) { /* connected? */ if (sim_con_ldsc.conn) return SCPE_OK; } /* still connected? */ for (i = 0; i < sec; i++) { /* loop */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */ - sim_con_ldsc.rcve = 1; /* rcv enabled */ - if (i) { /* if delayed */ - printf ("Running\n"); /* print transition */ - fflush (stdout); } - return SCPE_OK; } /* ready to proceed */ + sim_con_ldsc.rcve = 1; /* rcv enabled */ + if (i) { /* if delayed */ + printf ("Running\n"); /* print transition */ + fflush (stdout); } + return SCPE_OK; } /* ready to proceed */ c = sim_os_poll_kbd (); /* check for stop char */ if ((c == SCPE_STOP) || stop_cpu) return SCPE_STOP; if ((i % 10) == 0) { /* Status every 10 sec */ - printf ("Waiting for console Telnet connnection\n"); - fflush (stdout); } + printf ("Waiting for console Telnet connnection\n"); + fflush (stdout); } sim_os_sleep (1); /* wait 1 second */ } return SCPE_TTMO; /* timed out */ @@ -3335,7 +3475,7 @@ if ((c == SCPE_STOP) || (sim_con_tmxr.master == 0)) /* ^E or not Telnet? */ if (sim_con_ldsc.conn == 0) return SCPE_LOST; /* no Telnet conn? */ tmxr_poll_rx (&sim_con_tmxr); /* poll for input */ if (c = tmxr_getc_ln (&sim_con_ldsc)) /* any char? */ - return (c & 0377) | SCPE_KFLAG; + return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG; return SCPE_OK; } diff --git a/scp_tty.c b/scp_tty.c index 14b3c1f3..e7936d67 100644 --- a/scp_tty.c +++ b/scp_tty.c @@ -195,8 +195,8 @@ for (i = 0; i < 64; i++) { /* 64b quo */ tod[0] = tod[0] << 1; quo = quo << 1; /* shift quo */ if (htod >= 10000) { /* divd work? */ - htod = htod - 10000; /* subtract */ - quo = quo | 1; } } /* set quo bit */ + htod = htod - 10000; /* subtract */ + quo = quo | 1; } } /* set quo bit */ return quo; } @@ -379,28 +379,28 @@ static void updateCursor(void) { WindowPtr window; window = FrontWindow(); if (SIOUXIsAppWindow(window)) { - GrafPtr savePort; - Point localMouse; - GetPort(&savePort); - SetPort(window); + GrafPtr savePort; + Point localMouse; + GetPort(&savePort); + SetPort(window); #if TARGET_API_MAC_CARBON - GetGlobalMouse(&localMouse); + GetGlobalMouse(&localMouse); #else - localMouse = LMGetMouseLocation(); + localMouse = LMGetMouseLocation(); #endif - GlobalToLocal(&localMouse); - if (PtInRect(localMouse, &(*SIOUXTextWindow->edit)->viewRect) && iBeamCursorH) { - SetCursor(*iBeamCursorH); - } - else { - SetCursor(&qd.arrow); - } - TEIdle(SIOUXTextWindow->edit); - SetPort(savePort); + GlobalToLocal(&localMouse); + if (PtInRect(localMouse, &(*SIOUXTextWindow->edit)->viewRect) && iBeamCursorH) { + SetCursor(*iBeamCursorH); + } + else { + SetCursor(&qd.arrow); + } + TEIdle(SIOUXTextWindow->edit); + SetPort(savePort); } else { - SetCursor(&qd.arrow); - TEIdle(SIOUXTextWindow->edit); + SetCursor(&qd.arrow); + TEIdle(SIOUXTextWindow->edit); } return; } @@ -412,25 +412,25 @@ int ps_kbhit(void) { SIOUXUpdateScrollbar(); while (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | highLevelEventMask | diskEvt, &event)) { - SIOUXHandleOneEvent(&event); + SIOUXHandleOneEvent(&event); } if (SIOUXQuitting) { - exit(1); + exit(1); } if (EventAvail(keyDownMask,&event)) { - c = event.message&charCodeMask; - if ((event.modifiers & cmdKey) && (c > 0x20)) { - GetNextEvent(keyDownMask, &event); - SIOUXHandleOneEvent(&event); - if (SIOUXQuitting) { - exit(1); - } - return false; + c = event.message&charCodeMask; + if ((event.modifiers & cmdKey) && (c > 0x20)) { + GetNextEvent(keyDownMask, &event); + SIOUXHandleOneEvent(&event); + if (SIOUXQuitting) { + exit(1); } - return true; + return false; + } + return true; } else { - return false; + return false; } } @@ -440,22 +440,22 @@ int ps_getch(void) { fflush(stdout); updateCursor(); while(!GetNextEvent(keyDownMask,&event)) { - if (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | - highLevelEventMask | diskEvt, &event)) { - SIOUXUpdateScrollbar(); - SIOUXHandleOneEvent(&event); - } + if (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | + highLevelEventMask | diskEvt, &event)) { + SIOUXUpdateScrollbar(); + SIOUXHandleOneEvent(&event); + } } if (SIOUXQuitting) { - exit(1); + exit(1); } c = event.message&charCodeMask; if ((event.modifiers & cmdKey) && (c > 0x20)) { - SIOUXUpdateMenuItems(); - SIOUXDoMenuChoice(MenuKey(c)); + SIOUXUpdateMenuItems(); + SIOUXDoMenuChoice(MenuKey(c)); } if (SIOUXQuitting) { - exit(1); + exit(1); } return c; } @@ -477,7 +477,7 @@ t_stat ttinit (void) { strcat(title, " Simulator"); title[0] = strlen(title) - 1; /* Pascal string done */ for (i = 0; i <= title[0]; i++) { /* copy to unsigned char */ - ptitle[i] = title[i]; + ptitle[i] = title[i]; } SIOUXSetTitle(ptitle); return SCPE_OK; diff --git a/sim_defs.h b/sim_defs.h index 58a8efb2..6f4e18f2 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -1,6 +1,6 @@ /* sim_defs.h: simulator definitions - Copyright (c) 1993-2002, Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,8 +23,11 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 05-Jan-03 RMS Added hidden switch definitions, device dyn memory support, + parameters for function pointers, case sensitive SET support + 22-Dec-02 RMS Added break flag 08-Oct-02 RMS Increased simulator error code space - Added Telnet errors, + Added Telnet errors Added end of medium support Added help messages to CTAB Added flag and context fields to DEVICE @@ -128,6 +131,11 @@ typedef uint32 t_mtrlnt; /* magtape rec lnt */ #define PATH_MAX 512 #endif #define CBUFSIZE (128 + PATH_MAX) /* string buf size */ + +/* Extended switch definitions (bits >= 26) */ + +#define SIM_SW_HIDE (1u << 26) /* enable hiding */ +#define SIM_SW_REST (1u << 27) /* attach/restore */ /* Simulator status codes @@ -179,7 +187,8 @@ typedef uint32 t_mtrlnt; /* magtape rec lnt */ #define SCPE_MTRLNT (SCPE_BASE + 38) /* tape rec lnt error */ #define SCPE_LOST (SCPE_BASE + 39) /* Telnet conn lost */ #define SCPE_TTMO (SCPE_BASE + 40) /* Telnet conn timeout */ -#define SCPE_KFLAG 01000 /* tti data flag */ +#define SCPE_KFLAG 0010000 /* tti data flag */ +#define SCPE_BREAK 0020000 /* tti break flag */ /* Print value format codes */ @@ -215,25 +224,33 @@ struct device { int32 aincr; /* addr increment */ int32 dradix; /* data radix */ int32 dwidth; /* data width */ - t_stat (*examine)(); /* examine routine */ - t_stat (*deposit)(); /* deposit routine */ - t_stat (*reset)(); /* reset routine */ - t_stat (*boot)(); /* boot routine */ - t_stat (*attach)(); /* attach routine */ - t_stat (*detach)(); /* detach routine */ + t_stat (*examine)(t_value *v, t_addr a, struct unit *up, + int32 sw); /* examine routine */ + t_stat (*deposit)(t_value v, t_addr a, struct unit *up, + int32 sw); /* deposit routine */ + t_stat (*reset)(struct device *dp); /* reset routine */ + t_stat (*boot)(int32 u, struct device *dp); + /* boot routine */ + t_stat (*attach)(struct unit *up, char *cp); + /* attach routine */ + t_stat (*detach)(struct unit *up); /* detach routine */ void *ctxt; /* context */ int32 flags; /* flags */ + t_stat (*msize)(struct unit *up, int32 v, char *cp, void *dp); + /* mem size routine */ }; /* Device flags */ #define DEV_V_DIS 0 /* dev enabled */ #define DEV_V_DISABLE 1 /* dev disable-able */ +#define DEV_V_DYNM 2 /* mem size dynamic */ #define DEV_V_UF 12 /* user flags */ #define DEV_V_RSV 31 /* reserved */ #define DEV_DIS (1 << DEV_V_DIS) #define DEV_DISABLE (1 << DEV_V_DISABLE) +#define DEV_DYNM (1 << DEV_V_DYNM) #define DEV_UFMASK (((1u << DEV_V_RSV) - 1) & ~((1u << DEV_V_UF) - 1)) #define DEV_RFLAGS (DEV_UFMASK|DEV_DIS) /* restored flags */ @@ -249,7 +266,7 @@ struct device { struct unit { struct unit *next; /* next active */ - t_stat (*action)(); /* action routine */ + t_stat (*action)(struct unit *up); /* action routine */ char *filename; /* open file name */ FILE *fileref; /* file reference */ void *filebuf; /* memory buffer */ @@ -322,8 +339,10 @@ struct mtab { int32 match; /* match or max */ char *pstring; /* print string */ char *mstring; /* match string */ - t_stat (*valid)(); /* validation routine */ - t_stat (*disp)(); /* display routine */ + t_stat (*valid)(struct unit *up, int32 v, char *cp, void *dp); + /* validation routine */ + t_stat (*disp)(FILE *st, struct unit *up, int32 v, void *dp); + /* display routine */ void *desc; /* value descriptor */ /* REG * if MTAB_VAL */ /* int * if not */ @@ -334,6 +353,7 @@ struct mtab { #define MTAB_VUN 002 /* valid for unit */ #define MTAB_VAL 004 /* takes a value */ #define MTAB_NMO 010 /* only if named */ +#define MTAB_NC 020 /* no UC conversion */ /* Search table */ @@ -395,6 +415,9 @@ t_stat get_yn (char *ques, t_stat deflt); char *get_glyph (char *iptr, char *optr, char mchar); char *get_glyph_nc (char *iptr, char *optr, char mchar); t_value get_uint (char *cptr, int radix, t_value max, t_stat *status); +char *get_range (char *cptr, t_addr *lo, t_addr *hi, int32 rdx, + t_addr max, char term); +t_stat get_ipaddr (char *cptr, uint32 *ipa, uint32 *ipp); t_value strtotv (char *cptr, char **endptr, int radix); t_stat fprint_val (FILE *stream, t_value val, int32 rdx, int32 wid, int32 fmt); DEVICE *find_dev_from_unit (UNIT *uptr); @@ -406,5 +429,6 @@ int32 sim_rtcn_calb (int32 time, int32 tmr); t_stat sim_poll_kbd (void); t_stat sim_putchar (int32 out); t_bool sim_brk_test (t_addr bloc, int32 btyp); +int sim_os_sleep (unsigned int sec); #endif diff --git a/sim_ether.c b/sim_ether.c index 1005cb43..c5c3978f 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -26,8 +26,46 @@ ------------------------------------------------------------------------------ + This ethernet simulation is based on the PCAP and WinPcap packages. + + PCAP/WinPcap was chosen as the basis for network code since it is the most + "universal" of the various network packages available. Using this style has + allowed rapid network development for the major SIMH platforms. Developing + a network package specifically for SIMH was rejected due to the time required; + the advantage would be a more easily compiled and integrated code set. + + There are various problems associated with use of ethernet networking, which + would be true regardless of the network package used, since there are no + universally accepted networking methods. The most serious of these is getting + the proper networking package loaded onto the system, since most environments + do not come with the network interface packages loaded. + + The second most serious network issue relates to security. The network + simulation needs to simulate operating system level functionality (packet + driving). However, the host network programming interfaces tend to operate at + the user level of functionality, so getting to the full functionality of + the network interface usually requires that the person executing the + network code be a privileged user of the host system. See the PCAP/WinPcap + documentation for the appropriate host platform if unprivileged use of + networking is needed - there may be known workarounds. + + ------------------------------------------------------------------------------ + Modification history: + 15-Jan-03 DTH Corrected PacketGetAdapterNames parameter2 datatype + 26-Dec-02 DTH Merged Mark Pizzolato's enhancements with main source + Added networking documentation + Changed _DEBUG to ETH_DEBUG + 20-Dec-02 MP Added display of packet CRC to the eth_packet_trace. + This helps distinguish packets with identical lengths + and protocols. + 05-Dec-02 MP With the goal of draining the input buffer more rapidly + changed eth_read to call pcap_dispatch repeatedly until + either a timeout returns nothing or a packet allowed by + the filter is seen. This more closely reflects how the + pcap layer will work when the filtering is actually done + by a bpf filter. 31-Oct-02 DTH Added USE_NETWORK conditional Reworked not attached test Added OpenBSD support (from Federico Schwindt) @@ -58,9 +96,8 @@ ------------------------------------------------------------------------------ Work left to do: - 1) Add Asynchronous Packet Writing to WIN32 platform - 2) Addition of other host Operating Systems - 3) Addition of BPF packet filtering for efficiency + 1) Addition of other host Operating Systems (VMS, MAC, etc..) + 2) Possible efficiency increase by using BPF filtering ------------------------------------------------------------------------------ */ @@ -68,6 +105,8 @@ #include "sim_ether.h" +extern FILE *sim_log; + /*============================================================================*/ /* OS-independant ethernet routines */ /*============================================================================*/ @@ -79,15 +118,74 @@ void eth_mac_fmt(ETH_MAC* mac, char* buff) return; } +static const uint32 crcTable[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, + 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, + 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, + 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, + 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, + 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, + 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, + 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, + 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, + 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, + 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, + 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; + +uint32 eth_crc32(uint32 crc, const void* vbuf, size_t len) +{ + const uint32 mask = 0xFFFFFFFF; + const unsigned char* buf = (const unsigned char*)vbuf; + + crc ^= mask; + while (0 != len--) + crc = (crc >> 8) ^ crcTable[ (crc ^ (*buf++)) & 0xFF ]; + return(crc ^ mask); +} + + void eth_packet_trace(ETH_PACK* packet, char* msg) { unsigned char src[20]; unsigned char dst[20]; unsigned short* proto = (unsigned short*) &packet->msg[12]; + uint32 crc = eth_crc32(0, packet->msg, packet->len); eth_mac_fmt((ETH_MAC*)&packet->msg[0], dst); eth_mac_fmt((ETH_MAC*)&packet->msg[6], src); - printf("%s: dst: %s src: %s protocol: %d len: %d\n", - msg, dst, src, *proto, packet->len); + printf("Eth: %s dst: %s src: %s protocol: %d len: %d crc: %X\n", + msg, dst, src, *proto, packet->len, crc); } char* eth_getname(int number, char* name) @@ -130,7 +228,7 @@ int eth_devices (int max, ETH_LIST* dev) /*============================================================================*/ /* WIN32, Linux, NetBSD, and OpenBSD routines */ -/* Uses WinPCAP and libpcap packages */ +/* Uses WinPcap and libpcap packages */ /*============================================================================*/ #include @@ -152,7 +250,7 @@ t_stat eth_open(ETH_DEV* dev, char* name) char errbuf[PCAP_ERRBUF_SIZE]; char temp[1024]; char* savname = name; - int i, num; + int num; /* initialize device */ eth_zero(dev); @@ -169,13 +267,13 @@ t_stat eth_open(ETH_DEV* dev, char* name) } /* attempt to connect device */ + memset(errbuf, 0, sizeof(errbuf)); dev->handle = (void*) pcap_open_live(savname, bufsz, ETH_PROMISC, -1, errbuf); - if (!dev->handle) { /* can't open device */ -#ifdef _DEBUG - printf("pcap_open_live: %s\n", errbuf); -#endif + if (sim_log) fprintf (sim_log, "Eth: pcap_open_live error - %s\n", errbuf); return SCPE_OPENERR; + } else { + if (sim_log) fprintf (sim_log, "Eth: opened %s\n", savname); } /* save name of device */ @@ -183,10 +281,13 @@ t_stat eth_open(ETH_DEV* dev, char* name) strcpy(dev->name, savname); #if defined (__NetBSD__) || defined(__OpenBSD__) - /* tell the kernel that the header is fully-formed when it gets it. - this is required in order to fake the src address. */ - i = 1; - ioctl(pcap_fileno(dev->handle), BIOCSHDRCMPLT, &i); + /* Tell the kernel that the header is fully-formed when it gets it. + This is required in order to fake the src address. + Code is embedded in braces to create a scope for the local variable */ + { + int one = 1; + ioctl(pcap_fileno(dev->handle), BIOCSHDRCMPLT, &one); + } #endif /* __NetBSD__ || __OpenBSD__ */ #if defined(linux) || defined(__NetBSD__) || defined (__OpenBSD__) @@ -204,6 +305,7 @@ t_stat eth_close(ETH_DEV* dev) /* close the device */ pcap_close(dev->handle); + if (sim_log) fprintf (sim_log, "Eth: closed %s\n", dev->name); /* clean up the mess */ free(dev->name); @@ -225,7 +327,7 @@ t_stat eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) /* make sure packet is acceptable length */ if ((packet->len >= ETH_MIN_PACKET) && (packet->len <= ETH_MAX_PACKET)) { /* dispatch write request (synchronous; no need to save write info to dev) */ -#ifdef _DEBUG +#ifdef ETH_DEBUG eth_packet_trace (packet, "writing"); #endif status = pcap_sendpacket((pcap_t*)dev->handle, (u_char*)packet->msg, packet->len); @@ -242,13 +344,32 @@ void eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* { ETH_DEV* dev = (ETH_DEV*) info; - /*+ temporary packet filter - should be done by BPF filter */ + /* receive packet filter */ int to_me = 0; int from_me = 0; int i; for (i = 0; i < ETH_FILTER_MAX; i++) { if (memcmp(data, dev->filter_address[i], 6) == 0) to_me = 1; +#ifdef WIN32 + /* + WinPcap has a known bug/feature that whenever a packet is transmitted, + it is looped back into the receive buffers. This is not consistant with the + behavior of real ethernet adapters, so the extra packets must be disposed of. + + This behavior is seen when starting DECNET; DECNET broadcasts a packet + with the same source and destination addresses to make sure that no other + ethernet adapter on the network is using the DECNET address that it wants. + If it sees this test packet coming back in, it assumes that another node on + the network has the same DECNET address and refuses to start, giving an + "Invalid media address" error. + + This code section was ifdef'd for WIN32 only to allow other OS's a chance to + properly implement the above behavior. If it breaks the ethernet simulator + on other platforms, remove the ifdef so that it will affect your platform, + and then notify the author so that he can fix the ifdef. :-) + */ if (memcmp(&data[6], dev->filter_address[i], 6) == 0) from_me = 1; +#endif } /* for */ /* all multicast mode? */ @@ -259,26 +380,19 @@ void eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* if (to_me && !from_me) { - /*- temporary packet filter - should be done by driver filter */ + /* set data in passed read packet */ + dev->read_packet->len = header->len; + memcpy(dev->read_packet->msg, data, header->len); - - /* set data in passed read packet */ - dev->read_packet->len = header->len; - memcpy(dev->read_packet->msg, data, header->len); - -#ifdef _DEBUG - eth_packet_trace (dev->read_packet, "reading"); +#ifdef ETH_DEBUG + eth_packet_trace (dev->read_packet, "reading"); #endif - /* call optional read callback function */ - if (dev->read_callback) - (dev->read_callback)(0); - - - /*+ temporary packet filter - should be done by driver filter */ - } /* if use */ - /*- temporary packet filter - should be done by driver filter */ + /* call optional read callback function */ + if (dev->read_callback) + (dev->read_callback)(0); + } /* if to_me && !from_me */ } t_stat eth_read(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) @@ -293,13 +407,15 @@ t_stat eth_read(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) /* set read packet */ dev->read_packet = packet; + packet->len = 0; /* set optional callback routine */ dev->read_callback = routine; - /* dispatch read request */ - status = pcap_dispatch((pcap_t*)dev->handle, 1, ð_callback, (u_char*)dev); - + /* dispatch read request to either receive a packet (after filtering) or timeout */ + do { + status = pcap_dispatch((pcap_t*)dev->handle, 1, ð_callback, (u_char*)dev); + } while ((status) && (0 == packet->len)); return SCPE_OK; } @@ -311,8 +427,6 @@ t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* addresses, /* make sure device exists */ if (!dev) return SCPE_UNATT; - /* should be implemented as a BPF filter, but for now.. */ - /* filter count OK? */ if ((addr_count < 0) || (addr_count > ETH_FILTER_MAX)) return SCPE_ARG; @@ -326,7 +440,7 @@ t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* addresses, for (i = 0; i < addr_count; i++) memcpy(dev->filter_address[i], addresses[i], sizeof(ETH_MAC)); - /* set all_multicast and promiscuous flags */ + /* store other flags */ dev->all_multicast = all_multicast; dev->promiscuous = promiscuous; @@ -339,7 +453,7 @@ int eth_devices(int max, ETH_LIST* list) uint8 buffer[2048]; uint8 buffer2[2048]; uint8* cptr = buffer2; - int size = sizeof(buffer); + unsigned long size = sizeof(buffer); unsigned long ret; /* get names of devices from packet driver */ @@ -409,7 +523,7 @@ int pcap_sendpacket(pcap_t* handle, u_char* msg, int len) return (send(pcap_fileno(handle), msg, len, 0) == len)?0:-1; } -int PacketGetAdapterNames(char* buffer, int* size) +int PacketGetAdapterNames(char* buffer, unsigned long* size) { struct ifreq ifr; int iindex = 1; @@ -454,7 +568,7 @@ int pcap_sendpacket(pcap_t* handle, u_char* msg, int len) return (write(pcap_fileno(handle), msg, len) == len)?0:-1; } -int PacketGetAdapterNames(char* buffer, int* size) +int PacketGetAdapterNames(char* buffer, unsigned long* size) { const struct sockaddr_dl *sdl; struct ifaddrs *ifap, *ifa; diff --git a/sim_ether.h b/sim_ether.h index 46aa2ba2..809530b0 100644 --- a/sim_ether.h +++ b/sim_ether.h @@ -59,6 +59,20 @@ struct eth_packet { int len; }; +struct eth_message { + int type; + struct eth_packet pack; +}; + +struct eth_queue { + int max; + int count; + int head; + int tail; + int loss; + struct eth_message* arr; +}; + struct eth_list { int num; uint8 name[ETH_DEV_NAME_MAX]; diff --git a/sim_rev.h b/sim_rev.h index 11cfc1b9..196638ff 100644 --- a/sim_rev.h +++ b/sim_rev.h @@ -1,6 +1,6 @@ /* sim_rev.h: simulator revisions and current rev level - Copyright (c) 1993-2002, Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -24,14 +24,56 @@ in this Software without prior written authorization from Robert M Supnik. */ +#ifndef _SIM_REV_H_ +#define _SIM_REV_H_ 0 + #define SIM_MAJOR 2 #define SIM_MINOR 10 -#define SIM_PATCH 0 +#define SIM_PATCH 2 /* V2.10 revision history patch date module(s) and fix(es) + 2 15-Jan-03 scp.c: + -- added dynamic memory size flag and RESTORE support + -- added EValuate command + -- added get_ipaddr routine + -- added ! (OS command) feature (from Mark Pizzolato) + -- added BREAK support to sim_poll_kbd (from Mark Pizzolato) + + sim_tmxr.c: + -- fixed bugs in IAC+IAC handling (from Mark Pizzolato) + -- added IAC+BRK handling (from Mark Pizzolato) + + sim_sock.c: + -- added use count for Windows start/stop + -- added sim_connect_sock + + pdp1_defs.h, pdp1_cpu.c, pdp1_sys.c, pdp1_drm.c: + added Type 24 serial drum + + pdp18_defs.h: added PDP-4 drum support + + hp2100_cpu.c: added 21MX IOP support + + hp2100_ipl.c: added HP interprocessor link support + + pdp11_tq.c: fixed bug in transfer end packet length + + pdp11_xq.c: + -- added VMScluster support (thanks to Mark Pizzolato) + -- added major performance enhancements (thanks to Mark Pizzolato) + -- added local packet processing + -- added system id broadcast + + pdp11_stddev.c: changed default to 7b (for early UNIX) + + vax_cpu.c, vax_io.c, vax_stddev.c, vax_sysdev.c: + added console halt capability (from Mark Pizzolato) + + all terminals and multiplexors: added BREAK support + 1 21-Nov-02 pdp1_stddev.c: changed typewriter to half duplex (found by Derek Peschel) @@ -496,3 +538,5 @@ patch date module(s) and fix(es) sim_sock.c: added Macintosh sockets support */ + +#endif diff --git a/sim_sock.c b/sim_sock.c index fc91f942..87345e7f 100644 --- a/sim_sock.c +++ b/sim_sock.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 17-Dec-02 RMS Added sim_connect_socket, sim_create_socket 08-Oct-02 RMS Revised for .NET compatibility 22-Aug-02 RMS Changed calling sequence for sim_accept_conn 22-May-02 RMS Added OS2 EMX support from Holger Veit @@ -46,6 +47,8 @@ sim_msg_sock send message to socket */ +int32 sim_sock_cnt = 0; + /* First, all the non-implemented versions */ #if defined (__OS2__) && !defined (__EMX__) @@ -55,6 +58,11 @@ SOCKET sim_master_sock (int32 port) return INVALID_SOCKET; } +SOCKET sim_connect_sock (int32 ip, int32 port) +{ +return INVALID_SOCKET; +} + SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr) { return INVALID_SOCKET; @@ -84,54 +92,92 @@ return SOCKET_ERROR; /* UNIX, Win32, Macintosh, VMS, OS2 (Berkeley socket) routines */ +SOCKET sim_err_sock (SOCKET s, char *emsg, int32 flg) +{ +int32 err = WSAGetLastError (); + +printf ("Sockets: %s error %d\n", emsg, err); +sim_close_sock (s, flg); +return INVALID_SOCKET; +} + +SOCKET sim_create_sock (void) +{ +SOCKET newsock; +int32 err; + +#if defined (WIN32) +WORD wVersionRequested; +WSADATA wsaData; +wVersionRequested = MAKEWORD (1, 1); + +if (sim_sock_cnt == 0) { + err = WSAStartup (wVersionRequested, &wsaData); /* start Winsock */ + if (err != 0) { + printf ("Winsock: startup error %d\n", err); + return INVALID_SOCKET; } } +sim_sock_cnt = sim_sock_cnt + 1; +#endif /* endif Win32 */ + +newsock = socket (AF_INET, SOCK_STREAM, 0); /* create socket */ +if (newsock == INVALID_SOCKET) { /* socket error? */ + err = WSAGetLastError (); + printf ("Sockets: socket error %d\n", err); + return INVALID_SOCKET; } +return newsock; +} + SOCKET sim_master_sock (int32 port) { SOCKET newsock; struct sockaddr_in name; int32 sta; -#if defined (WIN32) -WORD wVersionRequested; -WSADATA wsaData; -wVersionRequested = MAKEWORD (1, 1); - -sta = WSAStartup (wVersionRequested, &wsaData); /* start Winsock */ -if (sta != 0) { - printf ("Winsock: startup error %d\n", sta); - return sta; } -#endif /* endif Win32 */ - -newsock = socket (AF_INET, SOCK_STREAM, 0); /* create socket */ -if (newsock == INVALID_SOCKET) { /* socket error? */ - perror ("Sockets: socket error"); - return INVALID_SOCKET; } +newsock = sim_create_sock (); /* create socket */ +if (newsock == INVALID_SOCKET) return newsock; /* socket error? */ name.sin_family = AF_INET; /* name socket */ name.sin_port = htons ((unsigned short) port); /* insert port */ -name.sin_addr.s_addr = htonl (INADDR_ANY); +name.sin_addr.s_addr = htonl (INADDR_ANY); /* insert addr */ + sta = bind (newsock, (struct sockaddr *) &name, sizeof (name)); -if (sta == SOCKET_ERROR) { /* bind error? */ - perror ("Sockets: bind error"); - sim_close_sock (newsock, 1); - return INVALID_SOCKET; } +if (sta == SOCKET_ERROR) /* bind error? */ + return sim_err_sock (newsock, "bind", 1); +sta = sim_setnonblock (newsock); /* set nonblocking */ +if (sta == SOCKET_ERROR) /* fcntl error? */ + return sim_err_sock (newsock, "fcntl", 1); +sta = listen (newsock, 1); /* listen on socket */ +if (sta == SOCKET_ERROR) /* listen error? */ + return sim_err_sock (newsock, "listen", 1); +return newsock; /* got it! */ +} + +SOCKET sim_connect_sock (int32 ip, int32 port) +{ +SOCKET newsock; +struct sockaddr_in name; +int32 sta; + +newsock = sim_create_sock (); /* create socket */ +if (newsock == INVALID_SOCKET) return newsock; /* socket error? */ + +name.sin_family = AF_INET; /* name socket */ +name.sin_port = htons ((unsigned short) port); /* insert port */ +name.sin_addr.s_addr = htonl (ip); /* insert addr */ sta = sim_setnonblock (newsock); /* set nonblocking */ -if (sta == SOCKET_ERROR) { /* fcntl error? */ - perror ("Sockets: fcntl error"); - sim_close_sock (newsock, 1); - return INVALID_SOCKET; } +if (sta == SOCKET_ERROR) /* fcntl error? */ + return sim_err_sock (newsock, "fcntl", 1); +sta = connect (newsock, (struct sockaddr *) &name, sizeof (name)); +if ((sta == SOCKET_ERROR) && (WSAGetLastError () != WSAEWOULDBLOCK)) + return sim_err_sock (newsock, "connect", 1); -sta = listen (newsock, 1); /* listen on socket */ -if (sta == SOCKET_ERROR) { /* listen error? */ - perror ("Sockets: listen error"); - sim_close_sock (newsock, 1); - return INVALID_SOCKET; } return newsock; /* got it! */ } SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr) { -int32 sta; +int32 sta, err; #if defined (macintosh) socklen_t size; #elif defined (WIN32) || defined (__EMX__) @@ -146,28 +192,46 @@ if (master == 0) return INVALID_SOCKET; /* not attached? */ size = sizeof (clientname); newsock = accept (master, (struct sockaddr *) &clientname, &size); if (newsock == INVALID_SOCKET) { /* error? */ - if (WSAGetLastError () != WSAEWOULDBLOCK) - perror ("Sockets: accept error"); + err = WSAGetLastError (); + if (err != WSAEWOULDBLOCK) + printf ("Sockets: accept error %d\n", err); return INVALID_SOCKET; } if (ipaddr != NULL) *ipaddr = ntohl (clientname.sin_addr.s_addr); sta = sim_setnonblock (newsock); /* set nonblocking */ -if (sta == SOCKET_ERROR) { /* fcntl error? */ - perror ("Sockets: fcntl error"); - sim_close_sock (newsock, 0); - return INVALID_SOCKET; } +if (sta == SOCKET_ERROR) /* fcntl error? */ + return sim_err_sock (newsock, "fcntl", 0); return newsock; } +int32 sim_check_conn (SOCKET sock, t_bool rd) +{ +fd_set rw_set, er_set; +fd_set *rw_p = &rw_set; +fd_set *er_p = &er_set; +struct timeval tz = { 0, 0}; + +FD_ZERO (rw_p); +FD_ZERO (er_p); +FD_SET (sock, rw_p); +FD_SET (sock, er_p); +if (rd) select ((int) sock + 1, rw_p, NULL, er_p, &tz); +else select ((int) sock + 1, NULL, rw_p, er_p, &tz); +if (FD_ISSET (sock, rw_p)) return 1; +if (FD_ISSET (sock, er_p)) return -1; +return 0; +} + int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes) { -int32 rbytes; +int32 rbytes, err; rbytes = recv (sock, buf, nbytes, 0); if (rbytes == 0) return -1; /* disconnect */ if (rbytes == SOCKET_ERROR) { - if (WSAGetLastError () == WSAEWOULDBLOCK) return 0; /* no data */ - perror("Sockets: read error"); + err = WSAGetLastError (); + if (err == WSAEWOULDBLOCK) return 0; /* no data */ + printf ("Sockets: read error %d\n", err); return -1; } return rbytes; } @@ -181,7 +245,11 @@ void sim_close_sock (SOCKET sock, t_bool master) { #if defined (WIN32) closesocket (sock); -if (master) WSACleanup (); +if (master) { + sim_sock_cnt = sim_sock_cnt - 1; + if (sim_sock_cnt <= 0) { + WSACleanup (); + sim_sock_cnt = 0; } } #else close (sock); #endif diff --git a/sim_sock.h b/sim_sock.h index 1e8d74d0..d393b2d8 100644 --- a/sim_sock.h +++ b/sim_sock.h @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 17-Dec-02 RMS Added sim_connect_sock 08-Oct-02 RMS Revised for .NET compatibility 20-Aug-02 RMS Changed calling sequence for sim_accept_conn 30-Apr-02 RMS Changed VMS stropts include to ioctl @@ -56,7 +57,9 @@ #endif SOCKET sim_master_sock (int32 port); +SOCKET sim_connect_sock (int32 ip, int32 port); SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr); +int32 sim_check_conn (SOCKET sock, t_bool rd); int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes); int32 sim_write_sock (SOCKET sock, char *msg, int32 nbytes); void sim_close_sock (SOCKET sock, t_bool master); diff --git a/sim_tmxr.c b/sim_tmxr.c index d5148030..5fbcbae0 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -26,12 +26,15 @@ Based on the original DZ11 simulator by Thord Nilson, as updated by Arthur Krewat. + 22-Dec-02 RMS Fixed bugs in IAC+IAC receive and transmit sequences + Added support for received break (all from by Mark Pizzolato) + Fixed bug in attach 31-Oct-02 RMS Fixed bug in 8b (binary) support 22-Aug-02 RMS Added tmxr_open_master, tmxr_close_master 30-Dec-01 RMS Added tmxr_fstats, tmxr_dscln, renamed tmxr_fstatus 03-Dec-01 RMS Changed tmxr_fconns for extended SET/SHOW 20-Oct-01 RMS Fixed bugs in read logic (found by Thord Nilson). - added tmxr_rqln, tmxr_tqln + Added tmxr_rqln, tmxr_tqln */ #include "sim_defs.h" @@ -45,6 +48,7 @@ #define TN_DO -3 /* do */ #define TN_WONT -4 /* wont */ #define TN_WILL -5 /* will */ +#define TN_BRK -13 /* break */ #define TN_BIN 0 /* bin */ #define TN_ECHO 1 /* echo */ #define TN_SGA 3 /* sga */ @@ -91,26 +95,27 @@ static char mantra[] = { newsock = sim_accept_conn (mp->master, &ipaddr); /* poll connect */ if (newsock != INVALID_SOCKET) { /* got a live one? */ for (i = 0; i < mp->lines; i++) { /* find avail line */ - lp = mp->ldsc[i]; /* ptr to ln desc */ - if (lp->conn == 0) break; } /* available? */ + lp = mp->ldsc[i]; /* ptr to ln desc */ + if (lp->conn == 0) break; } /* available? */ if (i >= mp->lines) { /* all busy? */ - tmxr_msg (newsock, "All connections busy\r\n"); - sim_close_sock (newsock, 0); } - else { lp = mp->ldsc[i]; /* get line desc */ - lp->conn = newsock; /* record connection */ - lp->ipad = ipaddr; /* ip address */ - lp->cnms = sim_os_msec (); /* time of conn */ - lp->rxbpr = lp->rxbpi = 0; /* init buf pointers */ - lp->txbpr = lp->txbpi = 0; - lp->rxcnt = lp->txcnt = 0; /* init counters */ - lp->tsta = 0; /* init telnet state */ - lp->xmte = 1; /* enable transmit */ - lp->dstb = 0; /* default bin mode */ - sim_write_sock (newsock, mantra, 15); - tmxr_msg (newsock, "\n\r\nConnected to the "); - tmxr_msg (newsock, sim_name); - tmxr_msg (newsock, " simulator\r\n\n"); - return i; } + tmxr_msg (newsock, "All connections busy\r\n"); + sim_close_sock (newsock, 0); } + else { + lp = mp->ldsc[i]; /* get line desc */ + lp->conn = newsock; /* record connection */ + lp->ipad = ipaddr; /* ip address */ + lp->cnms = sim_os_msec (); /* time of conn */ + lp->rxbpr = lp->rxbpi = 0; /* init buf pointers */ + lp->txbpr = lp->txbpi = 0; + lp->rxcnt = lp->txcnt = 0; /* init counters */ + lp->tsta = 0; /* init telnet state */ + lp->xmte = 1; /* enable transmit */ + lp->dstb = 0; /* default bin mode */ + sim_write_sock (newsock, mantra, 15); + tmxr_msg (newsock, "\n\r\nConnected to the "); + tmxr_msg (newsock, sim_name); + tmxr_msg (newsock, " simulator\r\n\n"); + return i; } } /* end if newsock */ return -1; } @@ -144,9 +149,10 @@ uint32 tmp; if (lp->conn && lp->rcve) { /* conn & enb? */ j = lp->rxbpi - lp->rxbpr; /* # input chrs */ if (j) { /* any? */ - tmp = lp->rxb[lp->rxbpr]; /* get char */ - lp->rxbpr = lp->rxbpr + 1; /* adv pointer */ - val = TMXR_VALID | (tmp & 0377); } /* valid + chr */ + tmp = lp->rxb[lp->rxbpr]; /* get char */ + val = TMXR_VALID | (tmp & 0377); /* valid + chr */ + if (lp->rbr[lp->rxbpr]) val = val | SCPE_BREAK; /* break? */ + lp->rxbpr = lp->rxbpr + 1; } /* adv pointer */ } /* end if conn */ if (lp->rxbpi == lp->rxbpr) /* empty? zero ptrs */ lp->rxbpi = lp->rxbpr = 0; @@ -181,6 +187,7 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ if (nbytes < 0) tmxr_reset_ln (lp); /* closed? reset ln */ else if (nbytes > 0) { /* if data rcvd */ j = lp->rxbpi; /* start of data */ + memset (&lp->rbr[j], 0, nbytes); /* clear status */ lp->rxbpi = lp->rxbpi + nbytes; /* adv pointers */ lp->rxcnt = lp->rxcnt + nbytes; @@ -201,7 +208,14 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ case TNS_IAC: /* IAC prev */ if ((tmp == TN_IAC) & !lp->dstb) { /* IAC + IAC, bin? */ lp->tsta = TNS_NORM; /* treat as normal */ + j = j + 1; /* advance j */ break; } /* keep IAC */ + if (tmp == TN_BRK) { /* IAC + BRK? */ + lp->tsta = TNS_NORM; /* treat as normal */ + lp->rxb[j] = 0; /* char is null */ + lp->rbr[j] = 1; /* flag break */ + j = j + 1; /* advance j */ + break; } if (tmp == TN_WILL) /* IAC + WILL? */ lp->tsta = TNS_WILL; else if (tmp == TN_WONT) /* IAC + WONT? */ @@ -223,7 +237,7 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ lp = mp->ldsc[i]; /* get line desc */ if (lp->rxbpi == lp->rxbpr) /* if buf empty, */ - lp->rxbpi = lp->rxbpr = 0; /* reset pointers */ + lp->rxbpi = lp->rxbpr = 0; /* reset pointers */ } /* end for */ return; } @@ -235,11 +249,13 @@ int32 tmxr_rqln (TMLN *lp) return (lp->rxbpi - lp->rxbpr); } -/* Remove character p from line l input buffer */ +/* Remove character p (and matching status) from line l input buffer */ void tmxr_rmvrc (TMLN *lp, int32 p) { -for ( ; p < lp->rxbpi; p++) lp->rxb[p] = lp->rxb[p + 1]; +for ( ; p < lp->rxbpi; p++) { + lp->rxb[p] = lp->rxb[p + 1]; + lp->rbr[p] = lp->rbr[p + 1]; } lp->rxbpi = lp->rxbpi - 1; return; } @@ -259,8 +275,12 @@ if (lp->conn == 0) return; /* no conn? done */ if (lp->txbpi < TMXR_MAXBUF) { /* room for char? */ lp->txb[lp->txbpi] = (char) chr; /* buffer char */ lp->txbpi = lp->txbpi + 1; /* adv pointer */ + if (((char) chr == TN_IAC) && /* IAC? */ + (lp->txbpi < TMXR_MAXBUF)) { /* room for char? */ + lp->txb[lp->txbpi] = (char) chr; /* IAC + IAC */ + lp->txbpi = lp->txbpi + 1; } /* adv pointer */ if (lp->txbpi > (TMXR_MAXBUF - TMXR_GUARD)) /* near full? */ - lp->xmte = 0; } /* disable line */ + lp->xmte = 0; } /* disable line */ else lp->xmte = 0; /* disable line */ return; } @@ -283,16 +303,16 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ if (lp->conn == 0) continue; /* skip if !conn */ nbytes = lp->txbpi - lp->txbpr; /* avail bytes */ if (nbytes) { /* >0? write */ - sbytes = sim_write_sock (lp->conn, - &(lp->txb[lp->txbpr]), nbytes); - if (sbytes != SOCKET_ERROR) { /* update ptrs */ - lp->txbpr = lp->txbpr + sbytes; - lp->txcnt = lp->txcnt + sbytes; - nbytes = nbytes - sbytes; } - } + sbytes = sim_write_sock (lp->conn, + &(lp->txb[lp->txbpr]), nbytes); + if (sbytes != SOCKET_ERROR) { /* update ptrs */ + lp->txbpr = lp->txbpr + sbytes; + lp->txcnt = lp->txcnt + sbytes; + nbytes = nbytes - sbytes; } + } if (nbytes == 0) { /* buf empty? */ - lp->xmte = 1; /* enable this line */ - lp->txbpr = lp->txbpi = 0; } + lp->xmte = 1; /* enable this line */ + lp->txbpr = lp->txbpi = 0; } } /* end for */ return; } @@ -340,6 +360,12 @@ t_stat tmxr_attach (TMXR *mp, UNIT *uptr, char *cptr) char* tptr; t_stat r; +if (uptr->flags & UNIT_ATT) { /* attached? */ + DEVICE *dptr = find_dev_from_unit (uptr); /* find device */ + if (dptr == NULL) return SCPE_IERR; + if (dptr->detach != NULL) r = dptr->detach (uptr); + else r = detach_unit (uptr); /* detach unit */ + if (r != SCPE_OK) return r; } tptr = malloc (strlen (cptr) + 1); /* get string buf */ if (tptr == NULL) return SCPE_MEM; /* no more mem? */ r = tmxr_open_master (mp, cptr); /* open master socket */ @@ -362,10 +388,10 @@ TMLN *lp; for (i = 0; i < mp->lines; i++) { /* loop thru conn */ lp = mp->ldsc[i]; if (lp->conn) { - tmxr_msg (lp->conn, "\r\nDisconnected from the "); - tmxr_msg (lp->conn, sim_name); - tmxr_msg (lp->conn, " simulator\r\n\n"); - tmxr_reset_ln (lp); } /* end if conn */ + tmxr_msg (lp->conn, "\r\nDisconnected from the "); + tmxr_msg (lp->conn, sim_name); + tmxr_msg (lp->conn, " simulator\r\n\n"); + tmxr_reset_ln (lp); } /* end if conn */ } /* end for */ sim_close_sock (mp->master, 1); /* close master socket */ mp->master = 0; diff --git a/sim_tmxr.h b/sim_tmxr.h index 4eb9bb8b..2091920a 100644 --- a/sim_tmxr.h +++ b/sim_tmxr.h @@ -26,6 +26,7 @@ Based on the original DZ11 simulator by Thord Nilson, as updated by Arthur Krewat. + 22-Dec-02 RMS Added break support (from Mark Pizzolato) 20-Aug-02 RMS Added tmxr_open_master, tmxr_close_master, tmxr.port 30-Dec-01 RMS Renamed tmxr_fstatus, added tmxr_fstats 20-Oct-01 RMS Removed tmxr_getchar, formalized buffer guard, @@ -56,6 +57,7 @@ struct tmln { int32 txbpi; /* xmt buf insert */ int32 txcnt; /* xmt count */ char rxb[TMXR_MAXBUF]; /* rcv buffer */ + char rbr[TMXR_MAXBUF]; /* rcv break */ char txb[TMXR_MAXBUF]; /* xmt buffer */ }; diff --git a/simh_doc.txt b/simh_doc.txt index 5b904eca..756bd75b 100644 --- a/simh_doc.txt +++ b/simh_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik -Subj: Simulator Usage, V2.10 -Date: 15-Nov-2002 +Subj: Simulator Usage, V2.10-2 +Date: 15-Jan-2003 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2002, written by Robert M Supnik - Copyright (c) 1993-2002, Robert M Supnik + Original code published in 1993-2003, written by Robert M Supnik + Copyright (c) 1993-2003, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -103,9 +103,16 @@ UNIX text conventions. This can be done with the UNIX UNZIP utility (unzip -a). The supplied makefile will compile the simulators for UNIX systems -which support the POSIX TERMIOS. The VAX and PDP-11 will be compiled -without Ethernet support; use makefile_ether to compile with Ethernet -support. Notes for hand compilation: +which support the POSIX TERMIOS. The VAX and PDP-11 can be compiled +with or without Ethernet support. To compile without Ethernet support: + + gmake {target|ALL} + +To compile with Ethernet support: + + gmake USE_NETWORK=1 {target|ALL} + +Notes for hand compilation: - The default UNIX terminal handling model is the POSIX TERMIOS interface, which is supported by Linux, Mac OS/X, and Alpha UNIX. @@ -150,7 +157,7 @@ simulators with Ethernet support. - Get the required .lib files (packet.lib, wpcap.lib) from the WinPCAP 3.0 developer's kit. If you're using Borland C++, use COFF2OMF to convert the .lib files into a format that can be used by the compiler. - Then move the libraries to the top level simulation directory. + Then move the libraries to the standard library directory. - Add -DUSE_NETWORK to the compilation command lines for the PDP-11 and VAX. @@ -609,7 +616,17 @@ quotation marks. If the switch -V is specified, the commands in the file are echoed before they are executed. -3.13 Getting Help +3.13 Executing System Commands + +The simulator can execute operating system commands with the ! (spawn) +command: + + sim> ! + +If no operating system command is provided, the simulator attempts to +launch the host operating system's command shell. + +3.14 Getting Help The HELP command prints out information about a command or about all commands: @@ -617,7 +634,7 @@ commands: sim> HELP -- print all HELP messages sim> HELP -- print HELP for command -3.14 Exiting The Simulator +3.15 Exiting The Simulator EXIT (synonyms QUIT and BYE) returns control to the operating system. @@ -716,6 +733,7 @@ extra terminal y y y - y hard disk y y y - h fixed disk y - h - h floppy disk y y y - - +drum - - - - h DECtape y y - h y mag tape h y y - h @@ -730,28 +748,30 @@ card reader y - - - - line printer y d y h y clock - d y h y extra terminal - h y - y -hard disk - h y - y -fixed disk - h - - - +hard disk - d y - y +fixed disk - n - - - floppy disk - - h - - +drum - n - - - DECtape - - - - - mag tape y d y - y - system GRI-909 1620 + system GRI-909 1620 i16 i32 SDS940 device -CPU h h -FPU - - -CIS - - -console h h -paper tape h h -card reader - h -line printer - h -clock h - -extra terminal - - -hard disk - h -fixed disk - - -floppy disk - - -DECtape - - -mag tape - - +CPU h h d d d +FPU - - d d - +CIS - - - - - +console h h d d h +paper tape h h d d h +card reader - h - - - +line printer - h d d h +clock h - d d n +extra terminal - - h h h +hard disk - h d d h +fixed disk - - - - h +floppy disk - - d d - +drum - - - - h +DECtape - - - - - +mag tape - - d d h legend: y = runs operating system or sample program d = runs diagnostics @@ -766,10 +786,12 @@ in file sim_rev.c. Rev 2.10, Nov, 02 Added Telnet console capability, removed VT emulation - Added DO with substitutable arguments - Added quiet mode + Added DO with substitutable arguments (from Brian Knittel) + Added quiet mode (from Brian Knittel) + Added ! command (from Mark Pizzolato) + Added Telnet BREAK support (from Mark Pizzolato) Added device enable/disable support - Added optional simulator for input, output, commands + Added optional simulator hooks for input, output, commands Added PDP-11 KW11P programmable clock Added PDP-11 RK611/RK06/RK07 disk Added PDP-11/VAX TMSCP tape @@ -782,11 +804,15 @@ Rev 2.10, Nov, 02 Added HP2100 12845A line printer Added HP2100 13183 magtape support Added HP2100 boot ROM support + Added HP2100 interprocessor link support Added IBM 1620 + Added SDS 940 + Added Interdata 16b and 32b systems Added 16b DECtape file format support Added support for statically buffered devices Added magtape end of medium support Added 7B/8B support to terminals and multiplexors + Added BREAK support to terminals and multiplexors Rev 2.9, Jan, 02 Added circular register arrays